diedrohne
Goto Top

Zugriffsrechte von Ordnern mit VB-Script auslesen

Script für VB oder CMD zum auslesen von Rechten

Hallo Gemeinde,

Der Beitrag Besitzer von Ordnern mit VB-Script auslesen&thread=false hat mir schon weitergeholfen. Allerdings möchte der User dort nur die Besitzer von Ordnern angezeigt bekommen.

Mein Problem ist, das ich einer von mehreren Ablageverwalter bin und für einen Teilbereich einer sehr großen Ablage Verantwortung trage. Jeder Verwalter hat seinen eigenen Bereich wo er User entsprechende Rechte auf die Ordner vergeben kann.

Ich möchte nun eine Dokumentation mit Excel2007(oder Access2007) und einem VBA Script oder einer Batchdatei(cmd) erstellen, mit der ich regelmäßig alle Ordner abfrage und mir dann in einer Liste die User mit ihren entsprechenden Rechten dargestellt werden.

Bisher mach ich das immer händisch, aber wenn ich mal ausfallen sollte, muss ja dokumentiert sein, wer was darf.

Ich benötige eine Übersicht in der Art:

Pfad Dateiname Erstellt User Rechte

Kann mir jemand da weiterhelfen? Denn ich habe jetzt mehrere dutzende Excel-, VB-, Script-Seiten durchsucht, aber nirgends etwas zufriedenstellendes gefunden.

Gruß
DieDrohne

Content-Key: 151233

Url: https://administrator.de/contentid/151233

Printed on: April 19, 2024 at 15:04 o'clock

Member: MonoTone
MonoTone Sep 17, 2010 at 13:19:45 (UTC)
Goto Top
HI.

Ein kleiner Ansatz:

