aivilon
Goto Top

Powershell- Software Versionen Zählen

Moin Moin

Brauch ein wenig Hilfe mit Powershell, da ich so gut wie kein bisschen Powershell kann. Ich möchte von ca. 70 Servern die vorhandene Software auslesen und pro Server Loggen.

Jo. Bis jetzt habe ich so weit ein PS Script, welches Server für Server die Softwareversionen ausliest. Was mir an diesem nicht so gefällt ist, dass ich für den Servernamen eine Variable habe. Diese wird immer um 1 erhöht. Da aber auch mal eine Zahl der Servernamen fehlen kann, ist das eine unschöne Lösung.
Ich möchte es so, dass in einer Schlaufe die Servernamen aus einem Textfile ausgelesen und abgearbeitet werden.
Also im Textfile steht zum Beispiel:
Server1
Server2
Server3
Server5

Das Script arbeitet jetzt einen nach dem anderen Durch. Das Resultat (Diesen Schritt habe ich auch schon) wird unter C:\Temp in ein Logfile das den Servernamen (C:\Temp\Test_Server1.log) trägt, geschrieben. Das ist soweit auch von mir gewünscht.

Im letzten Teil, und an diesem hänge ich gerade fest, möchte ich aus den eben erstellten Logs neue erstellen. Die Namen der Logs soll der Software und deren Version entsprechen (Beispiel: F-Secure_7.1.5.log). Darin enthalten sind die Server, auf denen diese Version läuft.
Bei diesem Teil brauche ich ein wenig hilfe =)


Die Situation ist kompliziert. Weiss kaum wie ich das schreiben soll. Also seid mir nicht böse wenns ein wenig kompliziert geschrieben ist. Bei fragen, fragen ;)

Grüsse
aivilon

Content-Key: 184016

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

Printed on: April 24, 2024 at 00:04 o'clock

Member: Connor1980
Connor1980 Apr 24, 2012 at 10:12:32 (UTC)
Goto Top
Hi,

hilfreich wäre, wenn du dein script hier mal bekanntgibst, so kann man nicht helfen.

Grundsätzlich: da du einmal nach Server und einmal nach Software sortiert/Gruppiert haben möchtest, bietet es sich an eine .csv Datei zu erstellen und in einer Tabellenkalkulation damit weiterzuarbeiten? Dann kannst du flexibel umsortieren, filtern etc, wie du möchtest.

Grüße
Member: Scriptex
Scriptex Apr 24, 2012 at 10:17:39 (UTC)
Goto Top
Hallo aivilon,

ein Vorschlag wäre (wenn ich dich richtig verstanden habe) sicherlich eine If-Abfrage für jedes Log:

$Server1 = gc "C:\Temp\Test_Server1.log"                                                                # Variable festlegen: Get-Content 'erste Logfile'  
If ($Server1 -like  "*F-Secure 7.1.5*")                                                             # erste Software-Abfrage (Sternchen nicht vergessen)  
   {
   Write-Output "Server1" > "C:\Temp\F-Secure7_1_5.txt"                                        # schreibt "Server1" in die Datei 'F-Secure7_1_5.txt'  
   }
else
   {
        If ($Server1 -like "*Software Nr2*")  
            {
            Write-Output "Server1" > "C:\Temp\SoftwareNr2..txt"  
            }
        else
            {
            # und so weiter....
            }
   }

Ich weiß nicht, wie genau dein Skript die Software-Versionen in die Datei schreibt, deswegen die Sternchen. Die Idee mit der Textfile mit den Servernamen ist auf jeden Fall viel besser als die mit der Variable.

Mein Ansatz oben müsste eigentlich funktionieren, das bekommt man sicherlich auch noch 'schöner' in einer ForEach-Schleife hin. Um nicht jedesmal das Skript verändern zu müssen, wenn du ein neues Logfile auslesen willst, kannst du z.B. Read-Host verwenden, um per GUI-Eingabe die Variable zu setzen.

