Admin Rechte in Laufzeit Anfordern

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

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Facebamm.

    Admin Rechte in Laufzeit Anfordern

    Moin, ich Arbeite aktuell an einem Programm welches in einer Funktion Dateien in einem Ordner löschen tut diese Befindet sich in den Dokumenten/FS21/FEdit

    das Problem ist manchmal das die Berechtigungen nicht ausreichen bestimmte Dateien zu Löschen.

    Daher meine Frage gibt es eine Möglichkeit wenn zum Beispiel die Berechtigung nicht ausreicht Erweiterte Rechte anzufordern (Also zum Beispiel der User Bestätigt und das Programm wird mit Erweiterten Rechten neu gestartet)

    Das Einzige was ich gefunden habe ist "<requestedExecutionLevel/>" dies ist ja aber Immer beim Start (Soweit ich weiß) und nicht nur wenn es Benötigt wird.

    Danke im Voraus.

    Wichtiger wäre es, herauszufinden warum dein Programm auf die Dateien keinen Zugriff hat.

    Wenn sie im UserProfile\Documents liegen, hat das Programm schon die richtigen Berechtigungen.
    Durch was werden die Dateien denn erstellt?

    Einem Programm pauschal Admin-Rechte zu geben halte ich für gefährlich. Wenn dann noch die UAC an ist und der Benutzer möglicherweise kein Admin-Rechte auf dem PC hat, funktioniert es nicht.

    Wenn der User jedes Mal beim Verwenden eine UAC Meldung mit Passwort Eingabe für ein Admin-Konto bekommt, wird er sich bedanken :)
    Also zuerstmal das Programm entpackt Zip dateien in den Ordner und Bearbeitet die XML.
    Soweit kann es die Dateien Löschen alle nur manchmal bei bestimmten Dateien gibt es Probleme.

    Diese wären zum Beispiel:
    • ClaasConspeed.i3d.shapes
    • leguan30.i3d.shapes
    • Lexion650.i3d.shapes
    • Lexion670.i3d.shapes
    • Vario750.i3d.shapes
    • Vario900.i3d.shapes

    Also die Zip Dateien sind immer Unterschiedlich, es gibt aber eben auch Dateien die diese das Problem mit dem nicht Löschen auslöst.
    Aktuell ist es nur bei den ".shapes" Dateien das er sagt "Zugriff Verweigert"


    ​Wenn der User jedes Mal beim Verwenden eine UAC Meldung mit Passwort Eingabe für ein Admin-Konto bekommt, wird er sich bedanken

    Die Erweiterten Rechte werden ja nur Benötigt wenn das Programm die Dateien nicht gelöscht bekommt (Was nicht Häufig vorkommen sollte)

    Eine Andere Idee ist mir Bislang nicht eingefallen :(

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „xX-Nick-Xx“ ()

    xChRoNiKx schrieb:

    Hast du eine genaue Meldung?


    Fehlermeldung:
    Message: Der Zugriff auf den Pfad "C:\Users\nico9\Documents\FarmingStudio21\ModEdit\Vario900.i3d.shapes" wurde verweigert. -- Source: mscorlib -- StackTrace: bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    bei System.IO.File.InternalDelete(String path, Boolean checkHost)
    bei System.IO.File.Delete(String path)
    bei Microsoft.VisualBasic.FileIO.FileSystem.DeleteFileInternal(String file, UIOptionInternal showUI, RecycleOption recycle, UICancelOption onUserCancel)
    bei FarmingStudio21.Form1.LoadMod() in C:\Users\nico9\Desktop\Nick\OFSync\FarmingStudio21\FarmingStudio21\Form1.vb:Zeile 135.


    Noch Genauer:
    ​System.UnauthorizedAccessException
    HResult=0x80070005
    Nachricht = Der Zugriff auf den Pfad "C:\Users\nico9\Documents\FarmingStudio21\ModEdit\ClaasConspeed.i3d.shapes" wurde verweigert.
    Quelle = mscorlib
    Stapelüberwachung:
    bei System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    bei System.IO.File.InternalDelete(String path, Boolean checkHost)
    bei System.IO.File.Delete(String path)
    bei Microsoft.VisualBasic.FileIO.FileSystem.DeleteFileInternal(String file, UIOptionInternal showUI, RecycleOption recycle, UICancelOption onUserCancel)
    bei FarmingStudio21.Form1.LoadMod()
    bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    bei System.Threading.ThreadHelper.ThreadStart()

    @xX-Nick-Xx Ich hatte mal Effekte unter Win10, wenn die Dateien von einem anderen Rechner kamen.
    ====
    Ich halte es durchaus für angebracht, zum expliziten Löschen von "externen" Dateien in den Admin-Mode zu wechseln, um dem User die besondere Lage zu verdeutlichen.
    Wenn allerdings diese Dateien zum normalen Gebrauch Deines Programmes dienen, sollte es so gehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    xX-Nick-Xx schrieb:

    wie man Admin anfordern kann in der Laufzeit?
    Du musst das eigene Programm mit Admin-Rechten neu starten.
    Das Snippet ist C#, das kannst Du aber problemlos nach VB übertragen:
    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.ComponentModel;
    3. using System.Diagnostics;
    4. using System.Security.Principal;
    5. using System.Windows.Forms;
    6. private void DoAdmin()
    7. {
    8. if (!MainForm.IsAdministrator())
    9. {
    10. // Get the full qualified path to the own executable
    11. string path = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase;
    12. // Start itself with adminrights
    13. if (MainForm.RunElevated(path))
    14. {
    15. // Close old program window
    16. this.Close();
    17. }
    18. }
    19. }
    20. //============================================
    21. /// <summary>
    22. /// Abfrage, ob this Programm mit Administratorrechten läuft
    23. /// </summary>
    24. /// <returns>Administrator</returns>
    25. private static bool IsAdministrator()
    26. {
    27. WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
    28. return principal.IsInRole(WindowsBuiltInRole.Administrator);
    29. }
    30. /// <summary>
    31. /// Run a program with elevated rights
    32. /// </summary>
    33. /// <param name="fileName">Path to the executable to run</param>
    34. /// <returns>True if no error has occurred</returns>
    35. private static bool RunElevated(string fileName)
    36. {
    37. ProcessStartInfo processInfo = new ProcessStartInfo();
    38. processInfo.Verb = "runas";
    39. processInfo.FileName = fileName;
    40. try
    41. {
    42. Process.Start(processInfo);
    43. return true;
    44. }
    45. catch (Win32Exception)
    46. {
    47. //Do nothing. Probably the user canceled the UAC window
    48. }
    49. return false;
    50. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    VisualStudio Code hat hier ne nette Lösung gefunden:
    Ist eine Datei durch fehlende Berechtigungen gesperrt, und der User möchte eine Änderung Speichern, wird ein Prozess mit der Eingabeaufforderung (ich gehe mal davon aus, dass die dann nen einfachen rm Befehl durchführen lassen) mit erweiterten Rechten gestartet, was dazu führt, dass die UAC natürlich das OK vom User möchte. Für einzelne Dateien denke ich ist sowas ganz praktisch. Sollte das jedoch öfters vorkommen, ist @RodFromGermanys vorgehensweise besser.

    BlueLagoonX schrieb:

    Wichtiger wäre es, herauszufinden warum dein Programm auf die Dateien keinen Zugriff hat. ...

    Dafür kann ich was kredenzen:

    VB.NET-Quellcode

    1. Private Const ERROR_SHARING_VIOLATION As Integer = 32
    2. Private Const ERROR_LOCK_VIOLATION As Integer = 33
    3. Public Shared Function FileIsFree(ByVal _fileName As String) As Boolean
    4. Try
    5. Using fileStream As FileStream = File.Open(_fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
    6. If fileStream IsNot Nothing Then
    7. End If
    8. End Using
    9. Catch ex As IOException
    10. If FileIsLocked(ex) Then Return False
    11. End Try
    12. Return True
    13. End Function
    14. Public Shared Function FileIsLocked(ByVal _ioException As IOException) As Boolean
    15. Dim errorCode As Integer = Marshal.GetHRForException(_ioException) And ((1 << 16) - 1)
    16. Return errorCode = ERROR_SHARING_VIOLATION OrElse errorCode = ERROR_LOCK_VIOLATION
    17. End Function

    Achtung: Da die Methode FileIsFree die komplette Datei in einen Stream einliest, ist sie unter umständen etwas unperformant.
    Daher ist es ratsam den Stream nicht mehrmals einzulesen und die Methode FileIsLocked da anzuwenden, wo die IOException geworfen wird.

    Hier noch VB code, der weitgehend dem von RodFromGermany entspricht.

    VB.NET-Quellcode

    1. Public Shared ReadOnly Property CurrentWindowsIdentityRole As WindowsBuiltInRole
    2. Get
    3. Dim currentWindowsIdentity As WindowsPrincipal = New WindowsPrincipal(WindowsIdentity.GetCurrent)
    4. With currentWindowsIdentity
    5. Select Case True
    6. Case .IsInRole(WindowsBuiltInRole.Administrator)
    7. Return WindowsBuiltInRole.Administrator
    8. Case .IsInRole(WindowsBuiltInRole.SystemOperator)
    9. Return WindowsBuiltInRole.SystemOperator
    10. Case .IsInRole(WindowsBuiltInRole.AccountOperator)
    11. Return WindowsBuiltInRole.AccountOperator
    12. Case .IsInRole(WindowsBuiltInRole.BackupOperator)
    13. Return WindowsBuiltInRole.BackupOperator
    14. Case .IsInRole(WindowsBuiltInRole.Replicator)
    15. Return WindowsBuiltInRole.Replicator
    16. Case .IsInRole(WindowsBuiltInRole.PrintOperator)
    17. Return WindowsBuiltInRole.PrintOperator
    18. Case .IsInRole(WindowsBuiltInRole.PowerUser)
    19. Return WindowsBuiltInRole.PowerUser
    20. Case .IsInRole(WindowsBuiltInRole.User)
    21. Return WindowsBuiltInRole.User
    22. Case .IsInRole(WindowsBuiltInRole.Guest)
    23. Return WindowsBuiltInRole.Guest
    24. Case Else
    25. Return Nothing
    26. End Select
    27. End With
    28. End Get
    29. End Property
    30. Public Shared ReadOnly Property CurrentUserCanHaveAdminRigths As Boolean
    31. Get
    32. Return Not CurrentWindowsIdentityRole = WindowsBuiltInRole.Guest OrElse
    33. CurrentWindowsIdentityRole = WindowsBuiltInRole.PrintOperator
    34. End Get
    35. End Property
    36. Public Shared ReadOnly Property CurrentUserHaveAdminRigths As Boolean
    37. Get
    38. Return CurrentWindowsIdentityRole = WindowsBuiltInRole.Administrator
    39. End Get
    40. End Property


    VB.NET-Quellcode

    1. Public Shared Sub RestartApplicationWithAdminRights(ByVal Optional _arguments As String = "")
    2. Dim startInfo As New ProcessStartInfo
    3. With startInfo
    4. .Arguments = _arguments
    5. .FileName = Application.ExecutablePath
    6. .UseShellExecute = True
    7. .Verb = "runas"
    8. End With
    9. Using process As New Process
    10. With process
    11. .StartInfo = startInfo
    12. .Start()
    13. End With
    14. End Using
    15. Application.Exit()
    16. End Sub

    Über den _arguments Parameter, kann man z.b. noch Location, oder Size, et cetera übergeben.
    Also die Methode mit den Erweiterten Rechten von @RodFromGermany und @FormFollowsFunction funktioniert nicht.

    Es Startet bei "Keine Berechtigung" Neu, aber sobald ich dann mit Erweiterten Rechte es Versuche startet das Programm Direkt wieder neu :D

    Code:

    VB.NET-Quellcode

    1. For Each items As String In IO.Directory.GetFiles(Opath)
    2. CountFiles = My.Computer.FileSystem.GetFiles(Opath, FileIO.SearchOption.SearchAllSubDirectories, "*.*").Count
    3. If CountFiles = 0 Then
    4. Else
    5. Try
    6. If CountFiles > 0 Then
    7. BeginInvoke(Sub() Label69.Text = "Bereinige Mod-Edit...")
    8. My.Computer.FileSystem.DeleteFile(items)
    9. System.IO.Directory.Delete(Opath, True)
    10. ElseIf CountFiles = 0 Then
    11. Exit For
    12. End If
    13. Catch ex As Exception
    14. BeginInvoke(Sub() Label69.Text = "Mod-Edit konnte nicht Vollständig Bereinigt werden.")
    15. RestartApplicationWithAdminRights()
    16. Exit For
    17. Exit Sub
    18. End If
    19. Next

    Die Anwendung muss neu gestartet werden, wenn sie Adminrechte braucht !
    Du kannst über die Arguments, die neu gestartete Instanz anweisen, da weiter zu machen wo die vorherige aufgehört hat,
    also deine Bereinigunsroutine nochmal auszuführen.

    xX-Nick-Xx schrieb:

    VB.NET-Quellcode

    1. RestartApplicationWithAdminRights()
    Poste diese Methode.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hier ist die Methode (außer das mit FileInUse)

    FormFollowsFunction schrieb:

    Dafür kann ich was kredenzen:
    VB.NET-Quellcode
    Private Const ERROR_SHARING_VIOLATION As Integer = 32
    Private Const ERROR_LOCK_VIOLATION As Integer = 33
    Public Shared Function FileIsFree(ByVal _fileName As String) As Boolean
    Try
    Using fileStream As FileStream = File.Open(_fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
    If fileStream IsNot Nothing Then
    End If
    End Using
    Catch ex As IOException
    If FileIsLocked(ex) Then Return False
    End Try
    Return True
    End Function
    Public Shared Function FileIsLocked(ByVal _ioException As IOException) As Boolean
    Dim errorCode As Integer = Marshal.GetHRForException(_ioException) And ((1 << 16) - 1)
    Return errorCode = ERROR_SHARING_VIOLATION OrElse errorCode = ERROR_LOCK_VIOLATION
    End Function

    Achtung: Da die Methode FileIsFree die komplette Datei in einen Stream einliest, ist sie unter umständen etwas unperformant.
    Daher ist es ratsam den Stream nicht mehrmals einzulesen und die Methode FileIsLocked da anzuwenden, wo die IOException geworfen wird.

    Hier noch VB code, der weitgehend dem von RodFromGermany entspricht.
    VB.NET-Quellcode
    Public Shared ReadOnly Property CurrentWindowsIdentityRole As WindowsBuiltInRole
    Get
    Dim currentWindowsIdentity As WindowsPrincipal = New WindowsPrincipal(WindowsIdentity.GetCurrent)
    With currentWindowsIdentity
    Select Case True
    Case .IsInRole(WindowsBuiltInRole.Administrator)
    Return WindowsBuiltInRole.Administrator
    Case .IsInRole(WindowsBuiltInRole.SystemOperator)
    Return WindowsBuiltInRole.SystemOperator
    Case .IsInRole(WindowsBuiltInRole.AccountOperator)
    Return WindowsBuiltInRole.AccountOperator
    Case .IsInRole(WindowsBuiltInRole.BackupOperator)
    Return WindowsBuiltInRole.BackupOperator
    Case .IsInRole(WindowsBuiltInRole.Replicator)
    Return WindowsBuiltInRole.Replicator
    Case .IsInRole(WindowsBuiltInRole.PrintOperator)
    Return WindowsBuiltInRole.PrintOperator
    Case .IsInRole(WindowsBuiltInRole.PowerUser)
    Return WindowsBuiltInRole.PowerUser
    Case .IsInRole(WindowsBuiltInRole.User)
    Return WindowsBuiltInRole.User
    Case .IsInRole(WindowsBuiltInRole.Guest)
    Return WindowsBuiltInRole.Guest
    Case Else
    Return Nothing
    End Select
    End With
    End Get
    End Property
    Public Shared ReadOnly Property CurrentUserCanHaveAdminRigths As Boolean
    Get
    Return Not CurrentWindowsIdentityRole = WindowsBuiltInRole.Guest OrElse
    CurrentWindowsIdentityRole = WindowsBuiltInRole.PrintOperator
    End Get
    End Property
    Public Shared ReadOnly Property CurrentUserHaveAdminRigths As Boolean
    Get
    Return CurrentWindowsIdentityRole = WindowsBuiltInRole.Administrator
    End Get
    End Property


    VB.NET-Quellcode
    Public Shared Sub RestartApplicationWithAdminRights(ByVal Optional _arguments As String = "")
    Dim startInfo As New ProcessStartInfo
    With startInfo
    .Arguments = _arguments
    .FileName = Application.ExecutablePath
    .UseShellExecute = True
    .Verb = "runas"
    End With
    Using process As New Process
    With process
    .StartInfo = startInfo
    .Start()
    End With
    End Using
    Application.Exit()
    End Sub

    Über den _arguments Parameter, kann man z.b. noch Location, oder Size, et cetera übergeben.

    Du solltest die Methode posten, nicht meinen ganzen post (und auch noch vollkommen entstell) ! :cursing:
    Auserdem solltest du mal anfangen, aufmersam zu lesen und Code auch zu verstehen !

    @RodFromGermany

    VB.NET-Quellcode

    1. Public Shared Sub RestartApplicationWithAdminRights(ByVal Optional _arguments As String = "")
    2. Dim startInfo As New ProcessStartInfo
    3. With startInfo
    4. .Arguments = _arguments
    5. .FileName = Application.ExecutablePath
    6. .UseShellExecute = True
    7. .Verb = "runas"
    8. End With
    9. Using process As New Process
    10. With process
    11. .StartInfo = startInfo
    12. .Start()
    13. End With
    14. End Using
    15. Application.Exit()
    16. End Sub


    Ich bin jetzt raus hier, das ist mir echt zu blöde !

    xX-Nick-Xx schrieb:

    Hier ist die Methode
    543 Posts im Forum und kannst nicht mal ein Zitat formatieren und spoilern :?:
    ======
    Dieser Code funktioniert bei mior auf Anhieb:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. RestartApplicationWithAdminRights()
    4. End Sub
    5. Public Shared Sub RestartApplicationWithAdminRights(Optional ByVal _arguments As String = "")
    6. Dim startInfo As New ProcessStartInfo
    7. With startInfo
    8. .Arguments = _arguments
    9. .FileName = Application.ExecutablePath
    10. .UseShellExecute = True
    11. .Verb = "runas"
    12. End With
    13. Using process As New Process
    14. With process
    15. .StartInfo = startInfo
    16. .Start()
    17. End With
    18. End Using
    19. Application.Exit()
    20. End Sub
    21. End Class

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Was du machen könntest wäre, du startest dein prozess mit admin rechten und gehst dann runter auf benutzer rechte.
    wenn jetzt in einen fall kommst beidem zu admin rechte brauchst, dann kannst du es via benutzer eingabe freischalten.
    dropping-privileges-in-c-on-windows