316 lines
14 KiB
PowerShell
316 lines
14 KiB
PowerShell
param(
|
|
[string]$HorizonServer = "",
|
|
[string]$OutFile = "",
|
|
[string]$InputXML = "",
|
|
[switch]$SaveCred = $false,
|
|
[switch]$debug = $false,
|
|
[switch]$help = $false
|
|
)
|
|
|
|
|
|
Write-Host $global:kishorizondebug
|
|
|
|
# Variables
|
|
$fileVersion = "1.1.0"
|
|
$fileDate = "2026-06-24"
|
|
$scriptName = Split-Path -Path $PSCommandPath -Leaf
|
|
$mypath = split-path -parent $MyInvocation.MyCommand.Definition
|
|
$now = (Get-Date).ToString("yyyy-MM-dd_HH:mm")
|
|
$userfolder = $env:USERPROFILE
|
|
|
|
# Display Script Banner
|
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
|
Write-Host "Export Pool Settings to Excel File" -ForegroundColor Green
|
|
Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green
|
|
Write-Host "Written by Charlie Silverman" -ForegroundColor Green
|
|
Write-Host "--------------------------------------------------" -ForegroundColor White
|
|
|
|
function CheckModuleInstalled($moduleName, $command) {
|
|
Write-Host "Checking that package $moduleName is installed..." -NoNewLine
|
|
if (-not(get-command $command -erroraction silentlycontinue)) {
|
|
Write-Host " Missing" -ForegroundColor Red
|
|
if (-not (Get-Module -ListAvailable -Name $moduleName)) {
|
|
$response = ""
|
|
while (($response -ne "yes") -and ($response -ne "no")) {
|
|
$response = (Read-Host "$moduleName module not instaled. Install now? (yes/no)").ToLower()
|
|
}
|
|
if ($response -eq "no") {
|
|
Write-Host "Operation aborted." -ForegroundColor Yellow
|
|
exit
|
|
}
|
|
Write-Host "Installing PowerShell module $moduleName..." -NoNewLine
|
|
Install-Module -Name $moduleName -Scope CurrentUser -Force
|
|
Write-Host " Success" -ForegroundColor Green
|
|
}
|
|
Write-Host "Loading PowerShell module $moduleName..." -NoNewLine
|
|
Import-Module $moduleName
|
|
Write-Host " Success" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " Found" -ForegroundColor Green
|
|
}
|
|
}
|
|
|
|
# Check for ImportExcel and install if missing
|
|
CheckModuleInstalled -moduleName "VCF.PowerCLI" -command "connect-viserver"
|
|
CheckModuleInstalled -moduleName "ImportExcel" -command "Open-ExcelPackage"
|
|
Import-Module $mypath\KISHorizon.psm1
|
|
$abyss = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Scope Session -Confirm:$false
|
|
|
|
if ($Help) {
|
|
Write-Host
|
|
Write-Host "Purpose: Resolve Horizon VMs with errors."
|
|
Write-Host "Command Syntax:"
|
|
Write-Host " $scriptName (-Horizon ""[cluster]"") (-SaveCred)" -ForegroundColor Green
|
|
Write-Host "Command Line Options:"
|
|
Write-Host
|
|
Write-Host -NoNewLine " -Horizon " -ForegroundColor Green
|
|
Write-Host "- The FQDN or IP address of a Horizon connection broker."
|
|
Write-Host -NoNewLine " -SaveCred " -ForegroundColor Green
|
|
Write-Host "- Ask for credentials and save them to current user's profile directory."
|
|
Write-Host
|
|
Write-Host "The Horizon server will be queried for all vCenter servers it is configured for and credentials will be required for each."
|
|
Write-Host "Any information not provided will be prompted for during script execution."
|
|
|
|
exit
|
|
}
|
|
|
|
if ($OutFile -eq "") {
|
|
$OutFile = "KISHorizonExport-$($HorizonServer).xlsx"
|
|
}
|
|
|
|
if (Test-Path -path $Outfile -PathType Leaf) {
|
|
Remove-Item -Path $Outfile
|
|
}
|
|
|
|
if ($inputXML -eq "") {
|
|
if ($HorizonServer -eq "") {
|
|
$HorizonServer = Read-Host "Enter FQDN or IP address of Horizon Connection Broker"
|
|
}
|
|
|
|
if ($SaveCred) {
|
|
$hzcred = Get-Credential -Message "Enter credentials for Horizon server $HorizonServer in the format DOMAIN\USERNAME"
|
|
$hzcred | Export-Clixml -path $userfolder\kistools-$HorizonServer.cred
|
|
Write-Host "Saving credentials."
|
|
}
|
|
|
|
if (Test-Path -path $userfolder\kistools-$HorizonServer.cred -PathType Leaf) {
|
|
$hzcred = Import-Clixml -path $userfolder\kistools-$HorizonServer.cred
|
|
Write-Host "- Using stored Horizon credentials"
|
|
} else {
|
|
$hzcred = Get-Credential -Message "Enter credentials for Horizon server $HorizonServer in the format DOMAIN\USERNAME"
|
|
if (!$hzcreds) {
|
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
|
exit
|
|
}
|
|
}
|
|
|
|
#Establish connection to Horizon
|
|
try {
|
|
Write-Host -NoNewLine "Connecting to Horizon Connection Broker $HorizonServer... "
|
|
$hzconn = Connect-HorizonServer -server $HorizonServer -credential $hzcred
|
|
Write-Host "Success" -ForegroundColor green
|
|
} catch {
|
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
|
Write-Host
|
|
exit
|
|
}
|
|
|
|
# Establish connection to all vCenter servers configured on this Horizon system
|
|
$vcenterlist = $hzconn | Get-HorizonvCenter
|
|
foreach ($thisvc in $vcenterlist) {
|
|
$vcname = $thisvc.server_name
|
|
|
|
if ($SaveCred) {
|
|
$vccred = Get-Credential -Message "Enter credentials for vCenter server $vcname"
|
|
$vccred| Export-Clixml -path $userfolder\kistools-$vcname.cred
|
|
Write-Host "Saving credentials."
|
|
}
|
|
|
|
if (Test-Path -path $userfolder\kistools-$vcname.cred -PathType Leaf) {
|
|
$vccred = Import-Clixml -path $userfolder\kistools-$vcname.cred
|
|
Write-Host "- Using stored vCenter credentials"
|
|
} else {
|
|
$vccred = Get-Credential -Message "Enter credentials for vCenter server $vcname"
|
|
if (!$vccred) {
|
|
Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow
|
|
exit
|
|
}
|
|
}
|
|
|
|
#Establish connection to vCenter
|
|
try {
|
|
Write-Host -NoNewLine "Connecting to vCenter $vcname... "
|
|
$vcconn = Connect-VIServer -server $vcname -Credential $vccred -Force -ErrorAction Stop
|
|
Write-Host "Success" -ForegroundColor green
|
|
} catch {
|
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
|
Write-Host
|
|
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
|
|
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
|
|
exit
|
|
}
|
|
}
|
|
|
|
$pools = $hzconn | Get-HorizonDesktopPool
|
|
} else {
|
|
$pools = Import-CliXml -path $inputXML
|
|
}
|
|
|
|
foreach ($thisvc in $vcenterlist) {
|
|
Write-Host -NoNewLine "Disconnecting from vCenter $vcname... "
|
|
try {
|
|
$abyss = Disconnect-ViServer $thisvc.server_name -confirm:$false
|
|
Write-Host "Success" -ForegroundColor green
|
|
} catch {
|
|
Write-Host "Failure" -ForegroundColor Yellow -BackgroundColor Red -NoNewLine
|
|
Write-Host
|
|
}
|
|
}
|
|
|
|
Write-Host -NoNewLine "Generating Excel File $OutFile... "
|
|
$workbook = Open-ExcelPackage -Path $OutFile -Create
|
|
|
|
#Create Initial Data Worksheet
|
|
$thissheet = Add-Worksheet -ExcelPackage $workbook -WorksheetName "General Horizon Data"
|
|
Set-ExcelRange -worksheet $thissheet -Range "A:A" -VerticalAlignment Top
|
|
Set-Format -Address $thissheet.Cells["B:B"] -WrapText
|
|
$thissheet.column(1).Width = 40
|
|
$thissheet.column(2).Width = 40
|
|
$thissheet.column(3).Width = 40
|
|
Set-ExcelRange -Worksheet $thissheet -Range "A1:E1" -Merge:$true
|
|
$domains = Get-HorizonADDomains -Horizon $hzconn
|
|
$vcenterservers = Get-HorizonvCenter -Horizon $hzconn
|
|
$goldimages = $pools.provisioning_settings.base_vm_name | Select-Object -Unique
|
|
$row = 1
|
|
$thissheet.cells["A1"].value = "General data for Horizon server $HorizonServer"
|
|
Set-Format -Address $thissheet.Cells["A1"] -Bold
|
|
Set-ExcelRange -Worksheet $thissheet -Range "A1" -FontSize 20
|
|
$row += 2
|
|
$thissheet.cells["A" + $row].value = "vCenter Servers"
|
|
Set-Format -Address $thissheet.Cells["A" + $row] -Bold
|
|
Set-ExcelRange -Worksheet $thissheet -Range "A$row" -FontSize 16
|
|
|
|
$row += 1
|
|
$vctabletop = $row
|
|
$thissheet.cells["A" + $row].value = "vCenter Server"
|
|
$thissheet.cells["B" + $row].value = "Version"
|
|
$thissheet.cells["C" + $row].value = "User Account"
|
|
$row += 1
|
|
foreach ($vc in $vcenterlist) {
|
|
$thissheet.cells["A" + $row].value = $vc.server_name
|
|
$thissheet.cells["B" + $row].value = $vc.version
|
|
$thissheet.cells["C" + $row].value = $vc.user_name
|
|
$row += 1
|
|
}
|
|
$vcTableRange = $thissheet.Cells[$vctabletop, 1, ($row-1), 3]
|
|
$vcTable = $thissheet.Tables.Add($vcTableRange, "vCenterList")
|
|
$vcTable.StyleName = "TableStyleMedium15"
|
|
|
|
$row += 1
|
|
$thissheet.cells["A" + $row].value = "Active Directory Domains"
|
|
Set-Format -Address $thissheet.Cells["A" + $row] -Bold
|
|
Set-ExcelRange -Worksheet $thissheet -Range "A$row" -FontSize 16
|
|
$row += 1
|
|
$adtabletop = $row
|
|
$thissheet.cells["A" + $row].value = "DNS Name"
|
|
$thissheet.cells["B" + $row].value = "NetBIOS Name"
|
|
$row += 1
|
|
foreach ($add in $domains) {
|
|
$thissheet.cells["A" + $row].value = $add.dns_name
|
|
$thissheet.cells["B" + $row].value = $add.netbios_name
|
|
$row += 1
|
|
}
|
|
$adTableRange = $thissheet.Cells[$adtabletop, 1, ($row-1), 2]
|
|
$adTable = $thissheet.Tables.Add($adTableRange, "ADDomains")
|
|
$adTable.StyleName = "TableStyleMedium15"
|
|
|
|
$row += 1
|
|
$thissheet.cells["A" + $row].value = "Published Gold Images"
|
|
Set-Format -Address $thissheet.Cells["A" + $row] -Bold
|
|
Set-ExcelRange -Worksheet $thissheet -Range "A$row" -FontSize 16
|
|
$row += 1
|
|
$adtabletop = $row
|
|
$thissheet.cells["A" + $row].value = "Gold Image VMs"
|
|
$thissheet.cells["B" + $row].value = "Pools"
|
|
$row += 1
|
|
foreach ($image in $goldimages) {
|
|
$thissheet.cells["A" + $row].value = $image
|
|
$thissheet.cells["B" + $row].value = (($pools | Where-Object {$_.provisioning_settings.base_vm_name -eq $image}).Name -Join "`r`n")
|
|
$row += 1
|
|
}
|
|
$giTableRange = $thissheet.Cells[$adtabletop, 1, ($row-1), 2]
|
|
$giTable = $thissheet.Tables.Add($giTableRange, "GoldImages")
|
|
$giTable.StyleName = "TableStyleMedium15"
|
|
|
|
foreach ($pool in $pools) {
|
|
$thissheet = Add-Worksheet -ExcelPackage $workbook -WorksheetName $pool.name
|
|
$entitlements = $pool.entitlements | ForEach-Object {
|
|
$_.Domain + "\" + $_.SamAccountName
|
|
}
|
|
|
|
$data = @(
|
|
[pscustomobject]@{Name = "Pool ID";Value=$pool.name}
|
|
[pscustomobject]@{Name = "Display Name";Value=$pool.display_name}
|
|
[pscustomobject]@{Name = "Description";Value=$pool.description}
|
|
[pscustomobject]@{Name = "Type";Value=$pool.session_type}
|
|
[pscustomobject]@{Name = "User Assignment";Value=$pool.user_assignment}
|
|
[pscustomobject]@{Name = "vCenter Server";Value=$pool.vcenter}
|
|
[pscustomobject]@{Name = "Naming Pattern";Value=$pool.pattern_naming_settings.naming_pattern}
|
|
[pscustomobject]@{Name = "Max Machines";Value=$pool.pattern_naming_settings.max_number_of_machines}
|
|
[pscustomobject]@{Name = "Spare Machines";Value=$pool.pattern_naming_settings.number_of_spare_machines}
|
|
[pscustomobject]@{Name = "Min Machines";Value=$pool.pattern_naming_settings.min_number_of_machines}
|
|
[pscustomobject]@{Name = "Datacenter";Value=$pool.provisioning_settings.datacenter_name}
|
|
[pscustomobject]@{Name = "Resource Pool";Value=$pool.provisioning_settings.resource_pool_name}
|
|
[pscustomobject]@{Name = "Parent VM";Value=$pool.provisioning_settings.base_vm_name}
|
|
[pscustomobject]@{Name = "Snapshot Path";Value=$pool.provisioning_settings.snapshot_path}
|
|
[pscustomobject]@{Name = "VM Folder Path";Value=$pool.provisioning_settings.base_folder_path}
|
|
[pscustomobject]@{Name = "Cluster";Value=$pool.cluster}
|
|
[pscustomobject]@{Name = "Resource Pool";Value=$pool.provisioning_settings.resource_pool_name}
|
|
[pscustomobject]@{Name = "Datacenter";Value=$pool.provisioning_settings.datacenter_name}
|
|
[pscustomobject]@{Name = "Datastores";Value=$pool.storage_settings.datastores.name -join "`r`n"}
|
|
[pscustomobject]@{Name = "Network";Value=($pool.machines.managed_machine_data.network_labels.network_label_name | Select-Object -Unique | Sort-Object) -join "`r`n"}
|
|
[pscustomobject]@{Name = "Use vSAN";Value=$pool.storage_settings.use_vsan}
|
|
[pscustomobject]@{Name = "Add Virtual TPM";Value=$pool.provisioning_settings.add_virtual_tpm}
|
|
[pscustomobject]@{Name = "vGPU Enabled";Value=$pool.GpuEnabled}
|
|
[pscustomobject]@{Name = "Customization Type";Value=$pool.customization_settings.customization_type}
|
|
[pscustomobject]@{Name = "Ad Container";Value=$pool.customization_settings.ad_container_rdn}
|
|
[pscustomobject]@{Name = "Reuse Existing AD Object";Value=$pool.customization_settings.reuse_pre_existing_accounts}
|
|
[pscustomobject]@{Name = "Cloneprep Script Settings";Value=$pool.customization_settings.cloneprep_script_settings}
|
|
[pscustomobject]@{Name = "Power Off Script Name";Value=$pool.customization_settings.cloneprep_customization_settings.power_off_script_name}
|
|
[pscustomobject]@{Name = "Power Off Script Parameters";Value=$pool.customization_settings.cloneprep_customization_settings.power_off_script_parameters}
|
|
[pscustomobject]@{Name = "Post Sync Script Name";Value=$pool.customization_settings.cloneprep_customization_settings.post_synchronization_script_name}
|
|
[pscustomobject]@{Name = "Post Sync Script Parameters";Value=$pool.customization_settings.cloneprep_customization_settings.post_synchronization_script_parameters}
|
|
[pscustomobject]@{Name = "Automatic Logoff Policy";Value=$pool.session_settings.disconnected_session_timeout_policy}
|
|
[pscustomobject]@{Name = "Automatic Logoff Minutes";Value=$pool.session_settings.disconnected_session_timeout_minutes}
|
|
[pscustomobject]@{Name = "Allow Users to Reset Machines";Value=$pool.session_settings.allow_users_to_reset_machines}
|
|
[pscustomobject]@{Name = "Allow Multiple Sessions Per User";Value=$pool.session_settings.allow_multiple_sessions_per_user}
|
|
[pscustomobject]@{Name = "Used VM Policy";Value=$pool.session_settings.delete_or_refresh_machine_after_logoff}
|
|
[pscustomobject]@{Name = "Logoff After Timeout";Value=$pool.session_settings.disconnected_session_timeout_policy}
|
|
[pscustomobject]@{Name = "Supported Display Protocols";Value=$pool.display_protocol_settings.display_protocols -join "`r`n"}
|
|
[pscustomobject]@{Name = "Default Display Protocol";Value=$pool.display_protocol_settings.default_display_protocol}
|
|
[pscustomobject]@{Name = "Allow Users to Choose Protocol";Value=$pool.display_protocol_settings.allow_users_to_choose_protocol}
|
|
[pscustomobject]@{Name = "External HTML Access";Value=$pool.display_protocol_settings.html_access_enabled}
|
|
[pscustomobject]@{Name = "Enable Collaboration";Value=$pool.display_protocol_settings.session_collaboration_enabled}
|
|
[pscustomobject]@{Name = "Entitlements";Value=$entitlements}
|
|
)
|
|
|
|
$rowcount = 1
|
|
foreach ($datum in $data) {
|
|
$thissheet.cells["A" + $rowcount].Value = $datum.name
|
|
$thissheet.cells["B" + $rowcount].Value = $datum.value
|
|
$rowcount += 1
|
|
}
|
|
|
|
$thissheet.Column(1).Style.HorizontalAlignment = "Right"
|
|
$thissheet.Column(1).Width = 40
|
|
$thissheet.Column(2).Width = 200
|
|
Set-Column -ExcelPackage $workbook -WorksheetName $pool.Name -Column 2 -WrapText
|
|
Set-Column -ExcelPackage $workbook -WorksheetName $pool.Name -Column 2 -HorizontalAlignment Left
|
|
Set-Column -ExcelPackage $workbook -WorksheetName $pool.Name -Column 1 -VerticalAlignment Top
|
|
Set-ExcelRange -Worksheet $thissheet -Range "A:B" -FontSize 14
|
|
$thissheet.cells["A:A"].Style.Indent = 2
|
|
Set-ExcelRange -Worksheet $thissheet -Range "B:B" -Bold
|
|
}
|
|
Close-ExcelPackage $workbook
|
|
Write-Host "Success" -ForegroundColor green
|