Ich hoffe ich konnte dir helfen!
Gruß Scriptex
Member: aivilon
aivilon Apr 24, 2012 at 10:20:03 (UTC)
Goto Top
Zitat von @Connor1980:
Hi,

hilfreich wäre, wenn du dein script hier mal bekanntgibst, so kann man nicht helfen.

Grundsätzlich: da du einmal nach Server und einmal nach Software sortiert/Gruppiert haben möchtest, bietet es sich an
eine .csv Datei zu erstellen und in einer Tabellenkalkulation damit weiterzuarbeiten? Dann kannst du flexibel umsortieren, filtern
etc, wie du möchtest.

Grüße

Jo mein Script sieht mal so aus:
$srvname=91401

while($srvname -ne 91403)
	{
		get-wmiobject -class Win32_Product -computername sfd$srvname | where-object{$_.Vendor -eq "Symantec Corporation"}| Out-File C:\Temp\Test_sfd$srvname.log  
		$srvname++
	}
echo ende

Wie schon erwähnt. ich möchte das mit dem Servernamen so umschreiben, dass diese aus einem Textfile Zeile für Zeile ausgelesen werden. Das wäre schöner, da ich so auch Kontrolliert abfragen kann.

Jo wäre sicher netter als CSV. Respektive zum Beispiel:
Zelle 1 Zelle 2 Zelle 3
ServerName Software Software Version
Member: aivilon
aivilon Apr 24, 2012 at 10:28:15 (UTC)
Goto Top
Zitat von @Scriptex:
Hallo aivilon,

ein Vorschlag wäre (wenn ich dich richtig verstanden habe) sicherlich eine If-Abfrage für jedes Log:

> $Server1 = gc "C:\Temp\Test_Server1.log"                                                                # Variable  
> festlegen: Get-Content 'erste Logfile'  
> If ($Server1 -like  "*F-Secure 7.1.5*")                                                             # erste  
> Software-Abfrage (Sternchen nicht vergessen)
>    {
>    Write-Output "Server1" > "C:\Temp\F-Secure7_1_5.txt"                                        # schreibt  
> "Server1" in die Datei 'F-Secure7_1_5.txt'  
>    }
> else
>    {
>         If ($Server1 -like "*Software Nr2*")  
>             {
>             Write-Output "Server1" > "C:\Temp\SoftwareNr2..txt"  
>             }
>         else
>             {
>             # und so weiter....
>             }
>    }
> 

Ich weiß nicht, wie genau dein Skript die Software-Versionen in die Datei schreibt, deswegen die Sternchen. Die Idee mit der
Textfile mit den Servernamen ist auf jeden Fall viel besser als die mit der Variable.

Mein Ansatz oben müsste eigentlich funktionieren, das bekommt man sicherlich auch noch 'schöner' in einer
ForEach-Schleife hin. Um nicht jedesmal das Skript verändern zu müssen, wenn du ein neues Logfile auslesen willst,
kannst du z.B. Read-Host verwenden, um per GUI-Eingabe die Variable zu setzen.

Ich hoffe ich konnte dir helfen!
Gruß Scriptex

Hmm. So weit ich dein Code verstanden habe, ist die Software Version statisch. Da ich mind. 3 verschiedene Programme drauf hab, gibt mir der (Sorry das hatte ich noch nicht erwähnt) get-wmiobject -class Win32_Product Befehl alle Software nach folgendem muster aus:

IdentifyingNumber : {FE2F6A2C-196E-4210-9C04-2B1BC21F07EF}
Name : VMware Tools
Vendor : VMware, Inc.
Version : 8.0.4.24748
Caption : VMware Tools

Aus dieser ausgabe möchte ich nun den Namen und die Version (und bei einem Programm Caption) auslesen. Diese Angaben sollen jeweils nach folgendem Muster hintereinander in das CSV platziert werden: Servername;Name (Software);Version;Caption

