Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
citrix:powershell_script_for_batch_update_vda [2019/01/30 09:30] – admin | citrix: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**) либо физических машинах. \\ | ||
+ | Разработка и тестирование этого скрипта проводились в сети с жесткими политиками безопасности, | ||
+ | В процессе тестирования были выявлены проблемы, | ||
+ | ====== Как работает ====== | ||
+ | - Скрипт берет из указанного пула машины, | ||
+ | - Затем обрабатывает каждую машину в отдельном job. Переводит машину в **Maintenance Mode**, включает ее, дожидается включения, | ||
+ | - Затем скачивает с http-сервера **VDA CleanUp Utility** и запускает его. Выполняется удаление **VDA** (с нужным количеством перезагрузок). | ||
+ | - Затем c http-сервера скачивается дистрибутив **VDA**, распаковывается, | ||
+ | - Затем устанавливается **VDA** и проверяется его версия, | ||
+ | - Скрипт способен выполняться параллельно на заданном числе машин. Сведения о проделанной работе сваливаются в файлик. | ||
+ | < | ||
+ | # | ||
+ | |||
+ | $catalogName=' | ||
+ | $MachinesPerRound=15 | ||
+ | $TargetAgentVersion=' | ||
+ | $Citrix_DDC=' | ||
+ | $timeout=1500 | ||
+ | Asnp Citrix* | ||
+ | |||
+ | |||
+ | $jobContent={ | ||
+ | ########################################### | ||
+ | $update_server=' | ||
+ | $VDA_sourcefile=' | ||
+ | $VDA_destfile=' | ||
+ | $VDA_CleanUp_source_file=' | ||
+ | $VDA_CleanUp_dest_file=' | ||
+ | $VDA_ExtractDir=' | ||
+ | $path_to_VDASetup=' | ||
+ | $setupargs='/ | ||
+ | $ApplicationName = ' | ||
+ | $TargetVersion = ' | ||
+ | $Citrix_DDC=' | ||
+ | $logfile=' | ||
+ | |||
+ | $username=' | ||
+ | $password=' | ||
+ | |||
+ | $password = ConvertTo-SecureString $password -asplaintext -force | ||
+ | $credentials = New-Object -Typename System.Management.Automation.PSCredential -argumentlist $username, | ||
+ | $MachineName=$args[0] | ||
+ | $Machine=Get-Brokermachine -MachineName $MachineName -AdminAddress $Citrix_DDC | ||
+ | $node=$Machine.DNSName | ||
+ | ############################################### | ||
+ | |||
+ | function DownloadFile ($node, $credentials, | ||
+ | $link=$update_server+'/' | ||
+ | $posh_string = ' | ||
+ | Write-Host " | ||
+ | $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=' | ||
+ | $file=Get-WmiObject -query $query -Credential $credentials -Computername $node | ||
+ | If ( $file -ne $null ) { | ||
+ | Write-Host " | ||
+ | return ' | ||
+ | else { | ||
+ | Write-Host " | ||
+ | return ' | ||
+ | } | ||
+ | function VDACleanUp ($node, $credentials, | ||
+ | $runstring = 'cmd /c "' | ||
+ | $removerebootflag = 'cmd /c "rmdir /Q /S c: | ||
+ | $executable = Split-Path $cleanuputility -leaf | ||
+ | do { | ||
+ | if ((Get-WMIObject win32_bios -Credential $credentials -Computername $node) -ne $null) { | ||
+ | if ((Get-WmiObject -Class Win32_Directory | ||
+ | if ((Get-WmiObject -Class Win32_Directory -Credential $credentials -Computername $node -Filter " | ||
+ | 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 " | ||
+ | } else { | ||
+ | Write-Host "" | ||
+ | Write-Host " | ||
+ | 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 " | ||
+ | $Win32OS=Get-WMIObject Win32_OperatingSystem -computername $node -Credential $credentials -EnableAllPrivileges | ||
+ | $Win32OS.win32shutdown(6) | Out-Null } | ||
+ | else { Write-Host " | ||
+ | Start-Sleep -Seconds 30 | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | Write-Host " | ||
+ | $cleanup=' | ||
+ | Invoke-WmiMethod -Class win32_process -Name Create -Argumentlist 'cmd /c "rmdir /Q /S c: | ||
+ | $setup_string=' | ||
+ | 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 ' | ||
+ | |||
+ | } | ||
+ | Function ExtractVDA ($node, $credentials, | ||
+ | $executable = Split-Path $VDA_distr -leaf | ||
+ | Write-Host -NoNewLine " | ||
+ | $setup_string = ' | ||
+ | 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 " | ||
+ | while ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where { $_.Name -eq $executable }) -ne $null) | ||
+ | Write-Host "VDA extraction completed!" | ||
+ | $setup_string=' | ||
+ | Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null | ||
+ | return ' | ||
+ | } | ||
+ | function InstallVDA ($node, $credentials, | ||
+ | $executable = Split-Path $path_to_VDASetup -leaf | ||
+ | $setup_string = $VDA_ExtractDir + ' | ||
+ | $iteration=0 | ||
+ | do { | ||
+ | Write-Host -NoNewLine " | ||
+ | Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null | ||
+ | Start-Sleep -Seconds 2 | ||
+ | do {(Write-Host -NoNewLine " | ||
+ | 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 " | ||
+ | Start-Sleep 15 | ||
+ | do { (Write-Host -NoNewLine " | ||
+ | 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 " | ||
+ | } | ||
+ | While ( $VDA_Present -eq $null -and $iteration -lt 3 ) | ||
+ | if ( $VDA_Present -ne $null ) { (Write-Host "VDA Update Completed !!!") | ||
+ | $status=' | ||
+ | else { $status=' | ||
+ | $setup_string=' | ||
+ | Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null | ||
+ | Return $status | ||
+ | } | ||
+ | function InstallPrerequisite ($node, $credentials, | ||
+ | $executable = Split-Path $path_to_setup -leaf | ||
+ | $setup_string = $VDA_ExtractDir + $path_to_setup + ' /q / | ||
+ | Write-Host -NoNewLine ' | ||
+ | Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null | ||
+ | Start-Sleep -Seconds 2 | ||
+ | do {(Write-Host -NoNewLine " | ||
+ | while ((Get-WMIObject -Class Win32_process -Credential $credentials -Computername $node | where { $_.Name -eq $executable }) -ne $null) | ||
+ | Write-Host " | ||
+ | } | ||
+ | function Install_MSU ($node, $credentials, | ||
+ | $link=$update_server+'/' | ||
+ | $destination_file=' | ||
+ | $posh_string = ' | ||
+ | $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=' | ||
+ | $file=Get-WmiObject -query $query -Credential $credentials -Computername $node | ||
+ | if ( $file -ne $null ){ | ||
+ | Write-Host -NoNewLine "Start installation of " $MSU_KBName " | ||
+ | $MSU_ExtractDir=' | ||
+ | $setup_string = ' | ||
+ | $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=' | ||
+ | $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 ' | ||
+ | $setup_string=' | ||
+ | $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 " | ||
+ | if ((Get-WMIObject -Class Win32_QuickFixEngineering -Credential $credentials -Computername $node | Where-Object { $_.HotFixID -like $cabname.split(' | ||
+ | else { (Write-Host ' | ||
+ | $setup_string=' | ||
+ | Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null | ||
+ | $setup_string=' | ||
+ | Invoke-WmiMethod -class Win32_Process -Name Create -Argumentlist $setup_string -Credential $credentials -Computername $node | Out-Null | ||
+ | return $status | ||
+ | } | ||
+ | function CheckVersion ($node, $credentials, | ||
+ | $App = Get-WMIObject -Class Win32_Product -Credential $credentials -Computername $node | Where-Object { $_.Name -like " | ||
+ | If (($App.Version).Equals($TargetVersion)) { | ||
+ | Write-Host ' | ||
+ | return ' | ||
+ | Else { Write-Host ' | ||
+ | return ' | ||
+ | } | ||
+ | function CheckFreeSpace ($node, $credentials){ | ||
+ | $Disk=get-WmiObject win32_logicaldisk -Credential $credentials -Computername $node | Where { $_.DeviceId -eq ' | ||
+ | If ($Disk.FreeSpace -gt 1080000000) { return ' | ||
+ | else { return ' | ||
+ | } | ||
+ | ######################################## | ||
+ | |||
+ | $duration=Measure-Command { | ||
+ | $Result=$node+' | ||
+ | if ($args[0].SessionState -ne ' | ||
+ | $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 | ||
+ | Write-Host -NoNewLine ' | ||
+ | do { (Start-Sleep 5), (Write-Host -NoNewLine ' | ||
+ | while ((Get-WMIObject win32_bios -Credential $credentials -Computername $node) -eq $null) | ||
+ | } | ||
+ | Start-Sleep 30 | ||
+ | # | ||
+ | if ( (CheckVersion -node $node -credentials $credentials -ApplicationName $ApplicationName | ||
+ | #Check FreeSpace on disk | ||
+ | if ((CheckFreeSpace -node $node -credentials $credentials) -eq ' | ||
+ | if ((DownloadFile -node $node -credentials $credentials -update_server $update_server -source_file $VDA_CleanUp_source_file -destination_file $VDA_CleanUp_dest_file) -eq ' | ||
+ | if ((VDACleanUp -node $node -credentials $credentials -cleanuputility $VDA_CleanUp_dest_file) -eq ' | ||
+ | if ((DownloadFile -node $node -credentials $credentials -update_server $update_server -source_file $VDA_sourcefile -destination_file $VDA_destfile) -eq ' | ||
+ | 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 ' | ||
+ | InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup ' | ||
+ | InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup ' | ||
+ | InstallPrerequisite -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_setup ' | ||
+ | if ((Install_MSU -node $node -credentials $credentials -update_server $update_server -MSU_KBName ' | ||
+ | if ((InstallVDA -node $node -credentials $credentials -VDA_ExtractDir $VDA_ExtractDir -path_to_VDASetup $path_to_VDASetup -setupargs $setupargs -ApplicationName $ApplicationName) -eq ' | ||
+ | if ((CheckVersion -node $node -credentials $credentials -ApplicationName $ApplicationName | ||
+ | else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | } else { $result=$result+' | ||
+ | |||
+ | |||
+ | |||
+ | #Check if Machine registered successfully | ||
+ | if ((Get-BrokerMachine -MachineName $MachineName -RegistrationState ' | ||
+ | $result=$result+' | ||
+ | #Revert to Initial MaintenanceMode | ||
+ | Set-BrokerMachineMaintenanceMode -InputObject $MachineName $InitialMaintenanceMode | ||
+ | } | ||
+ | else { | ||
+ | $result=$result+' | ||
+ | New-BrokerHostingPowerAction | ||
+ | } | ||
+ | } | ||
+ | #Revert to Initial Power State | ||
+ | if ( $InitialPowerState -eq ' | ||
+ | $result=$result+' | ||
+ | $Result >> $logfile | ||
+ | } | ||
+ | | ||
+ | |||
+ | ################################################################################################################### | ||
+ | $Filter=' | ||
+ | Get-BrokerMachine -Filter $Filter -ReturnTotalRecordCount -AdminAddress $Citrix_DDC | out-null | ||
+ | $machinescount = $error[0].TotalAvailableResultCount | ||
+ | $rounds=[math]:: | ||
+ | |||
+ | 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=' | ||
+ | if ((Get-Job -name $jobname | Where { $_.State -eq " | ||
+ | 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 " | ||
+ | If ($timer -ge $timeout) { | ||
+ | Write-Host ' | ||
+ | Get-Job | Where { $_.State -eq " | ||
+ | Get-Job | Where { $_.State -eq " | ||
+ | } | ||
+ | Write-Host ' ' | ||
+ | } | ||
+ | |||
+ | </ |