bommi1961
Goto Top

Mit Powershell in einer Datei eine Zeile auslesen

Hallo zusammen,

wie bekomme ich es hin, das ich einen Bestimmt wert aus einer Zeil auslesen kann?

Ich hab einen Job erstellt der die Registry 32 und 64 Bit in eine Datei einliest, jetzt suche ich in der Datei nach einem Bestimmt Eintrag um damit weiter zu arbeiten.

Die C:\temp\PS-INI\INSTALL.INI sieht so aus:

32
WinSCP 5.9.2
C:\TEMP\winscp592\Protokolle\SYS-1P16010-1-PS.log

Das Skipt:
#Einlesen der Datei INSTALL.INI, in der das zu überprüfende Programm genannt ist
$var = get-content 'C:\temp\PS-INI\INSTALL.INI' # Datei wird vom SW-Paket erstellt.


$LOG = $var[2]
Remove-Item $LOG
write "----------------- START Powershell ------------------">>$LOG
write "Varieabeln zuseisung: ">>$LOG
$TX0 = "var "+$var
$TX1 = "var[1] "+$var[1]
$TX2 = "var[2] "+$var[2]
$TX3 = "var[3] "+$var[3]
$TX4 = "var[4] "+$var[4]
$TX5 = "var[5] "+$var[5]
$TX6 = "var[6] "+$var[6]
Write-Output $TX0 >>$LOG
Write-Output $TX1 >>$LOG
Write-Output $TX2 >>$LOG
Write-Output $TX3 >>$LOG
Write-Output $TX4 >>$LOG
Write-Output $TX5 >>$LOG
Write-Output $TX6 >>$LOG

$BIT = $var # BIT
$REG = $var[1] # DISPLAYNAME
$LOG = $var[2] # C:\temp\[ParketName]\Protokolle\SYS-xxxxxxx-PS.log
$var11 = $var[3] # Bezeichung die gefunden wird

$unstall1 = 'C:\temp\PS-INI\unstall1.txt' # Registry ausgabe Datei (32 und 64 BIT)
$unstall2 = 'C:\temp\PS-INI\unstall2.txt' # Ausgabe der unstall1.txt auf eine Zeile gebracht


$TX1 = "BIT Version ="+$BIT
$TX2 = "DISPLAYNAME ="+$REG
$TX3 = "LOG-File ="+$LOG

$TX4 = "INSTALL Datei1 ="+$unstall1
$TX5 = "INSTALL Datei2 ="+$unstall2

$TX6 = "Dieser Eintrag wird gesucht ="+$var[3]


Write-Output $TX1 >>$LOG
Write-Output $TX2 >>$LOG
Write-Output $TX3 >>$LOG
Write-Output $TX4 >>$LOG
Write-Output $TX5 >>$LOG
Write-Output $TX6 >>$LOG


write "------------------------------------------------------">>$LOG


write " ">>$LOG
$TX = "Das Programm "+$REG+" wird in der Registry gesucht. Bei 64 Bit Systemen, wird die ganze Registry druch sucht. Bei 32 Bit Systemen nur die der Teil der für 32 Bit."
Write-Output $TX3 >>$LOG
write " ">>$LOG


$TX = "Gesucht wird: "+$REG
Write $TX >>$LOG
$TX = "Ausgabe in "+$unstall1
write $TX >>$LOG

#Wenn 64 Bit System, dann auch die Wow6432Node mit auslesen
if($BIT -eq '64')
{
            1. Reg Auswertung für 64 Bit
            write "Auswertung für 64 Bit">>$LOG
            write "hklm:\software\Wow6432Node\microsoft\windows\currentversion\uninstall einlesen">>$LOG

            $LIST = Get-ChildItem hklm:\software\Wow6432Node\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath|select -property DisplayName}
            write $LIST >$unstall1

            }

            write " ">>$LOG
            1. Reg Auswertung für 32 Bit
            write "Auswertung für 32 Bit">>$LOG
            write "hklm:\software\microsoft\windows\currentversion\uninstall einlesen">>$LOG
            $LIST1 = Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath|select -property DisplayName}
            write $LIST1 >>$unstall1

            $LIST2 = Select-String -path $unstall1 -SimpleMatch $REG
            write $LIST2 >>$unstall2


            $LIST3 = Get-Content $unstall2 -totalcount 2 | Select-Object -Skip 1
            $TX = "Ausgabe in "+$LIST3
            write $TX >>$LOG >>>>>>> Ausgabe sieht so aus: "C:\temp\PS-INI\unstall1.txt:24:WinSCP 5.9.2"

            ich brauch aber z.B. nur "WinSCP 5.9.2"

            Meine Frage ist jetzt, wie komme ich nur an den Wert "WinSCP 5.9.2" oder noch besser wie bekomme ich es nicht, das "C:\temp\PS-INI\unstall1.txt:24:" erst gar nicht mit angeführt wird?

            VG

Content-Key: 315928

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

