marcimarc85
Goto Top

Silent Setup mittels Powershell ausführen

Hallo,

Ich komm irgendwie nicht voran.
Ich möchte gern ein Setup automatisiert laufen lassen. Das soll komplett automatisch passierern (im späteren Verlauf). Aktuell geht es erstmal darum, dass der Aufruf überhaupt funktioniert. Das Setup läuft auf vielen verschiedenen Systemen und installiert eine Software. Diese Software beinhaltet diverse Schnittstellen, die als Windows Service installiert werden.
Da das von Server zu Server imme andere Services in Name und Anzahl sind, hatte ich überlegt, alle Services in eine ini-Datei aufzulisten und die Services auszukommentieren, die nicht installiert werden soll. Das Powershell Script, was das Setup ausführt, soll nun in dieseini-Datei reinschauen und die nicht auskommentierten Services als Parameter übernhemen und an den Installationsbefehl anhängen.
Und an dieser Stelle denke ich irgendwie zu verquer und weiß nicht, wie ich das Ganze angehen soll.

Die Ini-Datei soll quasi folgendermaßen ausshen:

Service1
Service2
Service3
Service4
Service5
Service6
Service7
...
...
...
Service 19

Diesen Aufruf hab ich von einem Programmentwickler bekommen:

 #Setup auf dem Server starten (Silent, Checksum nicht checken, Zielverzeichnis)
    [String]$PathOnServer = -join("D:", $LocalPath)  