Option Explicit 
Dim fso, csvFilePath,csvFile,fname
fname = "D:\Temp" 'Der Pfad zum Ordner wo die Rechte ausgelesen werden sollen  
csvFilePath = Left(WScript.ScriptFullName,InStrRev(WScript.ScriptFullName,"\")) & "myCsvlist.csv" 'csvFile wird In  
'selben Ordner wie das Script gelegt bzw erzeugt  

Set fso = CreateObject("Scripting.FileSystemObject")  
Set csvFile = fso.OpenTextFile(csvFilePath,8,True)
csvFile.WriteLine(VbCrLf & "Ausgelesene Daten vom " & Now & VbCrLf)  
Call main
MsgBox "fertig"  

Sub main()
Dim folder
Set folder = fso.GetFolder(fname)
recFolder(folder)

csvFile.Close

End Sub


Sub recFolder(fname)
Dim subfolder
csvFile.Write(readacl(fname))
For Each subfolder In fname.SubFolders
recFolder(subfolder)
Next

End Sub


Function readacl(Folder)

readacl = True
Dim wmi
Dim Result
Dim AFlags, FormatType,fss,sts,dce,sd

Result = Folder & ";"  
Set wmi = GetObject("winmgmts:{impersonationLevel=Impersonate,(TakeOwnership)}!\\.\root\cimv2")  
Set fss = wmi.Get("Win32_LogicalFileSecuritySetting='" & fname & "'")  
sts = fss.GetSecurityDescriptor(sd)

For Each dce In sd.dacl
		Result = Result &  dce.Trustee.Name & ";"  
		Result = Result &   dce.Trustee.SIDString & ";"  
		Select Case hex(dce.AccessMask)
		'Eine Dokumentation über die AccessMask findest du bei MSDN, ich habe die 3 geläufigsten aufgelistet:  
		Case "1F01FF"  
		FormatType= "Full"	  
		Case "1301BF"  
		FormatType = "Write"  
		Case "1200A9"  
		FormatType = "Read"			  
		Case Else
		FormatType = "Unspecified"  
		End Select
		
		Result = Result & FormatType & ";"  
		
		'Eine Dokumentation über die AceFlags findest du bei MSDN, ich habe dir ein paar Bsp gelistet:		  
		Select Case Hex(dce.AceFlags)
		Case "0"  
		AFlags = "NUR DIESER ORDNER ---- nicht geerbt"  
		Case "3"  
		AFlags = "diesen Ordner, Unterordner und Dateien  ---- nicht geerbt"  
		Case "13"  
		AFlags = "NUR DIESER ORDNER ---- geerbt"  
		Case "1B"  
		AFlags = "Nur Unterordner und Dateien --- geerbt"  
		End Select		
	    Result = Result & AFlags & ";" & VbCrLf & ";"  
	    
Next
Result  = Left(Result,Len(Result)-1)
readacl =  Result
End Function

Bei Fragen, einfach stellen bzw nachlesen

Gruss Mono
Member: DieDrohne
DieDrohne Sep 20, 2010 at 08:51:05 (UTC)
Goto Top
Hallo und Danke erstmal,

Ich habe den Code probiert und bekomme immer einer Fehlermeldung. Er markiert den Pfad und sagt "Fehler beim Kombilieren! Ausserhalb der Prozedure ungültig"

Ich bin total ratlos und meine Kollegen auch. Wir kommen einfach nicht drauf warum es zum Fehler kommt.

Hast du den Code in Excel 2007 probiert gehabt? Kann vielleicht bitte jemand den Code bei sich testen und mir Rückmeldung geben?

Dankeschön.
Member: MonoTone
MonoTone Sep 20, 2010 at 11:34:58 (UTC)
Goto Top
HI,

das ist ein VB Script.
Dazu muss du den Inhalt in eine Textdatei einfügen, diese mit der Endung .vbs abspeichern und danach ausführen.
Die PFade musst du natürlich anpassen. Am besten baust du dir ein paar Testordner mit verschiedenen Berechtigungen, legst im Script den Pfad auf die Testordner und startest es.
Danach erhältst du eine .csv Datei mit den entsprechenden Ausgaben.

Alternativ kannst du das auch in Excel direkt ausführen. Dazu musst es dir nur nach VBA anpassen und entsprechend aufrufen.
Member: DieDrohne
DieDrohne Sep 21, 2010 at 07:16:50 (UTC)
Goto Top
Hm das ist auch eine Möglichkeit, nur schein ich da zu blöd zu sein. Selbst die Hilfeseite von Microsoft hat mir nicht weitergeholfen.

Zu Hause geht das Script auf jeden Fall, nur ich bin hier auf Arbeit sehr eingeschränkt in meine Möglichkeiten. Sicherheitsgründe halt und dazu gehört leider das VBS nicht ausgeführt werden darf, VBA über Excel allerdings schon.

Findet sich ein findiger Programmierer der mir weiterhelfen kann und den Script anpasst? Das wäre superlieb!

Liebe Grüße
Member: DieDrohne
DieDrohne Sep 28, 2010 at 09:31:23 (UTC)
Goto Top
Schade um den schönen Code. Auf Arbeit darf kein VBScript ausgeführt werden und somit darf ich den Code da oben nicht nutzen. Nur VBA. Hatte mich nochmal rückversichert, ob es keine andere Möglichkeit gibt.

Schade.
Mitglied: 76109
76109 Sep 28, 2010 at 09:55:28 (UTC)
Goto Top
Hallo DieDrohne!

Dann versuch mal, ob Du hiermit weiterkommstface-wink

Der nachfolgende VBA-Code gestattet eine flexible Erstellung einer Csv-Datei mit den entsprechenden Folder-Zugriffsrechten.

Die ersten Zeilen mit ihren Konstanten sollten selbsterklärend sein.

Erklärung zu den Definitionen der Zugriffs-Konstanten:

Die Konstanten-Namen:
AF steht für AccessFlags, AT für Access-Type und AM für AccessMask und die Nummer dahinter ist die dazugehörige Bit-Nummer.

Die Konstanten mit einem x und einer Nummer z.B. AMx1 (Hex 1F01FF) definieren Bit-Masken und können beliebig definiert werden, wobei die Bezeichnungen nach den ersten beiden Buchstaben frei wählbar sind.

An dieser Stelle sei schonmal zu erwähnen, dass in der Definition nach dem "="-Zeichen im ersten Token z.B. "AM?;" eine Besonderheit zu beachten ist, die im Code eine wichtige Rolle spielt. Und zwar wird anhand des 3. Zeichens im Code unterschieden, ob ein Bit-Test (& alias And) oder ein Vergleich (= alias Compare) durchgeführt wird. Sprich ein Bit-Wert mit And und eine Bit-Maske oder der Wert 0 mit Compare testen. Hierbei ist ebenfalls zu beachten, dass der Vergleich (Compare) Vorang vor einem Bit-Test (And) hat, was bedeutet, wenn eine Bit-Maske True ist, dann wird kein Bit-Test durchgeführt.

Die Konstanten nach Wunsch registrieren:
Die Konstanten AFxx, ATxx, AMxx werden nun zwecks Flexibilität im Code in dem Array CsvListe eingetragen, in der sie ausgegeben werden sollen. D.h. das nur die Konstanten, die in der CsvListe eingetragen sind und in der Reihenfolge wie sie eingetragen sind, in die Csv-Datei geschrieben werden, wobei allerdings die ersten 4 Spalten schon mit "Pfad;Erstellt;Benutzer;SID-String" vordefiniert sind.

Anhand der CsvListe werden die Werte, die sich hinter dem "="-Zeichen befinden in einem Dictionary-Object registriert. D.h. es wird ein Schlüssel (Key/ID) mit einem dazugehörigen Wert (Item) erzeugt.

Der Eintrag für z.B. AM02 = "AM&;&H00000004;TitelText" würde dann so aussehen: Key = "AM&00000004 + Item = "00000004" und der wahlfreie TitelText wird in das Überschrift-Array Csv-Titel übernommen und als Überschriftzeile in die Csv-Datei geschrieben.

Hoffe das es bis hierher einigermaßen verständlich war, ansonsten nachfragenface-wink

Quellcode in ein Modul einfügen und einfach mal starten und die Csv-Datei anschauen und danach entsprechende Anpassungen vornehmen.
    Option Explicit
    Option Compare Text
    
    Const FoldersPath = "D:\Temp"                           'Start-Ordner  
    
    Const CsvFileName = "FolderUserRights.csv"              'Wird im Workbook-Pfad gespeichert  
   
    Const CsvDelim = ";"                                    'Beliebiges Trennzeichen festlegen  
  '______________________________________________________________________________________  
    
   'Spalte 1-4 = Path, Erstellungsdatum, Gruppe/Benutzername, G/B-Name-SID  
    Const CsvTextReserved = 4
   
   'Control-Flag Infos verfügbar  
    Const SE_DACL_PRESENT = &H4
    
   'Zugriffs-Flags, TitelText nach belieben festlegen  
    Const AF00 = "AF&;&H01;TitelText"             'OBJECT_INHERIT_ACE  
    Const AF01 = "AF&;&H02;TitelText"             'CONTAINER_INHERIT_ACE  
    Const AF02 = "AF&;&H04;TitelText"             'NO_PROPOGATE_INHERIT_ACE  
    Const AF03 = "AF&;&H08;TitelText"             'INHERIT_ONLY_ACE  
    Const AF04 = "AF&;&H10;TitelText"             'INHERIT_ACE"  
    
   'Zugriffs-Type  
    Const ATx0 = "AT=;&H00;TitelText"             'ACCESS_ALLOWED_ACE_TYPE  
    
    Const AT00 = "AT&;&H01;TitelText"             'ACCESS_DENIED_ACE_TYPE  
    Const AT01 = "AT&;&H02;TitelText"             'AUDIT  
      
   'Zugriffsrechte: Objektspezifisch  
    Const AM00 = "AM&;&H00000001;TitelText"       'DIR_LIST_DIRECTORY/FILE_READ_DATA  
    Const AM01 = "AM&;&H00000002;TitelText"       'DIR_ADD_FILE/FILE_WRITE_DATA  
    Const AM02 = "AM&;&H00000004;TitelText"       'DIR_ADD_SUBDIRECTORY/FILE_APPEND_DATA  
    Const AM03 = "AM&;&H00000008;TitelText"       'READ_NAMED_ATTRIBUTS  
    Const AM04 = "AM&;&H00000010;TitelText"       'WRITE_NAMED_ATTRIBUTS  
    Const AM05 = "AM&;&H00000020;TitelText"       'EXECUTE  
    Const AM06 = "AM&;&H00000040;TitelText"       'DELETE_CHILD  
    Const AM07 = "AM&;&H00000080;TitelText"       'READ_ATTRIBUTES  
    Const AM08 = "AM&;&H00000100;TitelText"       'WRITE_ATTRIBUTES  
    
    Const AMx1 = "AM=;&H001F01FF;TitelText"       'FILE_ALL_ACCESS"  
    
    'Zugriffsrechte: Standard --> Zugriffsrechte auf Objektspezifisch  
    Const AM16 = "AM&;&H00010000;TitelText"       'DELETE  
    Const AM17 = "AM&;&H00020000;TitelText"       'READ_ACL  
    Const AM18 = "AM&;&H00040000;TitelText"       'WRITE_ACL  
    Const AM19 = "AM&;&H00080000;TitelText"       'WRITE_OWNER  
    Const AM20 = "AM&;&H00100000;TitelText"       'SYNCHRONIZE  
    
    'Zugriffsrechte: Security-Descriptor SACL (System Access Control List)  
    Const AM24 = "AM&;&H01000000;TitelText"       'ACCESS_SYSTEM_SECURITY  
    
    'Zugriffsrechte Erweitert --> Zugriffsrechte auf Standard/Objektspezifisch  
    Const AM28 = "AM&;&H10000000;TitelText"       'GENERIC_ALL  
    Const AM29 = "AM&;&H20000000;TitelText"       'GENERIC_EXECUTE  
    Const AM30 = "AM&;&H40000000;TitelText"       'GENERIC_WRITE  
    Const AM31 = "AM&;&H80000000;TitelText"       'GENERIC_READ  
'______________________________________________________________________________________  
    
    Const Msg0 = "Der Vorgang kann je nach Anzahl der Ordner einige Minuten dauern!"  
    Const Msg1 = "Der Csv-Export ist abgeschlossen."  
    
    Dim Fso As Object, ACL As Object, objWMIService As Object, CsvFile As Object
    Dim CsvText As Variant, CsvSize As Integer

Sub GetFoldersAccessRights()
    Dim CsvListe As Variant, CsvTitel As Variant, Token As Variant, i As Integer
    
    If MsgBox(Msg0, vbOKCancel Or vbInformation, "Zugriffsrechte...") = vbCancel Then Exit Sub  
    
    CsvListe = Array(AF00, AF01, AF02, AF03, AF04, ATx0, AT00, AT01, AM00, AM01, AM02, AM03, AM04, AM05, AM06, AM07, AM08, AM16, AM17, AM18, AM19, AM20, AMx1)

    CsvSize = UBound(CsvListe) + CsvTextReserved
    
    ReDim CsvText(CsvSize):  ReDim CsvTitel(CsvSize)
    
    Set ACL = CreateObject("Scripting.Dictionary")  
    
    CsvTitel(0) = "Pfad"  
    CsvTitel(1) = "Erstellt"  
    CsvTitel(2) = "Benutzer"  
    CsvTitel(3) = "SID"  
    
    For i = 0 To UBound(CsvListe)
        Token = Split(CsvListe(i), ";")  
        ACL.Add Token(0) & Hex(Token(1)), i + CsvTextReserved & ";" & Token(1)  
        CsvTitel(i + CsvTextReserved) = Token(2)
    Next

    Set Fso = CreateObject("Scripting.FileSystemObject")  
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=Impersonate,(TakeOwnership)}!\\.\root\cimv2")  
    
    Set CsvFile = Fso.CreateTextFile(ThisWorkbook.Path & "\" & CsvFileName)  
    
    CsvFile.WriteLine Join(CsvTitel, ";")  
    
    Call GetFolder(Fso.GetFolder(FoldersPath)):   CsvFile.Close
    
    MsgBox Msg1, vbInformation, "Csv-Export..."  
End Sub

Private Sub GetFolder(ByRef Folder)
    Dim Subfolder As Object, i As Integer
    
    CsvText(0) = Folder.Path
    
    If Folder.Name = "" Then  
        CsvText(1) = ""  
    Else
        CsvText(1) = FormatDateTime(Folder.DateCreated, vbShortDate)
    End If
            
    Call GetSecuritySettings(Folder)
    
    On Error Resume Next
    
    For Each Subfolder In Folder.SubFolders
        If Err.Number = 0 Then
            Call GetFolder(Subfolder)
        Else
            Err.Clear
            Call WriteCsvFile("Zugriff verweigert")  
        End If
    Next
End Sub

Private Sub GetSecuritySettings(ByRef Folder)
    Dim objFSS As Object, objSD As Object, objACL As Variant
    Dim LastName As String, DoWrite As Boolean, i As Integer
    
    On Error Resume Next
    
    Set objFSS = objWMIService.Get("Win32_LogicalFileSecuritySetting='" & Folder & "'")  
    
    If Err.Number <> 0 Then
        Call WriteCsvFile("Nicht verfügbar"):  Exit Sub  
    End If
    
    On Error GoTo 0
    
    If objFSS.GetSecurityDescriptor(objSD) = 0 Then
        If (objSD.ControlFlags And SE_DACL_PRESENT) <> 0 Then
            For Each objACL In objSD.DACL
                With objACL
                    CsvText(2) = .Trustee.Name
                    CsvText(3) = .Trustee.SIDString
                        
                    For i = 4 To CsvSize:  CsvText(i) = "":  Next  
                    
                    Call SetSecuritySettings("AM", .AccessMask)  
                    Call SetSecuritySettings("AF", .AceFlags)  
                    Call SetSecuritySettings("AT", .AceType)  
                       
                    CsvFile.WriteLine Join(CsvText, CsvDelim)
                End With
            Next
        Else
            Call WriteCsvFile("Nicht verfügbar")  
        End If
    Else
        Call WriteCsvFile("Nicht verfügbar")  
    End If
End Sub

Private Sub SetSecuritySettings(ByRef Target, ByVal Value)
    Dim Key As Variant, Token As Variant
    
    If ACL.Exists(Target & "=" & Hex(Value)) Then  
        Token = Split(ACL.Item(Target & "=" & Hex(Value)), ";")  
        CsvText(Token(0)) = "x"  
    Else
        For Each Key In ACL.Keys
            If Left(Key, 3) = Target & "&" Then  
                Token = Split(ACL.Item(Key), ";")  
                If (Value And CLng(Token(1))) Then CsvText(Token(0)) = "x"  
            End If
        Next
    End If
End Sub

Private Sub WriteCsvFile(ByRef Text)
    Dim i As Integer

    CsvText(2) = Text
    
    For i = 3 To CsvSize:  CsvText(i) = "":  Next  
    
    CsvFile.WriteLine Join(CsvText, CsvDelim)
End Sub

Gruß Dieter

[edit] geändert [/edit]
Member: DieDrohne
DieDrohne Sep 29, 2010 at 06:28:14 (UTC)
Goto Top
Erstmal vielen vielen Dank und es funktioniert fast perfekt. Nur eine Frage:

Ich habe nur ein Problem mit
Const CsvAusgabe = "System, Administratoren, Benutzer"  'Csv-Daten ausgeben für?  
.

Wenn ich die Abfrage starte, steht bei Benutzer entweder nichts oder Administrator.
Wenn ich meinen kompletten Namen dort eintrage, also nach dem Format "MustermannM@domäne.de" dann gibt er mich auch aus. Wildcards wie * funktionieren wohl nicht? Also das er mir einfach jeden Benutzer für die Ordner ausgibt? Oder muss ich eine Liste schreiben mit allen Benutzern und diese muss er dann nach und nach abarbeiten?

Schöner wäre es natürlich wenn er einfach alle ausgibt.


P.S.: Was mir grad noch aufgefallen ist. Egal welchen Startordner ich nehme, es steht in den Zeilen 2-4 genau dasselbe drin. Also er wiederholt die Zeile 2 noch 2 mal und dann geht er erst weiter.
Mitglied: 76109
76109 Sep 29, 2010 at 08:34:22 (UTC)
Goto Top
Hallo DieDrohne!

Setze mal in der Codezeile 115 und Codezeile 135 ein Kommentarzeichen (Hochkomma) davor.

Zitat von @DieDrohne:
P.S.: Was mir grad noch aufgefallen ist. Egal welchen Startordner ich nehme, es steht in den Zeilen 2-4 genau dasselbe drin. Also
er wiederholt die Zeile 2 noch 2 mal und dann geht er erst weiter.
Das kann ich für den Moment leider nicht nachvollziehenface-sad

Gruß Dieter
Member: DieDrohne
DieDrohne Sep 29, 2010 at 11:15:46 (UTC)
Goto Top
Hallo,

Ich habs rausgenommen und jetzt listet er mir alle auf, ok er versuchts. Keine Ahnung warum, aber er bricht bei übergeordneten Ordnern bei 1-2 Einträgen ab und untergeordnete bei 2 Einträgen und geht dann schon zum nächsten Ordner.

Standardmäßig sind aber ca. 5-6 Sicherheitsgruppen eingetragen + eventuell einzelne Benutzer.

Kann ich irgendwo einstellen, wie oft er durchläuft oder macht er das von sich aus.

Und noch ne Frage, ich habe sehr viele Ordner, kann es zu einem Überlauf kommen wo er dann abschaltet und mir eine Meldung ausgibt "Vorgang abgebrochen"?

Gruß
André
Member: DieDrohne
DieDrohne Sep 29, 2010 at 11:33:25 (UTC)
Goto Top
So habe jetzt wieder die Fehlermeldung:

Ungültiger Objektpfad. Tritt nach ca. 10 Minuten durchlaufen erst auf.

Nach dem ich auf Debuggen gegangen bin, führte er mich zur Zeile:

    Set objFSS = objWMIService.Get("Win32_LogicalFileSecuritySetting='" & Folder & "'")  

Eine Idee?
Mitglied: 76109
76109 Sep 29, 2010 at 16:39:46 (UTC)
Goto Top
Hallo DieDrohne!

Zitat von @DieDrohne:
So habe jetzt wieder die Fehlermeldung:
Ungültiger Objektpfad. Tritt nach ca. 10 Minuten durchlaufen erst auf.

Nach dem ich auf Debuggen gegangen bin, führte er mich zur Zeile:
Set objFSS = objWMIService.Get("Win32_LogicalFileSecuritySetting='" & Folder & "'")

Ersetze die Codezeile 107 mal durch diese Codezeilen, die beim Auftreten des Fehlers den betreffenden Ordner-Pfad in einer MsgBox anzeigt:
    On Error Resume Next
    
    Set objFSS = objWMIService.Get("Win32_LogicalFileSecuritySetting='" & Folder & "'")  
    
    If Err.Number <> 0 Then MsgBox Folder
    
    On Error GoTo 0

Gruß Dieter

PS. Den Teil Mit Csv-Ausgabe (Benutzer...) habe ich im Code (oben) entfernt
Mitglied: 76109
76109 Sep 29, 2010 at 16:55:49 (UTC)
Goto Top
Hallo DieDrohne!

Zitat von @DieDrohne:
Ich habs rausgenommen und jetzt listet er mir alle auf, ok er versuchts. Keine Ahnung warum, aber er bricht bei
übergeordneten Ordnern bei 1-2 Einträgen ab und untergeordnete bei 2 Einträgen und geht dann schon zum
nächsten Ordner.
Kommt da irgendeine Meldung "Zugriff verweigert" sowas in der Art?

Kann ich irgendwo einstellen, wie oft er durchläuft oder macht er das von sich aus.
Verstehe ich jetzt irgendwie nicht so ganz?

Und noch ne Frage, ich habe sehr viele Ordner, kann es zu einem Überlauf kommen wo er dann abschaltet und mir eine Meldung
ausgibt "Vorgang abgebrochen"?
Das sollte meines Wissens nicht passieren?

Gruß Dieter
Member: DieDrohne
DieDrohne Sep 29, 2010 at 20:24:15 (UTC)
Goto Top
Hi,

Ja "Zugriff verweigert" kam, nach der Änderung auf alle anzeigen, kam dann irgendwann die Meldung "Vorgang abgebrochen".

Gruß
André
Mitglied: 76109
76109 Sep 29, 2010 at 21:03:03 (UTC)
Goto Top
Hallo DieDrohne!

Ok, werde ich morgen eine entsprechende Fehlerbehandlung mit einbauen, wobei diese Ordner dann übersprungen werden.

Gruß Dieter
Member: DieDrohne
DieDrohne Sep 30, 2010 at 08:21:03 (UTC)
Goto Top
Hallo didi1954,

Danke für den angepassten Code. Dadurch konnte ich ermitteln warum er abbrach. Mein Kollege hatte den Ordnernamen mit einem Hochkomma ' versehen gehabt. Dadurch hat er an der Stelle immer abgebrochen.

Ordner umbenannt und jetzt geht es.

Da ist aber immer noch eine Sache die ich nicht verstehe. Er listet mir zu 99% die Ordner auf und gibt 2 eingetragene Benutzer aus. Es sind aber mindestens bei jedem Ordner 7 Sicherheitsgruppen mit unterschiedlichen Rechten eingetragen. Auf manche Ordner müssen noch mehr Kollegen darauf zugreifen, dann werden es auch mal schnell 10-15 noch zusätzlich eingetragene Personen.

Das sieht dann ca. so aus:

Pfad 1ErstellungsdatumGruppe 1Rechte...
Pfad 1ErstellungsdatumGruppe 2Rechte...
Pfad 2ErstellungsdatumGruppe 1Rechte...
Pfad 2ErstellungsdatumGruppe 2Rechte...
Pfad 3ErstellungsdatumGruppe 1Rechte...
Pfad 3ErstellungsdatumGruppe 2Rechte...
Pfad 4ErstellungsdatumGruppe 1Rechte...
Pfad 4ErstellungsdatumGruppe 2Rechte...

usw.

Hast du eine Idee warum er die anderen nicht mit ausgibt?

Gruß
André
Mitglied: 76109
76109 Sep 30, 2010 at 08:55:24 (UTC)
Goto Top
Hallo André!

Den Code habe ich nochmal ab Codezeile 60 komplett geändert.

Dabei wird in der Spalte Benutzer dann bei Zugriffsverweigerung "Zugriff verweigert" eingetragen. In anderen Fällen wird "Nicht verfügbar" eingetragenface-wink

Zu Beginn kommt jetzt noch eine MsgBox, die darauf hinweist, dass der Vorgange je nach Ordner-Anzahl einige Minuten dauern kann.

Da ist aber immer noch eine Sache die ich nicht verstehe. Er listet mir zu 99% die Ordner auf und gibt 2 eingetragene Benutzer aus. Es sind aber mindestens bei
jedem Ordner 7 Sicherheitsgruppen mit unterschiedlichen Rechten eingetragen. Auf manche Ordner müssen noch mehr Kollegen darauf zugreifen, dann werden es
auch mal schnell 10-15 noch zusätzlich eingetragene Personen.
Dazu habe ich leider keine Ideeface-sad

Gruß Dieter
Member: DieDrohne
DieDrohne Sep 30, 2010 at 12:45:54 (UTC)
Goto Top
Hi,

Ich habe jetzt den Code übernommen und durchlaufen lassen. Es geht jetzt irgendwie schneller als vorher ;)

Allerdings habe ich halt immer noch das Problem das er mir max 2 Benutzer ausgibt. Keine ahnung warum, habe es schon Schrittweise durchlaufen lassen. Und dennoch komme ich auf das gleiche Ergebniss. Aus irgendeinem Grund geht er zum nächsten Ordner, obwohl er noch garnicht mit auflisten fertig ist.

Aber wie dem auch sein, LIEBEN DANK für diesen Code!

Gruß
André
Member: DieDrohne
DieDrohne Oct 01, 2010 at 08:32:31 (UTC)
Goto Top
Hallo Dieter,

Fehler gefunden. Ich hab es immer und immer wieder durchlaufen lassen per Einzelschritt bis ich drauf kam.

Der hat die erste Zeile geschrieben und die zweite immer und immer wieder überschrieben bis er alle Benutzer durch hatte. Bei deinem Code gibt es einen kleinen (Denk-)Fehler. Und zwar Zeile 146 und 153 war das DoWrite falsch herum.

So sieht es jetzt bei mir aus:

    If objFSS.GetSecurityDescriptor(objSD) = 0 Then
        If (objSD.ControlFlags And SE_DACL_PRESENT) <> 0 Then
            For Each objACL In objSD.DACL
                With objACL
                    If .Trustee.Name <> LastName Then
                        DoWrite = True
                        LastName = .Trustee.Name
                        CsvText(2) = .Trustee.Name
                        CsvText(3) = .Trustee.SIDString
                        
                        For i = 4 To CsvSize:  CsvText(i) = "":  Next  
                    Else
                        DoWrite = False
                    End If
                        
                    Call SetSecuritySettings("AM", .AccessMask)  
                    Call SetSecuritySettings("AF", .AceFlags)  
                    Call SetSecuritySettings("AT", .AceType)  
                       
                    If DoWrite Then CsvFile.WriteLine Join(CsvText, CsvDelim)
                End With
            Next
        Else
            Call WriteCsvFile("Nicht verfügbar")  
        End If
    Else
        Call WriteCsvFile("Nicht verfügbar")  
    End If

Nun zeigt er mir alle Benutzer bei den Ordnern an und das ist genau das was ich wollte ;)

