Derzeit gibt es das „Microsoft Visual Basic 2010 – Das Entwicklerbuch“ kostenlos zum Download über Microsoft Press zu beziehen. Für den Download wird die Angabe einer E-Mail-Adresse benötigt. Nach deren Eingabe ist der direkte Download des PDFs möglich.
Kategorie: Programmierung
Powershell: Verzeichnisstruktur in Textdatei exportieren
Mit diesem Code können Ordnerstrukturen des Filesystems in eine Textdatei exportiert werden. Es wird der Startordner sowie der Pfad und der Dateiname der Exportdatei angegeben werden. Nach der Erstellung kann direkt die Textdatei geöffnet werden.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $objForm = New-Object System.Windows.Forms.Form $objForm.Text = "FolderListGenerator" $objForm.Size = New-Object System.Drawing.Size(300,200) $objForm.StartPosition = "CenterScreen" $objForm.KeyPreview = $True $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") { $path=$objTextBox.Text;$objForm.Close()} }) $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") { $objForm.Close()} }) $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Size(75,120) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = "OK" $OKButton.Add_Click({$path=$objTextBox1.Text;$file=$objTextBox2.Text;$objForm.Close()}) $objForm.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Size(150,120) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = "Cancel" $CancelButton.Add_Click({$objForm.Close()}) $objForm.Controls.Add($CancelButton) $objLabel1 = New-Object System.Windows.Forms.Label $objLabel1.Location = New-Object System.Drawing.Size(10,20) $objLabel1.Size = New-Object System.Drawing.Size(280,20) $objLabel1.Text = "Bitte Verzeichnispfad eingeben (z.B. C:\Folder):" $objForm.Controls.Add($objLabel1) $objTextBox1 = New-Object System.Windows.Forms.TextBox $objTextBox1.Location = New-Object System.Drawing.Size(10,40) $objTextBox1.Size = New-Object System.Drawing.Size(260,20) $objTextBox1.Text = "" $objForm.Controls.Add($objTextBox1) $objLabel2 = New-Object System.Windows.Forms.Label $objLabel2.Location = New-Object System.Drawing.Size(10,70) $objLabel2.Size = New-Object System.Drawing.Size(280,20) $objLabel2.Text = "Bitte Dateiablage eingeben (z.B. C:\temp\folder.txt):" $objForm.Controls.Add($objLabel2) $objTextBox2 = New-Object System.Windows.Forms.TextBox $objTextBox2.Location = New-Object System.Drawing.Size(10,90) $objTextBox2.Size = New-Object System.Drawing.Size(260,20) $objTextBox2.Text = "" $objForm.Controls.Add($objTextBox2) [void] $objForm.ShowDialog() Get-Childitem $objTextBox1.Text -recurse -filter * | ? { $_.PSisContainer -eq $true} | % {$_.fullname -replace "\\","`t" } | sort | out-file $objTextBox2.Text $a = new-object -comobject wscript.shell $intAnswer = $a.popup("Exportdatei öffnen?",0,"FolderListGenerator",4) If ($intAnswer -eq 6) { Invoke-Item $file } else { $a.popup("Datei erstellt") }
Als Trennzeichen wird der TAB genutzt, so dass ein Import z.B. in Excel ohne Probleme funktionieren sollte.
Probleme nach Gruppenumbennenung unter Nutzung von KiXtart
Vor längerer Zeit wollte ich in einem Projekt „mal eben fix“ einige Gruppennamen in einer Active Directory auf einen neueren Stand bringen. Dieses wollte ich ganz gern in einer sowieso stattfindenen Wochenend-Aktion durchführen.
Ich änderte einen Gruppennamen in der Active Directory sowie im KiXScript und startete das System neu. Allerdings erhielt ich nicht den gewünschten Erfolg. Der neue Gruppenname wurde ignoriert, als ob dieser nicht im Skript eingebaut wäre. Ich testete noch etwas weiter; für das Wochenende musste es halt mit 3 neuen Gruppen realisiert werden.
Nun steht wieder ein Projekt an, bei dem viele Anpassungen durchgeführt werden müssen und somit wollte ich dem noch einmal auf den Grund gehen. Recht schnell fand ich den Grund des entsprechenden Verhaltens bei der Namensänderung:
Group-membership information cache
Im Standard-Aufruf werden die Gruppen des Benutzers unter dem Registry-Pfad des angemeldeten Benutzers samt SID eingelagert. Dieser Cache wird für 30 Tage aufrecht erhalten. Dieses Verhalten kann allerdings auser Kraft gesetzt werden in dem man beim Aufruf des Skripts einen Optionsschalter mitliefert:
kix32.exe script.kix /f
Mit der dem Schalter „/f“ wird die Aktualisierung der Gruppen forciert und die 30-tägige Cachezeit nicht genutzt.
Probleme bei .NET Framework 4-Updates
Bei einer meiner Installationen kam es zu Problemen bei der Aktualisierung durch diefolgenden Microsoft-Updates:
- Update für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2533523)
- Sicherheitsupdate für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2656351)
- Update für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2468871)
- Sicherheitsupdate für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2604121)
- Sicherheitsupdate für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2487367)
- Sicherheitsupdate für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2656368)
- Sicherheitsupdate für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2656405)
- Sicherheitsupdate für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2686827)
- Update für Microsoft .NET Framework 4 unter Windows XP, Windows Server 2003, Windows Vista, Windows 7, Windows Server 2008 x86 (KB2600217)
Ich konnte diese Installationsmöglichkeit mit der Funktion „Software“ der Systemsteuerung (adaptiv „Programme und Funktionen“ seit Windows Vista) wieder zur Verfügung stellen.
Ich musste dafür die Software „.NET Framework 4 Client Profile“ reparieren. Sollte der Button „Ändern/Entfernen“ nicht zur Verfügung stehen, muss nur das entsprechende MSI-Paket von Microsoft geladen werden und die Reparatur-Funktion wird bei der Ausführung angeboten.
Alle Domänengruppen inkl. Mitglieder in HTML auflisten
Aufgrund von umfangreicher Benutzerlöschungen habe ich einen Report erstellen wollen, welcher Benutzer in welcher Gruppe als Mitglied zum aktuellen Zeitpunkt eingebunden ist.
Dafür habe ich ein sehr angenehmes VBS-Skript gefunden, welches ich minimal für die Abfrage des Managers erweitert habe. Der Report selber wird als HTML-Datei angelegt.
' DocumentGroups.vbs ' VBScript program to document all groups in Active Directory. ' Outputs group name, type of group, all members, and types of member. ' Lists all groups that are members, but does not list the nested group ' membership. '---------------------------------------------------------------------- ' Copyright (c) 2002 Richard L. Mueller ' Hilltop Lab web site - http://www.rlmueller.net ' Version 1.0 - November 10, 2002 ' Version 1.1 - February 19, 2003 - Standardize Hungarian notation. ' Version 1.2 - March 11, 2003 - Remove SearchScope property. ' *** MODIFIED March 13, 2006 - Added HTML File Out, Addtional Group/User Properties ' ' This script is designed to be run at a command prompt, using the ' Cscript host. The output can be redirected to a text file. ' For example: ' cscript //nologo DocumentGroups.vbs > groups.txt ' ' You have a royalty-free right to use, modify, reproduce, and ' distribute this script file in any way you find useful, provided that ' you agree that the copyright owner above has no warranty,obligations, ' or liability for such use. ' ' Version 1.3 - June 25, 2012 - Added attribute "managedby" by Daniel Lensing Option Explicit Dim objConnection, objCommand, objRootDSE, strDNSDomain, strQuery Dim objRecordSet, strDN, objGroup Dim FileSystem, oFile ' Open Text File for Output Set FileSystem = WScript.CreateObject("Scripting.FileSystemObject") Set oFile = FileSystem.CreateTextFile("GroupMemebrshipNew.html", True) oFile.writeLine "<HTML><HEAD><TITLE>Group Membership for MyDomain.com</TITLE><HEAD><BODY>" oFile.writeLine "<h4><TABLE width=100% border=0 padding=0 cellspacing=0 valign=top>" ' Use ADO to search Active Directory. Set objConnection = CreateObject("ADODB.Connection") Set objCommand = CreateObject("ADODB.Command") objConnection.Provider = "ADsDSOObject" objConnection.Open "Active Directory Provider" Set objCommand.ActiveConnection = objConnection ' Determine the DNS domain from the RootDSE object. Set objRootDSE = GetObject("LDAP://RootDSE") strDNSDomain = objRootDSE.Get("defaultNamingContext") ' Search for all groups, return the Distinguished Name of each. strQuery = "<LDAP://" & strDNSDomain _ & ">;(objectClass=group);distinguishedName;subtree" objCommand.CommandText = strQuery objCommand.Properties("Page Size") = 100 objCommand.Properties("Timeout") = 30 objCommand.Properties("Cache Results") = False Set objRecordSet = objCommand.Execute If objRecordSet.EOF Then Wscript.Echo "No groups found" objConnection.Close Set objRootDSE = Nothing Set objConnection = Nothing Set objCommand = Nothing Set objRecordSet = Nothing Wscript.Quit End If ' Enumerate all groups, bind to each, and document group members. Do Until objRecordSet.EOF strDN = objRecordSet.Fields("distinguishedName") Set objGroup = GetObject("LDAP://" & strDN) ' OUTPUT oFile.writeLine "<TR>" oFile.writeLine "<TD width=20% valign=top bgcolor=black><font color=white><strong><u>" & "Group Name:" &_ "</u></strong></font></TD><TD width=80% valign=top><strong>" &_ objGroup.SAMaccountName & "</strong></TD>" oFile.writeLine "</TR><TR>" oFile.writeLine "<TD valign=top bgcolor=black><font color=white><strong><u>" & "Distinguished Name:" &_ "</u></strong></font></TD><TD valign=top><strong>" &_ objGroup.distinguishedName & "</strong></TD>" oFile.writeLine "</TR><TR>" oFile.writeLine "<TD valign=top bgcolor=black><font color=white><strong><u>" & "Description:" &_ "</u></strong></font></TD><TD valign=top><strong>" &_ objGroup.description & "</strong></TD>" oFile.writeLine "</TR><TR>" oFile.writeLine "<TD valign=top bgcolor=black><font color=white><strong><u>" & "Manager:" &_ "</u></strong></font></TD><TD valign=top><strong>" &_ objGroup.managedby & "</strong></TD>" oFile.writeLine "</TR><TR>" oFile.writeLine "<TD valign=top bgcolor=black><font color=white><strong><u>" & "Type:" & "</u></strong></font></TD><TD valign=top><strong>" & GetType(objGroup.groupType) & "</strong></TD>" oFile.writeLine "</TR>" oFile.writeLine "<TR><TD valign=top bgcolor=black><font color=white><strong><u>Members:</font></TD><TD align=left valign=top>" oFile.writeLine "<TABLE width=70% border=0 cellspacing=0 cellpadding=0>" oFile.writeLine "<Tr>" oFile.writeLine " <TD valign=top><strong><u> Name </u></strong></TD>" oFile.writeLine " <TD valign=top><strong><u> Account </u></strong></TD>" oFile.writeLine " <TD valign=top><strong><u> Type </u></strong></TD>" oFile.writeLine "</Tr>" Call GetMembers(objGroup) oFile.writeLine "</TABLE>" oFile.writeLine "</TD></TR>" oFile.writeLine "<TR><TD COLSPAN=2><hr width=90%></TD></TR>" objRecordSet.MoveNext Loop oFile.writeLine "</TABLE></BODY></HTML>" msgBox "Done !!!" ' Clean up. objConnection.Close Set objRootDSE = Nothing Set objGroup = Nothing Set objConnection = Nothing Set objCommand = Nothing Set objRecordSet = Nothing Function GetType(intType) ' Function to determine group type from the GroupType attribute. If (intType And &h01) <> 0 Then GetType = "Built-in" ElseIf (intType And &h02) <> 0 Then GetType = "Global" ElseIf (intType And &h04) <> 0 Then GetType = "Local" ElseIf (intType And &h08) <> 0 Then GetType = "Universal" End If If (intType And &h80000000) <> 0 Then GetType = GetType & "/Security" Else GetType = GetType & "/Distribution" End If End Function Sub GetMembers(objADObject) ' Subroutine to document group membership. ' Members can be users or groups. Dim objMember, strType For Each objMember In objADObject.Members If UCase(Left(objMember.objectCategory, 8)) = "CN=GROUP" Then strType = "Group" Else strType = "User" End If ' OUTPUT oFile.writeLine "<TR>" oFile.writeLine "<TD valign=top>" & objMember.displayName & _ "</TD><TD valign=top>" & objMember.SAMaccountName & _ "</TD><TD valign=top>" & strType & "</TD>" oFile.writeLine "</TR>" ' Wscript.Echo " Member: " & objMember.sAMAccountName & " (" & strType & ")" Next Set objMember = Nothing End Sub
Skript: Server-Erstkonfiguration per Powershell
Häufig muss ich für Testumgebungen Windows Server 2008 R2 installieren. Dieses kann in Testumgebungen oder auch in Produktiv-Umgebungen vorkommen. Regelmäßig muss man dann die selben Einstellungen vornehmen. Dafür habe ich mir ein Powershell-Skript erstellt, welches folgende Konfiguration herstellt:
- Installation des SNMP-Service
- Installation des Telnet-Clients
- Installation des .NET Framework 3.5.1
- Installation von Bitlocker
- Gesammte Firewall deaktivieren
- Verstärkte Sicherheitskonfiguration füe IE für alle Benutzer deaktivieren
- Start des „Assistent für die Erstkonfiguration“ deaktivieren
- Start des „Server-Manager“ deaktivieren
- Remote Desktop aktivieren
Um dieses Ausführen zu können muss erst die Berechtigung für Skripts angepasst werden. Dafür wird die Powershell geöffnet und der folgende Befehl eingeegben:
Set-ExecutionPolicy unrestrictedAnschließend kann das folgende Skript gestartet werden. Dafür muss es in eine Datei kopiert und mit der Datei-Endung „ps1“ versehen werden.
# Vorbereitung zur Feature-Installation Import-Module Servermanager # SNMP installieren Add-WindowsFeature SNMP-Services Set-Service SNMP -StartupType Automatic Start-Service SNMP #Telnet-Client installieren Add-WindowsFeature Telnet-Client #.NET Framework 3.5.1 installieren Add-WindowsFeature AS-NET-Framework #Bitlocker installieren Add-WindowsFeature Bitlocker # Firewall deaktivieren netsh advfirewall set allprofiles state off # Registry für Routing-Anpassung Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "IPEnableRouter" -value "0" # Registry für IE ESC Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}" -Name "IsInstalled" -Value "0" Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}" -Name "IsInstalled" -Value "0" # Registry für Assistent für Erstkonfiguration Set-ItemProperty -Path "HKLM:\Software\Microsoft\ServerManager\Oobe" -Name "DoNotOpenInitialConfigurationTasksAtLogon" -Value "1" # Registry für Server-Manager Set-ItemProperty -Path "HKLM:\Software\Microsoft\ServerManager\" -Name "DoNotOpenServerManagerAtLogon" -Value "1" # RemoteDesktop Set-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Terminal Server" -Name "fDenyTSConnections" -Value "0" # Restart des Computers Restart-Computer
VBA: LastLogonTimeStamp in Excel-Tabelle
Um eine Auswertung der letzten Anmeldung von Benutzern zu erstellen habe ich das folgende Skript genutzt.
Es können mehrere Anpassungen durchgeführt werden:
– Domäne => dc=domain,dc=local
– Ausschließen von deaktivierten Konten => (!userAccountControl:1.2.840.113556.1.4.803:=2)
– Anpassung der Zeit auf alle Anmeldungen älter 90 Tage =>Format(Now() - 90
Das Skript muss einfach nur aus Excel gestartet werden und man erhält eine sehr übersichtliche Liste. Es ist allerdings zu beachten, dass der Wert "LastLogonTimeStamp" ein sychnronisierter Wert ist und nicht unbedingt tagesaktuell.
Option Explicit Const ADS_UF_ACCOUNTDISABLE = 2 Const ADS_SCOPE_SUBTREE = 2 Const ADS_UF_DONT_EXPIRE_PASSWD = 65536 Const FLD_FULLNAME = 1 Const FLD_SAM_ACCTNAME = 2 Const FLD_CREATEDATE = 3 Const FLD_PWD_LASTCHNG = 4 Const FLD_PWD_DONTEXPIRE = 5 Const FLD_UAC = 6 Const FLD_LASTLOGON = 7 Const FLD_ADSPATH = 8 Const FLD_MAX = 8 Const HEADROW = 1 Const ASCII_OFFSET = 64 Sub AD_QUERY() Dim objUser, objLogon, objConnection, objCommand, objRecordSet Dim strPath, strFullName, strSamAccountName Dim intUAC, intLogonTime Dim createdate, pwdchanged Dim Disabled, PWDexpire, intCounter Dim objsheet As Excel.Worksheet Dim rngData As Excel.Range Set objConnection = CreateObject("ADODB.Connection") Set objCommand = CreateObject("ADODB.Command") objConnection.Provider = "ADsDSOObject" objConnection.Properties("ADSI Flag") = 1 objConnection.Open "Active Directory Provider" Set objCommand.ActiveConnection = objConnection objCommand.Properties("Page Size") = 10000 objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 'Search AD Global catalog for user objects that are not disabled objCommand.CommandText = "<GC://dc=domain,dc=local>; (&(objectClass=user)(objectCategory=person));adspath, samAccountName; subtree" Application.StatusBar = "Executing AD Query. Please wait..." Set objRecordSet = objCommand.Execute Application.StatusBar = "Populating Worksheet with data. Please wait..." Set objsheet = Application.ActiveWorkbook.Worksheets.Add() objsheet.Name = Format(Date, "dd-mm-yyyy") & " Raw Data" intCounter = 2 'Initialise worksheet row counter objsheet.Cells(HEADROW, FLD_FULLNAME).Value = "Full Name" objsheet.Cells(HEADROW, FLD_SAM_ACCTNAME).Value = "SAM Account name" objsheet.Cells(HEADROW, FLD_CREATEDATE).Value = "Create Date (UTC)" objsheet.Cells(HEADROW, FLD_PWD_LASTCHNG).Value = "PWD Last Changed" objsheet.Cells(HEADROW, FLD_PWD_DONTEXPIRE).Value = "PWD Don't Expire" objsheet.Cells(HEADROW, FLD_UAC).Value = "UAC" objsheet.Cells(HEADROW, FLD_LASTLOGON).Value = "LastLogonTimestamp" objsheet.Cells(HEADROW, FLD_ADSPATH).Value = "ADSPATH" objRecordSet.MoveFirst Do Until objRecordSet.EOF strPath = objRecordSet.Fields("adspath") 'Change the global catalog path to an ldap path so that we can access 'all the attributes when binding to the object. strPath = Replace(strPath, "GC://", "LDAP://") Set objUser = GetObject(strPath) intUAC = objUser.userAccountControl If (intUAC And ADS_UF_DONT_EXPIRE_PASSWD) = 0 Then PWDexpire = False Else PWDexpire = True End If On Error Resume Next Err.Clear 'Set objLogon = objUser.LastLogonTimestamp Set objLogon = objUser.LastLogon If Err.Number <> 0 Then intLogonTime = 0 Err.Clear Else intLogonTime = objLogon.HighPart * (2 ^ 32) + objLogon.LowPart intLogonTime = intLogonTime / (60 * 10000000) intLogonTime = intLogonTime / 1440 End If strFullName = objUser.FullName If Err.Number <> 0 Then strFullName = "" Err.Clear End If createdate = objUser.whenCreated If Err.Number <> 0 Then createdate = "" Err.Clear End If pwdchanged = objUser.passwordLastChanged If Err.Number <> 0 Then pwdchanged = "" Err.Clear End If On Error GoTo 0 strSamAccountName = objUser.SamAccountName objsheet.Cells(intCounter, FLD_FULLNAME).Value = strFullName objsheet.Cells(intCounter, FLD_SAM_ACCTNAME).Value = strSamAccountName objsheet.Cells(intCounter, FLD_CREATEDATE).Value = createdate objsheet.Cells(intCounter, FLD_PWD_LASTCHNG).Value = pwdchanged objsheet.Cells(intCounter, FLD_PWD_DONTEXPIRE).Value = PWDexpire objsheet.Cells(intCounter, FLD_UAC).Value = intUAC If intLogonTime <> 0 Then objsheet.Cells(intCounter, FLD_LASTLOGON).Value = intLogonTime + #1/1/1601# Else objsheet.Cells(intCounter, FLD_LASTLOGON).Value = "#1/1/1601#" End If objsheet.Cells(intCounter, FLD_ADSPATH).Value = strPath objRecordSet.MoveNext intCounter = intCounter + 1 Loop Set rngData = objsheet.Range("A1:" & Chr(ASCII_OFFSET + FLD_MAX) & intCounter - 1) 'if the named range already exists we need to delete is before we create it again. 'This will allow more than one audit set to be retained in the same workbook. On Error Resume Next ActiveWorkbook.Names("AD_DATA_SET").Delete On Error GoTo 0 rngData.Name = "AD_DATA_SET" rngData.Columns.AutoFit Application.StatusBar = "Ready" End Sub Sub filter_lastlogon() Dim rngData As Excel.Range Set rngData = Range("AD_DATA_SET") rngData.Worksheet.AutoFilterMode = False 'Filter function seems to ignore locale info so dates must be in US format rngData.AutoFilter Field:=FLD_LASTLOGON, Criteria1:="=#1/1/1601#", Operator:=xlOr, _ Criteria2:="<" & Format(Now() - 90, "mm/dd/yyyy") End Sub Sub filter_pwd_dontexpire() Dim rngData As Excel.Range Set rngData = Range("AD_DATA_SET") rngData.Worksheet.AutoFilterMode = False rngData.AutoFilter Field:=FLD_PWD_DONTEXPIRE, Criteria1:="=True" End Sub Sub RemoveFilter() Dim rngData As Excel.Range Set rngData = Range("AD_DATA_SET") rngData.Worksheet.AutoFilterMode = False End Sub Sub CopyPW() 'Copies the filtered data to a new Worksheet 'Code modified from http://www.contextures.com/xlautofilter03.html#Copy 'Viewed 7/6/2007 Dim rngData As Excel.Range Dim rng As Range Dim rng2 As Range Dim objsheet As Worksheet Set rngData = Range("AD_DATA_SET") Call filter_pwd_dontexpire If Not rngData.Worksheet.FilterMode Then MsgBox "Filter Data before selecting this option", vbExclamation Exit Sub End If With rngData.Worksheet.AutoFilter.Range On Error Resume Next Set rng2 = .Offset(1, 0).Resize(.Rows.Count - 1, 1) _ .SpecialCells(xlCellTypeVisible) On Error GoTo 0 End With If rng2 Is Nothing Then MsgBox "No data to copy" Else Set objsheet = Application.ActiveWorkbook.Worksheets.Add() objsheet.Name = Format(Date, "dd-mm-yyyy") & " Password dont expire" Set rng = rngData.Worksheet.AutoFilter.Range rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy _ Destination:=objsheet.Range("A2") objsheet.Cells(HEADROW, FLD_FULLNAME).Value = "Full Name" objsheet.Cells(HEADROW, FLD_SAM_ACCTNAME).Value = "SAM Account name" objsheet.Cells(HEADROW, FLD_CREATEDATE).Value = "Create Date (UTC)" objsheet.Cells(HEADROW, FLD_PWD_LASTCHNG).Value = "PWD Last Changed" objsheet.Cells(HEADROW, FLD_PWD_DONTEXPIRE).Value = "PWD Don't Expire" objsheet.Cells(HEADROW, FLD_UAC).Value = "UAC" objsheet.Cells(HEADROW, FLD_LASTLOGON).Value = "LastLogonTimestamp" objsheet.Cells(HEADROW, FLD_ADSPATH).Value = "ADSPATH" objsheet.Columns.AutoFit End If End Sub Sub CopyLstLogon() 'Copies the filtered data to a new Worksheet 'Code modified from http://www.contextures.com/xlautofilter03.html#Copy 'Viewed 7/6/2007 Dim rngData As Excel.Range Dim rng As Range Dim rng2 As Range Dim objsheet As Worksheet Set rngData = Range("AD_DATA_SET") Call filter_lastlogon If Not rngData.Worksheet.FilterMode Then MsgBox "Filter Data before selecting this option", vbExclamation Exit Sub End If With rngData.Worksheet.AutoFilter.Range On Error Resume Next Set rng2 = .Offset(1, 0).Resize(.Rows.Count - 1, 1) _ .SpecialCells(xlCellTypeVisible) On Error GoTo 0 End With If rng2 Is Nothing Then MsgBox "No data to copy" Else Set objsheet = Application.ActiveWorkbook.Worksheets.Add() objsheet.Name = Format(Date, "dd-mm-yyyy") & " LastLogon > 90 days" Set rng = rngData.Worksheet.AutoFilter.Range rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy _ Destination:=objsheet.Range("A2") objsheet.Cells(HEADROW, FLD_FULLNAME).Value = "Full Name" objsheet.Cells(HEADROW, FLD_SAM_ACCTNAME).Value = "SAM Account name" objsheet.Cells(HEADROW, FLD_CREATEDATE).Value = "Create Date (UTC)" objsheet.Cells(HEADROW, FLD_PWD_LASTCHNG).Value = "PWD Last Changed" objsheet.Cells(HEADROW, FLD_PWD_DONTEXPIRE).Value = "PWD Don't Expire" objsheet.Cells(HEADROW, FLD_UAC).Value = "UAC" objsheet.Cells(HEADROW, FLD_LASTLOGON).Value = "LastLogonTimestamp" objsheet.Cells(HEADROW, FLD_ADSPATH).Value = "ADSPATH" objsheet.Columns.AutoFit End If End Sub
Als Gundlage wurde das Skript von der folgenden Seite eingesetzt:
Link