Ausgedruckt am: 19.03.2024 um 05:03 Uhr

Mitglied: colinardo
Lösung colinardo 22.09.2016, aktualisiert am 26.09.2016 um 17:14:00 Uhr
Goto Top
Hallo Bommi,
was soll die ganze "Textschreiberei" face-smile Das ist vielleicht noch zu Batchzeiten eine genutzte Methode, aber mit Powershell ist das absolut nicht mehr nötig jeden Schritt in eine Textdatei zu schreiben.
So wie ich das sehe liest du die installierten Programme über die Registry aus und möchtest ein bestimmtes Programm herausfiltern.

Ich würde daher folgendes vorschlagen, was auch die Registry eines Remote-Computers abfragen kann (wenn der Remote-Registry-Dienst läuft) wenn es nötig werden sollte (Ich weiß es geht auch über gci und get-itemproperty die jedoch nicht für remote computer geeignet sind):
function Get-InstalledSoftware(){
    param(
        [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][string]$Computer
    )
    $all = @()
    $key = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"  
    $key64 = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"  
    try{
        $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer)  
        $root = $reg.OpenSubKey($key)
        $all += $root.GetSubKeyNames() | %{$root.OpenSubKey($_).GetValue("DisplayName")}  
        $root.Close() | out-null
        if ((gwmi Win32_OperatingSystem -Computer $computer).OSArchitecture -eq '64-Bit'){  
            $root = $reg.OpenSubKey($key64)
            $all += $root.GetSubKeyNames() | %{$root.OpenSubKey($_).GetValue("DisplayName")}  
            $root.Close() | out-null
        }
    }catch{
        throw $_.Exception.Message
    }finally{
        if($reg){$reg.Close | out-null}
    }
    return ($all | sort | select -Unique)
}

# Liest auf dem aktuellen System installierte Programme aus und filtert nach "WinSCP" 
Get-InstalledSoftware -Computer $env:COMPUTERNAME | ?{$_ -like 'WinSCP*'}  

Nun zu deinem Code:
Ausgabe sieht so aus: "C:\temp\PS-INI\unstall1.txt:24:WinSCP 5.9.2"
Das ist die Default-Ausgabeformatierung von Select-String. Wenn du dir mal die Eigenschaften eines Select-String Ergebnisses ansiehst wirst du feststellen das der pure String in der Eigenschaft Line des resultierenden Objekts enthalten ist:
Select-String -path $unstall1 -SimpleMatch $REG | fl *
Ausgabe
IgnoreCase : True
LineNumber : 750
Line       : WinSCP 5.9.2
Filename   : InputStream
Path       : InputStream
Pattern    : Windows
Context    : 
Matches    : {}

Die reine Zeile erhältst du dann wie immer so
Select-String -path $unstall1 -SimpleMatch $REG | select -Expand Line
# bzw. so
(Select-String -path $unstall1 -SimpleMatch $REG).Line

Hoffe ich konnte dich in dieser Hinsicht aufklären face-smile.
Viel Erfolg weiterhin beim Lernen von Powershell..., und gewöhne dir das zwischenspeichern und Ausgeben in Textdateien ab, das ist eine blöde Angewohnheit aus ganz frühen Batchzeiten. In Powershell schreibt man meist alles erst in eine Variable und dann das Log ganz zum Schluss auf einen Rutsch.

Grüße Uwe
Mitglied: Bommi1961
Bommi1961 23.09.2016 um 10:50:58 Uhr
Goto Top
Vielen Dank Uwe für Deine Hilfe!

Konnte ich gut um setzten.

Wünsche ein schönes Wochenende

Viele Grüße

Thilo
Mitglied: Bommi1961
Bommi1961 26.09.2016 um 14:49:50 Uhr
Goto Top
Hallo Uwe,

hab doch noch mal eine Frage zu Deinem Tollen Skript.
Du schreibst das ich auch die Registry eines Remote-Computers abfragen kann, dass habe ich heute mal ersucht und bin gescheitert, weil er immer den Lokalen PC genommen hat.

Wo müsste ich denn die "VAR" eingeben um einen Remote-Computer zu erreichen?

Ich hatte versucht $Computer über ein Eingabefenster einen Remote-Computer zu zuweisen.

VG Thilo
Mitglied: colinardo
colinardo 26.09.2016 aktualisiert um 15:42:41 Uhr
Goto Top
Hallo Thilo,
den Computer gibst du in der letzten Zeile mit:
Get-InstalledSoftware -Computer 'COMPUTERNAME' | ?{$_ -like 'WinSCP*'}  
an.

Bitte beachte das in diesem Fall der aktuelle Account mit dem das Script ausgeführt wird über Admin-Rechte am Remote-Rechner verfügen muss, du kannst die Credentials auch im Windows Tresor hinterlegen.
Zusätzlich muss der Dienst Remoteregistrierung auf dem Remote-Rechner laufen, das ist per Default nicht der Fall. Zum Abschluss muss natürlich auch die Firewall des Remotesystems die "Remoteverwaltung" durchlassen damit der Zugriff klappt.
Hast du keine Domäne und UAC ist aktiviert muss ebenfalls in der Registry noch der LocalAccountTokenfilterPolicy Eintrag gesetzt sein.