VIELEN VIELEN DANK!!!!

Gruß André

P.S.: Ich weiß ich bin jetzt frech, aber wenn er das aus Excel heraus eine CSV Datei erstellt, kann man dann das ganze nicht auch so machen, das er das gleich in Excel abspeichert?
Mitglied: 76109
76109 Oct 01, 2010 at 08:48:08 (UTC)
Goto Top
Hallo André!

Aja, danke für den Hinweisface-wink Muss ich mir heute Abend oder morgen nochmal ansehen.

Gruß Dieter
Mitglied: 76109
76109 Oct 01, 2010 at 18:54:39 (UTC)
Goto Top
Hallo André!

Also, ich hatte tatsächlich einen Denkfehlerface-sad

Allerdings stimmt Deine Code-Änderung auch nichtface-smile Da fehlen ebenfalls wieder Einträge.

Ich hatte leider nur auf meiner Daten-Partition getestet und da ist es so, dass für System, Admin, Benutzer.. immer 2 Datensätze zurückgegeben werden. Von daher dachte ich, dass dies generell so wäre, was aber leider ein Irtum war. Deswegen hatte ich den Code so geschrieben, das erst mit dem 2. Datensatz eine Zeile in die Csv-Datei geschrieben wird, was in diesem Fall auch funktioniert hat.

