Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
citrix:powershell_script_for_batch_update_vda [2019/01/30 09:30] admincitrix:powershell_script_for_batch_update_vda [2019/02/11 09:13] (current) – external edit 127.0.0.1
Line 1: Line 1:
 +====== Для чего это всё ======
 +Данный скрипт предназначен для массового апдейта **Citrix VDA** (в моем случае с версии 7.8 до 7.15) на виртуальных (**Machine Creation Service**) либо физических машинах. \\
 +Разработка и тестирование этого скрипта проводились в сети с жесткими политиками безопасности, где запрещены файловые шары, невозможно использование **RPC** (в том числе **psexec.exe** - на машинах выключена служба "Сервер"), невозможно использование удаленного **powershell**, запрещена даже установка пакетов **MSU** с помощью **wusa.exe**.  Есть только учетные данные локального администратора. Все манипуляции на удаленных машинах производятся с помощью вызова методов **WMI**. \\
 +В процессе тестирования были выявлены проблемы, связанные с библиотеками **С++** (ошибки **1603**, **1157** и **1723**). Решение этой проблемы - [[citrix:vda_7.x_installation_error_1723_applycomsecuritycustomaction|ТУТ.]]
  
 +====== Как работает ======
 +  - Скрипт берет из указанного пула машины, версия **VDA** на которых не соответствует целевой. 
 +  - Затем обрабатывает каждую машину в отдельном job. Переводит машину в **Maintenance Mode**, включает ее, дожидается включения, затем проверяет версию установленного **VDA** средствами **WMI** (на случай, если нужная версия уже установлена, но машина не регистрируется и на **DDC** новая версия не видна).
 +  - Затем скачивает с http-сервера **VDA CleanUp Utility** и запускает его. Выполняется удаление **VDA** (с нужным количеством перезагрузок). 
 +  - Затем c http-сервера скачивается дистрибутив **VDA**, распаковывается, устанавливаются **prerequisites**, устанавливается нужный апдейт(ы) (пакет **MSU**). 
 +  - Затем устанавливается **VDA** и проверяется его версия, а также возможность регистрации на **DDC**. 
 +  - Скрипт способен выполняться параллельно на заданном числе машин. Сведения о проделанной работе сваливаются в файлик. 
 +<code>
 +#$ErrorActionPreference='SilentlyContinue'
 +
 +$catalogName='Developers'                         # Citrix Machine Catalog name
 +$MachinesPerRound=15                              # Number of simultaneously upgraded machines
 +$TargetAgentVersion='7.15.0.15097'                # Verision of VDA, showed in Citrix Studio and Director
 +$Citrix_DDC='ddc.domain.local'                    # FQDN of Citrix Delivery Controller
 +$timeout=1500                                     # Timeout for jobs in seconds
 +Asnp Citrix*
 +
 +
 +$jobContent={
 +    ########################################### Job Block ############################################################ 
 +            $update_server='http://updates.domain.local'                                         # HTTP Resource from which updates to be downloaded
 +            $VDA_sourcefile='VDAWorkstationSetup_7.15.exe'                                       # VDA distr file name on update server
 +            $VDA_destfile='c:\windows\temp\VDAWorkstationSetup_7.15.exe'                         # VDA distr file name on target machine
 +            $VDA_CleanUp_source_file='VDACleanupUtility.exe'                                     # VDA CleanUpUtility file name on update server
 +            $VDA_CleanUp_dest_file='c:\windows\temp\VDACleanupUtility.exe'                       # VDA CleanUpUtility file name on target machine
 +            $VDA_ExtractDir='c:\windows\temp\VDA_Install\'                                       # 
 +            $path_to_VDASetup='\Extract\Image-full\x64\XenDesktop Setup\XenDesktopVdaSetup.exe'  # Path to XenDesktopVDASetup.exe file
 +            $setupargs='/quiet /components VDA /controllers "ddc.domain.local ddc2.domain.local" /remotepc /optimize /virtualmachine /enable_hdx_ports /enable_real_time_transport'
 +            $ApplicationName = 'Citrix Virtual Desktop Agent - x64'
 +            $TargetVersion = '7.15.0.82' ### Version of $ApplicationName (Citrix Virtual Desktop Agent - x64) component 
 +            $Citrix_DDC='ddc.domain.local'
 +            $logfile='c:\temp\VDA_Update_Results.txt'
 +
 +            $username='.\Администратор'
 +            $password='P@ssw0rd'
 +
 +            $password = ConvertTo-SecureString $password -asplaintext -force
 +            $credentials = New-Object -Typename System.Management.Automation.PSCredential -argumentlist $username,$password
 +            $MachineName=$args[0]
 +            $Machine=Get-Brokermachine -MachineName $MachineName -AdminAddress $Citrix_DDC
 +            $node=$Machine.DNSName
 +    ############################################### Functions ##################################################
 +
 +            function DownloadFile ($node, $credentials, $update_server, $source_file, $destination_file) {
 +                $link=$update_server+'/'+$source_file
 +                $posh_string = 'powershell -nop -exec bypass -c (New-Object Net.WebClient).DownloadFile(' + '''' + $link + '''' + ', ' + '''' + $destination_file + '''' + ')'
 +                Write-Host "Starting download file" $link to $destination_file
 +                $proc=Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $posh_string -Credential $credentials -Computername $node
 +                $duration=Measure-Command { 
 +                    do {
 +                    Start-Sleep -Seconds 1 
 +                    } 
 +                    until ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where {$_.ProcessID -eq $proc.ProcessId}) -eq $null)
 +                }
 +                $query='Select * From CIM_datafile Where Name = ' + ''''+($destination_file -replace '\\', '\\')+''''
 +                $file=Get-WmiObject -query $query -Credential $credentials -Computername $node
 +                If ( $file -ne $null ) { 
 +                    Write-Host "Download completed in" $([math]::Round($duration.TotalSeconds,1)) "Seconds"
 +                    return 'OK' }
 +                else { 
 +                Write-Host "Download Failed"
 +                return 'DWNLD_FAILED' }
 +            }
 +            function VDACleanUp ($node, $credentials, $cleanuputility) {
 +            $runstring = 'cmd /c "'+ $cleanuputility + ' /unattended && mkdir c:\windows\temp\vdacleanup_ok || mkdir c:\windows\temp\reboot_needed"'
 +            $removerebootflag = 'cmd /c "rmdir /Q /S c:\windows\temp\reboot_needed"'
 +            $executable = Split-Path $cleanuputility -leaf
 +            do {
 +                if ((Get-WMIObject win32_bios -Credential $credentials -Computername $node) -ne $null) {
 +                    if ((Get-WmiObject -Class Win32_Directory  -Credential $credentials -Computername $node -Filter "Name='c:\\windows\\temp\\vdacleanup_ok'") -eq $null) {
 +                        if ((Get-WmiObject -Class Win32_Directory -Credential $credentials -Computername $node -Filter "Name='c:\\windows\\temp\\reboot_needed'") -eq $null) {
 +                            if ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where {$_.Name -eq $executable}) -eq $null) {
 +                                Write-Host -NoNewLine 'VDA CleanUp in progress...'
 +                                $proc=Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $runstring -Credential $credentials -Computername $node
 +                                Start-Sleep -Seconds 10
 +                            } else { (Write-Host -NoNewLine "."), (Start-Sleep -Seconds 3) }
 +                        } else {
 +                        Write-Host ""
 +                        Write-Host "Rebooting..."
 +                        Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $removerebootflag -Credential $credentials -Computername $node | Out-Null
 +                        Start-Sleep -Seconds 4
 +                        if ((Get-WmiObject -Class Win32_Directory -Credential $credentials -Computername $node -Filter "Name='c:\\windows\\temp\\reboot_needed'") -eq $null) {
 +                            $Win32OS=Get-WMIObject Win32_OperatingSystem -computername $node -Credential $credentials -EnableAllPrivileges
 +                            $Win32OS.win32shutdown(6) | Out-Null }
 +                        else { Write-Host "Cannot remove c:\windows\temp\reboot_needed..." }
 +                        Start-Sleep -Seconds 30 
 +                        }
 +                    }
 +                    else {
 +                        Write-Host "CleanUp Completed"
 +                        $cleanup='OK'
 +                        Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist 'cmd /c "rmdir /Q /S c:\windows\temp\vdacleanup_ok"' -Credential $credentials -Computername $node  | Out-Null
 +                        $setup_string='cmd /c "del /F /Q /S '+$cleanuputility+'"'
 +                        Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                        return $cleanup
 +                    }
 +                }
 +                else {Start-Sleep -Seconds 15}
 +            }
 +            while ($cleanup -ne 'OK')
 +
 +            }
 +            Function ExtractVDA ($node, $credentials, $VDA_distr, $VDA_ExtractDir) {
 +                $executable = Split-Path $VDA_distr -leaf
 +                Write-Host -NoNewLine "Extracting VDA..."
 +                $setup_string = 'cmd.exe /c "mkdir ' + $VDA_ExtractDir +'"'
 +                Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                $setup_string = $VDA_distr + ' /extract '+ $VDA_ExtractDir
 +                Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                Start-Sleep -Seconds 1
 +                do {(Write-Host -NoNewLine ".."), (Start-Sleep -Seconds 1)}
 +                while ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where { $_.Name -eq $executable }) -ne $null)
 +                Write-Host "VDA extraction completed!"
 +                $setup_string='cmd /c "del /F /Q /S '+$VDA_distr+'"'
 +                Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                return 'OK'
 +            }
 +            function InstallVDA ($node, $credentials, $VDA_ExtractDir, $path_to_VDASetup, $setupargs, $ApplicationName) {
 +                $executable = Split-Path $path_to_VDASetup -leaf
 +                $setup_string = $VDA_ExtractDir + '\' + $path_to_VDASetup + ' ' + $setupargs
 +                $iteration=0
 +                do {
 +                    Write-Host -NoNewLine "Setting up VDA... Running" $executable
 +                    Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                    Start-Sleep -Seconds 2
 +                    do {(Write-Host -NoNewLine "."), (Start-Sleep -Seconds 1)}
 +                    while ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where { $_.Name -eq $executable }) -ne $null)
 +                    $Win32OS=Get-WMIObject Win32_OperatingSystem -computername $node -Credential $credentials -EnableAllPrivileges
 +                    $Win32OS.win32shutdown(6) | Out-Null
 +                    Write-Host ""
 +                    Write-Host -NoNewLine "Rebooting..."
 +                    Start-Sleep 15
 +                    do { (Write-Host -NoNewLine "."), (Start-Sleep 15) }
 +                    While ((Get-WMIObject win32_bios -Credential $credentials -Computername $node) -eq $null)
 +                    $iteration++
 +                    $VDA_Present=Get-WMIObject -Class Win32_Product -Credential $credentials -Computername $node | Where-Object { $_.Name -like "*"+$ApplicationName+"*" }
 +                }
 +                While ( $VDA_Present -eq $null -and $iteration -lt 3 )
 +                if ( $VDA_Present -ne $null ) { (Write-Host "VDA Update Completed !!!")
 +                $status='OK' }
 +                else { $status='VDA_Not_Installed' }
 +                $setup_string='cmd /c "rmdir /Q /S '+$VDA_ExtractDir +'"'
 +                Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                Return $status
 +            }
 +            function InstallPrerequisite ($node, $credentials, $VDA_ExtractDir, $path_to_setup) {
 +                $executable = Split-Path $path_to_setup -leaf
 +                $setup_string = $VDA_ExtractDir + $path_to_setup + ' /q /norestart'
 +                Write-Host -NoNewLine 'Setting up ' $setup_string
 +                Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                Start-Sleep -Seconds 2
 +                do {(Write-Host -NoNewLine "."), (Start-Sleep -Seconds 1)}
 +                while ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where { $_.Name -eq $executable }) -ne $null) 
 +                Write-Host "Complete!"
 +            }
 +            function Install_MSU ($node, $credentials, $update_server, $MSU_KBName) {
 +                $link=$update_server+'/'+$MSU_KBName
 +                $destination_file='c:\windows\temp\'+$MSU_KBName
 +                $posh_string = 'powershell -nop -exec bypass -c (New-Object Net.WebClient).DownloadFile(' + '''' + $link + '''' + ', ' + '''' + $destination_file + '''' + ')'
 +                $proc=Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $posh_string -Credential $credentials -Computername $node
 +                do {Start-Sleep -Seconds 1} 
 +                until ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where {$_.ProcessID -eq $proc.ProcessId}) -eq $null)
 +                $query='Select * From CIM_datafile Where Name = ' + ''''+($destination_file -replace '\\', '\\')+''''
 +                $file=Get-WmiObject -query $query -Credential $credentials -Computername $node
 +                if ( $file -ne $null ){
 +                    Write-Host -NoNewLine "Start installation of " $MSU_KBName "...."
 +                    $MSU_ExtractDir='c:\windows\temp\'+($destination_file -replace '\.[^.\\/]+$').split('\')[-1]
 +                    $setup_string = 'cmd.exe /c "mkdir ' + $MSU_ExtractDir +'"'
 +                    $proc=Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                    do {Start-Sleep -Seconds 1} 
 +                    until ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where {$_.ProcessID -eq $proc.ProcessId}) -eq $null)
 +                    $setup_string='wusa.exe '+$destination_file+' /extract:'+$MSU_ExtractDir 
 +                    $proc=Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                    do {Start-Sleep -Seconds 1} 
 +                    until ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where {$_.ProcessID -eq $proc.ProcessId}) -eq $null)
 +                    $cabname=($destination_file -replace '\.[^.\\/]+$').split('\')[-1] +'.cab'
 +                    $setup_string='cmd.exe /c "dism.exe /online /add-package /PackagePath:'+$MSU_ExtractDir+'\'+$cabname+'"'
 +                    $proc=Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                    do {Start-Sleep -Seconds 1} 
 +                    until ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where {$_.ProcessID -eq $proc.ProcessId}) -eq $null)
 +                    Start-Sleep -Seconds 15
 +                }
 +                else { (Write-Host "Download " $MSU_KBName "failed"), ($status='DWNLD_FAILED') }
 +                if ((Get-WMIObject -Class Win32_QuickFixEngineering -Credential $credentials -Computername $node | Where-Object { $_.HotFixID -like $cabname.split('-')[-2] }) -ne $null){(Write-Host 'Installation of ' $MSU_KBName 'completed!'), ($status='OK')}
 +                else { (Write-Host 'Installation of ' $MSU_KBName 'NOT completed!'), ($status='INSTALLATION_NOT_COMPLETED') }
 +                $setup_string='cmd /c "del /F /Q /S '+$destination_file+'"'
 +                Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                $setup_string='cmd /c "rmdir /Q /S '+$MSU_ExtractDir+'"'
 +                Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null
 +                return $status
 +            }
 +            function CheckVersion ($node, $credentials, $ApplicationName, $TargetVersion) {
 +                $App = Get-WMIObject -Class Win32_Product -Credential $credentials -Computername $node | Where-Object { $_.Name -like "*"+$ApplicationName+"*" }
 +                If (($App.Version).Equals($TargetVersion)) { 
 +                    Write-Host 'Installed version of the' $ApplicationName 'match target version'
 +                    return 'OK' }
 +                Else  { Write-Host 'Installed version of the' $ApplicationName 'NOT match target version'
 +                    return 'VersionBAD'}
 +            }
 +            function CheckFreeSpace ($node, $credentials){
 +                $Disk=get-WmiObject win32_logicaldisk -Credential $credentials -Computername $node | Where { $_.DeviceId -eq 'C:' }
 +                If ($Disk.FreeSpace -gt 1080000000) { return 'OK'}
 +                else { return 'LowDiskSpace'}
 +            }
 +    ######################################## Script ########################################################
 +
 +            $duration=Measure-Command {
 +            $Result=$node+' '
 +            if ($args[0].SessionState -ne 'Active') {
 +            $InitialMaintenanceMode=(Get-BrokerMachine -MachineName $MachineName).InMaintenanceMode
 +            $InitialPowerState=(Get-BrokerMachine -MachineName $MachineName).PowerState
 +            #Enable MaintenanceMode
 +            Set-BrokerMachineMaintenanceMode -InputObject $MachineName $true
 +            if ((Get-BrokerMachine -MachineName $MachineName | fl InMaintenanceMode) -ne $null) {
 +                if ((Get-WMIObject win32_bios -Credential $credentials -Computername $node) -eq $null) { 
 +                    #PowerOn Machine
 +                    New-BrokerHostingPowerAction  -Action "TurnOn" -MachineName $MachineName
 +                    Write-Host -NoNewLine 'Starting Machine ' $node 
 +                    do { (Start-Sleep 5), (Write-Host -NoNewLine '.') }
 +                    while ((Get-WMIObject win32_bios -Credential $credentials -Computername $node) -eq $null)
 +                } 
 +                Start-Sleep 30
 +                #CheckVersion
 +                if ( (CheckVersion -node $node -credentials $credentials -ApplicationName $ApplicationName  -TargetVersion $TargetVersion) -ne 'OK' ) {
 +                    #Check FreeSpace on disk
 +                    if ((CheckFreeSpace -node $node -credentials $credentials) -eq 'OK') {
 +                        if ((DownloadFile -node $node -credentials $credentials -update_server $update_server -source_file $VDA_CleanUp_source_file -destination_file $VDA_CleanUp_dest_file) -eq 'OK') {
 +                            if ((VDACleanUp -node $node -credentials $credentials -cleanuputility $VDA_CleanUp_dest_file) -eq 'OK') {
 +                                if ((DownloadFile -node $node -credentials $credentials -update_server $update_server -source_file $VDA_sourcefile -destination_file $VDA_destfile) -eq 'OK') {
 +                                    ExtractVDA -node $node -credentials $credentials -VDA_distr $VDA_destfile -VDA_ExtractDir $VDA_ExtractDir
 +                                    InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup '\Extract\Image-Full\Support\VcRedist_2013_RTM\vcredist_x86.exe'
 +                                    InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup '\Extract\Image-Full\Support\VcRedist_2013_RTM\vcredist_x64.exe'
 +                                    InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup '\Extract\Image-Full\Support\VcRedist_2015\vc_redist.x86.exe'
 +                                    InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup '\Extract\Image-Full\Support\VcRedist_2015\vc_redist.x64.exe'
 +                                    if ((Install_MSU -node $node -credentials $credentials -update_server $update_server -MSU_KBName 'Windows6.1-KB2999226-x64.msu') -eq 'OK') {
 +                                        if ((InstallVDA -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_VDASetup $path_to_VDASetup -setupargs $setupargs -ApplicationName $ApplicationName) -eq 'OK') {
 +                                            if ((CheckVersion -node $node -credentials $credentials -ApplicationName $ApplicationName  -TargetVersion $TargetVersion) -eq 'OK'){ $result=$result+'VDA Installed. Version Checked.' }
 +                                            else { $result=$result+'VDA Present, But Version Mismatch.'}
 +                                        } else {  $result=$result+'VDA NOT Installed.' }
 +                                    } else {  $result=$result+'MSU Install failed.' }
 +                                } else {  $result=$result+'VDA Download Failed.' }
 +                            } else {  $result=$result+'VDA CleanUp Failed.' }
 +                        } else {  $result=$result+'VDA CleanUp Utility Download Failed.' }
 +                    } else { $result=$result+'Not enough disk free space.'}
 +                } else {  $result=$result+'No need to upgrade VDA.' }
 +            } else { $result=$result+'Can not enable maintenance mode.' }
 +
 +
 +
 +            #Check if Machine registered successfully
 +            if ((Get-BrokerMachine -MachineName $MachineName -RegistrationState 'Registered') -ne $null) {
 +            $result=$result+' Machine Registered.' 
 +            #Revert to Initial MaintenanceMode
 +            Set-BrokerMachineMaintenanceMode -InputObject $MachineName $InitialMaintenanceMode
 +            }
 +                else {
 +                $result=$result+' Machine UnRegistered. Leave Machine in Maintenance Mode.'
 +                New-BrokerHostingPowerAction  -Action "ShutDown" -MachineName $MachineName
 +                }
 +            }
 +            #Revert to Initial Power State
 +            if ( $InitialPowerState -eq 'Off' ) { New-BrokerHostingPowerAction  -Action "ShutDown" -MachineName $MachineName } 
 +            $result=$result+' Initial Maintenance Mode - '+ $InitialMaintenanceMode + "Job completed in" $([math]::Round($duration.TotalSeconds,1)) "Seconds."
 +            $Result >> $logfile
 +            }
 +   }########################################## End of Job #######################################################
 +
 +###################################################################################################################
 +$Filter='CatalogName -like "'+$catalogName+'" -and AgentVersion -ne "'+$TargetAgentVersion+'"'
 +Get-BrokerMachine -Filter $Filter -ReturnTotalRecordCount -AdminAddress $Citrix_DDC | out-null
 +$machinescount = $error[0].TotalAvailableResultCount
 +$rounds=[math]::floor($machinescount / $MachinesPerRound)
 +
 +for ( $round=0; $round -le $rounds; $round++) {
 +    Write-Host 'Round - ' $round
 +    Get-Brokermachine -Filter $Filter -Skip ($round*$MachinesPerRound) -MaxRecordCount $MachinesPerRound -AdminAddress $Citrix_DDC | Select MachineName
 +    Get-Brokermachine -Filter $Filter -Skip ($round*$MachinesPerRound) -MaxRecordCount $MachinesPerRound -AdminAddress $Citrix_DDC | ForEach-Object {
 +    $jobname='VDA_Install_'+$_.HostedMachineName
 +    if ((Get-Job -name $jobname | Where { $_.State -eq "Running" } ) -eq $null) {
 +        Start-Job -name $jobname -initializationScript { Asnp Citrix* } -ArgumentList $_.MachineName -scriptblock $jobContent | out-null }
 +}
 +$timer=0
 +Do { 
 +    Start-Sleep 10
 +    Write-Host -NoNewline '.'
 +    $timer=$timer + 10
 +    }
 +while ((Get-Job | Where { $_.State -eq "Running" }) -ne $null -and $timer -lt $timeout)
 +If ($timer -ge $timeout) { 
 +    Write-Host 'Timeout for Jobs:'
 +    Get-Job | Where { $_.State -eq "Running" } | Select Name
 +    Get-Job | Where { $_.State -eq "Running" } | Stop-Job
 +}
 +Write-Host ' '
 +}
 +
 +</code>
  • citrix/powershell_script_for_batch_update_vda.txt
  • Last modified: 2019/02/11 09:13
  • by 127.0.0.1