Somit hätte ich dann eine gesamte übersicht über die Verwendet Software.

Grüsse
aivilon
Member: Scriptex
Scriptex Apr 24, 2012 at 10:54:46 (UTC)
Goto Top
Hallo aivilon,

hiermit erhälst du schonmal nur die gewünschten Eigenschaften aus der Ausgabe:

$Serverliste = gc "C:\Temp\Serverliste.txt"   
ForEach ($line in $Serverliste)
        {
        Get-WmiObject -Class Win32_Product| ft -Property Name, Version, Caption
        }

Sieht allerdings nicht so bombe aus. Ich wüsste aber gerade nicht, wie man das zurechtbiegen kann, irgendwie geht es mit Sicherheit.

Der Code liest auf jedem Server die installierte Software aus und zeigt dann Name, Version und Caption jeder Software spaltenweise (tabellenartig) an.
Member: aivilon
aivilon Apr 24, 2012 at 11:48:40 (UTC)
Goto Top
Zitat von @Scriptex:
Hallo aivilon,

hiermit erhälst du schonmal nur die gewünschten Eigenschaften aus der Ausgabe:

> $Serverliste = gc "C:\Temp\Serverliste.txt"   
> ForEach ($line in $Serverliste)
>         {
>         Get-WmiObject -Class Win32_Product| ft -Property Name, Version, Caption
>         }
> 

Sieht allerdings nicht so bombe aus. Ich wüsste aber gerade nicht, wie man das zurechtbiegen kann, irgendwie geht es mit
Sicherheit.

Der Code liest auf jedem Server die installierte Software aus und zeigt dann Name, Version und Caption jeder Software spaltenweise
(tabellenartig) an.

Hmm hatte grad was ähnliches zusammengestiefelt. Funktionierte aber nicht.
Dementsprechend habe ich jetzt deinen Code noch ein wenig angepasst:
$srvlist = GC C:\Temp\Serverlist.txt
 foreach ( $zeile in $srvlist )
	{
		$srvname=$zeile
		$Software=get-wmiobject -class Win32_Product -computername $srvname | ft -Property Name, Version, Caption
	}
Out-File -FilePath C:\Temp\grossertest.csv -InputObject $srvname;$Software

Klappt wunderbar. Nur, wie bringe ich diese jetzt in ein csv? der Out-File befehl schreibt nur den Servernamen auf.
Member: Connor1980
Connor1980 Apr 24, 2012 at 12:08:36 (UTC)
Goto Top
Member: Scriptex
Scriptex Apr 24, 2012 at 12:52:13 (UTC)
Goto Top
Ich benutze Out-File meist immer nur in Form von '>', also müsste es doch gehen, wenn man es dreht...

$srvname;$Software > "C:\Temp\grossertest.csv" -Append  

Es könnte sein, dass man das -Append auch weglassen kann. Bin mir nicht sicher.
Oder alternativ:

$srvname  > "C:\Temp\grossertest.csv"  
$Software >>  > "C:\Temp\grossertest.csv"  

Ich kann es leider gerade nicht testen, würde mich mal interessieren, ob die Spalten korrekt angehängt werden oder erst die Namen, und dann die Eigenschaften...
Member: aivilon
aivilon Apr 24, 2012 at 12:55:57 (UTC)
Goto Top

Entweder ich raff das net...oder es hilft mir nicht direkt.

ich hatte es versucht, aber die ausgabe konnte ich nicht brauchen.

Ich bin jetzt so weit, dass die ausgabe wie folgt aussieht:

Name Version Caption
------- -------
F-Secure Anti-Virus for... 9.00 F-Secure Anti-Virus fo...
Windows Automated Insta... 2.0.0.0 Windows Automated Inst...
Symantec NetBackup 7.1 Symantec NetBackup
F-Secure Anti-Virus for... 900.08 F-Secure Anti-Virus fo...
VMware Tools 8.0.4.24748 VMware Tools
F-Secure Anti-Virus for... 900.02 F-Secure Anti-Virus fo...
Symantec NetBackup 7.1.... 0000.2000 Symantec NetBackup 7.1...