Bei einem weiteren Test auf meiner W7-Partition ist mir das leider jetzt erst aufgefallenface-sad

Den Code oben habe ich jetzt nochmal so geändert, dass jeder Datensatz in die Csv-Datei geschrieben wird, wobei allerdings für System, Admin... dann teilweise wieder 2 Datensätze (sprich 2 Zeilen) ausgegeben werden.

Gut das ich den Code mal auf meiner W7-Partition hab laufen lassen. Dabei ist mir nämlich erst aufgefallen, dass mein Win7 2 Endlos-Ordnerstrukturen enthält z.B.
C:\Users\Default User\Lokale Einstellungen\Anwendungsdaten\Anwendungsdaten\Anwendungsdaten\Endlos.....
Bei 260 MB mit fast 1 Million Zeilen habe ich dann mal abgebrochenface-smile

Nach Behebung des Problems hat das Auslesen meiner Win7-Partition mit ca 26.000 Ordnern ca 15 Minuten gedauert, wobei die Csv-Datei eine Größe von rund 20 MB erreichte (ca 118.000 Zeilen).

Gruß Dieter

[edit] Kommentar aktualisiert [/edit]
Member: DieDrohne
DieDrohne Oct 05, 2010 at 18:18:22 (UTC)
Goto Top
Hallo Dieter.

