Netz-Weise Logo

Weisheiten - der Netz-Weise Blog

Hier finden Sie Tipps und Tricks für vor, während und nach der Schulung.

Zwei XML-Dateien mit Powershell vergleichen und einen HTML-Report erzeugen

Das XML-Format ist allgegenwärtig. Als Windows-Administrator stolpert man regelmäßig über Eventlogs im XML-Format, Anweisungsdateien für die unbeaufsichtigte Installation, Vorlagen für Gruppenrichtlinien usw. Und manchmal wäre es ganz schön, wenn man sich den Unterschied zwischen zwei ähnlichen XML-Dateien einfach anzeigen lassen könnte. Mit Powershell und ein bißchen .net ist das in der Tag auch gar kein Problem, denn Microsoft hat vor fast 15 Jahren eine .Net-Bibliothek zur Verfügung gestellt, die genau das tut - das XML Diff & Patch GUI Tool. Das Tool stellt eine Klasse zur Verfügung, über die es möglich ist, zwei XML-Dateien zu vergleichen und die Unterschiede in der XML DIfference Language (Diffgram) auszugeben. Mit einer weiteren Klasse kann man aus einer Diffgram-Datei und einer der beiden Vergleichsdateien eine HTML-Datei erzeugen, die die Unterschiede grafisch darstellt.

Wenn Sie die heruntergeladene Bibliothek entpacken, finden Sie im zwei .dlls, die Sie laden müssen, die XmlDiffPath.dll, die die Compare()-Methode zur Verfügung stellt, und die XmlDiffPath.View.dll, die die Methode GetHtml() bereitstellt. GetHtml erstellt aus einer Diffgram-Datei eine HTML-Datei. Laden Sie die Klassen und erstellen Sie zwei neue Objekte.

Add-Type -Path "xmldiffpatch.dll"
$XmlDiff = New-Object -TypeName Microsoft.XmlDiffPatch.XmlDiff
Add-Type -Path "XmlDiffPatch.View.dll"
$XmlDiffView = New-Object -TypeName Microsoft.XmlDiffPatch.XmlDiffView

Anschließend können Sie die Methode Compare() aufrufen. Compare hat eine Reihe von Überladungen (verschiedene Parameter-Kombinationen). Zum Erstellen eines Diffgramwriters benötigen Sie die beiden zu vergleichenden XML-Dateien, $false und einen .Net-Streamwriter zum Schreiben der Diffgram-Datei:

$DiffGramWriter = [System.Xml.XmlWriter]::Create( 'C:\temp\Diffgram.xml' )
#call Compare method from Microsoft.XmlDiffPatch.XmlDiff object
$XmlDiff.Compare('C:\temp\File1.xml','C:\Temp\File2.xml',$false,$DiffGramWriter)
$DiffGramWriter.Close()

Weiterlesen
Markiert in:
  5860 Aufrufe

USB-Geräte mit Powershell und WMI auslesen

Am USB angeschlossene Geräte kann man per WMI auslesen. WMI stellt dafür die WMI Association Klasse Win32_USBControllerDevice zur Verfügung, die zwei Klassen miteinander verbindet - in diesem Fall die Daten des USB-Controllers und die installierten Treiber. Die verknüpften Treiber kann man aus der Eigenschaft Dependent auslesen.

Get-WmiObject Win32_USBControllerDevice | Foreach-Object { [Wmi]$_.Dependent }

[WMI] Wandelt den String, der in der Eigenschaft $_.Dependent hinerlegt ist, wieder eine WMI-Klasse um. Um einen überschaubaren Überblick über die installierten Geräte zu bekommen, wählt man am Besten erst einmal die Eigenschaften Descritption und DeviceID aus.

Get-WmiObject Win32_USBControllerDevice | ForEach-Object { [wmi]$_.dependent } | select-Object description,deviceid

Das Ergebnis sieht dann ungefähr so aus:

Weiterlesen
  14219 Aufrufe

Den Windows Lizenzkey aus der Firmware aka Bios auslesen und aktivieren per Powershell

