Je cherche un moyen de continuer un script Powershell d'où il s'était arrêté après avoir appelé un redémarrage dans le script. Par exemple, je crée un DC via l'automatisation Powershell, et après avoir renommé le PC en TESTDC01, je dois redémarrer, mais après le redémarrage, continuez avec le script pour passer à dcpromo, etc.
Est-ce possible?
À votre santé!
Il existe un excellent article sur TechNet de la série Hey, Scripting Guy qui décrit une situation très similaire à ce que vous décrivez: renommer un ordinateur et reprendre le script après le redémarrage. La magie est d'utiliser les nouveaux workflows qui font partie de la version 3:
workflow Rename-And-Reboot {
param ([string]$Name)
Rename-Computer -NewName $Name -Force -Passthru
Restart-Computer -Wait
Do-MoreStuff
}
Une fois le workflow déclaré (vous ne l'assignez pas à une variable), vous pouvez l'appeler comme s'il s'agissait d'une applet de commande standard. La vraie magie est le -Wait
paramètre sur la cmdlet Restart-Computer.
Rename-And-Reboot PowerShellWorkflows
Si PowerShell v3 ou version ultérieure n'est pas un choix disponible, vous pouvez diviser votre script existant en plusieurs scripts plus petits et avoir un script maître qui s'exécute au démarrage, vérifier un état enregistré quelque part (fichier, registre, etc.), puis commencer à exécuter un nouveau script pour continuer le cas échéant. Quelque chose comme:
$state = Get-MyCoolPersistedState
switch ($state) {
"Stage1" { . \Path\To\Stage1.ps1 ; break }
"Stage2" { . \Path\To\Stage2.ps1 ; break }
"Stage3" { . \Path\To\Stage3.ps1 ; break }
default { "Uh, something unexpected happened" }
}
N'oubliez pas de définir votre état de manière appropriée lorsque vous parcourez vos petits scripts.
La réponse ci-dessus est vraie, mais elle ne s'appliquera qu'à l'exécution à distance de scripts PowerShell. Selon le portail Web Windows , la façon de faire reprendre votre script en cours d'exécution localement là où il s'était arrêté après le redémarrage de la machine locale est la suivante:
workflow Resume_Workflow
{
.....
Rename-Computer -NewName some_name -Force -Passthru
Restart-Computer -Wait
# Do some stuff
.....
}
# Create the scheduled job properties
$options = New-ScheduledJobOption -RunElevated -ContinueIfGoingOnBattery -StartIfOnBattery
$secpasswd = ConvertTo-SecureString "Aa123456!" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ("WELCOME\Administrator", $secpasswd)
$AtStartup = New-JobTrigger -AtStartup
# Register the scheduled job
Register-ScheduledJob -Name Resume_Workflow_Job -Trigger $AtStartup -ScriptBlock ({[System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager = $true; Import-Module PSWorkflow; Resume-Job -Name new_resume_workflow_job -Wait}) -ScheduledJobOption $options
# Execute the workflow as a new job
Resume_Workflow -AsJob -JobName new_resume_workflow_job
Notez que le [System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager
L'indicateur ne doit être défini sur true que si les actions de workflow sont destinées à s'exécuter localement après le redémarrage.
Découvrez PS 3.0 avec Workflows. Je n'ai pas encore travaillé avec eux, mais ils sont censés se remettre des redémarrages.
Si cela aide quelqu'un, je redémarre le serveur puis boucle jusqu'à ce que \\server\c$
Se déconnecte. Ensuite, je boucle While (-not(Test-path "\\$server\c$"))
pour confirmer que le serveur est de nouveau en ligne et continue simplement mon script.
Ce code fonctionne mais pourrait certainement être amélioré. Il génère un journal CSV des serveurs en cours de redémarrage. Il devrait également fonctionner dans PowerShell v2 et plus récent.
Param([Parameter(Mandatory=$true)][string]$server)
$ErrorActionPreference = "SilentlyContinue"
Try{
$LastReboot = Get-EventLog -ComputerName $server -LogName system | Where-Object {$_.EventID -eq '6005'} | Select -ExpandProperty TimeGenerated | select -first 1
(Invoke-WmiMethod -ComputerName $server -Path "Win32_Service.Name='HealthService'" -Name PauseService).ReturnValue | Out-Null
Restart-Computer -ComputerName $server -Force
#New loop with counter, exit script if server did not reboot.
$max = 20;$i = 0
DO{
IF($i -gt $max){
$hash = @{
"Server" = $server
"Status" = "FailedToReboot!"
"LastRebootTime" = "$LastReboot"
"CurrentRebootTime" = "FailedToReboot!"
}
$newRow = New-Object PsObject -Property $hash
$rnd = Get-Random -Minimum 5 -Maximum 40
Start-Sleep -Seconds $rnd
Export-Csv D:\RebootResults.csv -InputObject $newrow -Append -Force
"Failed to reboot $server"
exit}#exit script and log failed to reboot.
$i++
"Wait for server to reboot"
Start-Sleep -Seconds 15
}#end DO
While (Test-path "\\$server\c$")
$max = 20;$i = 0
DO{
IF($i -gt $max){
$hash = @{
"Server" = $server
"Status" = "FailedToComeOnline!"
"LastRebootTime" = "$LastReboot"
"CurrentRebootTime" = "FailedToReboot!"
}
$newRow = New-Object PsObject -Property $hash
$rnd = Get-Random -Minimum 5 -Maximum 40
Start-Sleep -Seconds $rnd
Export-Csv D:\RebootResults.csv -InputObject $newrow -Append -Force
"$server did not come online"
exit}#exit script and log failed to come online.
$i++
"Wait for [$server] to come online"
Start-Sleep -Seconds 15
}#end DO
While (-not(Test-path "\\$server\c$"))
$CurrentReboot = Get-EventLog -ComputerName $server -LogName system | Where-Object {$_.EventID -eq '6005'} | Select -ExpandProperty TimeGenerated | select -first 1
$hash = @{
"Server" = $server
"Status" = "RebootSuccessful"
"LastRebootTime" = $LastReboot
"CurrentRebootTime" = "$CurrentReboot"
}
$newRow = New-Object PsObject -Property $hash
$rnd = Get-Random -Minimum 5 -Maximum 40
Start-Sleep -Seconds $rnd
Export-Csv D:\RebootResults.csv -InputObject $newrow -Append -Force
}#End Try.
Catch{
$errMsg = $_.Exception
"Failed with $errMsg"
}
Faites-le à distance:
Rename-Computer -ComputerName $computer -NewName "TESTDC01" -DomainCredential $domain\$username -Force -Restart
Et continuez votre script à partir de cela 8)