Ich bin diese woche sehr im Stress auf Arbeit mit anderen Sachen und kann daher erst nächste Woche deinen Code weiter anschauen und bearbeiten. Aktuell funktioniert er super...

Aber da ist immer noch eine Sache, Kann man den umschreiben das er ein 2. Tabellenblatt in der aktuellen Exceldatei automatisch befüllt, ohne den Umweg über eine csv Datei zu machen?

Liebe Grüße
André
Mitglied: 76109
76109 Oct 05, 2010 at 20:02:55 (UTC)
Goto Top
Hallo André!

Zitat von @DieDrohne:
Aber da ist immer noch eine Sache, Kann man den umschreiben das er ein 2. Tabellenblatt in der aktuellen Exceldatei automatisch
befüllt, ohne den Umweg über eine csv Datei zu machen?
Ja, dass wäre im Prinzip keine große Sache. Hierbei besteht allerdings, je nach Anzahl der Ordner, die Gefahr eines Überlaufs (Max-Zeilen).

Gruß Dieter
Member: DieDrohne
DieDrohne Oct 06, 2010 at 06:05:15 (UTC)
Goto Top
Hi,

Ich glaub ich habe irgendwo mal ein Script gesehen, wo man bei einer gewissen Anzahl auf ein 2. 3. usw Tabellenblatt weiterschreiben kann. Aber 1 Tabellenblatt reicht auch aus, wenn man ab einem bestimmten Ordner erst anfängt ;)