Name Version Caption
------- -------
Symantec NetBackup Client 7.1 Symantec NetBackup Client
F-Secure Anti-Virus for... 9.00 F-Secure Anti-Virus fo...
VMware Tools 8.0.4.24748 VMware Tools
Symantec NetBackup 7.1.... 0000.2000 Symantec NetBackup 7.1...

Nur kann ich das so nicht wirklich brauchen. auch, weil alles in Spalte A geschrieben wird.
Es sollte so aussehen:
Servername Name Version Caption

Ich denke da an eine Abfolge wie diese:
 foreach ( $zeile in $srvlist )
	{
		$srvname=$zeile
		$srvname;(get-wmiobject -class Win32_Product -computername $srvname | ft -Property Name, Version, Caption)
		foreach (Programm in get-wmiobject -class Win32_Product -computername $srvname)
			{
				$srvname;Name;Version;Caption | Out-File C:\Temp\Test.csv
			}
dass PS dann für jedes programm gleich eine solche Zeile in ein csv schreibt.
Member: aivilon
aivilon Apr 24, 2012 at 12:57:21 (UTC)
Goto Top
Zitat von @Scriptex:
Ich benutze Out-File meist immer nur in Form von '>', also müsste es doch gehen, wenn man es dreht...

> $srvname;$Software > "C:\Temp\grossertest.csv" -Append  
> 

Es könnte sein, dass man das -Append auch weglassen kann. Bin mir nicht sicher.

Was ins CSV schreiben tut es. Nur ist ja das Problem, dass ich jetzt eine Variable für mehrere Programme habe face-confused
Member: Scriptex
Scriptex Apr 24, 2012 at 13:03:13 (UTC)
Goto Top
Prinzipiell kann PS die Informationen so verarbeiten, wie du es wünschst. Was meiner Meinung nach nur noch als letztes fehlt, ist, dass PS Spalten in der CSV "erkennt" und jede Eigenschaft in eine eigene schreibt. Ich habe alle Tabellen, die ich mit PowerShell irgendwann mal erstellt habe, durchgeschaut und alle haben die Daten in eine Spalte geschrieben.
Irgendeinen Parameter muss es aber doch geben, ist doch schließlich nur Kosmetik... :/


EDIT: Ich habe gerade eine TXT gefunden, wo PS es richtig schön übersichtlich abgespeichert hat. Vielleicht ist das die Lösung.
Member: aivilon
aivilon Apr 24, 2012 at 13:15:00 (UTC)
Goto Top
Zitat von @Scriptex:
Prinzipiell kann PS die Informationen so verarbeiten, wie du es wünschst. Was meiner Meinung nach nur noch als letztes fehlt,
ist, dass PS Spalten in der CSV "erkennt" und jede Eigenschaft in eine eigene schreibt. Ich habe alle Tabellen, die ich
mit PowerShell irgendwann mal erstellt habe, durchgeschaut und alle haben die Daten in eine Spalte geschrieben.
Irgendeinen Parameter muss es aber doch geben, ist doch schließlich nur Kosmetik... :/


EDIT: Ich habe gerade eine TXT gefunden, wo PS es richtig schön übersichtlich abgespeichert hat. Vielleicht ist das die
Lösung.

wenn ich das in ein txt schreibe ist es schon übersichtlich. Aber es wäre übersichtlicher wenn ich das so in ein csv schreiben könnte. wegen dem sortieren face-confused
Member: Connor1980
Connor1980 Apr 24, 2012 at 13:18:48 (UTC)
Goto Top
Hi,

wenn es txt ist, wie sieht es aus? csv ist ja nichts anderes als Trennzeichen-getrennte Textdatei. Wenn du z.B. ";" als delimiter benutzt kannst du das teil einfach in excel importieren/öffnen, evtl. noch über "Daten in Spalten" richtig zuordnen.

Grüße
Member: aivilon
aivilon Apr 24, 2012 at 13:22:56 (UTC)
Goto Top
Zitat von @Connor1980:
Hi,

wenn es txt ist, wie sieht es aus? csv ist ja nichts anderes als Trennzeichen-getrennte Textdatei. Wenn du z.B. ";" als
delimiter benutzt kannst du das teil einfach in excel importieren/öffnen, evtl. noch über "Daten in Spalten"
richtig zuordnen.

Grüße

im editor selber sieht es schöner aus. Also grössere Abstände.

F-Secure Anti-Virus for... 9.00 F-Secure Anti-Virus fo...
Windows Automated Insta... 2.0.0.0 Windows Automated Inst...
Symantec NetBackup 7.1 Symantec NetBackup
F-Secure Anti-Virus for... 900.08 F-Secure Anti-Virus fo...
VMware Tools 8.0.4.24748 VMware Tools
F-Secure Anti-Virus for... 900.02 F-Secure Anti-Virus fo...
Symantec NetBackup 7.1.... 0000.2000 Symantec NetBackup 7.1...


Symantec NetBackup Client 7.1 Symantec NetBackup Client
F-Secure Anti-Virus for... 9.00 F-Secure Anti-Virus fo...
VMware Tools 8.0.4.24748 VMware Tools
Symantec NetBackup 7.1.... 0000.2000 Symantec NetBackup 7.1...


Edit:

wie kann ich bei custom Tables als trennzeichen ein ; angeben? Dann wäre das Problem gelöst face-confused

$a = @{Expression={$_.Name};Label="Process Name";width=25}, `  
@{Expression={$_.ID};Label="Process ID";width=15}, `  
@{Expression={$_.MainWindowTitle};Label="Window Title";width=40}  

		$srvname;(get-wmiobject -class Win32_Product -computername $srvname | ft $a -Property Name, Version, Caption -hide) | Out-File C:\Temp\grossertest.csv -append
Member: aivilon
aivilon Apr 26, 2012 at 13:08:46 (UTC)
Goto Top
Ha...hab mein gewünschtes ziel FAST erreicht!!
$srvname;get-wmiobject -class "Win32_Product" -namespace "root\CIMV2" -computername $srvname | select-object Vendor, Name, Version, InstallDate, HelpLink | Export-Csv -path c:\Temp\installierte_programme.csv -UseCulture  

Nur hab ich jetzt das Problem, dass der Servername nicht am Anfang im csv vor jeder zeile steht (also in spalte A). hinzu kommt, dass das csv nicht erweitert, sondern überschrieben wird.

weiss da grad jemand abhilfe?
Member: aivilon
aivilon Apr 30, 2012 at 08:44:00 (UTC)
Goto Top
Also, ich habs jetzt fast. Faster als vorhin :P

#Erstelle Ordner für die CSV-Files
mkdir C:\temp\ServerProgramme
#Variable für die Serverliste inkl. Pfad
$srvlist = GC C:\Temp\Serverlist.txt
#Jeder Server auf der Serverliste wird nach den installierten
#Programmen abgefragt. Resultat wird in ein csv geschrieben
 foreach ( $zeile in $srvlist )
	{
		$srvname=$zeile
		$pfad = 'C:\Temp\ServerProgramme\' + $srvname + '_installierte_programme.csv'  
		$srvname;get-wmiobject -class Win32_Product -namespace root\CIMV2 -computername $srvname | select-object @{name='Server'; expression={$srvname}}, Vendor, Name, Version, InstallDate, HelpLink | Export-Csv -path $pfad -UseCulture -NoTypeInformation   

	}
	
#Variable wird mit null gefüllt damit sie vorerst vorhanden ist
$content = @()
 
#Pfad, in welchem die CSV Files liegen
$directory = "C:\Temp\ServerProgramme"  
#liest die CSV File namen aus und blendet alle anderen files aus
$csvFiles = Get-ChildItem -Path $directory -Filter *.csv
 
#jedes file wird abgearbeitet und der inhalt in ein merged file geschrieben
foreach($csv in $csvFiles)
{
	$content += Import-Csv $directory\$csv
}
 
#Schreibt ein Tag-Zeit Stempel in den namen des neuen Files und exportiert $content
$datetime = Get-Date -Format "yyyyMMddhhmmss"  
$content | Export-Csv -Path "C:\Temp\ServerProgramme\merged_$datetime.csv" -UseCulture -NoTypeInformation  

Mein letztes Problem ist, dass das zusammengeführte CSV sporadisch bei einigen zeilen einfach was abschneided, respektive nicht mehr enthält. bei den einzelnen csvs in der ersten foreach schleife ist alles vorhanden.

ich nehme an, dass die lösung dieses problems auch das problem löst, dass das zusammengeführte csv file wieder jede zeile in eine zelle steckt.
Member: aivilon
aivilon Apr 30, 2012 at 09:11:11 (UTC)
Goto Top
Zitat von @aivilon:
Also, ich habs jetzt fast. Faster als vorhin :P

> #Erstelle Ordner für die CSV-Files
> mkdir C:\temp\ServerProgramme
> #Variable für die Serverliste inkl. Pfad
> $srvlist = GC C:\Temp\Serverlist.txt
> #Jeder Server auf der Serverliste wird nach den installierten
> #Programmen abgefragt. Resultat wird in ein csv geschrieben
>  foreach ( $zeile in $srvlist )
> 	{
> 		$srvname=$zeile
> 		$pfad = 'C:\Temp\ServerProgramme\' + $srvname + '_installierte_programme.csv'  
> 		$srvname;get-wmiobject -class Win32_Product -namespace root\CIMV2 -computername $srvname | select-object
> @{name='Server'; expression={$srvname}}, Vendor, Name, Version, InstallDate, HelpLink | Export-Csv -path $pfad  
> -UseCulture -NoTypeInformation 
> 
> 	}
> 	
> #Variable wird mit null gefüllt damit sie vorerst vorhanden ist
> $content = @()
>  
> #Pfad, in welchem die CSV Files liegen
> $directory = "C:\Temp\ServerProgramme"  
> #liest die CSV File namen aus und blendet alle anderen files aus
> $csvFiles = Get-ChildItem -Path $directory -Filter *.csv
>  
> #jedes file wird abgearbeitet und der inhalt in ein merged file geschrieben
> foreach($csv in $csvFiles)
> {
> 	$content += Import-Csv $directory\$csv
> }
>  
> #Schreibt ein Tag-Zeit Stempel in den namen des neuen Files und exportiert $content
> $datetime = Get-Date -Format "yyyyMMddhhmmss"  
> $content | Export-Csv -Path "C:\Temp\ServerProgramme\merged_$datetime.csv" -UseCulture -NoTypeInformation  
> 

Mein letztes Problem ist, dass das zusammengeführte CSV sporadisch bei einigen zeilen einfach was abschneided, respektive
nicht mehr enthält. bei den einzelnen csvs in der ersten foreach schleife ist alles vorhanden.

ich nehme an, dass die lösung dieses problems auch das problem löst, dass das zusammengeführte csv file wieder jede
zeile in eine zelle steckt.


PROBLEM gelöst!
Ich weiss nicht warum es zeilen abgeschnitten hat, aber folgende zeilen wurde mit -useculture ergänzt:
foreach($csv in $csvFiles)
{
	$content += Import-Csv $directory\$csv -UseCulture
}


Beitrag demnach auch gelöst!

Danke und Grüsse
aivilon