Public/Invoke-CitrixRestart.ps1

<#
.SYNOPSIS
    Restarts Citrix machines.
 
.DESCRIPTION
    This function restarts Citrix machines using the specified DDC server.
 
.PARAMETER UserName
    Specifies the username used for authentication.
 
.PARAMETER ComputerName
    Specifies the name of the Citrix machine to be restarted.
 
.PARAMETER DDC
    Specifies the Delivery Controller (DDC) server for Citrix.
 
.PARAMETER DecryptPath
    Specifies the path to the file containing the encrypted password.
 
.EXAMPLE
    Invoke-CitrixRestart -UserName "domain\user" -ComputerName "CitrixServer" -DDC "DDCServer" -DecryptPath "C:\PPD\RPA\RPA_Logoff_Reboot_Tool\RPA.encrypted"
 
    This example restarts the Citrix server named "CitrixServer" using the specified DDC server and the provided username/password.
     
.NOTES
    Requires Citrix PowerShell SDK and appropriate administrative credentials.
#>

function Invoke-CitrixRestart {
    param (
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$UserName,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$ComputerName,

        [Parameter(Mandatory)]
        [string]$DDC,

        [Parameter(Mandatory)]
        [string]$DecryptPath
    )

    # Get the decrypted password from the file
    $Key = [byte[]](1..16)
    $DecryptedPassword = Get-Content -Path $DecryptPath | ConvertTo-SecureString -Key $Key
    $Credential = New-Object System.Management.Automation.PSCredential($UserName, $DecryptedPassword)

    $startTime = Get-Date
    $LOGGING_FILENAME = "RPAConfigTool.log"
    $logfile = [System.IO.StreamWriter]::new($env:APPDATA+"\"+$LOGGING_FILENAME, $true)
    $logfile.WriteLine((Get-Date -Format G) + " - " + "Citrix Restart on $ComputerName Started at: $startTime")

    $ScriptBlock = {
        param (
            $Param1,
            $Param2
        )

        $statusCode = 0  # 0: Success, 1: Failure

        foreach ($c in $Param2) {
            try {
                # Check if computer is pingable
                $pingable = Test-Connection -ComputerName $c -Count 1 -Quiet

                if ($pingable) {
                    # Restart Citrix machine
                    $restartResult = New-BrokerHostingPowerAction -AdminAddress $Param1 -Action Restart -MachineName $c -ErrorAction SilentlyContinue
                    Start-Sleep -Seconds 20
                    if ($null -eq $restartResult) {
                        $statusCode = 1  # Set status code to indicate failure
                    } else {
                        # Wait until the Citrix machine is registered
                        do {
                            try {
                                $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $c)
                                $RegKey = $Reg.OpenSubKey("SOFTWARE\Citrix\VirtualdesktopAgent\state")
                                $Value = $RegKey.GetValue("Registered")

                                # Check if the value is 0 (Initializing), wait if not
                                if ($Value -eq 0) {
                                    Start-Sleep -Seconds 10
                                }
                            } catch {
                                # Ignore remote registry errors silently
                            }
                        } while ($Value -ne 2)  # Continue loop until registered (value 2)
                    }
                } else {
                    Write-Host "Computer $c is not pingable. Skipping Citrix restart."
                    $statusCode = 1  # Set status code to indicate failure
                }
            } catch {
                Write-Host "Error occurred while processing $c : $_"
                $statusCode = 1  # Set status code to indicate failure
            }
        }

        $statusCode  # Return the status code
    }

    # Start the job and wait for it to complete with a timeout
    $timeout = 300 # Set your desired timeout in seconds
    $Job = Start-Job -ScriptBlock $ScriptBlock -ArgumentList $DDC, $ComputerName -Credential $Credential
    $statusCode = Wait-Job $Job -Timeout $timeout | Receive-Job

    $RestartEndTime = Get-Date
    $RestartDuration = $RestartEndTime - $startTime
    $logfile.WriteLine("Citrix machine $ComputerName is now registered. Restart Duration: $RestartDuration")
    $logfile.WriteLine((Get-Date -Format G) -f " - $ComputerName Registered at: $RestartEndTime")
    $logfile.WriteLine((Get-Date -Format G) + " - " + "Total time taken to register the $ComputerName : $RestartDuration")

    Remove-Job $Job -Force

    $statusCode  # Return the status code
    $logfile.Close()
}