LG
André
Mitglied: 76109
76109 Oct 06, 2010 at 11:01:05 (UTC)
Goto Top
Hallo André!

Hier der neue Code, der die Daten in die Arbeitsmappe schreibt.

Schritt 1:
Jenachdem, ob die Arbeitsmappe bereits Tabellen beinhaltet oder nicht, muss eine Tabelle mit dem Namen angelegt werden, der der Konstanten SheetName entspricht und am Ende muss die Ziffer 1 stehen z.B Tabelle1, Liste1...

Schritt 2:
Die Konstante StartLine besagt, dass die Rechte ab dieser Zeile eingetragen werden. Die Überschrift wird jedoch in die Zeile 1 eingetragen.

Sofern eine Tabelle mit dem Namen (SheetName) existiert, wobei ich jetzt als Beispiel den Namen Rechte1 verwende, dann ist der weitere Ablauf in etwa so:
Beim Start des Makro, wird eine CleanUp-Funktion durchgeführt, in der alle Sheets, die dem Namen Rechte entsprechen - mit Ausnahme von Rechte1 - gelöscht werden.
Im weiteren Verlauf werden je nach Bedarf, automatisch weitere Sheets in fortlaufender Reihenfolge und hintereinander angelegt z.B. Rechte1, Rechte2 usw.

In der Schluss-Meldung wird noch zusätzlich die Gesamtzahl der eingelesenen Ordner mit ausgegeben.

Neuer Code:
       Option Explicit
    Option Compare Text
    
    Const FoldersPath = "C:\"       'Start-Ordner  
    
    Const SheetName = "Rechte1"     'Tabellenname wahlweise, am Ende muss die Ziffer 1 stehen  
    
    Const StartLine = 2             'Ab Zeile  
