Prüfen, ob aktueller Benutzer Adminrechte hat

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von Dideldum.

    @Dideldum Dein Code.... kann man machen. Wobei dieses aufrufen von cmd .... Schaust Du hier: learn.microsoft.com/en-us/wind…eapi-checktokenmembership Ja es gibt noch die API IsUserAnAdmin. Doch da steht: [IsUserAnAdmin ist für die Verwendung in den im Abschnitt Anforderungen angegebenen Betriebssystemen verfügbar. Sie kann in nachfolgenden Versionen geändert oder nicht verfügbar sein.] mit dem Hinweis auf die API CheckTokenMembership. Ist zwar für VB6, sollte sich dennoch leicht nach .NET übersetzten lassen: stackoverflow.com/questions/18…ecktokenmembership-in-vb6 (die Antwort mit dem grünen Häkchen) Zumindest funktioniert das bei mir.
    Mfg -Franky-
    Danke Dir, @-Franky-

    Habe mal versucht, den Code zu übersetzen:

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. <StructLayout(LayoutKind.Sequential)>
    3. Public Structure SID_IDENTIFIER_AUTHORITY
    4. <MarshalAs(UnmanagedType.ByValArray, SizeConst:=6)>
    5. Public Value() As Byte
    6. End Structure
    7. Public Class Mainform
    8. ' Is User an Admin
    9. Private Const SECURITY_BUILTIN_DOMAIN_RID As Long = &H20
    10. Private Const DOMAIN_ALIAS_RID_ADMINS As Long = &H220
    11. Private Declare Function AllocateAndInitializeSid Lib "advapi32.dll" (
    12. ByRef pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY,
    13. ByVal nSubAuthorityCount As Byte,
    14. ByVal nSubAuthority0 As Long,
    15. ByVal nSubAuthority1 As Long,
    16. ByVal nSubAuthority2 As Long,
    17. ByVal nSubAuthority3 As Long,
    18. ByVal nSubAuthority4 As Long,
    19. ByVal nSubAuthority5 As Long,
    20. ByVal nSubAuthority6 As Long,
    21. ByVal nSubAuthority7 As Long,
    22. ByRef lpPSid As IntPtr
    23. ) As Integer
    24. Private Declare Sub FreeSid Lib "advapi32.dll" (ByVal pSid As IntPtr)
    25. Private Declare Function CheckTokenMembership Lib "advapi32.dll" (ByVal hToken As IntPtr, ByVal pSidToCheck As IntPtr, ByRef pbIsMember As Integer) As Integer
    26. Private Function PvIsAdmin() As Boolean
    27. Dim mySid As SID_IDENTIFIER_AUTHORITY
    28. ReDim mySid.Value(5)
    29. mySid.Value = New Byte() {1, 2, 3, 4, 5, 6}
    30. Dim pSidAdmins As IntPtr
    31. Dim lResult As Integer
    32. mySid.Value(5) = 5
    33. If AllocateAndInitializeSid(mySid, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, pSidAdmins) <> 0 Then
    34. If CheckTokenMembership(IntPtr.Zero, pSidAdmins, lResult) <> 0 Then
    35. PvIsAdmin = (lResult <> 0)
    36. End If
    37. Call FreeSid(pSidAdmins)
    38. End If
    39. PvIsAdmin = False
    40. End Function
    41. End Class


    Aber irgendwo würmelt es noch da drin.
    PVIsAdmin gibt mir "False" zurück, obwohl ich als "Admin" angemeldet bin.
    Hast Du 'ne Ahnung, wo ich mich verknotet habe?

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Dideldum“ ()

    @Dideldum Du darfst nicht vergessen, alles was in VB6 ein Long ist, ist in .NET ein Integer. Ausnahmen sind: Alles was einen Handler/Pointer erwartet, ist ein IntPtr. Daher sind Deine Const/APIs schon mal nicht richtig. Wobei, wenn Du Dir die APIs in der MS-Doku anschaust, wird aus einem DWORD eigentlich ein UInteger. Einige API-Rückgaben hast Du als Integer deklariert, ist aber ein BOOL. Hier musst Du entsprechend marshallen -> Boolean. Dann dieser Teil: mySid.Value = New Byte() {1, 2, 3, 4, 5, 6} kommt gar nicht im VB6 Code vor und wäre auch falsch? Such Dir auch für mySid.Value(5) = 5 die entsprechende Konstante aus der MS-Doku damit Du weist wofür die 5 steht. In der Structure SID_IDENTIFIER_AUTHORITY würde ich eine Sub New(Param) einfügen damit Du schon bei New SID_IDENTIFIER_AUTHORITY das ByteArray dimensionierst und den passenden Parameter/Const (5) übergeben kannst. Die API FreeSid ist eigentlich eine Funktion. -> If the function succeeds, the function returns NULL. If the function fails, it returns a pointer to the SID structure represented by the pSid parameter. Die Rückgabe kann aber ignoriert werden.

    Mfg -Franky-

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „-Franky-“ ()

    Ägyptisch? =O :D
    Oh jeh...
    Danke Dir - ist sicher alles richtig, was Du geschrieben hast.
    Aber das alles ist mir nach der kurzen Zeit, in welcher ich erst mit VB.net zugange bin, noch nicht verständlich.
    Ich glaube, ich bleibe beim CMD-Aufruf, bis ich das, was Du geschrieben hast, irgendwann auch verstehe. ;)
    Dann komme ich aber gerne auf Deine Beschreibung zurück.
    Habe mir Deine Antwort auf alle Fälle gespeichert. ^^

    Dideldum schrieb:

    Ägyptisch?
    Neeee. Probier mal. Ich kann das im Moment nur auf meinem ArbeitsPC testen wo ich selbst keine Adminrechte habe. Ich kann nur die Exe mit Ausführen als Administrator bzw. Ausführen mit anderem Benutzer testen, der Adminrechte hat und da funktioniert der Code.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Private Const DOMAIN_ALIAS_RID_ADMINS As UInteger = &H220
    4. Private Const SECURITY_BUILTIN_DOMAIN_RID As UInteger = &H20
    5. Private Const SECURITY_NT_AUTHORITY As Byte = 5
    6. <StructLayout(LayoutKind.Sequential)>
    7. Private Structure SID_IDENTIFIER_AUTHORITY
    8. <MarshalAs(UnmanagedType.ByValArray, SizeConst:=6, ArraySubType:=UnmanagedType.I1)> Dim Value() As Byte
    9. Public Sub New(AuthorityIdentifier As Byte)
    10. Value = New Byte(5) {0, 0, 0, 0, 0, AuthorityIdentifier}
    11. End Sub
    12. End Structure
    13. <DllImport("advapi32.dll", EntryPoint:="FreeSid")>
    14. Private Shared Function FreeSid(<[In]> pSid As IntPtr) As IntPtr
    15. End Function
    16. <DllImport("advapi32.dll", EntryPoint:="AllocateAndInitializeSid")>
    17. Private Shared Function AllocateAndInitializeSid(<[In], MarshalAs(UnmanagedType.Struct)> ByRef pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY,
    18. <[In]> nSubAuthorityCount As Byte,
    19. <[In]> nSubAuthority0 As UInteger,
    20. <[In]> nSubAuthority1 As UInteger,
    21. <[In]> nSubAuthority2 As UInteger,
    22. <[In]> nSubAuthority3 As UInteger,
    23. <[In]> nSubAuthority4 As UInteger,
    24. <[In]> nSubAuthority5 As UInteger,
    25. <[In]> nSubAuthority6 As UInteger,
    26. <[In]> nSubAuthority7 As UInteger,
    27. <Out> ByRef pSid As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    28. End Function
    29. <DllImport("advapi32.dll", EntryPoint:="CheckTokenMembership")>
    30. Private Shared Function CheckTokenMembership(<[In]> hToken As IntPtr,
    31. <[In]> pSidToCheck As IntPtr,
    32. <Out, MarshalAs(UnmanagedType.Bool)> ByRef pbIsMember As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean
    33. End Function
    34. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    35. Me.Text = "IsUserAdmin: " & IsUserAdmin.ToString
    36. End Sub
    37. Private Function IsUserAdmin() As Boolean
    38. Dim Ret As Boolean
    39. Dim pSidAdmins As IntPtr
    40. If AllocateAndInitializeSid(New SID_IDENTIFIER_AUTHORITY(SECURITY_NT_AUTHORITY),
    41. 2, SECURITY_BUILTIN_DOMAIN_RID,
    42. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
    43. pSidAdmins) Then
    44. Dim IsMember As Boolean
    45. If CheckTokenMembership(IntPtr.Zero, pSidAdmins, IsMember) Then Ret = IsMember
    46. FreeSid(pSidAdmins)
    47. End If
    48. Return Ret
    49. End Function
    50. End Class

    Mfg -Franky-
    Wow, super - Danke Dir @-Franky-
    Mein Problem ist, dass die Funktion zur Erkennung der aktuellen Benutzer-Rechte auch in der Debug-Konfiguration vom VB funktionieren muss.
    Nicht nur in der Release-Konfiguration.
    Werde Deine Korrektur gerne testen, ob diese da auch funzt. :)

    Edit: Leider erkennt Deine Funktion die Benutzerrechte auch nur in der Release-Konfiguration - nicht aber in der Debug-Konfiguration.
    Sicher ist Deine Lösung prima für die Einbindung in der Exe.

    Habe meinen Code daher nun so geändert:

    VB.NET-Quellcode

    1. ' AktUser Benutzerrechte
    2. Private Const DOMAIN_ALIAS_RID_ADMINS As UInteger = &H220
    3. Private Const SECURITY_BUILTIN_DOMAIN_RID As UInteger = &H20
    4. Private Const SECURITY_NT_AUTHORITY As Byte = 5
    5. <StructLayout(LayoutKind.Sequential)>
    6. Private Structure SID_IDENTIFIER_AUTHORITY
    7. <MarshalAs(UnmanagedType.ByValArray, SizeConst:=6, ArraySubType:=UnmanagedType.I1)> Dim Value() As Byte
    8. Public Sub New(AuthorityIdentifier As Byte)
    9. Value = New Byte(5) {0, 0, 0, 0, 0, AuthorityIdentifier}
    10. End Sub
    11. End Structure
    12. <DllImport("advapi32.dll", EntryPoint:="FreeSid")>
    13. Private Shared Function FreeSid(<[In]> pSid As IntPtr) As IntPtr
    14. End Function
    15. <DllImport("advapi32.dll", EntryPoint:="AllocateAndInitializeSid")>
    16. Private Shared Function AllocateAndInitializeSid(<[In], MarshalAs(UnmanagedType.Struct)> ByRef pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY,
    17. <[In]> nSubAuthorityCount As Byte,
    18. <[In]> nSubAuthority0 As UInteger,
    19. <[In]> nSubAuthority1 As UInteger,
    20. <[In]> nSubAuthority2 As UInteger,
    21. <[In]> nSubAuthority3 As UInteger,
    22. <[In]> nSubAuthority4 As UInteger,
    23. <[In]> nSubAuthority5 As UInteger,
    24. <[In]> nSubAuthority6 As UInteger,
    25. <[In]> nSubAuthority7 As UInteger,
    26. <Out> ByRef pSid As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    27. End Function
    28. <DllImport("advapi32.dll", EntryPoint:="CheckTokenMembership")>
    29. Private Shared Function CheckTokenMembership(<[In]> hToken As IntPtr,
    30. <[In]> pSidToCheck As IntPtr,
    31. <Out, MarshalAs(UnmanagedType.Bool)> ByRef pbIsMember As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean
    32. End Function
    33. Public aktUserIsAdmin As Boolean = false
    34. #If DEBUG Then
    35. aktUserIsAdmin = CheckAdministrator_Debug()
    36. #Else
    37. aktUserIsAdmin = CheckAdministrator_Release()
    38. #End If
    39. Private Function CheckAdministrator_Debug() As Boolean
    40. Using p As New Process()
    41. p.StartInfo = New ProcessStartInfo With {
    42. .FileName = "cmd",
    43. .RedirectStandardInput = True,
    44. .RedirectStandardOutput = True,
    45. .CreateNoWindow = True,
    46. .UseShellExecute = False}
    47. p.Start()
    48. p.StandardInput.WriteLine("net user " & Chr(34) & Environment.UserName & Chr(34))
    49. p.StandardInput.WriteLine("exit")
    50. Do
    51. Dim line = p.StandardOutput.ReadLine
    52. If line Is Nothing Then Return False
    53. If line.ToLower.Contains("administrator") Then Return True
    54. Loop
    55. End Using
    56. Return False
    57. End Function
    58. Private Function CheckAdministrator_Release() As Boolean
    59. Dim Ret As Boolean
    60. Dim pSidAdmins As IntPtr
    61. If AllocateAndInitializeSid(New SID_IDENTIFIER_AUTHORITY(SECURITY_NT_AUTHORITY),
    62. 2, SECURITY_BUILTIN_DOMAIN_RID,
    63. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
    64. pSidAdmins) Then
    65. Dim IsMember As Boolean
    66. If CheckTokenMembership(IntPtr.Zero, pSidAdmins, IsMember) Then Ret = IsMember
    67. FreeSid(pSidAdmins)
    68. End If
    69. Return Ret
    70. End Function


    So prüft in der Debug-Konfiguration die CMD-Funktion die Benutzerrechte und in der Release-Konfiguration dann aber Deine Funktion.
    Bilder
    • VS2022_Benutzerrechte.jpg

      119,93 kB, 1.006×611, 34 mal angesehen

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „Dideldum“ ()

    @Dideldum Ich hab mal VS2022 mit einem Benutzer, der Adminrechte besitzt, gestartet und meinen Code getestet. Sowohl im Debug als auch im Release gibt der Code beim testen in der IDE True zurück.
    Test:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. #If DEBUG Then
    3. Me.Text = "Debug: IsUserAdmin: " & IsUserAdmin.ToString
    4. #Else
    5. Me.Text = "Release: IsUserAdmin: " & IsUserAdmin.ToString
    6. #End If
    7. End Sub
    Bilder
    • Debug.png

      7,7 kB, 435×191, 19 mal angesehen
    • Release.png

      7,25 kB, 432×192, 20 mal angesehen
    Mfg -Franky-

    -Franky- schrieb:

    @Dideldum Ich hab mal VS2022 mit einem Benutzer, der Adminrechte besitzt, gestartet und meinen Code getestet. Sowohl im Debug als auch im Release gibt der Code beim testen in der IDE True zurück.


    Hi @-Franky-
    Das ist seltsam.
    Ich habe eben von meinem Kunden in der Schweiz Rückmeldung bekommen, dass in seiner Release-Version mit Deiner Funktion wieder das Problem "User" auftritt.

    Es wurde bei ihm korrekt "Administrator" angezeigt, bis er in den Einstellungen meines Proggis den Start mit erweiterten Rechten deaktivierte.
    Beim nächsten Start meines Programms mit normalen User-Rechten war er wieder zum "User" degradiert und hat damit in meinem Proggi keine Rechte mehr, die Einstellung "Start with extended rights (administrator rights)" zu aktivieren.

    Ich glaube, ich muss doch wieder auf das CMD-Script wechseln.
    Dieses funzt in allen Lagen.

    EDIT: Nachtrag
    Ja, das CMD-Script tut, was es soll - siehe Bild 2
    Auch auf dem eidgenössischen Rechenknecht. ^^
    Bilder
    • BenutzerAngemeldetAlsUser.jpg

      116,08 kB, 1.006×611, 21 mal angesehen
    • BenutzerAngemeldetAlsAdministrator.jpg

      118,79 kB, 1.006×611, 17 mal angesehen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Dideldum“ ()

    Ich versteh nicht warum du so ein gefummel machst. Ich handhabe das anders. Exceptions kann man abfangen, man weis wo welche Exceptions vorkommen können. Gibt es eine UnauthorizedAccessException brauch man mehr Rechte, ich zeige dann eine messageBox an(yes no) und frage ob als Admin neu gestartet werden soll. Bei klick auf ja, drauf achten das evtl. änderungen gespeichert werden, neue Instanz als Admin via Code starten und die erste Instanz beenden. Kann der User via UAC bestätigen, das er als Admin ausführen darf startet das Programm, sonst nicht. Da braucht man nicht so eine fummelei machen.

    PS
    @Dideldum
    Ich hab @-Franky- s Code probiert, funktioniert. Aber, starte ich das Programm nicht als Admin, bekomme ich false als Antwort. Obwohl ich als Admin starten könnte. Starte ich VS/das Programm als Admin, bekomme ich True. Sowohl beim Debug- wie auch beim Release-Build.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    Dideldum schrieb:

    Es wurde bei ihm korrekt "Administrator" angezeigt, bis er in den Einstellungen meines Proggis den Start mit erweiterten Rechten deaktivierte.


    Das ist ja auch korrekt. Ist das Programm als Admin also mit angeforderten Adminrechten gestartet worden, kommt true, sonst false. Ich glaub ich weis jetzt wo der Hund begraben liegt, in der Kommunikation hier.
    Adminrechte haben ist ungleich zur Gruppe der Admins zu gehören. Nur weil es ein Adminaccount ist, bedeutet das nicht, das dieser die ganze Zeit diese Rechte inne hat(wäre zu gefährlich), die werden ja immer via UAC angefordert.

    Wenn du prüfen willst, ob der User zur Gruppe der Administratoren gehört, dann so:

    C#-Quellcode

    1. using System.Diagnostics;
    2. using System.DirectoryServices.AccountManagement;
    3. //...
    4. UserPrincipal userPrincipal = new UserPrincipal(new PrincipalContext(ContextType.Machine));
    5. userPrincipal.SamAccountName = "Ich";
    6. PrincipalSearcher searcher = new PrincipalSearcher(userPrincipal);
    7. userPrincipal = (UserPrincipal)searcher.FindOne();
    8. if(userPrincipal != null)
    9. {
    10. PrincipalSearchResult<Principal> principalSearchResult = userPrincipal.GetGroups();
    11. foreach (Principal principal in principalSearchResult)
    12. {
    13. Debug.WriteLine(principal.Name);
    14. }
    15. }
    16. else
    17. {
    18. Debug.WriteLine("User not found");
    19. }
    20. //...

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DTF“ ()

    Hi @DTF
    danke Dir für Deine Hilfe! :)
    Vielleicht habe ich mich wie so oft unklar ausgedrückt. ;(
    Ja, genau das macht ja das CMD-Script - es liest die Gruppenzugehörigkeit des angemeldeten Benutzers aus.
    Mein Proggi ist so gestaltet, dass normale User bestimmte Settings in den Einstellungen nicht verbiegen können.
    Das können nur User, die in der Administrator-Gruppe sind.

    Du hast sicher recht, höhere Rechte nur bei Bedarf vom Benutzer einzufordern.
    Die erhöhten Rechte brauchen in meinem Proggi eigentlich nur die User, die auf alle Programme zugreifen müssen. Die UAC-Blockade verhindert das Auslesen mancher Fenstertitel und deren Owner und damit deren Nutzung in meinem Programm.
    Der zweite Grund für den Start mit erweiterten Rechten ist, wenn die User Screenshots mit einer Funktion in meiner App oder mit der "Drucken"-Taste in mein Programm importieren wollen.
    Eben bei dieser "Drucken"-Tasten-Funktion habe ich keine Exception feststellen können, auf welche ich mit einer Aufforderung zum Start mit erhöhten Rechten reagieren könnte. Da reagiert einfach (die Zwischenablage) KORREKTUR der Clipboardwatcher in meinem Programm nicht auf das Dücken der "Drucken"-Taste.

    Ich werde gerne Deine Funktion testen, ob die so funktioniert, wie die CMD-Funktion.
    Hupe dann Bescheid, wie der Test lief. ;)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Dideldum“ ()