SFDiagnostics.psm1

<#
Rene Alfonso Version 3.0
9/02/2021
  
READ ME
This script will perform various checks for StoreFront
Use PowerShell ISE executing under Administrator account
DO NOT Execute under X86 Environment
   
To Execture
Perform-SFDiagnostics
 
Data gathered based
https://support.citrix.com/article/CTX207518
https://support.citrix.com/article/CTX207162
 
#>

#==============================================================================================

#Requires -RunAsAdministrator

Function Write-Div([string] $DIVPath) {
 
    Write-Output `
        "----------------------------------------------------------------------------------------------------------------------" >> "$DIVPath"
}
 
Function Get-SFSdkData([string] $OutputPath) {
 
    Write-Host "Getting PS SDK Data..." | Tee-Object -FilePath $OutputPath -Append
    Get-STFVersion  >> $OutputPath
    #Get-STFAuthenticationService >> $OutputPath
    #Get-STFServiceMonitor >> $OutputPath
    $stores = Get-STFStoreService
 
    Write-Output "StoreFront Stores Configuration Get-STFStoreService Output" | Tee-Object -FilePath $OutputPath -Append
 
    foreach ($store in $stores) {
        Write-Output "$($store.FriendlyName) ==============================================================================" >> $OutputPath
        Write-Output $store >> $OutputPath
        Write-Output "Advanced Settings =============================================================================" >> $OutputPath
        Write-Output $store.FarmsConfiguration >> $OutputPath
   
        foreach ($farm in $store.FarmsConfiguration.Farms) {
            Write-Output "Controller Settings =============================================================================" >> $OutputPath
            Write-Output $farm >> $OutputPath
            #Test-CTXGateway( $OutputPath, $gateway)
            foreach ($server in $farm.Servers) {
                Write-Output "Testing DDC $server =============================================================================" >> $OutputPath
                 
                Try {
                    Resolve-DnsName -Name $server  -ErrorAction Stop  >>  $OutputPath
                }
                catch {
                    Write-Output "$_.Exception.Message $server DNS Failed"   | Tee-Object -FilePath $OutputPath -Append
                 
                }

                Test-NetConnection $server >>  $OutputPath
                Check-CVADHealth $server $OutputPath
            }
        }
 
        foreach ($gateway in $store.Gateways) {
            Write-Output "Gateways =============================================================================" >> $OutputPath
            Write-Output $gateway >> $OutputPath
            #Test-CTXGateway( $OutputPath, $gateway)
            foreach ($gw in $gateway.Hostnames) {
                Write-Output "Testing Gateway $gateway =============================================================================" >> $OutputPath
                 
                Try {
                    Resolve-DnsName -Name $gw -ErrorAction Stop  >>  $OutputPath
                }
                catch {
                    Write-Output "$_.Exception.Message $gw DNS Failed"   | Tee-Object -FilePath $OutputPath -Append
                 
                }

                Test-NetConnection $gw >>  $OutputPath
            }

        }
 
 
    }
 
 
 
}
 
Function Check-CVADHealth(
 [string] $DDC,
 [string] $OutputPath)
 {
 #https://support.citrix.com/article/CTX238581
 Write-Output "Check-CVADHealth Controller = $DDC" | Out-File $OutputPath  -Append
 Invoke-Command -ComputerName $DDC  -ScriptBlock{
 asnp *Citrix*


 Write-Output "Get-ConfigRegisteredServiceInstance | Measure"
 Get-ConfigRegisteredServiceInstance | Measure  
 
 Write-Output " Get-BrokerController"
 Get-BrokerController 
 
 Write-Output " Get-LogDatastore"
 Get-LogDatastore  
 
 Write-Output " Get-MonitorDatastore "
 Get-MonitorDatastore  

 #Check Services
  Write-Output "Get-AcctServiceStatus"
 Get-AcctServiceStatus    
 
 Write-Output "Get-AdminServiceStatus "
 Get-AdminServiceStatus    
 
 Write-Output "Get-AnalyticsServiceStatus"
 Get-AnalyticsServiceStatus 
 
 Write-Output "Get-AppLibServiceStatus "
 Get-AppLibServiceStatus  
 
 Write-Output "Get-BrokerServiceStatus "
 Get-BrokerServiceStatus    
 
 Write-Output "Get-ConfigServiceStatus "
 Get-ConfigServiceStatus    
 
 Write-Output "Get-EnvTestServiceStatus"
 Get-EnvTestServiceStatus   
 
 Write-Output "Get-HypServiceStatus "
 Get-HypServiceStatus       
 
 Write-Output "Get-LogServiceStatus"
 Get-LogServiceStatus       
 
 Write-Output "Get-MonitorServiceStatus"
 Get-MonitorServiceStatus   
 
 Write-Output "Get-OrchServiceStatus "
 Get-OrchServiceStatus      
 
 Write-Output "Get-ProvServiceStatus"
 Get-ProvServiceStatus      
 
 Write-Output "Get-SfServiceStatus "
 Get-SfServiceStatus        
 
 Write-Output "Get-TrustServiceStatus "
 Get-TrustServiceStatus     

 #Get DB Versions

Write-Output "Get-AcctInstalledDBVersion "
Get-AcctInstalledDBVersion 

Write-Output "Get-AdminInstalledDBVersion"     
Get-AdminInstalledDBVersion 

Write-Output "Get-AnalyticsInstalledDBVersion "       
Get-AnalyticsInstalledDBVersion   

Write-Output "Get-AppLibInstalledDBVersion "  
Get-AppLibInstalledDBVersion    

Write-Output "Get-BrokerInstalledDbVersion"  
Get-BrokerInstalledDbVersion    

Write-Output "Get-ConfigInstalledDBVersion"  
Get-ConfigInstalledDBVersion    

Write-Output "Get-EnvTestInstalledDBVersion"  
Get-EnvTestInstalledDBVersion   

Write-Output "Get-HypInstalledDBVersion "  
Get-HypInstalledDBVersion       

Write-Output "Get-LogInstalledDBVersion "  
Get-LogInstalledDBVersion       

Write-Output "Get-MonitorInstalledDBVersion"  
Get-MonitorInstalledDBVersion   

Write-Output "Get-OrchInstalledDBVersion "  
Get-OrchInstalledDBVersion      

Write-Output "Get-ProvInstalledDBVersion "  
Get-ProvInstalledDBVersion      

Write-Output "Get-SfInstalledDBVersion"  
Get-SfInstalledDBVersion

Write-Output "Get-TrustInstalledDBVersion "          
Get-TrustInstalledDBVersion     


#Test DB Connections
Write-Output "Test-AcctDBConnection"
Test-AcctDBConnection (Get-AcctDBConnection) 

Write-Output "Test-AdminDBConnection"  
Test-AdminDBConnection (Get-AdminDBConnection)    

Write-Output "Test-AnalyticsDBConnection"
Test-AnalyticsDBConnection (Get-AnalyticsDBConnection)  

Write-Output "Test-AppLibDBConnection"
Test-AppLibDBConnection   (Get-AppLibDBConnection)  

Write-Output "Test-BrokerDBConnection"
Test-BrokerDBConnection   (Get-BrokerDBConnection)  

Write-Output "Test-ConfigDBConnection"
Test-ConfigDBConnection   (Get-ConfigDBConnection)  

Write-Output "Test-EnvTestDBConnection"
Test-EnvTestDBConnection  (Get-EnvTestDBConnection)  

Write-Output "Test-HypDBConnection"
Test-HypDBConnection      (Get-HypDBConnection)  

Write-Output "Test-LogDBConnection"
Test-LogDBConnection      (Get-LogDBConnection)  

Write-Output "Test-MonitorDBConnection"
Test-MonitorDBConnection  (Get-MonitorDBConnection)  

Write-Output "Test-OrchDBConnection"
Test-OrchDBConnection     (Get-OrchDBConnection)  

Write-Output "Test-ProvDBConnection"
Test-ProvDBConnection     (Get-ProvDBConnection)  

Write-Output "Test-SfDBConnection"
Test-SfDBConnection       (Get-SfDBConnection)  

Write-Output "Test-TrustDBConnection "
Test-TrustDBConnection   (Get-TrustDBConnection)  

 }  | Out-File $OutputPath  -Append

 }


 
Function Get-SFVersion([string] $Path) {
    $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4C3793F5-8FE6-4DDF-BA2A-CCB51187D492}"
    $value = "DisplayVersion"
    $StoreFrontVersion = (Get-ItemProperty -Path $key -Name $value).$value
    
    Write-Output  "StoreFrontVersion = $StoreFrontVersion" | Tee-Object -FilePath $Path -Append
}
 
Function Get-CitrixProdInfo([string] $OutputPath) {
    Write-Output "Citrix Product Information Found"
    Get-WmiObject -Class Win32_Product  | Where-Object vendor -Like "Citrix*" | Select Name, Vendor, Version
    Write-Output "Citrix Product Information Found" | Tee-Object -FilePath $OutputPath -Append
    Get-WmiObject -Class Win32_Product  | Where-Object vendor -Like "Citrix*" | Select Name, Vendor, Version  >> $OutputPath
 
}
 
Function Get-SFLogMode([string] $OutputPath) {
 
    $LogModePath = Get-SFInstallDir
    $LogModePath = $LogModePath + "Services\\ServiceMonitor\Citrix.DeliveryServices.ServiceMonitor.ServiceHost.exe.config"
     
    Write-Output "Check Logging Mode CTX139592" | Tee-Object -FilePath $OutputPath -Append
    $xmlFrameWorkCS = [xml](Get-Content $LogModePath)
    $TraceMode = $xmlFrameWorkCS.configuration.'system.diagnostics'.switches.add[0]
    Write-Output "Logging Mode = $($TraceMode.value)" >> "$OutputFile"
    If ($TraceMode.value -eq "Off") {
        Write-Host "Logging Mode = $($TraceMode.value)" -ForegroundColor White
    }
    else {
        Write-Host "Logging Mode = $($TraceMode.value)" -ForegroundColor Green
    }
 
 
 
}
 
Function Get-SFInstallDir() {
    $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Citrix\DeliveryServices"
    $value = "InstallDir"
    $InstallDir = $StoreFrontDir = (Get-ItemProperty -Path $key -Name $value).$value
    return $InstallDir
}
Function Get-TimeZoneInfo([string] $OutputPath) {
 
     
    Write-Output "TimeZone Details" | Tee-Object -FilePath $OutputPath -Append
    Write-Output "$(Get-TimeZone) - $(Get-Date)" >> "$OutputFile"
 
}
Function Get-DiskInfo([string] $OutputPath) {
 
    Write-Output "Check Disk Space"
    Write-Output "Check Disk Space" >> "$OutputFile"
    Get-WmiObject -Class Win32_LogicalDisk  | ? {$_. DriveType -eq 3} | select DeviceID, {$_.Size /1GB}, {$_.FreeSpace /1GB} >> "$OutputFile"
 
}
Function Get-SFEvents([string] $OutputPath) {
 
    Write-Output "Event Log Citrix Delivery Service Warnings and Errors" | Tee-Object -FilePath $OutputPath -Append
    Get-EventLog -LogName 'Citrix Delivery Services' -Newest $EventLogEntries -EntryType Error, Warning >> "$OutputFile"
     
}
Function Test-Framework([string] $OutputPath) {
 
    write-output "Check FrameworkData.XML for File Structure" | Tee-Object -FilePath $OutputPath -Append
    $FrameworkPath = Get-SFInstallDir
    $FrameworkPath = $FrameworkPath + "Framework\FrameworkData\FrameWork.xml"
    $CheckFrameworkData = Test-Path -Path $FrameworkPath -PathType Leaf
    write-output "CheckFrameworkData $FrameworkPath = $($CheckFrameworkData)" | Tee-Object -FilePath $OutputPath -Append
 
    $SFFileSystem = Select-String -Path $FrameworkPath -Pattern 'inetpub' | select Line
    foreach ($i in $SFFileSystem) {
        $resultsfile = Test-Path -Path $i.Line.Substring($i.Line.IndexOf('>') + 1, ($i.Line.LastIndexOf('<') - $i.Line.IndexOf('>') - 1 )) 
        if ($resultsfile -eq $true) {
            write-host "$($i.Line.Substring($i.Line.IndexOf('>')+1,($i.Line.LastIndexOf('<')-$i.Line.IndexOf('>')-1 ))) = $resultsfile" -ForegroundColor Green
        }
        else {
            write-host "$($i.Line.Substring($i.Line.IndexOf('>')+1,($i.Line.LastIndexOf('<')-$i.Line.IndexOf('>')-1 ))) = $resultsfile" -ForegroundColor Red
        }
        write-output "$($i.Line.Substring($i.Line.IndexOf('>')+1,($i.Line.LastIndexOf('<')-$i.Line.IndexOf('>')-1 ))) = $resultsfile" >> "$OutputFile"
 
    }
 
}
Function Get-SFConfigDetails([string] $OutputPath) {
    Write-Output "StoreFront Configuration Details"
    Write-Output "Configuration Details" | Tee-Object -FilePath $OutputPath -Append
    Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Citrix\DeliveryServices >> "$OutputFile"
    Write-Output "Configuration Details" | Tee-Object -FilePath $OutputPath -Append
    Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Citrix\Roles\DeliveryServicesRole\DeliveryServices\DeliveryServicesPkg >> "$OutputFile"
    Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\{4C3793F5-8FE6-4DDF-BA2A-CCB51187D492}' >> "$OutputFile"
 
}
Function Test-Port([string] $OutputPath) {
    Write-Output "Port Check"
    Write-Output "Port Check" >> "$OutputFile"
    $PortCheck = Test-NetConnection -ComputerName $SFServer -Port 808
    Test-NetConnection -ComputerName $SFServer -Port 808 | Tee-Object -FilePath $OutputPath -Append
    if ($true -eq $true) {
        Write-Host "Port Check Succes = $PortCheck.TcpTestSucceeded" -ForegroundColor Green
    }
    else {
        Write-Host "Port Check Failed = $PortCheck.TcpTestSucceeded" -ForegroundColor Red
    }
 
}
 
Function Get-IISDetails([string] $OutputPath) {
 
    write-output "IIS Details" | Tee-Object -FilePath $OutputPath -Append
    $IISPathKey = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\INetStp"
    $value = "InstallPath"
    $IISPath = (Get-ItemProperty -Path $IISPathKey -Name $value).$value
    #Uncomment to get security info
    #dir C:\inetpub\wwwroot | Get-Acl | select Path -ExpandProperty Access >> "$OutputFile"
    & "C:\Windows\System32\inetsrv\appcmd.exe" list vdir >> "$OutputFile"
    Get-IISSite  >> "$OutputFile"
}
 
Function Get-SFSiteInfo([string] $OutputPath) {
    $FrameworkPath = Get-SFInstallDir
    $FrameworkPath = $FrameworkPath + "Framework\FrameworkData\FrameWork.xml"
     
    Write-Output "StoreFront Site Information" | Tee-Object -FilePath $OutputPath -Append
    $xmlFrameWork = [xml](Get-Content $FrameworkPath)
    $xmlFrameWork.framework.iisSites.iisSite | Select hostbaseUrl, siteId >> "$OutputFile"
}
 
Function Get-CitrixServices([string] $OutputPath) {
     
    Write-Output "Check Citrix Services" | Tee-Object -FilePath $OutputPath -Append
    Get-Service "Citrix*" >> "$OutputFile"
 
}
 
Function Get-LocalAdmin([string] $OutputPath) {
     
    Write-Output "Check Local Admin Group Membership" | Tee-Object -FilePath $OutputPath -Append
    Get-LocalGroupMember -Group "Administrators" >> "$OutputFile"
 
}
 
Function Get-CertInfo([string] $OutputPath) {
    
    Write-Output "Certificate Thumbprints" | Tee-Object -FilePath $OutputPath -Append
    Get-ChildItem -Path 'Cert:\LocalMachine\Citrix Delivery Services' >> "$OutputFile"
}
 
Function Get-CLusterInfo([string] $OutputPath) {
    Write-Output "Cluster Group Information"
    Write-Output "Cluster Group Information" >> "$OutputFile"
    $FeatureConfigPath = "$StoreFrontDir\ClusterManagement\feature.config"
    #Select-Xml -Path $Path -XPath $Xpath
    $xml = [xml](Get-Content $FeatureConfigPath)
    $xml.configuration.'citrix.deliveryservices'.clusterInformation.cluster.members.member  | Select hostname, servername, certificateThumbprint  >> "$OutputFile"
     
    foreach ($srv in $xml.configuration.'citrix.deliveryservices'.clusterInformation.cluster.members.member  ) {
        Write-Output 'DNS Check ' $srv.hostname | Tee-Object -FilePath $OutputPath -Append
        try {
            Resolve-DnsName $srv.hostname  -ErrorAction Stop | Tee-Object -FilePath $OutputPath -Append
        }
        catch {
            Write-Host  'DNS Check Failed' $srv.hostname -ForegroundColor DarkRed
            Write-Output  'DNS Check Failed' $srv.hostname  | Tee-Object -FilePath $OutputPath -Append
 
        }
 
    }
 
    foreach ($srvrep in $xml.configuration.'citrix.deliveryservices'.clusterInformation.cluster.members.member  ) {
        Write-Host 'Cluster Check ' $srvrep.hostname
        try {
            Write-Output 'Check Get-DSConfigurationReplicationState ->' $srvrep.hostname  | Tee-Object -FilePath $OutputPath -Append
            Get-DSConfigurationReplicationState -Hostname $srvrep.hostname  -ErrorAction Stop >> "$OutputFile"
        }
        catch {
            Write-Host  'Cluster Check Failed' $srvrep.hostname -ForegroundColor DarkRed
            Write-Output 'Failed Get-DSConfigurationReplicationState ->' $srvrep.hostname  | Tee-Object -FilePath $OutputPath -Append
 
        }
    }
 
 
}
 
Function  Get-RepFolderInfo([string] $OutputPath) {
      
    $FrameworkPath = Get-SFInstallDir
    $FrameworkPath = $FrameworkPath + "Framework\FrameworkData\FrameWork.xml"
    $xmlFrameWork = [xml](Get-Content $FrameworkPath)
    
    Write-Output "Replicated Folder Information" | Tee-Object -FilePath $OutputPath -Append
    $xmlFrameWork.framework.replicatedFolders.replicatedFolder >> "$OutputPath"
}
 
 
Function Test-SChannel ([string] $OutputPath) {
 
    
    Write-Output "Check Secure Channel" | Tee-Object -FilePath $OutputPath -Append
    Test-ComputerSecureChannel -verbose >> "$OutputPath"
 
}
 
 
Function Get-IISPool([string] $OutputPath) {
 
    Write-Output "IIS Pool Info" | Tee-Object -FilePath $OutputPath -Append
    Get-IISAppPool  >> "$OutputPath"
 
    Write-Output "Get-DSApplicationPool Pool Info" | Tee-Object -FilePath $OutputPath -Append
    Get-DSApplicationPool >> "$OutputPath"
 
}

Function Get-Beacon([string] $OutputPath)
{
    Write-Output "Internal Beacon" | Tee-Object -FilePath $OutputPath -Append
    Get-STFRoamingBeacon -Internal  | Tee-Object -FilePath $OutputPath -Append
    Write-Output "External Beacon" | Tee-Object -FilePath $OutputPath -Append
    Get-STFRoamingBeacon -External  | Tee-Object -FilePath $OutputPath -Append


}
 
#==============================================================================================

Function Perform-SFDiagnostics()
{
Clear-Host
 
if ((Get-PSSnapin "Citrix.*" -EA silentlycontinue) -eq $null) {
    try { Add-PSSnapin Citrix.* -ErrorAction Stop }
    catch { write-error "Error Get-PSSnapin Citrix.* Powershell snapin"; Return }
}
 
$Version = "StoreFront Diag 3.0"
 
#variables
$SFServer = "localhost"
$EventLogEntries = 50
$OutputFile = "$($env:USERPROFILE)\Desktop\StoreFrontDiag.txt"
$StoreFrontDir = Get-SFInstallDir
 
Write-Host "$Version - Script Starting Output to $OutputFile" -ForegroundColor Green
$HostName = [System.Net.Dns]::GetHostName()
Write-Output " HostName = $HostName" > "$OutputFile"
 
Write-Output " StoreFrontDiag = $Version" >> "$OutputFile"
Get-SFVersion($OutputFile)
Write-Div($OutputFile)
 
Get-SFSdkData($OutputFile)
Write-Div($OutputFile)

Get-Beacon($OutputFile)
Write-Div($OutputFile)

Get-CitrixProdInfo($OutputFile)
Write-Div($OutputFile)
 
Get-SFLogMode($OutputFile)
Write-Div($OutputFile)
 
Test-SChannel($OutputFile)
Write-Div($OutputFile)
 
Get-TimeZoneInfo($OutputFile)
Write-Div($OutputFile)
 
Get-DiskInfo($OutputFile)
Write-Div($OutputFile)
 
Get-SFEvents($OutputFile)
Write-Div($OutputFile)
 
#%SystemDrive% setting
write-output " '%SystemDrive%' = $([System.Environment]::ExpandEnvironmentVariables('%SystemDrive%'))" >> "$OutputFile"
Write-Div($OutputFile)
write-output "StoreFront Directory = $StoreFrontDir" >> "$OutputFile"
Write-Div($OutputFile)
 
Test-Framework($OutputFile)
Write-Div($OutputFile)
 
Get-SFConfigDetails($OutputFile)
Write-Div($OutputFile)
 
Test-Port($OutputFile)
Write-Div($OutputFile)
 
Get-IISDetails($OutputFile)
Write-Div($OutputFile)
 
Get-SFSiteInfo($OutputFile)
Write-Div($OutputFile)
 
Get-CitrixServices($OutputFile)
Write-Div($OutputFile)
 
Get-LocalAdmin($OutputFile)
Write-Div($OutputFile)
 
Get-CertInfo($OutputFile)
Write-Div($OutputFile)
 
Get-CLusterInfo($OutputFile)
Write-Div($OutputFile)
 
Get-RepFolderInfo($OutputFile)
Write-Div($OutputFile)
 
Get-IISPool($OutputFile)
Write-Div($OutputFile)
 
Write-Output "End Of Script "
}