'______________________________________________________________________________________  
    
   'Spalte 1-4 = Path, Erstellungsdatum, Gruppe/Benutzername, G/B-Name-SID  
    Const TextReserved = 4
   
   'Control-Flag Infos verfügbar  
    Const SE_DACL_PRESENT = &H4
    
   'Zugriffs-Flags, TitelText nach belieben festlegen  
    Const AF00 = "AF&;&H01;TitelText"             'OBJECT_INHERIT_ACE  
    Const AF01 = "AF&;&H02;TitelText"             'CONTAINER_INHERIT_ACE  
    Const AF02 = "AF&;&H04;TitelText"             'NO_PROPOGATE_INHERIT_ACE  
    Const AF03 = "AF&;&H08;TitelText"             'INHERIT_ONLY_ACE  
    Const AF04 = "AF&;&H10;TitelText"             'INHERIT_ACE"  
    
   'Zugriffs-Type  
    Const ATx0 = "AT=;&H00;TitelText"             'ACCESS_ALLOWED_ACE_TYPE  
    
    Const AT00 = "AT&;&H01;TitelText"             'ACCESS_DENIED_ACE_TYPE  
    Const AT01 = "AT&;&H02;TitelText"             'AUDIT  
      
   'Zugriffsrechte: Objektspezifisch  
    Const AM00 = "AM&;&H00000001;TitelText"       'DIR_LIST_DIRECTORY/FILE_READ_DATA  
    Const AM01 = "AM&;&H00000002;TitelText"       'DIR_ADD_FILE/FILE_WRITE_DATA  
    Const AM02 = "AM&;&H00000004;TitelText"       'DIR_ADD_SUBDIRECTORY/FILE_APPEND_DATA  
    Const AM03 = "AM&;&H00000008;TitelText"       'READ_NAMED_ATTRIBUTS  
    Const AM04 = "AM&;&H00000010;TitelText"       'WRITE_NAMED_ATTRIBUTS  
    Const AM05 = "AM&;&H00000020;TitelText"       'EXECUTE  
    Const AM06 = "AM&;&H00000040;TitelText"       'DELETE_CHILD  
    Const AM07 = "AM&;&H00000080;TitelText"       'READ_ATTRIBUTES  
    Const AM08 = "AM&;&H00000100;TitelText"       'WRITE_ATTRIBUTES  
    
    Const AMx1 = "AM=;&H001F01FF;TitelText"       'FILE_ALL_ACCESS"  
    
    'Zugriffsrechte: Standard --> Zugriffsrechte auf Objektspezifisch  
    Const AM16 = "AM&;&H00010000;TitelText"       'DELETE  
    Const AM17 = "AM&;&H00020000;TitelText"       'READ_ACL  
    Const AM18 = "AM&;&H00040000;TitelText"       'WRITE_ACL  
    Const AM19 = "AM&;&H00080000;TitelText"       'WRITE_OWNER  
    Const AM20 = "AM&;&H00100000;TitelText"       'SYNCHRONIZE  
    
    'Zugriffsrechte: Security-Descriptor SACL (System Access Control List)  
    Const AM24 = "AM&;&H01000000;TitelText"       'ACCESS_SYSTEM_SECURITY  
    
    'Zugriffsrechte Erweitert --> Zugriffsrechte auf Standard/Objektspezifisch  
    Const AM28 = "AM&;&H10000000;TitelText"       'GENERIC_ALL  
    Const AM29 = "AM&;&H20000000;TitelText"       'GENERIC_EXECUTE  
    Const AM30 = "AM&;&H40000000;TitelText"       'GENERIC_WRITE  
    Const AM31 = "AM&;&H80000000;TitelText"       'GENERIC_READ  
'______________________________________________________________________________________  
    
    Const Msg0 = "Der Vorgang kann je nach Anzahl der Ordner einige Minuten dauern!"  
    Const Msg1 = "Das Einlesen der Rechte aus %1 Ordnern ist abgeschlossen."  
    
    Dim Fso As Object, ACL As Object, objWMIService As Object, TextLine As Variant, TitelLine As Variant
    Dim TextSize As Long, CellSize As Long, FoldersCount As Long, NewLine As Long, EndLine As Long

Sub GetFoldersAccessRights()
    Dim TextList As Variant, Token As Variant, i As Integer
    
    If MsgBox(Msg0, vbOKCancel Or vbInformation, "Zugriffsrechte...") = vbCancel Then Exit Sub  
    
    TextList = Array(AF00, AF01, AF02, AF03, AF04, ATx0, AT00, AT01, AM00, AM01, AM02, AM03, AM04, AM05, AM06, AM07, AM08, AM16, AM17, AM18, AM19, AM20, AMx1)

    TextSize = UBound(TextList) + TextReserved:  CellSize = TextSize + 1
    
    ReDim TextLine(TextSize):  ReDim TitelLine(TextSize)
    
    Set ACL = CreateObject("Scripting.Dictionary")  
    
    TitelLine(0) = "Pfad"  
    TitelLine(1) = "Erstellt"  
    TitelLine(2) = "Benutzer"  
    TitelLine(3) = "SID"  
    
    For i = 0 To UBound(TextList)
        Token = Split(TextList(i), ";")  
        ACL.Add Token(0) & Hex(Token(1)), i + TextReserved & ";" & Token(1)  
        TitelLine(i + TextReserved) = Token(2)
    Next

    Set Fso = CreateObject("Scripting.FileSystemObject")  
    Set objWMIService = GetObject("winmgmts:{impersonationLevel=Impersonate,(TakeOwnership)}!\\.\root\cimv2")  
    
    FoldersCount = 0
    
    Call CleanUpSheets
    
    Range(Range("A1"), Cells(1, CellSize)) = TitelLine  
    
    Call GetFolder(Fso.GetFolder(FoldersPath))
    
    MsgBox Replace(Msg1, "%1", FoldersCount), vbInformation, "Rechte einlesen..."  