Grüße Uwe
Mitglied: Bommi1961
Bommi1961 26.09.2016 um 17:07:14 Uhr
Goto Top
Hallo Uwe,

Admin-Rechte am Remote-Rechner alles kein Thema, ist alles eingerichtet und gehört zur täglichen arbeit. face-smile

Aber jetzt kommt immer ein anderer Fehler und ich muss leider noch mal fragen:

cls
[void] [System.Reflection.Assembly]::LoadWithPartialName(„System.Drawing“)
[void] [System.Reflection.Assembly]::LoadWithPartialName(„System.Windows.Forms“)
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = „Dateneingabe“
$objForm.Size = New-Object System.Drawing.Size(400,300)
$objForm.StartPosition = „CenterScreen“
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq „Enter“) { $objForm.DialogResult=“OK“;$objForm.Close()} })
$objForm.Add_KeyDown({if ($_.KeyCode -eq „Escape“) { $objForm.DialogResult=“Cancel“;$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.DialogResult = „OK“
$OKButton.Add_Click({$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.DialogResult = „Cancel“
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = „Bitte geben Sie die SYSTEM Nr. ein: “
$objForm.Controls.Add($objLabel)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,40)
$objTextBox.Size = New-Object System.Drawing.Size(260,20)
#Vorgabe!

$objTextBox.Text = „SYS-1“
#$objTextBox.Text = „SYS-1p16010“
$objForm.Controls.Add($objTextBox)

[void] $objForm.ShowDialog()

$SYSNR = $objTextBox.Text

write ""System= " $SYSNR"

#$Computer = $SYSNR

#Prüfen ob eine Sys Nr. eingegeben wurde!
#if ($SYSNR -eq "SYS-") { Write-Host "ERROOR! Falsche Eingabe!" }&{EXIT 4}
#if ($SYSNR -eq "SYS-") {ECHO""} else {EXIT 4}

If ($objForm.DialogResult -like „OK“) {echo ""} else {„Abbruch geklickt"}
If ($objForm.DialogResult -like „OK“) {echo ""} else {EXIT 5}


$ping = Test-Connection -source $SYSNR -ComputerName $SYSNR
write $ping

if (-not (Test-Connection -ComputerName $SYSNR -Quiet)){Write-Host "Host nicht erreichbar!"}
if (-not (Test-Connection -ComputerName $SYSNR -Quiet)){EXIT 5}


$Computer=$SYSNR


echo ".........................................."

function Get-InstalledSoftware(){

param(

[parameter(mandatory=$true)][ValidateNotNullOrEmpty()][string]$Computer

)

$all = @()

$key = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

$key64 = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"

try{

$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer)
#$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($SYSNR, $Computer)
$root = $reg.OpenSubKey($key)

$all += $root.GetSubKeyNames() | %{$root.OpenSubKey($_).GetValue("DisplayName")}

$root.Close() | out-null

if ((gwmi Win32_OperatingSystem).OSArchitecture -eq '64-Bit'){

$root = $reg.OpenSubKey($key64)

$all += $root.GetSubKeyNames() | %{$root.OpenSubKey($_).GetValue("DisplayName")}

$root.Close() | out-null


}

}catch{

throw $_.Exception.Message #>>>>>hier bekomme ich immer eine Fehlermeldung: Siehe untern 1)

}finally{

if($reg){$reg.Close | out-null}

}

return ($all | sort | select -Unique)

}


$TMP = "C:\TEMP\REG "+$Computer+".csv"

  1. Liest auf dem aktuellen System installierte Programme aus und filtert nach "$Process"

#Get-InstalledSoftware -Computer $env:COMPUTERNAME | ?{$_ -like $Process+'*'}
Get-InstalledSoftware -Computer $env:COMPUTERNAME >>$TMP # Ausgabe in eine Datei
Get-InstalledSoftware -Computer $env:COMPUTERNAME # Ausgabe in eine BS
Get-InstalledSoftware -Computer 'SYS-1PM900-1' # Ausgabe in eine BS
#$NAME = (Get-InstalledSoftware -Computer $env:COMPUTERNAME)


$msg = $TMP+" Erstellt!"
[System.Windows.Forms.MessageBox]::Show($msg,"Auswertung!",0)


1)Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
An F:\Powershell-Skipte\SW_in_REG_suchen_DEV_PC.ps1:Zeile:108 Zeichen:9

back-to-topt <<<< hrow $_.Exception.Message


VG Thilo
Mitglied: colinardo
colinardo 26.09.2016 aktualisiert um 17:17:53 Uhr
Goto Top
Dann war das Herstellen der Verbindung nicht erfolgreich wenn eine Exception geworfen wird, das ist der Zweck der Zeile.

Siehe alle Hinweise oben.