und sich beispielsweise darüber beklagt, dass der Verwaltungsdienst für Virtuelle Computer nicht laufe, obwohl die bereits installierten Gastmaschinen hervorragend funktionieren, dann kann es helfen, aus einer als Administrator gestarteten Eingabeaufforderung heraus den folgenden Befehl aufzurufen:
mofcomp %SYSTEMROOT%\System32\WindowsVirtualization.V2.mof
Hierdurch werden die zu Hyper-V WMI-Klassen neu registriert und ganz ohne jeden Neustart funktionierte jedenfalls auf einem betroffenen Gerät alles wieder, wie es sollte.
Gerüchteweise bringt eine Installation von HP-Verwaltungswerkzeugen (in einer ausgewählten Version?) dieses Ungemach mit sich.
Montag, 24. April 2017
Windows 10: Windows Explorer standardmäßig auf Dieser PC öffnen
Der Schnellzugriff im Windows Explorer ist manchmal gar nicht so schnell. Viele, die noch mit Laufwerksbuchstaben arbeiten, finden ihn sogar ziemlich langsam, da es mehrerer Klicks bedarf, um auf die Laufwerke zugreifen zu können.
Um den Explorer auf den aktuellen PC zu justieren, kann folgendermaßen vorgegangen werden:
Öffnen Sie den Windows Explorer.
Klicken Sie auf das Menü Ansicht und dort ganz rechts auf Optionen.
Wählen Sie Ordner- und Suchoptionen ändern.
Auf der bereits offenen Registerkarte Allgemein wählen Sie bei Dateiexplorer öffnen für den Eintrag Dieser PC und bestätigen die Änderung mit OK.
Um den Explorer auf den aktuellen PC zu justieren, kann folgendermaßen vorgegangen werden:
Öffnen Sie den Windows Explorer.
Klicken Sie auf das Menü Ansicht und dort ganz rechts auf Optionen.
Wählen Sie Ordner- und Suchoptionen ändern.
Auf der bereits offenen Registerkarte Allgemein wählen Sie bei Dateiexplorer öffnen für den Eintrag Dieser PC und bestätigen die Änderung mit OK.
Donnerstag, 27. Oktober 2016
Windows: Datenträger sicher löschen
Will man eine einzelne Festplatte veräußern, ist die Sache recht einfach:
Mit diskpart lässt sich eine Festplatte, die nicht gerade das aktive Betriebssystem beherbergt und auf der auch sonst keine Dateien offengehalten werden, löschen und komplett überschreiben:
Aufrufen einer Eingabeaufforderung (per Rechtsklick als Administrator)
Eingabe der folgenden Befehle:
diskpart
list disk (zeigt die erkannten Festplatten mit Nummern an, merken Sie sich hier die Nummer der zu löschenden Festplatte)
select disk x (ersetzen Sie x mit der Nummer)
clean all
Der letzte Befehl wird still ausgeführt, entfernt alle Volumen von einem Laufwerk und überschreibt die Sektoren des Datenträgers. Dieser Vorgang dauert je nach Größe und Schnelligkeit des Datenträgers durchaus mehrere Stunden.
Danach lässt sich mittels
create partition primary
format fs=ntfs quick
noch schnell ein neues leeres Volumen anlegen
und mit
assign letter=Z
bei Bedarf ein noch nicht verwendeter Laufwerksbuchstabe zuweisen, im Beispielbefehl Z:.
Geht es darum, die Überreste gelöschter Dateien in einem noch genutzten Volumen zu vernichten, lässt sich das mit dem Befehl cipher bewerkstelligen:
Aufrufen einer Eingabeaufforderung (per Rechtsklick als Administrator)
Eingabe des folgenden Befehls:
cipher /W:C:\
Dieser Befehl überschreibt alle nicht von aktuellen Dateien genutzten Bereiche des Volumens C: mehrfach durch Erzeugen temporärer Dateien mit wechselnden Inhalten, die den leeren Plattenplatz füllen. Vorsicht ist geboten bei Anwendung des Befehls auf SSDs, da ein komplettes Vollschreiben bei einigen Modellen zu nachhaltigen Performanceeinbrüchen führen kann, zudem ist nicht immer garantiert, dass alle Sektoren überschrieben werden können. Hier empfiehlt es sich, auf der Website des Herstellers nach Hinweisen und Werkzeugen für Secure Erase Ausschau zu halten.
Mit diskpart lässt sich eine Festplatte, die nicht gerade das aktive Betriebssystem beherbergt und auf der auch sonst keine Dateien offengehalten werden, löschen und komplett überschreiben:
Aufrufen einer Eingabeaufforderung (per Rechtsklick als Administrator)
Eingabe der folgenden Befehle:
diskpart
list disk (zeigt die erkannten Festplatten mit Nummern an, merken Sie sich hier die Nummer der zu löschenden Festplatte)
select disk x (ersetzen Sie x mit der Nummer)
clean all
Der letzte Befehl wird still ausgeführt, entfernt alle Volumen von einem Laufwerk und überschreibt die Sektoren des Datenträgers. Dieser Vorgang dauert je nach Größe und Schnelligkeit des Datenträgers durchaus mehrere Stunden.
Danach lässt sich mittels
create partition primary
format fs=ntfs quick
noch schnell ein neues leeres Volumen anlegen
und mit
assign letter=Z
bei Bedarf ein noch nicht verwendeter Laufwerksbuchstabe zuweisen, im Beispielbefehl Z:.
Geht es darum, die Überreste gelöschter Dateien in einem noch genutzten Volumen zu vernichten, lässt sich das mit dem Befehl cipher bewerkstelligen:
Aufrufen einer Eingabeaufforderung (per Rechtsklick als Administrator)
Eingabe des folgenden Befehls:
cipher /W:C:\
Dieser Befehl überschreibt alle nicht von aktuellen Dateien genutzten Bereiche des Volumens C: mehrfach durch Erzeugen temporärer Dateien mit wechselnden Inhalten, die den leeren Plattenplatz füllen. Vorsicht ist geboten bei Anwendung des Befehls auf SSDs, da ein komplettes Vollschreiben bei einigen Modellen zu nachhaltigen Performanceeinbrüchen führen kann, zudem ist nicht immer garantiert, dass alle Sektoren überschrieben werden können. Hier empfiehlt es sich, auf der Website des Herstellers nach Hinweisen und Werkzeugen für Secure Erase Ausschau zu halten.
Dienstag, 25. Oktober 2016
Windows 10: Connected Standby deaktivieren
Gelegentlich kommt es vor, dass schlummernde Notebooks in diesem Zustand binnen verhältnismäßig kurzer Zeit den Akku leeren, obwohl sie das eigentlich nicht tun sollten. Werden sie dann plötzlich gebraucht, gibt es ein böses Erwachen - des Nutzers.
Um einen Grund für dieses Verhalten zu unterbinden, kann man mittels eines Wertes in der Registrierung das Connected Standby ausschalten, welches neueren Apps ermöglicht, in Intervallen über das Netz Statusupdates einzuholen.
Starten Sie den Registrierungseditor (regedit.exe).
Navigieren Sie zum Schlüssel HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power.
Doppelklicken Sie den Wert CsEnabled, ändern diesen auf 0 und bestätigen Sie die Änderung durch Klick auf OK.
Nach einem Neustart ist Connected Standby dann deaktiviert.
Um einen Grund für dieses Verhalten zu unterbinden, kann man mittels eines Wertes in der Registrierung das Connected Standby ausschalten, welches neueren Apps ermöglicht, in Intervallen über das Netz Statusupdates einzuholen.
Starten Sie den Registrierungseditor (regedit.exe).
Navigieren Sie zum Schlüssel HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power.
Doppelklicken Sie den Wert CsEnabled, ändern diesen auf 0 und bestätigen Sie die Änderung durch Klick auf OK.
Nach einem Neustart ist Connected Standby dann deaktiviert.
PowerShell: Mitglieder einer Gruppe im Active Directory auflisten
Gelegentlich möchte man sich schnell einen Überblick verschaffen, wer Mitglied einer bestimmten Gruppe der Domäne ist.
Eigentlich sollte sich das ja über die Konsole Active Directory-Benutzer und -Computer schnell lösen lassen.
Problematisch wird dies, wenn die Namen der Benutzerkonten nicht direkt auf den Namen des Anwenders schließen lassen, der im Anzeigenamen hinterlegt ist. Der Anzeigename lässt sich auch nicht in das Dialogfenster integrieren. Ein weiterer Nachteil ist, dass man aus der grafischen Oberfläche heraus keine Liste für die Weiterverarbeitung generieren kann.
Hier hilft PowerShell wieder einmal weiter.
In neueren Versionen des Windows Servers wird das Modul ActiveDirectory automatisch importiert, wenn Befehle daraus aufgerufen werden, ansonsten muss das manuell durchgeführt werden mit dem Befehl
Import-Module ActiveDirectory
Um beispielsweise alle Domänenadministratoren anzuzeigen, genügt der folgende Befehl:
Get-ADGroupMember “Domänen-Admins” | Get-ADUser -Properties DisplayName | Select Name, Displayname
Mittels Get-ADGroupMember werden die Mitglieder erfragt. Das Ergebnis wird an Get-ADUser weitergereicht, um von hier den Anzeigenamen (DisplayName) zu erhalten und schließlich werden nur der Name und der Anzeigename der Benutzer aufgelistet. Weitere Eigenschaften können je nach Bedarf und Strukturierung des eigenen AD abgefragt werden.
Um das Ergebnis direkt in eine CSV-Datei zu exportieren, hängen wir noch
| Export-CSV -Path "C:\Logs\adgruppe.csv"
an obigen Befehl an. Hierfür ist zu berücksichtigen, dass das Zielverzeichnis bereits existieren muss.
Der vollständige Befehl für dieses Beispiel lautet somit:
Get-ADGroupMember “Domänen-Admins” | Get-ADUser -Properties DisplayName | Select Name, Displayname | Export-CSV "C:\Logs\adgroup.csv"
Eigentlich sollte sich das ja über die Konsole Active Directory-Benutzer und -Computer schnell lösen lassen.
Problematisch wird dies, wenn die Namen der Benutzerkonten nicht direkt auf den Namen des Anwenders schließen lassen, der im Anzeigenamen hinterlegt ist. Der Anzeigename lässt sich auch nicht in das Dialogfenster integrieren. Ein weiterer Nachteil ist, dass man aus der grafischen Oberfläche heraus keine Liste für die Weiterverarbeitung generieren kann.
Hier hilft PowerShell wieder einmal weiter.
In neueren Versionen des Windows Servers wird das Modul ActiveDirectory automatisch importiert, wenn Befehle daraus aufgerufen werden, ansonsten muss das manuell durchgeführt werden mit dem Befehl
Import-Module ActiveDirectory
Um beispielsweise alle Domänenadministratoren anzuzeigen, genügt der folgende Befehl:
Get-ADGroupMember “Domänen-Admins” | Get-ADUser -Properties DisplayName | Select Name, Displayname
Mittels Get-ADGroupMember werden die Mitglieder erfragt. Das Ergebnis wird an Get-ADUser weitergereicht, um von hier den Anzeigenamen (DisplayName) zu erhalten und schließlich werden nur der Name und der Anzeigename der Benutzer aufgelistet. Weitere Eigenschaften können je nach Bedarf und Strukturierung des eigenen AD abgefragt werden.
Um das Ergebnis direkt in eine CSV-Datei zu exportieren, hängen wir noch
| Export-CSV -Path "C:\Logs\adgruppe.csv"
an obigen Befehl an. Hierfür ist zu berücksichtigen, dass das Zielverzeichnis bereits existieren muss.
Der vollständige Befehl für dieses Beispiel lautet somit:
Get-ADGroupMember “Domänen-Admins” | Get-ADUser -Properties DisplayName | Select Name, Displayname | Export-CSV "C:\Logs\adgroup.csv"
Samstag, 8. Oktober 2016
Windows Server: WSUS-Wartung automatisieren
Bei den Windows Server Update Services fallen oft Datenmengen an, welche die Konsole zu irgend einem Zeitpunkt unbenutzbar machen. Eine manuelle Wartung über die Konsole steigt oftmals mit einer Zeitüberschreitung aus und muss viele Male wiederholt werden, bis sie schließlich erfolgreich durchläuft.
Folgendes PowerShell-Skript, über die Aufgabenplanung mit einem administrativen Konto und ggf. erhöhten Rechten allnächtlich ausgeführt, ermöglicht die Automatisierung der Aufräumvorgänge und sorgt dafür, dass uns die Timeouts in der WSUS-Konsole künftig verschonen.
#Skript: WSUS aufräumen
#Ausgabe der Ergebnisse in $outFilePath, falls die angegebene Datei trotz ausreichender Berechtigung
#nicht erzeugt/aktualisiert wird, ist in der Regel der Vorgang wie auch in der Konsole ausgestiegen
$outFilePath = '.\wsusClean.txt'
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(“localhost”,$false,8530);
$cleanupScope = new-object Microsoft.UpdateServices.Administration.CleanupScope;
$cleanupScope.DeclineSupersededUpdates = $true
$cleanupScope.DeclineExpiredUpdates = $true
$cleanupScope.CleanupObsoleteUpdates = $true
$cleanupScope.CompressUpdates = $true
$cleanupScope.CleanupObsoleteComputers = $true
$cleanupScope.CleanupUnneededContentFiles = $true
$cleanupManager = $wsus.GetCleanupManager();
$cleanupManager.PerformCleanup($cleanupScope) | Out-File -FilePath $outFilePath
Folgendes PowerShell-Skript, über die Aufgabenplanung mit einem administrativen Konto und ggf. erhöhten Rechten allnächtlich ausgeführt, ermöglicht die Automatisierung der Aufräumvorgänge und sorgt dafür, dass uns die Timeouts in der WSUS-Konsole künftig verschonen.
#Skript: WSUS aufräumen
#Ausgabe der Ergebnisse in $outFilePath, falls die angegebene Datei trotz ausreichender Berechtigung
#nicht erzeugt/aktualisiert wird, ist in der Regel der Vorgang wie auch in der Konsole ausgestiegen
$outFilePath = '.\wsusClean.txt'
[reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer(“localhost”,$false,8530);
$cleanupScope = new-object Microsoft.UpdateServices.Administration.CleanupScope;
$cleanupScope.DeclineSupersededUpdates = $true
$cleanupScope.DeclineExpiredUpdates = $true
$cleanupScope.CleanupObsoleteUpdates = $true
$cleanupScope.CompressUpdates = $true
$cleanupScope.CleanupObsoleteComputers = $true
$cleanupScope.CleanupUnneededContentFiles = $true
$cleanupManager = $wsus.GetCleanupManager();
$cleanupManager.PerformCleanup($cleanupScope) | Out-File -FilePath $outFilePath
Donnerstag, 6. Oktober 2016
PowerShell / Active Directory / SharePoint: Erzeugen einer Telefonliste aus dem AD
Ziel dieses Skripts ist es, die Telefonnummern bestimmter Benutzer im AD einzulesen und diese nach Büro und Abteilung des Benutzers sortiert als einfache tabellarisch aufgebaute HTML-Datei im SharePoint abzulegen. Das Skript wird als geplanter Vorgang täglich ausgeführt, um die Telefonliste aktuell zu halten.
#Festlegen der in die Liste aufzunehmenden Büros (Feld "Office" im Active Directory englische Version)
$offices = @("Hamburg","Berlin","München","Frankfurt")
#Auflisten der Büros, die nur über eine einzige Benutzergruppe (=Abteilung) verfügen, um bei diesen keine Zwischenüberschrift zu erzeugen
$singlegroup = @("","MUC","FRA","BER")
#Erzeugen einer Liste und Ablage in Variable $list
$list = @{Expression={[string]$_.DisplayName};Label="Name";width=45}, `
@{Expression={[string]$_.telephoneNumber};Label="Durchwahl";width=25}
$Date = Get-Date -Format dd.MM.yyyy
#Formatieren der Html-Seite
$head = @'
Telefonverzeichnis der Mitarbeiter in Deutschland
'@
#Einfügen der Überschriften und des Aktualisierungsdatums in die Html-Datei
ConvertTo-HTML -head $head -body "" | out-file D:\Script\telefonliste.html Telefonverzeichnis der Mitarbeiter in Deutschland
´
Zuletzt aktualisiert: $Date
foreach ( $office in $offices ) {
ConvertTo-HTML -head $head -body "$Office
" | out-file D:\Script\telefonliste.html -append
switch ($office)
{
"Hamburg" {$groups = 'Verwaltung','Verkauf','IT'}
"Berlin" {$groups = 'Verkauf_BER'}
"München" {$groups = 'Verkauf_MUC'}
"Frankfurt" {$groups = 'Verkauf_FRA'}
}
foreach ( $group in $groups )
{
#Gruppenüberschrift nur für Büros mit mehreren Gruppen
if ( $group -notin $singlegroup ) {
ConvertTo-HTML -head $head -body "$Group
" | out-file D:\Script\telefonliste.html -append
}
#Auslesen der Anwenderdaten aus dem AD
get-aduser -Filter 'enabled -eq $true' -Properties displayname,department,telephonenumber,office -SearchBase 'DC=europe,DC=contoso,DC=com' | select-object displayname,department,telephonenumber,office | where { ( $.telephoneNumber.length -gt 0 ) -AND ($.Office -eq $office ) -AND ($.Department -eq $group ) } | select-object @{Name="Name";Expression={$.DisplayName}}, @{Name="Durchwahl";Expression={$_.telephoneNumber}} | sort Name | convertto-html -Fragment | out-file D:\Script\telefonliste.html -Append
}
}
#Auf SharePoint hochladen
$wc = new-object System.Net.WebClient
$wc.Credentials = [System.Net.CredentialCache]::DefaultCredentials
function getdestname($filename){ "http://meinsharepoint/InformationResources/" + $(split-path -leaf $filename)}
dir "d:\script\telefonliste.html" | % { $uploadname=getdestname $; $wc.UploadFile($uploadname,"PUT", $.FullName) }
add-content d:\script\telefonliste.log "Telefonliste aktualisiert am $date"
#Nachkontrolle bei manueller Ausführung ohne Kommentarzeichen
#invoke-item D:\Script\telefonliste.html
#write-host "Telefonliste aktualisiert."
Samstag, 1. Oktober 2016
PowerShell / Excel: PC Hardware inventarisieren: 8. CSV-Datei öffnen und als Tabelle formatieren
So eine CSV-Datei ist hilfreich, wenn man sie beispielsweise als Tabelle in Access verlinken oder in Excel importieren kann. Für einen schnellen Blick braucht es aber nicht immer die ausgewachsene Datenbank, sondern mit den aktuellen Logdateien lässt sich recht zügig die gewünschte Ansicht erstellen. Da eine CSV-Datei kein natives Excel-Format ist und damit das Verknüpfen mit Makros beim Öffnen etwas problematischer wird, kann uns an dieser Stelle die PowerShell bei einer ordentlich strukturierten CSV-Tabelle zu Hilfe kommen.
#Festlegen der Quelldatei
$targetfile = "T:\Asset_DB\computers.csv"
#Mit Excel öffnen
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$ExcelWorkBook = $Excel.Workbooks.Open($targetfile)
#Benennen des Arbeitsblattes und automatische Anpassung der Spaltenbreite
$ExcelWorkSheet = $Excel.WorkSheets.item("Computer")
$ExcelWorkSheet.UsedRange.Columns.Autofit() | Out-Null
#Benennen des Tabellenbereichs als "Tabellendaten", um beispielsweise in Formeln den Bereich zu adressieren und Formatieren als Tabelle (für Filter- und Sortierfunktionen)
$ListObject = $Excel.ActiveSheet.ListObjects.Add([Microsoft.Office.Interop.Excel.XlListObjectSourceType]::xlSrcRange, $Excel.ActiveCell.CurrentRegion, $null ,[Microsoft.Office.Interop.Excel.XlYesNoGuess]::xlYes)
$ListObject.Name = "Tabellendaten"
$ListObject.TableStyle = "TableStyleMedium9"
#Festlegen der Quelldatei
$targetfile = "T:\Asset_DB\computers.csv"
#Mit Excel öffnen
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$ExcelWorkBook = $Excel.Workbooks.Open($targetfile)
#Benennen des Arbeitsblattes und automatische Anpassung der Spaltenbreite
$ExcelWorkSheet = $Excel.WorkSheets.item("Computer")
$ExcelWorkSheet.UsedRange.Columns.Autofit() | Out-Null
#Benennen des Tabellenbereichs als "Tabellendaten", um beispielsweise in Formeln den Bereich zu adressieren und Formatieren als Tabelle (für Filter- und Sortierfunktionen)
$ListObject = $Excel.ActiveSheet.ListObjects.Add([Microsoft.Office.Interop.Excel.XlListObjectSourceType]::xlSrcRange, $Excel.ActiveCell.CurrentRegion, $null ,[Microsoft.Office.Interop.Excel.XlYesNoGuess]::xlYes)
$ListObject.Name = "Tabellendaten"
$ListObject.TableStyle = "TableStyleMedium9"
Donnerstag, 29. September 2016
PowerShell: PC-Hardware inventarisieren: 7. Dateien zusammenziehen
Das Skript von Teil 6 gibt separate Dateien für jeden PC und für die Monitore vom Typ CSV aus. Diese Textdateien beinhalten genau eine Zeile.
Für den PC beispielsweise EURITX.csv mit folgendem Inhalt:
EURITX HP Compaq 8000 Elite SFF PC CZC01234567 Intel Core2 Quad CPU Q8400 @ 2.66GHz 2.67 GHz 8196 256 Microsoft Windows 10 Enterprise 172.22.3.111 OU=WIN10Pilot,OU=TEST,OU=DE,DC=europe,DC=hanjin,DC=com 04912345 (Engelke, Olaf) IT 09-28-2016 17:04 Inventory Script 1 176.31
Im Zielverzeichnis für die Logdateien befinden sich zahlreiche dieser Dateien, die so noch nicht besonders gut lesbar sind. Damit wir besser damit umgehen können und eine einfache Verarbeitung mit Access oder Excel möglich wird, ziehen wir diese Dateien mit folgendem PowerShell-Skript zusammen:
#Erzeugt eine einzelne Logdatei aus den durch das Asset WMI-Skript generierten Dateien, getrennt für PC und Monitore unter T:\Asset\logfile.csv and monitors.csv
#Archiviert erfasste Einzeldateien durch Verschieben
$ErrorActionPreference = 'SilentlyContinue'
#Festlegen der Pfade
$pcsource = "\\server\assetLog$\Computer*.csv"
$pclog = "t:\asset_db\logfile.csv"
$dspsource = "\\server\assetLog$\Monitor*.csv"
$dsplog = "t:\asset_db\monitors.csv"
$pcarchive = "\\server\assetlog$\oldlog\computer\"
$dsparchive = "\\server\assetlog$\oldlog\monitor\"
#Löschen der alten Logdateien
del $pclog
del $dsplog
#Überschriftszeile generieren
$pcinfo="SystemName"+"`t"+"ModelName"+"`t"+"SerialNbr"+"`t"+"Property1"+"`t"+"Property2"+"`t"+"Property3"+"`t"+"Property4"+"`t"+"Property5"+"`t"+"Property6"+"`t"+"SystemADOU"+"`t"+"LastUser"+"`t"+"Team"+"`t"+"LastModified"+"`t"+"LastModifiedBy"+"`t"+"StatusID"
#Überschrift in neue Gesamtlogdatei übertragen und die Inhalte der Dateien an diese anhängen
write-output $pcinfo | format-table | out-file $pclog
cat $pcsource >> $pclog
#Verschieben der alten Einzellogs für Computer
move-item $pcsource $pcarchive -force
#Wiederholung für Monitore, gefiltert für die Hersteller der Monitore, um virtuelle und sonstige Displays auszuklammern sowie Entfernen störender Inhalte
$dspinfo="ModelName"+"`t"+"SerialNbr"+"`t"+"PCSerial"+"`t"+"LastModified"+"`t"+"LastModifiedBy"+"`t"+"StatusID"
write-output $dspinfo | format-table | out-file $dsplog
cat $dspsource | select-string -pattern "Dell","HP" | foreach-object {$_ -replace "`0",""} >> $dsplog
#Verschieben der alten Einzellogs für Displays
move-item $dspsource $dsparchive -force
Im Ergebnis erhalten wir zwei CSV-Dateien, in denen die wichtigsten Daten aller geloggten PCs und Monitore tabellarisch abgelegt sind.
Für den PC beispielsweise EURITX.csv mit folgendem Inhalt:
EURITX HP Compaq 8000 Elite SFF PC CZC01234567 Intel Core2 Quad CPU Q8400 @ 2.66GHz 2.67 GHz 8196 256 Microsoft Windows 10 Enterprise 172.22.3.111 OU=WIN10Pilot,OU=TEST,OU=DE,DC=europe,DC=hanjin,DC=com 04912345 (Engelke, Olaf) IT 09-28-2016 17:04 Inventory Script 1 176.31
Im Zielverzeichnis für die Logdateien befinden sich zahlreiche dieser Dateien, die so noch nicht besonders gut lesbar sind. Damit wir besser damit umgehen können und eine einfache Verarbeitung mit Access oder Excel möglich wird, ziehen wir diese Dateien mit folgendem PowerShell-Skript zusammen:
#Erzeugt eine einzelne Logdatei aus den durch das Asset WMI-Skript generierten Dateien, getrennt für PC und Monitore unter T:\Asset\logfile.csv and monitors.csv
#Archiviert erfasste Einzeldateien durch Verschieben
$ErrorActionPreference = 'SilentlyContinue'
#Festlegen der Pfade
$pcsource = "\\server\assetLog$\Computer*.csv"
$pclog = "t:\asset_db\logfile.csv"
$dspsource = "\\server\assetLog$\Monitor*.csv"
$dsplog = "t:\asset_db\monitors.csv"
$pcarchive = "\\server\assetlog$\oldlog\computer\"
$dsparchive = "\\server\assetlog$\oldlog\monitor\"
#Löschen der alten Logdateien
del $pclog
del $dsplog
#Überschriftszeile generieren
$pcinfo="SystemName"+"`t"+"ModelName"+"`t"+"SerialNbr"+"`t"+"Property1"+"`t"+"Property2"+"`t"+"Property3"+"`t"+"Property4"+"`t"+"Property5"+"`t"+"Property6"+"`t"+"SystemADOU"+"`t"+"LastUser"+"`t"+"Team"+"`t"+"LastModified"+"`t"+"LastModifiedBy"+"`t"+"StatusID"
#Überschrift in neue Gesamtlogdatei übertragen und die Inhalte der Dateien an diese anhängen
write-output $pcinfo | format-table | out-file $pclog
cat $pcsource >> $pclog
#Verschieben der alten Einzellogs für Computer
move-item $pcsource $pcarchive -force
#Wiederholung für Monitore, gefiltert für die Hersteller der Monitore, um virtuelle und sonstige Displays auszuklammern sowie Entfernen störender Inhalte
$dspinfo="ModelName"+"`t"+"SerialNbr"+"`t"+"PCSerial"+"`t"+"LastModified"+"`t"+"LastModifiedBy"+"`t"+"StatusID"
write-output $dspinfo | format-table | out-file $dsplog
cat $dspsource | select-string -pattern "Dell","HP" | foreach-object {$_ -replace "`0",""} >> $dsplog
#Verschieben der alten Einzellogs für Displays
move-item $dspsource $dsparchive -force
Im Ergebnis erhalten wir zwei CSV-Dateien, in denen die wichtigsten Daten aller geloggten PCs und Monitore tabellarisch abgelegt sind.
Samstag, 24. September 2016
PowerShell: PC-Hardware inventarisieren: 6. Skript und Hinweise
An dieser Stelle das vollständige Skript, wie es sich im Einsatz bewährt hat. Nicht alle Befehlssequenzen und Abläufe mögen optimal sein, da dieses historisch gewachsen ist, mit der einen oder anderen Anleihe aus Fundstellen im Internet.
Dieses Skript wird beim Herunterfahren des Rechners über entsprechende Gruppenrichtlinien im Active Directory ausgeführt.
Falls das Skript unter Windows 10 beim Herunterfahren nicht ausgeführt wird, muss der Schnellstart deaktiviert werden.
Auf die Freigabe für die Logdateien brauchen die Domänenrechner Schreibzugriff, ebenso jener Anwender, der die Auswertung ggf. manuell im weiteren Verlauf vornimmt. PowerShell-Scripting auf den PCs muss aktiviert sein, ggf. sollte das Skript nach Anpassung an die eigene Umgebung signiert werden.
Variablen und Einträge, die angepasst werden müssen:
$strRelevantGroups - sollte die jeweilige primäre Gruppe der Benutzer beinhalten, um die logischen PC-Zuweisungen auswerten zu können
$logfile - muss auf eine beschreibbare Freigabe verweisen
Der Name der Datei wird mittels des Computernamens gebildet (und selbige überschrieben), das Dateidatum hilft dabei, den letzten erfolgreichen Vorgang direkt im Dateisystem zu erkennen.
#PC-Information sammeln
Function Get-FreeDiskSpace($drive)
{
$driveData = Get-WmiObject -class win32_LogicalDisk -filter "Name = '$drive'"
"{0:n2}" -f ($driveData.FreeSpace/1GB)# + " GB"
}
$ErrorActionPreference = 'SilentlyContinue'
$strCompName = ($env:Computername)
$CompNameLength = ($env:Computername).length
$logfile = "\\server\assetLog$\Computer\$strCompName.csv"
#Benutzerinfos des letzten angemeldeten Benutzers ermitteln und Variablen zuweisen
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.SearchScope = "Subtree"
$objSearcher.Filter = "(&(objectClass=computer)(cn=$strCompName))"
$system = $objSearcher.FindOne()
$dn = $system.properties["distinguishedname"]
$dn = $dn[0].toString()
$ou = $dn.substring(4+$CompNameLength)
$lastuser = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI).LastLoggedOnSAMUser
$lastuser = $lastuser.split("\")
$lastuser = $lastuser[1]
$objSearcher.Filter = "(&(objectClass=user)(cn=$lastuser))"
$userinfo = $objSearcher.FindOne()
$userdn = [adsi]$userinfo.path
$username = $userdn.displayname
$lastuser = $lastuser + " (" + $username + ")"
$strRelevantGroups = "Domain Users" #durch kommaseparierte reale Benutzergruppen ersetzen!
$groups = $userdn.memberof
$strGroups = ""
foreach($group in $groups)
{
$strGroup = $group.split(',')[0]
$strGroup = $strGroup.split('=')[1]
if($strRelevantGroups.contains($strGroup))
{
$strGroups = $strGroups + "," + $strGroup
}
}
if($strGroups.Length -gt 0){
$strGroups = $strGroups.split(",")
$team = [string]$strGroups[1]
} else {
$team = "N/A"
}
#Seriennummer des PCs auslesen
$computer = gwmi win32_computersystem
$bios = gwmi win32_bios
$os = (gwmi win32_operatingsystem).caption
$serial = $bios.serialnumber
#Prozessoren ermitteln
$colCPUs = gwmi win32_processor
$n = 0
foreach ($cpu in $colCPUs)
{
$n = $n + 1
$processor = ((($cpu.name -replace ' {2,}',' ') -replace "\(TM\)") -replace '\(R\)')
}
$cpuspeed = "{0:0.00 GHz}" -f($cpu.maxclockspeed/1000)
#Größe des physischen Arbeitsspeichers ermitteln
$totalmem = 0
$memsticks = gwmi -Class win32_physicalmemory
foreach ($stick in $memsticks) { $totalmem += $stick.capacity }
$physmem = ([int] ($($totalmem) / 1MB))
#Größe der Datenträger ermitteln
$disk = gwmi win32_diskdrive -filter "InterfaceType <> 'USB'"
$disksize=""
foreach ($objitem in $disk) {$disksize=$disksize+";"+[Convert]::ToString(([int]($objitem.size/1000000000)))}
$disksize = $disksize.substring(1)
$diskfree = ""
$diskfree = Get-FreeDiskSpace -drive "C:"
#Ermitteln der IP-Adresse(n)
# new (Test): $ip = Get-WmiObject Win32_NetworkAdapterConfiguration -filter 'IPEnabled="True"' | Select -expand IPAddress | ?{$_ -notmatch ':'}
$lan = get-wmiobject win32_networkadapterconfiguration -filter "ipenabled=true"
$lancount = get-wmiobject win32_networkadapterconfiguration -filter "ipenabled=true"
$ip=""
foreach($lan in $lancount){$ip = $ip + ";" + [string]($lan.ipaddress[0])}
$ip = $ip.substring(1)
#Erzeugen der Logdatei mit Zeitstempel im Logeintrag
$timestamp = get-date -format "M/d/yyyy HH:mm"
#Testausgabe am Bildschirm
#write-host $computer.name $computer.model $serial $processor $cpuspeed $physmem $disksize $os $ip $ou $lastuser $team $timestamp $diskfree -separator ";"
#Zusammenfassung für CSV-tauglichen String, separiert mit Tabulatoren
$allinfo=[string]$computer.name+"`t"+[string]$computer.model+"`t"+[string]$serial+"`t"+[string]$processor+"`t"+[string]$cpuspeed+"`t"+[string]$physmem+"`t"+[string]$disksize+"`t"+[string]$os+"`t"+[string]$ip+"`t"+[string]$ou+"`t"+[string]$lastuser+"`t"+$team+"`t"+[string]$timestamp+"`t Inventory Script`t1"+"`t"+[string]$diskfree
#Ausgabe in Logdatei
write-output $allinfo | format-table | out-file $logfile -encoding ASCII
#Informationen zu angeschlossenen Monitoren sammeln (ab Windows 7/2008R2)
try {
$ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID
}
catch {
break
$computer.name
}
$monitorInfo = @()
$pcserial = $serial
$i = 1
foreach ($monitor in $ActiveMonitors)
{
$mon = New-Object PSObject
$manufacturer = $null
$dspserial = $null
$name = $null
$week = $null
$year = $null
$monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
$monitor.SerialNumberID | foreach {$dspserial += [char]$_}
$monitor.UserFriendlyName | foreach {$name += [char]$_}
$mon | Add-Member NoteProperty Manufacturer $manufacturer
$mon | Add-Member NoteProperty PCSerial $serial
$mon | Add-Member NoteProperty SerialNumber $dspserial
$mon | Add-Member NoteProperty Name $name
$mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
$mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
$mon.SerialNumber = $dspserial.trim()
$monitorInfo += $mon
#Erzeugen eines Strings für Datei, Name wird aus DSP und Computername erzeugt, um die relevante Datei schnell im Dateisystem zu finden
$displayinfo = [string]$name+"`t"+[string]$dspserial+"`t"+$pcserial+"`t"+[string]$timestamp+"`t Inventory Script`t1"
$dsplogfile = "DSP" + $i + "_" + $computer.name
$dsplogfile = "\\server\assetLog$\Monitor\$dsplogfile.csv"
$i++
$displayinfo | format-table | out-file $dsplogfile -encoding ASCII
}
Dieses Skript wird beim Herunterfahren des Rechners über entsprechende Gruppenrichtlinien im Active Directory ausgeführt.
Falls das Skript unter Windows 10 beim Herunterfahren nicht ausgeführt wird, muss der Schnellstart deaktiviert werden.
Auf die Freigabe für die Logdateien brauchen die Domänenrechner Schreibzugriff, ebenso jener Anwender, der die Auswertung ggf. manuell im weiteren Verlauf vornimmt. PowerShell-Scripting auf den PCs muss aktiviert sein, ggf. sollte das Skript nach Anpassung an die eigene Umgebung signiert werden.
Variablen und Einträge, die angepasst werden müssen:
$strRelevantGroups - sollte die jeweilige primäre Gruppe der Benutzer beinhalten, um die logischen PC-Zuweisungen auswerten zu können
$logfile - muss auf eine beschreibbare Freigabe verweisen
Der Name der Datei wird mittels des Computernamens gebildet (und selbige überschrieben), das Dateidatum hilft dabei, den letzten erfolgreichen Vorgang direkt im Dateisystem zu erkennen.
#PC-Information sammeln
Function Get-FreeDiskSpace($drive)
{
$driveData = Get-WmiObject -class win32_LogicalDisk -filter "Name = '$drive'"
"{0:n2}" -f ($driveData.FreeSpace/1GB)# + " GB"
}
$ErrorActionPreference = 'SilentlyContinue'
$strCompName = ($env:Computername)
$CompNameLength = ($env:Computername).length
$logfile = "\\server\assetLog$\Computer\$strCompName.csv"
#Benutzerinfos des letzten angemeldeten Benutzers ermitteln und Variablen zuweisen
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.SearchScope = "Subtree"
$objSearcher.Filter = "(&(objectClass=computer)(cn=$strCompName))"
$system = $objSearcher.FindOne()
$dn = $system.properties["distinguishedname"]
$dn = $dn[0].toString()
$ou = $dn.substring(4+$CompNameLength)
$lastuser = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI).LastLoggedOnSAMUser
$lastuser = $lastuser.split("\")
$lastuser = $lastuser[1]
$objSearcher.Filter = "(&(objectClass=user)(cn=$lastuser))"
$userinfo = $objSearcher.FindOne()
$userdn = [adsi]$userinfo.path
$username = $userdn.displayname
$lastuser = $lastuser + " (" + $username + ")"
$strRelevantGroups = "Domain Users" #durch kommaseparierte reale Benutzergruppen ersetzen!
$groups = $userdn.memberof
$strGroups = ""
foreach($group in $groups)
{
$strGroup = $group.split(',')[0]
$strGroup = $strGroup.split('=')[1]
if($strRelevantGroups.contains($strGroup))
{
$strGroups = $strGroups + "," + $strGroup
}
}
if($strGroups.Length -gt 0){
$strGroups = $strGroups.split(",")
$team = [string]$strGroups[1]
} else {
$team = "N/A"
}
#Seriennummer des PCs auslesen
$computer = gwmi win32_computersystem
$bios = gwmi win32_bios
$os = (gwmi win32_operatingsystem).caption
$serial = $bios.serialnumber
#Prozessoren ermitteln
$colCPUs = gwmi win32_processor
$n = 0
foreach ($cpu in $colCPUs)
{
$n = $n + 1
$processor = ((($cpu.name -replace ' {2,}',' ') -replace "\(TM\)") -replace '\(R\)')
}
$cpuspeed = "{0:0.00 GHz}" -f($cpu.maxclockspeed/1000)
#Größe des physischen Arbeitsspeichers ermitteln
$totalmem = 0
$memsticks = gwmi -Class win32_physicalmemory
foreach ($stick in $memsticks) { $totalmem += $stick.capacity }
$physmem = ([int] ($($totalmem) / 1MB))
#Größe der Datenträger ermitteln
$disk = gwmi win32_diskdrive -filter "InterfaceType <> 'USB'"
$disksize=""
foreach ($objitem in $disk) {$disksize=$disksize+";"+[Convert]::ToString(([int]($objitem.size/1000000000)))}
$disksize = $disksize.substring(1)
$diskfree = ""
$diskfree = Get-FreeDiskSpace -drive "C:"
#Ermitteln der IP-Adresse(n)
# new (Test): $ip = Get-WmiObject Win32_NetworkAdapterConfiguration -filter 'IPEnabled="True"' | Select -expand IPAddress | ?{$_ -notmatch ':'}
$lan = get-wmiobject win32_networkadapterconfiguration -filter "ipenabled=true"
$lancount = get-wmiobject win32_networkadapterconfiguration -filter "ipenabled=true"
$ip=""
foreach($lan in $lancount){$ip = $ip + ";" + [string]($lan.ipaddress[0])}
$ip = $ip.substring(1)
#Erzeugen der Logdatei mit Zeitstempel im Logeintrag
$timestamp = get-date -format "M/d/yyyy HH:mm"
#Testausgabe am Bildschirm
#write-host $computer.name $computer.model $serial $processor $cpuspeed $physmem $disksize $os $ip $ou $lastuser $team $timestamp $diskfree -separator ";"
#Zusammenfassung für CSV-tauglichen String, separiert mit Tabulatoren
$allinfo=[string]$computer.name+"`t"+[string]$computer.model+"`t"+[string]$serial+"`t"+[string]$processor+"`t"+[string]$cpuspeed+"`t"+[string]$physmem+"`t"+[string]$disksize+"`t"+[string]$os+"`t"+[string]$ip+"`t"+[string]$ou+"`t"+[string]$lastuser+"`t"+$team+"`t"+[string]$timestamp+"`t Inventory Script`t1"+"`t"+[string]$diskfree
#Ausgabe in Logdatei
write-output $allinfo | format-table | out-file $logfile -encoding ASCII
#Informationen zu angeschlossenen Monitoren sammeln (ab Windows 7/2008R2)
try {
$ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID
}
catch {
break
$computer.name
}
$monitorInfo = @()
$pcserial = $serial
$i = 1
foreach ($monitor in $ActiveMonitors)
{
$mon = New-Object PSObject
$manufacturer = $null
$dspserial = $null
$name = $null
$week = $null
$year = $null
$monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
$monitor.SerialNumberID | foreach {$dspserial += [char]$_}
$monitor.UserFriendlyName | foreach {$name += [char]$_}
$mon | Add-Member NoteProperty Manufacturer $manufacturer
$mon | Add-Member NoteProperty PCSerial $serial
$mon | Add-Member NoteProperty SerialNumber $dspserial
$mon | Add-Member NoteProperty Name $name
$mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
$mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
$mon.SerialNumber = $dspserial.trim()
$monitorInfo += $mon
#Erzeugen eines Strings für Datei, Name wird aus DSP und Computername erzeugt, um die relevante Datei schnell im Dateisystem zu finden
$displayinfo = [string]$name+"`t"+[string]$dspserial+"`t"+$pcserial+"`t"+[string]$timestamp+"`t Inventory Script`t1"
$dsplogfile = "DSP" + $i + "_" + $computer.name
$dsplogfile = "\\server\assetLog$\Monitor\$dsplogfile.csv"
$i++
$displayinfo | format-table | out-file $dsplogfile -encoding ASCII
}
Montag, 19. September 2016
PowerShell: PC Hardware inventarisieren - 5. Monitore
Eine besondere Schwierigkeit stellt oft die Ermittlung des Verbleibs eines Monitors dar, da diese nicht aktiv abgefragt werden können, sondern nur über den angeschlossenen PC. Daher ist es sinnvoll, die ermittelten Daten mit jenen des PCs zu verknüpfen, an dem der Monitor angeschlossen ist. Nicht jeder Monitor kann über WMI abgefragt werden, aber fast alle moderneren Monitore liefern entsprechende Werte zurück.
Verwendete Variablen:
$ActiveMonitors: die am PC angeschlossenen und eingeschalteten Monitore
$monitor: der gerade ausgewertete Monitor im Fall von mehreren
$monitorInfo: die ausgelesenen Informationen der Monitore aus der Variable $mon als Array
$mon: ein neues PowerShell-Objekt, welches Herstellername, PC-Seriennummer, Monitorseriennummer, Modellname, Herstellungswoche und -jahr des Monitors aufnimmt
$pcserial: die Seriennummer des PCs, ist in einem anderen Teil des vollständigen Skripts zu ermitteln
$i: Zähler für die erkannten Monitore
Falls kein Monitor angeschlossen ist, beispielsweise bei Servern oder VMs, sollte diese Fehlerquelle von vornherein abgefangen werden.
try {
$ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID
}
catch {
break
$computer.name
}
Die gesammelte Information wird im Array $monitorInfo abgelegt.
$monitorInfo = @()
$pcserial = $serial
$i = 1
foreach ($monitor in $ActiveMonitors)
{
$mon = New-Object PSObject
$manufacturer = $null
$dspserial = $null
$name = $null
$week = $null
$year = $null
Da die Werte codiert hinterlegt sind, müssen sie zunächst in eine lesbare Zeichenkette umgewandelt werden.
Ursprünglich wird beispielsweise die Modellbezeichnung ausgelesen über $monitor.userfriendlyname | foreach { $_ } wie folgt dargestellt:
72
80
32
76
49
57
52
53
119
0
0
0
0
Zu Zeichen umgewandelt mittels [char] $monitor.userfriendlyname | foreach { [char]$_ } lässt die Lesbarkeit immer noch ein wenig zu wünschen übrig:
H
P
L
1
9
4
5
w
Daher erzeugen wir neue Strings, denen wir die einzelnen Zeichen dann hinzufügen:
$monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
$monitor.SerialNumberID | foreach {$dspserial += [char]$_}
$monitor.UserFriendlyName | foreach {$name += [char]$_}
$mon | Add-Member NoteProperty Manufacturer $manufacturer
$mon | Add-Member NoteProperty PCSerial $serial
$mon | Add-Member NoteProperty SerialNumber $dspserial
$mon | Add-Member NoteProperty Name $name
$mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
$mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
Unnütze Leerzeichen werden eliminiert:
$mon.SerialNumber = $dspserial.trim()
$monitorInfo += $mon
Auf geht's zum nächsten Monitor:
$i++
}
Die fertige Ausgabe ohne Formatierung und Export stellt sich wie folgt dar:
>$monitorInfo
Manufacturer : HWP
PCSerial : ABCDEFG
SerialNumber : CNN8xxxxxx
Name : HP L1945w
Week : 21
Year : 2008
Verwendete Variablen:
$ActiveMonitors: die am PC angeschlossenen und eingeschalteten Monitore
$monitor: der gerade ausgewertete Monitor im Fall von mehreren
$monitorInfo: die ausgelesenen Informationen der Monitore aus der Variable $mon als Array
$mon: ein neues PowerShell-Objekt, welches Herstellername, PC-Seriennummer, Monitorseriennummer, Modellname, Herstellungswoche und -jahr des Monitors aufnimmt
$pcserial: die Seriennummer des PCs, ist in einem anderen Teil des vollständigen Skripts zu ermitteln
$i: Zähler für die erkannten Monitore
Falls kein Monitor angeschlossen ist, beispielsweise bei Servern oder VMs, sollte diese Fehlerquelle von vornherein abgefangen werden.
try {
$ActiveMonitors = Get-WmiObject -Namespace root\wmi -Class wmiMonitorID
}
catch {
break
$computer.name
}
Die gesammelte Information wird im Array $monitorInfo abgelegt.
$monitorInfo = @()
$pcserial = $serial
$i = 1
foreach ($monitor in $ActiveMonitors)
{
$mon = New-Object PSObject
$manufacturer = $null
$dspserial = $null
$name = $null
$week = $null
$year = $null
Da die Werte codiert hinterlegt sind, müssen sie zunächst in eine lesbare Zeichenkette umgewandelt werden.
Ursprünglich wird beispielsweise die Modellbezeichnung ausgelesen über $monitor.userfriendlyname | foreach { $_ } wie folgt dargestellt:
72
80
32
76
49
57
52
53
119
0
0
0
0
Zu Zeichen umgewandelt mittels [char] $monitor.userfriendlyname | foreach { [char]$_ } lässt die Lesbarkeit immer noch ein wenig zu wünschen übrig:
H
P
L
1
9
4
5
w
Daher erzeugen wir neue Strings, denen wir die einzelnen Zeichen dann hinzufügen:
$monitor.ManufacturerName | foreach {$manufacturer += [char]$_}
$monitor.SerialNumberID | foreach {$dspserial += [char]$_}
$monitor.UserFriendlyName | foreach {$name += [char]$_}
$mon | Add-Member NoteProperty Manufacturer $manufacturer
$mon | Add-Member NoteProperty PCSerial $serial
$mon | Add-Member NoteProperty SerialNumber $dspserial
$mon | Add-Member NoteProperty Name $name
$mon | Add-Member NoteProperty Week $monitor.WeekOfManufacture
$mon | Add-Member NoteProperty Year $monitor.YearOfManufacture
Unnütze Leerzeichen werden eliminiert:
$mon.SerialNumber = $dspserial.trim()
$monitorInfo += $mon
Auf geht's zum nächsten Monitor:
$i++
}
Die fertige Ausgabe ohne Formatierung und Export stellt sich wie folgt dar:
>$monitorInfo
Manufacturer : HWP
PCSerial : ABCDEFG
SerialNumber : CNN8xxxxxx
Name : HP L1945w
Week : 21
Year : 2008
Dienstag, 13. September 2016
PowerShell: PC Hardware inventarisieren - 4. IP-Adressen
Die zuletzt verwendete IP-Adresse ist hilfreich, wenn es darum geht, einen PC im Netzwerk ausfindig zu machen. DNS, DHCP und WINS-Einträge können verschwinden, so dass der letzte Standort eines ausgeschalteten PCs nur schlecht zu ermitteln ist. Also erfassen wir diese ebenfalls im Rahmen der Auffrischung der Inventarinformationen.
Verwendete Variablen:
$lan: Netzwerkadapterobjekte, bei denen das TCP/IP-Protokoll aktiv ist
$lancount: Gesamtheit der entsprechenden Netzwerkadapter bei multihomed PC
$ip: Ein String mit allen IP-v4-Adressen des PCs
$lancount = get-wmiobject win32_networkadapterconfiguration -filter "ipenabled=true"
$ip=""
foreach($lan in $lancount){$ip = $ip + ";" + [string]($lan.ipaddress[0])}
$ip = $ip.substring(1)
Verwendete Variablen:
$lan: Netzwerkadapterobjekte, bei denen das TCP/IP-Protokoll aktiv ist
$lancount: Gesamtheit der entsprechenden Netzwerkadapter bei multihomed PC
$ip: Ein String mit allen IP-v4-Adressen des PCs
$lancount = get-wmiobject win32_networkadapterconfiguration -filter "ipenabled=true"
$ip=""
foreach($lan in $lancount){$ip = $ip + ";" + [string]($lan.ipaddress[0])}
$ip = $ip.substring(1)
Freitag, 9. September 2016
PowerShell: PC Hardware inventarisieren - 3. Datenträger
Der performanteste PC geht in die Knie, wenn die Festplatte oder SSD überfüllt ist. Daher gehört deren Größe mit in die Inventarisierung.
Verwendete Variablen:
$disk: die erfassten Datenträger
$disksize: die Kapazität der Laufwerke, lesbar gemacht durch Herunterbrechen der Zahl auf GByte
Die Abfrage der Datenträger erfolgt mittels des Befehls get-wmiobject win32_diskdrive. Um die Ergebnisse auf die fest erbauten Datenträger zu beschränken, werden USB-Laufwerke ausgefiltert. (Da die Filterung über WMI erfolgt, wird der Vergleich nicht mit dem PowerShell-Operator -neq vorgenommen.) Mit dem Stringformat wird an dieser Stelle gearbeitet, um gegebenenfalls auch die Größe mehrerer eingebauter Datenträger in einem Feld erfassen zu können, die mit Semikolon voneinander getrennt werden.
$disk = gwmi win32_diskdrive -filter "InterfaceType <> 'USB'"
$disksize=""
foreach ($objitem in $disk) {$disksize=$disksize+";"+[Convert]::ToString(([int]($objitem.size/1000000000)))}
$disksize = $disksize.substring(1)
Verwendete Variablen:
$disk: die erfassten Datenträger
$disksize: die Kapazität der Laufwerke, lesbar gemacht durch Herunterbrechen der Zahl auf GByte
Die Abfrage der Datenträger erfolgt mittels des Befehls get-wmiobject win32_diskdrive. Um die Ergebnisse auf die fest erbauten Datenträger zu beschränken, werden USB-Laufwerke ausgefiltert. (Da die Filterung über WMI erfolgt, wird der Vergleich nicht mit dem PowerShell-Operator -neq vorgenommen.) Mit dem Stringformat wird an dieser Stelle gearbeitet, um gegebenenfalls auch die Größe mehrerer eingebauter Datenträger in einem Feld erfassen zu können, die mit Semikolon voneinander getrennt werden.
$disk = gwmi win32_diskdrive -filter "InterfaceType <> 'USB'"
$disksize=""
foreach ($objitem in $disk) {$disksize=$disksize+";"+[Convert]::ToString(([int]($objitem.size/1000000000)))}
$disksize = $disksize.substring(1)
Samstag, 3. September 2016
PowerShell: PC Hardware inventarisieren - 2. Arbeitsspeicher
Auch der Arbeitsspeicher spielt eine wesentliche Rolle für die Performance eines PCs, daher ist die korrekte Anzeige des vorhandenen RAM Bestandteil einer informativen Inventarisierung.
Verwendete Variablen:
$totalmem: Gesamter installierter RAM
$memsticks: die eingebauten physischen Module
$physmem: lesbar formatierte Größe des RAM
Mittels get-wmiobject win32_physicalmemory lassen sich die Eigenschaften der einzelnen Speichermodule auslesen. Aus der umfangreichen Liste interessiert uns im Beispiel lediglich die Kapazität. Diese steckt für die einzelnen Module in der Eigenschaft capacity. Diese wird für alle Module zusammenaddiert und dann auf MByte heruntergebrochen.
$totalmem = 0
$memsticks = gwmi -Class win32_physicalmemory
foreach ($stick in $memsticks) { $totalmem += $stick.capacity }
$physmem = ([int] ($($totalmem) / 1MB))
Die Ausgabe erscheint dann als einfache Zahl, die für Sortier- und Vergleichsoperationen weiter verwendet werden kann:
8196
Verwendete Variablen:
$totalmem: Gesamter installierter RAM
$memsticks: die eingebauten physischen Module
$physmem: lesbar formatierte Größe des RAM
Mittels get-wmiobject win32_physicalmemory lassen sich die Eigenschaften der einzelnen Speichermodule auslesen. Aus der umfangreichen Liste interessiert uns im Beispiel lediglich die Kapazität. Diese steckt für die einzelnen Module in der Eigenschaft capacity. Diese wird für alle Module zusammenaddiert und dann auf MByte heruntergebrochen.
$totalmem = 0
$memsticks = gwmi -Class win32_physicalmemory
foreach ($stick in $memsticks) { $totalmem += $stick.capacity }
$physmem = ([int] ($($totalmem) / 1MB))
Die Ausgabe erscheint dann als einfache Zahl, die für Sortier- und Vergleichsoperationen weiter verwendet werden kann:
8196
Donnerstag, 1. September 2016
PowerShell: PC Hardware inventarisieren - 1. Prozessoren
Die folgende Beitragsserie hilft bei der Erfassung von PC-Inventar nur mit PowerShell und MS Office in Active Directory-Umgebungen, ohne dass eine spezielle Softwarelösung vorhanden sein muss.
Beginnen wir mit der Erkennung des Prozessors:
Angaben zu den installierten Prozessoren lassen sich mit get-wmiobject Win32_Processor ermitteln.
Die Ausgabe des Befehls sieht beispielsweise so aus:
Caption : Intel64 Family 6 Model 23 Stepping 10
DeviceID : CPU0
Manufacturer : GenuineIntel
MaxClockSpeed : 2667
Name : Intel(R) Core(TM)2 Quad CPU Q8400 @ 2.66GHz
SocketDesignation : XU1 PROCESSOR
Innerhalb des Inventarisierungsskripts legen wir diese Information in die Variable $colCPUs:
$colCPUs = gwmi win32_processor
Da wir bei Servern oder Workstations auch einmal auf mehrere Prozessoren stoßen können, sollten wir auch alle erfassen.
Interessant sind für uns der Prozessorname (hinterlegt in der neuen Variable $processor) und die Geschwindigkeit (hinterlegt in $cpuspeed).
$n = 0
foreach ($cpu in $colCPUs)
{
$n = $n + 1
$processor = ((($cpu.name -replace ' {2,}',' ') -replace "\(TM\)") -replace '\(R\)')
}
In diesem Beispiel ersetzen wir einige aus technischer Sicht uninteressante Zeichenfolgen und Leerzeichen entweder durch Leerzeichen oder durch gar nichts, um die Lesbarkeit zu erhöhen.
Das Ergebnis liest sich dann:
Intel Core2 Quad CPU Q8400 @ 2.66GHz
Die Geschwindigkeit wird in der Eigenschaft maxclockspeed standardmäßig in KHz ausgegeben, die folgende Zeile konvertiert diese Information zu GHz und formatiert sie entsprechend:
$cpuspeed = "{0:0.00 GHz}" -f($cpu.maxclockspeed/1000)
hinterlegt in der Variable $cpuspeed den Eintrag
2.67 GHz
Beginnen wir mit der Erkennung des Prozessors:
Angaben zu den installierten Prozessoren lassen sich mit get-wmiobject Win32_Processor ermitteln.
Die Ausgabe des Befehls sieht beispielsweise so aus:
Caption : Intel64 Family 6 Model 23 Stepping 10
DeviceID : CPU0
Manufacturer : GenuineIntel
MaxClockSpeed : 2667
Name : Intel(R) Core(TM)2 Quad CPU Q8400 @ 2.66GHz
SocketDesignation : XU1 PROCESSOR
Innerhalb des Inventarisierungsskripts legen wir diese Information in die Variable $colCPUs:
$colCPUs = gwmi win32_processor
Da wir bei Servern oder Workstations auch einmal auf mehrere Prozessoren stoßen können, sollten wir auch alle erfassen.
Interessant sind für uns der Prozessorname (hinterlegt in der neuen Variable $processor) und die Geschwindigkeit (hinterlegt in $cpuspeed).
$n = 0
foreach ($cpu in $colCPUs)
{
$n = $n + 1
$processor = ((($cpu.name -replace ' {2,}',' ') -replace "\(TM\)") -replace '\(R\)')
}
In diesem Beispiel ersetzen wir einige aus technischer Sicht uninteressante Zeichenfolgen und Leerzeichen entweder durch Leerzeichen oder durch gar nichts, um die Lesbarkeit zu erhöhen.
Das Ergebnis liest sich dann:
Intel Core2 Quad CPU Q8400 @ 2.66GHz
Die Geschwindigkeit wird in der Eigenschaft maxclockspeed standardmäßig in KHz ausgegeben, die folgende Zeile konvertiert diese Information zu GHz und formatiert sie entsprechend:
$cpuspeed = "{0:0.00 GHz}" -f($cpu.maxclockspeed/1000)
hinterlegt in der Variable $cpuspeed den Eintrag
2.67 GHz
(Seite 1 von 2, insgesamt 25 Einträge)
nächste Seite »