WMI Objekte Abfragen

  • Hallo ich habe ein riesenproblem mit WMI Abfragen.

    Ich möchte die eigenschaften von Files und Directorys abfragen, das ergebniss soll in etwa so sein als wenn ich unter Windows ein File selektiere und unter Eigenschaft den
    Reiter Sicherheit anklicke. Unter Gruppen und Benutzernamen bekomme ich alle User und Gruppen die einer Datei oder einem Directory zugewiesen sind incl. die Rechte.
    So etwas brauche ich. Den Eigentümer bekomme ich auch mittels WMI-Abfrage raus, allerdings nicht die anderen Parameter und auch nicht alle Benutzer.
    Irgendwie mache ich was falsch nur weiss ich nicht was.

    Die Function ReadFileOwner_Single geht wie vorgesehen
    Die Function ReadFileOwner_Alles gibt mir nur einen leeren String zurück aber es kommt keine Fehlermeldung

    Währe schön wenn einer ein Tipp hätte Irgenwie habe ich den durchblick verloren

    ;Autoitscript

    $wbemFlagReturnImmediately = 0x10
    Local $File_Pfad = @WindowsDir & "\hh.exe" ; Nur zum Test, nur Lesezugriff

    ; impersonationLevel = impersonate ist bevorzugte Standardvorgabe MS
    Local $Obj_WMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & @ComputerName & "\root\cimv2")

    ReadFileOwner_Single ($File_Pfad) ; TEST ein Wert auslesen
    ReadFileOwner_Alles ($File_Pfad) ; TEST alles auslesen was das Objekt hergibt

    Func ReadFileOwner_Single ($Obj_CheckFile)
    Dim $Obj_Owner
    $Obj_Owner_of_File = $Obj_WMIService.Get("Win32_LogicalFileSecuritySetting='" & $Obj_CheckFile & "'")
    $intRetVal = $Obj_Owner_of_File.GetSecurityDescriptor($Obj_Owner)

    If (IsObj($Obj_WMIService)) And (Not @error) Then ; Ist das Objekt $Obj_WMIService ein bekannetes Objekt
    MsgBox (0, "ReadFileOwner", "Owner: " & $Obj_Owner.Owner.Domain & "\" & $Obj_Owner.Owner.Name)
    Else
    Msgbox(0,"WMI Output","Keine WMI Objects gefunden: " & "Win32_LogicalFileSecuritySetting" )
    Endif

    EndFunc


    Func ReadFileOwner_Alles ($Obj_CheckFile)
    Local $a_Text = ""
    Local $Obj_Properties = ""
    Dim $Obj_SecureRead

    $Obj_Owner_of_File = $Obj_WMIService.Get("Win32_LogicalFileSecuritySetting='" & $Obj_CheckFile & "'")
    $intRetVal = $Obj_Owner_of_File.GetSecurityDescriptor($Obj_SecureRead)

    If (IsObj($Obj_WMIService)) And (Not @error) Then ; Ist das Objekt $Obj_WMIService ein bekannetes Objekt

    ConsoleWrite ("Func ReadFileOwner_Alles nach IsObj Abfrage ")

    For $Obj_Properties In $Obj_SecureRead
    $a_Text = 'Description: ' & $Obj_Properties.Description & @CRLF
    $a_Text = $a_Text & 'Caption: ' & $Obj_Properties.Caption & @CRLF
    $a_Text = $a_Text & 'OwnerPermissions: ' & $Obj_Properties.OwnerPermissions & @CRLF
    $a_Text = $a_Text &'ControlFlags ' & $Obj_Properties.ControlFlags & @CRLF
    $a_Text = $a_Text & 'Path: ' & $Obj_Properties.Path & @CRLF
    $a_Text = $a_Text &'SettingID: ' & $Obj_Properties.SettingID & @CRLF
    Next

    MsgBox (0,"TEST Komplett", $a_Text)
    EndIf
    EndFunc

  • Um Com-Fehler abzufangen benötigst du noch eine spezielle Funktion, füge mal folgenden Code in dein Script ein:

    [autoit]

    Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")

    [/autoit][autoit][/autoit][autoit]

    ; ##############
    ; Hier dein Code
    ; ##############

    [/autoit][autoit][/autoit][autoit]

    ; User's COM error function. Will be called if COM error occurs
    Func _ErrFunc($oError)
    ; Do anything here.
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
    @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
    @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
    @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
    @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
    @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
    @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
    @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
    @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
    @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
    EndFunc ;==>_ErrFunc

    [/autoit]


    Dann siehst du, das deine For-Schleife einen Error wirft.

  • Schau Dir mal im engl. Forum in der Sektion "Example Scripts" das Tool "Scriptomatic" an. Das generiert für WMI Abfragen das AutoIt Skript dazu.
    Gibt zumindest gute Anregungen!

  • Hallo,

    vielen Dank schon mal für die Vorschläge,

    die Function um Com-Fehler auszuwerten kannte ich noch nicht, funktioniert tadellos.
    Aber ich bekomme jetzt eine Fehlermeldung die ich mir schon fasst gedacht habe, nämlich "Mitglied nicht gefunden".
    Das ist ja zumindestens ein aussage mit der man was anfangen kann.

    In der Func ReadFileOwner_Alles mache ich irgndetwas falsch, wahrscheinlich in dieser Zeile,

    "$intRetVal = $Obj_Owner_of_File.GetSecurityDescriptor($Obj_Owner)" meine vermutung.

    Ich habe schon das Web stundenlang durchsucht, vieles gefunden aber auch immer mehr irritiert, weil man viele
    Examples findet die auch ungefähr das gleiche Thema behandeln aber alle ganz unterschiedlich umgesetzt sind.
    Viele diese Examples kann ich leider auch nicht ausprobieren weil es oft um Netzwerke und Administration geht.
    Privat für mein kleines Home-Netzwerk nicht zugebrauchen.

    Das Tool Scriptomatic hatte ich auch schon gefunden und ausprobiert, leider stürzt es bei anwahl einiger Funktionen
    einfach ohne jegliche ankündigung ab.

    Eine noch einfache Frage
    Ich habe gesehen das mein Code nicht als solcher aussieht wie ihn eingestellt habe, es sollte so aussehen wie von
    Ahnungslos, weisser Hintergrund mit Zeilennumerierung wie geht das ?

  • Um Quelltext formatiert ins Forum zu stellen benötigst du den BBCode autoit, also einfach dein Quelltext in [autoit]dein Code[/autoit] stellen.

    Zum eigentlichen Thema:
    GetSecurityDescriptor erzeugt ein Objekt vom Typ SecurityDescriptor und kein Array, daher kannst du mit der For-Schleife nicht darauf zugreifen. Wie der Aufruf richtig aussehen muss, kann ich dir leider nicht sagen. Was für Daten möchtest du denn genau ermitteln?

    Edit:
    Beim quälen der MSDN noch etwas gefunden ;)
    Die gesuchten Informationen stehen nicht im SecurityDescriptor sondern direkt in Win32_LogicalFileSecuritySetting.


    [autoit]


    ;Autoitscript

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $wbemFlagReturnImmediately = 0x10
    Local $File_Pfad = @WindowsDir & "\hh.exe" ; Nur zum Test, nur Lesezugriff

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    ; impersonationLevel = impersonate ist bevorzugte Standardvorgabe MS
    Local $Obj_WMIService = ObjGet("winmgmts:{impersonationLevel = impersonate}!\\" & @ComputerName & "\root\cimv2")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    ReadFileOwner_Single($File_Pfad) ; TEST ein Wert auslesen
    ReadFileOwner_Alles($File_Pfad) ; TEST alles auslesen was das Objekt hergibt

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func ReadFileOwner_Single($Obj_CheckFile)
    Dim $Obj_Owner
    $Obj_Owner_of_File = $Obj_WMIService.Get("Win32_LogicalFileSecuritySetting='" & $Obj_CheckFile & "'")
    $intRetVal = $Obj_Owner_of_File.GetSecurityDescriptor($Obj_Owner)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    If (IsObj($Obj_WMIService)) And (Not @error) Then ; Ist das Objekt $Obj_WMIService ein bekannetes Objekt
    MsgBox(0, "ReadFileOwner", "Owner: " & $Obj_Owner.Owner.Domain & '\' & $Obj_Owner.Owner.Name)
    Else
    MsgBox(0, "WMI Output", "Keine WMI Objects gefunden: " & "Win32_LogicalFileSecuritySetting")
    EndIf

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    EndFunc ;==>ReadFileOwner_Single

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func ReadFileOwner_Alles($Obj_CheckFile)
    Local $a_Text = ""
    Local $Obj_Properties = ""
    Dim $Obj_SecureRead

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $Obj_Owner_of_File = $Obj_WMIService.Get("Win32_LogicalFileSecuritySetting='" & $Obj_CheckFile & "'")

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    If (IsObj($Obj_WMIService)) And (Not @error) Then ; Ist das Objekt $Obj_WMIService ein bekannetes Objekt
    ConsoleWrite("Func ReadFileOwner_Alles nach IsObj Abfrage" & @CRLF)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $a_Text &= 'Description: ' & $Obj_Owner_of_File.Description & @CRLF
    $a_Text &= 'Caption: ' & $Obj_Owner_of_File.Caption & @CRLF
    $a_Text &= 'OwnerPermissions: ' & $Obj_Owner_of_File.OwnerPermissions & @CRLF
    $a_Text &= 'ControlFlags ' & $Obj_Owner_of_File.ControlFlags & @CRLF
    $a_Text &= 'Path: ' & $Obj_Owner_of_File.Path & @CRLF
    $a_Text &= 'SettingID: ' & $Obj_Owner_of_File.SettingID & @CRLF

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    MsgBox(0, "TEST Komplett", $a_Text)
    EndIf
    EndFunc ;==>ReadFileOwner_Alles

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    ; User's COM error function. Will be called if COM error occurs
    Func _ErrFunc($oError)
    ; Do anything here.
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
    @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
    @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
    @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _
    @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
    @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
    @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _
    @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
    @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
    @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
    EndFunc ;==>_ErrFunc

    [/autoit]
  • Informationen dazu gibt es hier.
    Beispiel generiert von Scriptomatic um die Informationen von C:\temp\test.au3 auszulesen:

  • Hallo,

    und besten dank für die anregungen, hat mir schon gut geholfen.

    Was ich möchte ist eigentlich trivial, hab ich zumindestens gedacht.
    Ich habe mir ein Autoit Script geschrieben das bei jedem Rechnerstart automatisch die Benutzer bzw. User Files die im
    "User" VZ von Windows liegen sichert.Also simpel gesagt Kopiere von A nach B. Das geht auch, nur beim zurückspielen wollen einige Programme nicht
    richtig laufen wegen falschen Rechten, vor allem dann nicht wenn ich sie von mein PC auf mein Laptop kopiere.
    Das liegt eindeutig an den Rechten und den Besitz von den Dateien emperisch ausprobiert.

    Ich muss also beim kopieren der Files den Besitzer ausmachen, sowie alle eingetragenen User sowie die dazugehörigen Rechte.
    Es reicht wenn ich weiss ob volle Zugriffsrechte ,oder nur lesen, oder nur lesen und ausführen für jeden Nutzer eingestellt ist.

    Im Prinzip das gleiche, als wenn ich mit der Maus auf ein File zum selektieren klicke und dann mit der rechten Maustaste unter Eigenschaften
    anklicke, dann auf den Tab für Sicherheit gehe. Dort werden alle User die die Datei nutzen können mit den dazugehörigen Rechten angezeigt.
    Beim TAB Sicherheit gibt es noch ein Buttom Erweitert wo ich den Besitzer ausfindig machen kann.