Letzte Woche habe ich durch Zufall festgestellt, dass der Rechner einer Kollegin, der schon vor Jahren per automatischem Update auf Windows 10 aktualisiert worden ist, immer noch nicht aktiviert war, obwohl das vorher installierte Windows 8.1 es war und Windows 10 sich außerdem den Key automatisch aus der Firmware ziehen soll, wenn er da hinterlegt ist. Glücklicherweise ist die Aktivierung von Windows 10 immer noch mit den Keys voriger Versionen möglich. Der Key selbst ist im BIOS nicht einsehbar, läßt sich aber über WMI einfach auslesen. Er ist in der Klasse SoftwareLicensingService in der Eigenschaft OA3xOriginalProductKey hinterlegt. Mit Powershell nutzen Sie für das Auslesen einfach Get-WMIObject oder Get-CIMClass:

(Get-WmiObject -Class SoftwareLicensingService).OA3xOriginalProductKey

oder ab Powershell 4 auch

(Get-CimInstance -ClassName SoftwareLicensingService ).OA3xOriginalProductKey

Mit dem Tool slmgr.vbs können Sie die LIzenz auch gleich installieren und aktivieren:

Weiterlesen
  6095 Aufrufe

Für Powershell Cmdlet-Parameter Standardwerte definieren

Das Feature ist nicht neu, aber trotzdem noch mal eine Erinnerung wert. Wenn Sie in einem Skript für einen Parameter immer wieder das gleiche Argument verwenden, können Sie es auch als Standard-Wert hinterlegen. Konkret könnte das z.B. der Domänencontroller sein, der die Einzelbetriebsmasterrolle PDC-Emulator inne hat. Powershell stellt Ihnen dafür die Systemvariable $PSDefaultParameterValues zur Verfügung. Sie wird mit einem Hash-Array befüllt, das für jedes Cmdlet als Schlüsselwert den Cmdlet-Namen und, mit einem ":" getrennt, den Parameternamen enthält, sowie als Wert das Standard-Argument.

$Pdc = Get-ADDomainController -Service PrimaryDC -Discover
$ServerDefaults = @{ "Get-ADUser:Server"=$pdc.HostName
   "Get-ADComputer:Server"=$Pdc.HostName
   "Get-ADObject:Server"=$Pdc.Hostname
 }
$PSDefaultParameterValues = $ServerDefaults
$PSDefaultParameterValues
Get-ADUser -Filter *

Markiert in:
  2411 Aufrufe

Eine Zahlenreihe in zwei alternierende (wechselnde) Gruppen aufteilen mit Powershell

Stellen Sie sich vor, Sie haben eine aufsteigende Reihe natürlicher (ganzer) Zahlen. Sie wollen die Zahlenreihe in 2 Blöcke aufteilen, die nach einer bestimmten Menge von Zahlen jeweils wechselt. Dazu ein Beispiel:

Gruppe 1Gruppe 2
1-500501-1000
1001-1500 1501-2000
2001-25002501-3000

 

 

 

 

Weiterlesen
Markiert in:
  3930 Aufrufe

Computernamen und DNS-Namen einer Maschine mit Powershell ermitteln

Um den Computernamen zu ermitteln, kann man den Kommandozeilenbefehl Hostname verwenden. Es gibt in Powershell aber keine direkte Möglichkeit, den DNS-Namen eines Computers abzufragen. Hier hilft die DNS-Klasse aus dem .Net Framework aus:

Hostname # Zeigt den Netbios-Computernamen an
$ComputerSystem = [System.Net.Dns]::GetHostByName(($env:computerName))

Das zurückgelieferte Objekt hat drei Eigenschaften, Hostname, Aliases und Addresslist

HostName          Aliases AddressList
--------          ------- -----------
DC1.netz-weise.eu {}      {10.1.0.200}

 

Markiert in:
  11705 Aufrufe

Mehrfach-Umbenennen mit Powershell, Rename-Item und regulären Ausdrücken

Eine Datei umzubenennen ist mit Powershell mit Hilfe des Cmdlets Rename-Item relativ einfach möglich. Sie müssen nur den Namen der Datei und den neuen Namen angeben:

Rename-Item -Path C:\temp\Test.txt -NewName Produktion.txt

Es gibt aber auch die Möglichkeit, mehrere Dateien in einem Rutsch umzubenennen. Hierfür können Sie die umzubennenden Dateien per Pipeline an Rename-Item weiterleiten und neuen Namen über einen Skriptblock definieren:

Get-ChildItem -Path C:\Skripte\*.ps1 | Rename-Item -NewName { $_.basename + ".txt"  }