[String]$arguments = -join(" /S /NCRC /INSTDIR=`"", $PathOnServer, "`"", " /sil /<Service1> /<Service4> /<Service usw>")  
[String]$FullCommand = -join($PathOnServer, $SetupFilename, $arguments)
Hinter dem /sil müssten dann also die nicht auskommentierten Services aus der ini-Datei automatisch eingefügt werden


So gehts dann weiter:

Write-Host (-join("          Starte ", $FullCommand))  

    #Opens a batch file process on Remote Computer using Invoke-WMIMethod
    $process = Invoke-WMIMethod -Class Win32_Process -Name Create -Computername $ServerName -ArgumentList $FullCommand
    if ($process.ReturnValue -eq 0)
    {
        $processId = $process.ProcessId

        #Installation abwarten und maximal 5 Minuten warten
        $runningCheck = { Get-WmiObject -Class Win32_Process -Filter "ProcessId='$processId'" -ComputerName $ServerName -ErrorAction SilentlyContinue }  
        while ($null -ne (& $runningCheck))
        {
            Start-Sleep -m 500
        }        

        #Zur Sicherheit noch 1 Sekunde warten
        Start-Sleep -s 1
    }
    else
    {
        Write-Host ("Installieren von", $SetupFilename, "auf", $ServerName, "ist fehlgeschlagen.") -ForegroundColor "red"  
        $global:FailedInstalls += $ServerName
    }

    checkReturnCode -join("Installieren auf ", $ServerName, " ist fehlgeschlagen.") $process.ExitCode  

    #Setup-File löschen
    deleteFile $TargetFile

    # Aufräumen
    silentDeleteFile "err.txt"  
    silentDeleteFile "out.txt"  
}

Content-Key: 4968944185

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

Printed on: April 28, 2024 at 06:04 o'clock

Member: TK1987
Solution TK1987 Dec 15, 2022 updated at 11:29:31 (UTC)
Goto Top
Moin,

Zitat von @MarciMarc85:
Und an dieser Stelle denke ich irgendwie zu verquer und weiß nicht, wie ich das Ganze angehen soll.

Die Ini-Datei soll quasi folgendermaßen ausshen:

Service1
Service2
Service3
Service4
Service5
Service6
Service7
...
...
[String]$arguments = -join(" /S /NCRC /INSTDIR=`"", $PathOnServer, "`"", " /sil /<Service1> /<Service4> /<Service   
Hinter dem /sil müssten dann also die nicht auskommentierten Services aus der ini-Datei automatisch eingefügt werden
Da die Variable $arguments als Typ [string] deklariert ist, kannst du dir den join sparen. Bei der Umwandlung von Arrays in den Type String, werden alle Elemente immer automatisch mit Leerzeichen verbunden.

Auskommentieren heisst mit führender Raute? Dann So:
[String]$arguments = " /S /NCRC /INSTDIR=""$PathOnServer"" /sil "+  
  (Select-String -NotMatch "^#" -Path <Pfad zur Ini>).Foreach({"/"+$_.Line})  

tio.run

Gruß Thomas
Member: MarciMarc85
MarciMarc85 Dec 15, 2022 at 13:26:44 (UTC)
Goto Top
Danke. funktioniert perfekt
Member: MarciMarc85
MarciMarc85 Dec 22, 2022 updated at 06:59:53 (UTC)
Goto Top
Hallo Thomas,

eine Frage hätte ich doch noch, da ich das Script gern noch um die Funktion erweitern möchte, dass ich per Schalter noch entscheiden kann, ob der Dienst manuell oder automatisch gestartet werden soll. Default wird er als automatischer Start angelegt und gestartet. Manchmal ist aber auch ein manueller Start notwendig, bzw. darf der Dienst auf keinen Fall nach Beendigung des Setups direkt starten. ich hatte das biosher immer durch den Aufruf eines extra Powershell Scripts gelöst, in dem ich die Dienste untereinader in eizelnen Kommandos angegeben hab:

gwmi win32_service|?{$_.name -like "Service 1"}|%{$_.changestartmode("Manual")}  
gwmi win32_service|?{$_.name -like "Service 3"}|%{$_.changestartmode("Manual")}  
gwmi win32_service|?{$_.name -like "Service8"}|%{$_.changestartmode("Manual")}  
usw...

Die für mich nun eleganteste Lösung wäre, wenn man in der eh eingelesenden ini-Datei einfach noch hinter den zu installierenden Dienst, den man auf manuell gesetzt haben möchte ein z.B. "/man" setzt, was dann erkannt wird und den Befehl oben in einer Schleife für die entsprechenden Dienste zusätzlich ausführt.

Beispiel:

Service1
#Service2 
Service3 /man
Service4 /man
#Service5
#Service6
Service7
...

Ist das denn überhaupt so einfach möglich?

Beste Grüße

Marc
Member: TK1987
TK1987 Dec 22, 2022 updated at 07:46:22 (UTC)
Goto Top
Moin Marc,

mit Powershell und ein bisschen RegEx ist fast alles so einfach möglich face-wink
$ini = "C:\Pfad\zur\services.ini"  
$arguments = " /S /NCRC /INSTDIR=""$PathOnServer"" /sil "  

$arguments += Foreach ($Service in Select-String -Pattern '^(?!#)([^ ]+)( /man)?' -Path $ini) {  
  
  # Service zu Argumenten hinzufügen
  "/"+$Service.Matches.Groups[1].Value  
  
  # Wenn hinter Service "/man", Starttyp auf manuell festlegen 
  if ($Service.Matches.Groups[2].Success) {
    Set-Service -Name $Service.Matches.Groups[1].Value -StartupType Manual
  }
  
} # Ende Foreach $Service

tio.run

Gruß Thomas
Member: MarciMarc85
MarciMarc85 Dec 22, 2022 at 09:33:16 (UTC)
Goto Top
Zitat von @TK1987:

Moin Marc,

mit Powershell und ein bisschen RegEx ist fast alles so einfach möglich face-wink
$ini = "C:\Pfad\zur\services.ini"  
$arguments = " /S /NCRC /INSTDIR=""$PathOnServer"" /sil "  

$arguments += Foreach ($Service in Select-String -Pattern '^(?!#)([^ ]+)( /man)?' -Path $ini) {  
  
  # Service zu Argumenten hinzufügen
  "/"+$Service.Matches.Groups[1].Value  
  
  # Wenn hinter Service "/man", Starttyp auf manuell festlegen 
  if ($Service.Matches.Groups[2].Success) {
    Set-Service -Name $Service.Matches.Groups[1].Value -StartupType Manual
  }
  
} # Ende Foreach $Service

tio.run

Gruß Thomas

Super. Danke für die schnelle Antwort. Ichhatte nur nicht bedacht, dass die angegebenen Servicenamen in der ini-Datei auf die exe.datei hinter dem Service verweisen. Bedeutet:

In der Ini steht z.b. Service1. Durch diesen Parameter wird der Service mit dem Namen "App Service 1" un der ausführbaren Datei Service1.exe installiert. Mit dem Befehl zum setzten des Startmodus auf manuell benötige ich demnach den Anzeigenamen als Variable
Member: TK1987
TK1987 Dec 22, 2022 updated at 09:58:55 (UTC)
Goto Top
Zitat von @MarciMarc85:
In der Ini steht z.b. Service1. Durch diesen Parameter wird der Service mit dem Namen "App Service 1" un der ausführbaren Datei Service1.exe installiert. Mit dem Befehl zum setzten des Startmodus auf manuell benötige ich demnach den Anzeigenamen als Variable
Ok. Ich gehe mal davon aus, die Services können erst nach dem eigentlichen Setup auf manuell gesetzt werden, da sie vorher noch gar nicht existieren, richtig?

Versuche mal folgendes:
$ini = "C:\Pfad\zur\services.ini"  
$arguments = " /S /NCRC /INSTDIR=""$PathOnServer"" /sil "  

$arguments += Foreach ($Service in Select-String -Pattern '^(?!#)([^ ]+)( /man)?' -Path $ini) {  
  
  # Service zu Argumenten hinzufügen
  "/"+$Service.Matches.Groups[1].Value  
  
  # Wenn hinter Service "/man", Starttyp auf manuell festlegen 
  if ($Service.Matches.Groups[2].Success) {
    [Array]$startManual += $Service.Matches.Groups[1].Value
  }
  
} # Ende Foreach $Service

# Setupprozess
# ... 

$Services = gcim Win32_Service
Foreach ($Service in $startManual) {
  $Services | ? PathName -like "*$Service*" |%{Set-Service -Name $_.Name -StartupType Manual}  
}
Member: MarciMarc85
Solution MarciMarc85 Dec 22, 2022 at 10:10:54 (UTC)
Goto Top
Zitat von @TK1987:

Zitat von @MarciMarc85:
In der Ini steht z.b. Service1. Durch diesen Parameter wird der Service mit dem Namen "App Service 1" un der ausführbaren Datei Service1.exe installiert. Mit dem Befehl zum setzten des Startmodus auf manuell benötige ich demnach den Anzeigenamen als Variable
Ok. Ich gehe mal davon aus, die Services können erst nach dem eigentlichen Setup auf manuell gesetzt werden, da sie vorher noch gar nicht existieren, richtig?

Versuche mal folgendes:
$ini = "C:\Pfad\zur\services.ini"  
$arguments = " /S /NCRC /INSTDIR=""$PathOnServer"" /sil "  

$arguments += Foreach ($Service in Select-String -Pattern '^(?!#)([^ ]+)( /man)?' -Path $ini) {  
  
  # Service zu Argumenten hinzufügen
  "/"+$Service.Matches.Groups[1].Value  
  
  # Wenn hinter Service "/man", Starttyp auf manuell festlegen 
  if ($Service.Matches.Groups[2].Success) {
    [Array]$startManual += $Service.Matches.Groups[1].Value
  }
  
} # Ende Foreach $Service

# Setupprozess
# ... 

$Services = gcim Win32_Service
Foreach ($Service in $startManual) {
  $Services | ? PathName -like "*$Service*" |%{Set-Service -Name $_.Name -StartupType Manual}  
}

exakt. Die Services sind vorher noch nicht bekannt bzw. werden durch ein Update einmal deinstalliert und anschließend in neuer Version wieder installiert. Der Startmode kann daher erst nach erfolgter Installation angepasst werden. Ich probier das mal aus.
Member: MarciMarc85
MarciMarc85 Dec 22, 2022 at 10:15:57 (UTC)
Goto Top
Was soll ich sagen. es funktioniert genauso, wie es soll !!! Vielen vielen Dank!
Wünsche frohe Weihnachten !
Member: TK1987
TK1987 Dec 22, 2022 at 10:33:27 (UTC)
Goto Top
Zitat von @MarciMarc85:
Wünsche frohe Weihnachten !
Danke gleichfalls.