End Sub

Private Sub GetFolder(ByRef Folder)
    Dim Subfolder As Object, i As Integer
    
    TextLine(0) = Folder.Path
    
    If Folder.Name = "" Then  
        TextLine(1) = ""  
    Else
        TextLine(1) = FormatDateTime(Folder.DateCreated, vbShortDate)
    End If
            
    Call GetSecuritySettings(Folder)
    
    On Error Resume Next
    
    For Each Subfolder In Folder.SubFolders
        If Err.Number = 0 Then
            Call GetFolder(Subfolder)
        Else
            Err.Clear
            Call WriteText("Zugriff verweigert")  
        End If
    Next
End Sub

Private Sub GetSecuritySettings(ByRef Folder)
    Dim objFSS As Object, objSD As Object, objACL As Variant
    Dim LastName As String, DoWrite As Boolean, i As Integer
    
    FoldersCount = FoldersCount + 1
    
    On Error Resume Next
    
    Set objFSS = objWMIService.Get("Win32_LogicalFileSecuritySetting='" & Folder & "'")  
    
    If Err.Number <> 0 Then
        Call WriteText("Nicht verfügbar"):  Exit Sub  
    End If
    
    On Error GoTo 0
    
    If objFSS.GetSecurityDescriptor(objSD) = 0 Then
        If (objSD.ControlFlags And SE_DACL_PRESENT) <> 0 Then
            For Each objACL In objSD.DACL
                With objACL
                    TextLine(2) = .Trustee.Name
                    TextLine(3) = .Trustee.SIDString
                        
                    For i = 4 To TextSize:  TextLine(i) = "":  Next  
                    
                    Call SetSecuritySettings("AM", .AccessMask)  
                    Call SetSecuritySettings("AF", .AceFlags)  
                    Call SetSecuritySettings("AT", .AceType)  
                       
                    If NewLine > EndLine Then Call CreateNewSheet
                    
                    Range(Cells(NewLine, 1), Cells(NewLine, CellSize)) = TextLine: NewLine = NewLine + 1
                End With
            Next
        Else
            Call WriteText("Nicht verfügbar")  
        End If
    Else
        Call WriteText("Nicht verfügbar")  
    End If
End Sub

Private Sub SetSecuritySettings(ByRef Target, ByVal Value)
    Dim Key As Variant, Token As Variant
    
    If ACL.Exists(Target & "=" & Hex(Value)) Then  
        Token = Split(ACL.Item(Target & "=" & Hex(Value)), ";")  
        TextLine(Token(0)) = "x"  
    Else
        For Each Key In ACL.Keys
            If Left(Key, 3) = Target & "&" Then  
                Token = Split(ACL.Item(Key), ";")  
                If (Value And CLng(Token(1))) Then TextLine(Token(0)) = "x"  
            End If
        Next
    End If
End Sub

Private Sub WriteText(ByRef Text)
    Dim i As Integer

    TextLine(2) = Text
    
    For i = 3 To TextSize:  TextLine(i) = "":  Next  
    
    If NewLine > EndLine Then Call CreateNewSheet
                    
    Range(Cells(NewLine, 1), Cells(NewLine, CellSize)) = TextLine: NewLine = NewLine + 1
End Sub

Private Sub CleanUpSheets()
    Dim Wks As Worksheet
    
    ThisWorkbook.Activate
    
    Sheets(SheetName).Cells.Clear
    
    For Each Wks In Sheets
        If Wks.Name Like Left(SheetName, Len(SheetName) - 1) & "[!1]" Then  
            Application.DisplayAlerts = False
            Wks.Delete
            Application.DisplayAlerts = True
        End If
    Next
    Sheets(SheetName).Activate:  Range("A1").Select  
    
    NewLine = StartLine:  EndLine = Rows.Count
End Sub

Private Sub CreateNewSheet()
    Dim LastNumber As Integer, LastName As String
    
    LastName = ActiveSheet.Name
    LastNumber = Right(LastName, 1)
    
    Sheets.Add After:=ActiveSheet
    
    ActiveSheet.Name = Replace(LastName, LastNumber, LastNumber + 1)
    
    Range(Range("A1"), Cells(1, CellSize)) = TitelLine  
    
    NewLine = StartLine
End Sub

Gruß Dieter
Member: DieDrohne
DieDrohne Oct 07, 2010 at 08:39:46 (UTC)
Goto Top
Hallo Dieter!

Du bist der Größte!

Es funktioniert alles ohne Probleme und dafür sage ich schonmal tausend Dank!

Jetzt muss ich nur noch ein wenig Feinarbeit betreiben und dann habe ich genau das, was ich wollte!

Danke Danke Danke!

Gruß
André
Mitglied: 76109
76109 Oct 07, 2010 at 15:11:33 (UTC)
Goto Top
Hallo André!

Zitat von @DieDrohne:
Es funktioniert alles ohne Probleme und dafür sage ich schonmal tausend Dank!
Freut mich zu hörenface-smile
Danke Danke Danke!
Yepp, gern geschehenface-wink

Dann fehlt ja nur noch das grüne Gelöst-Häkchenface-wink

Gruß Dieter
Member: ZurigoX
ZurigoX Nov 14, 2012 at 14:17:25 (UTC)
Goto Top
Hallo zusammen

Da hier schon seit mehr als zwei Jahren Funkstille herrscht, bin ich mir nicht sicher, ob ich eine Antwort bekomme. Ich versuchs mal und bin dankbar, wenn mir jemand, der mehr von der Sache verstehet, weiterhilft.
Das Script hier würde genau das machen, das ich benötige. Lokal funktioniert das auch 1A. Sobald ich es aber auf Netzlaufwerke anwende, bekommen ich beim Benutzer nur ein "Nicht verfügbar". Dabei spielt es keine Rolle, ob ich es von meinem Rechner aus mache, oder ob es auf einem Server ausgeführt wird. Was mach ich falsch.

Beste Dank im Voraus

ZurigoX