In diesem einfachen Beispiel werden alle Dateien mit der Endung .ps1 im Ordner c:\Skripte in .txt umbenannt - $_ ist ein Platzhalter für die einzelnen Dateien, .basename beinhaltet den Dateinamen ohne Dateiendung.

Weiterlesen
Markiert in:
  20219 Aufrufe

Send-Mailmessage erzeugt keine verwendbaren Fehler - und wie man damit umgeht

Send-Mailmessage ist ein sehr nützliches Cmdlet, um Emails direkt aus Powershell an einen Mailserver zu senden. Er steht seit Powershell 2.0 zur Verfügung und vermeidet so, dass man sich direkt mit dem [System.net.mail]-Typ herumschlagen muß. Allerdings zeigt das Cmdlet ein sehr merkwürdiges Fehlerverhalten.

Wenn man versucht, Verbindungsfehler abzufangen, ist ein erster vernünftiger Ansatz, einfach auf den Parameter -Errorvariable zurückzugreifen:

Send-Mailmessage -SmtpServer mail.meineFirma.de -Subject 'Warnung' -Body 'Hier kommt die Maus' -From 'Elefant@netz-weise.xyz' -to 'Maulwurf@netz-weise.xyz' -ErrorVariable Fehlermeldung
If ( $Fehlermeldung ) { $Fehlermeldung.Exception.Message }

Tritt ein Fehler auf, wird dieser direkt in der Variablen $Fehlermeldung gespeichert. Achtung, bei der Angabe der Fehlervariablen wird kein $-Zeichen angegeben!

Weiterlesen
Markiert in:
  5370 Aufrufe

Sichere Kennwörter in Powershell generieren, jetzt mit dem .NET Framework

In meinem Blogeintrag Zufällige (Komplexe) Kennwörter erzeugen mit Powershell vom 23.04 habe ich gezeigt, wie man komplexe Kennwörter mit Powershell generieren kann, indem man zufällige Zeichen mit Get-Random erzeugt. Aber es geht auch einfacher, denn das .NET-Framework bietet bereits eine fertige statische Methode zum generieren von Kennwörtern, die man in Powershell nur noch laden muß. Die Methode heißt GeneratePassword und befindet sich in der [System.Web]-Assembly. Die Assembly ist in Powershell allerdings nicht standardmäßig geladen. Dies kann man mit dem Cmdlet Add-Type erledigen: 

Add-Type -AssemblyName System.web

Nun können Sie die Methode GeneratePassword aus der Klasse [System.Web.Security.Membership] aufrufen. Der Aufruf erfolgt über [Klasse]::Methodenname(Parameter):

[System.Web.Security.Membership]::GeneratePassword(10,3)

Die beiden Parameter 10 und 3 bestimmen die Anzahl der Zeichen sowie die nicht-Alphanumerischen Zeichen, die das Kennwort enthalten muß. 

Weiterlesen
Markiert in:
  5107 Aufrufe

Inaktive Benutzer oder Computer mit Powershell finden und deaktivieren

Das Cmdlet Search-ADAccount ist das Schweizer Messer des AD-Administrators. Es zeigt gesperrte Konten genauso an wie deaktiviert Konten, ablaufende Konten und Konten, deren Kennwort niemals abläuft. Der vielleicht hilfreichste Parameter ist aber -AccountInactive, der Konten anzeigt, die sich schon lange nicht mehr in der Domäne angemeldet haben. Grundsätzlich kann man dieses auch mit Get-ADUser und Get-ADComputer lösen, aber das ist aufwändiger und außerdem muß man auch darauf achten, welches AD-Attribut man auswertet, denn es gibt mehrere Eigenschaften, die die letzte Anmeldung speichern, aber nicht alle sind gleich gut geeignet. Eine gute Auflistung der Attribute und deren Unterschiede finden Sie im Technet-Wiki

Um inaktive Konten anzuzeigen, nutzen Sie einfach

Search-ADAccount -AccountInactive

Der Parameter findet sowohl Benutzer- als auch Computerkonten, die sich seit 60 Tagen nicht mehr angemeldet haben. Wenn Sie nur Benutzer suchen, verwenden Sie den Parameter -Usersonly, wenn Sie die Zeitspanne angeben wollen, benutzen Sie den Parameter Timespan, gefolgt von den Tagen seit dem letzten Login:

Search-ADAccount -AccountInactive -TimeSpan 90 -UsersOnly

Weiterlesen
  15254 Aufrufe