<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>powershell &#8211; Carl Webster</title>
	<atom:link href="https://www.carlwebster.com/tag/powershell/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.carlwebster.com</link>
	<description>The Accidental Citrix Admin - The site for those who find themselves supporting Citrix involuntarily or accidentally</description>
	<lastBuildDate>Mon, 12 Jun 2023 19:20:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.2</generator>
<site xmlns="com-wordpress:feed-additions:1">42228915</site>	<item>
		<title>Citrix XenDesktop Personal vDisk Stats using Microsoft Excel and PowerShell V2.1</title>
		<link>https://www.carlwebster.com/citrix-xendesktop-personal-vdisk-stats-using-microsoft-excel-powershell-v2-1/</link>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Sat, 01 Feb 2014 16:33:56 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[XenDesktop 5.x]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[Personal vDisk]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[PvD]]></category>
		<category><![CDATA[sending email via office365 and powershell]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=6809</guid>

					<description><![CDATA[Yeah, I know.  I just updated the script a couple of days ago and here is another update.  Well, I just couldn&#8217;t stand it that the script couldn&#8217;t support sending&#8230;]]></description>
										<content:encoded><![CDATA[<p>Yeah, I know.  I just updated the script a couple of days ago and here is another update.  Well, I just couldn&#8217;t stand it that the script couldn&#8217;t support sending email over anything but the default SMTP port 25.  I just had to fix that but doing so required basing the script on PowerShell version 3.  The script now requires at least PowerShell version 3 and there are a couple of more parameters.</p>
<p><span id="more-6809"></span><br />
The script will not work for sending emails if you are using PowerShell version 2 so the first line in the script is now:</p>
<pre class="brush: powershell; title: ; notranslate">
#Requires -Version 3
</pre>
<p>The two new parameters are SmtpPort and UseSSL. SmtpPort sets the SMTP port and UseSSL tells whether to use SSL for making the connection to the SmtpServer.</p>
<p>In order to send authenticated SMTP emails, a username and password are required.</p>
<pre class="brush: powershell; title: ; notranslate">
$emailCredentials = Get-Credential -Message &quot;Enter the email account and password to send emails&quot;
</pre>
<figure id="attachment_49492" aria-describedby="caption-attachment-49492" style="width: 326px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2014/02/Figure001.png"><img fetchpriority="high" decoding="async" class="size-full wp-image-49492" src="https://www.carlwebster.com/wp-content/uploads/2014/02/Figure001.png" alt="Figure 1" width="326" height="254" /></a><figcaption id="caption-attachment-49492" class="wp-caption-text">Figure 1</figcaption></figure>
<p>The credentials are the same used when configuring an email client.  i.e. <a href="mailto:SomeUser@emaildomain.com">SomeUser@emaildomain.com</a> and the account&#8217;s password. I tested this using my Office365 account and it worked with no issues.</p>
<p>The email body is read in from a file.  I use the -BodyAsHtml parameter for Send-MailMessage.  To get line breaks just use &lt;br /&gt; at the end of each line and for spacing lines.  The file I used for my testing looks like this:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;br /&gt;
&lt;br /&gt;
Your Personal vDisk space has reached over 90% of its capacity.   &lt;br /&gt;
You should resolve this as soon as possible before your Personal &lt;br /&gt;
vDisk fills up and needs to be reset.  When that happens, you &lt;br /&gt;
will need to reinstall your applications.&lt;br /&gt;
&lt;br /&gt;
You should move your 'User Data' from your C and or PvD drive &lt;br /&gt;
and it should be kept on your home drive.  The free space on your &lt;br /&gt;
workstation is to be used for application installs, temp files, &lt;br /&gt;
and other general system and application configurations.&lt;br /&gt;
&lt;br /&gt;
Let us know if you need any help.&lt;br /&gt;
&lt;br /&gt;
Thanks&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The XenDesktop Help Desk Team at CarlWebster.com&lt;br /&gt;
</pre>
<p>Which looks like this in Outlook 2010.</p>
<figure id="attachment_49493" aria-describedby="caption-attachment-49493" style="width: 506px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2014/02/Figure002.png"><img decoding="async" class="size-full wp-image-49493" src="https://www.carlwebster.com/wp-content/uploads/2014/02/Figure002.png" alt="Figure 2" width="506" height="696" srcset="https://www.carlwebster.com/wp-content/uploads/2014/02/Figure002.png 506w, https://www.carlwebster.com/wp-content/uploads/2014/02/Figure002-218x300.png 218w" sizes="(max-width: 506px) 100vw, 506px" /></a><figcaption id="caption-attachment-49493" class="wp-caption-text">Figure 2</figcaption></figure>
<p>Example of running the script:</p>
<pre class="brush: bash; title: ; notranslate">
.\get-pvdstatsexcel.ps1 -AdminAddress xd71studio1 -XDVersion 7 -SmtpServer smtp.office365.com -SmtpPort 587 -UseSSL -From Webster@CarlWebster.com -InputFile c:\webster\emailbody.txt -verbose
</pre>
<p>Example screen output:</p>
<pre class="brush: plain; title: ; notranslate">
PS C:\webster&gt; .\get-pvdstatsexcel.ps1 -AdminAddress xd71studio1 -XDVersion 7 -SmtpServer smtp.office365.com -SmtpPort 5
87 -UseSSL -From Webster@CarlWebster.com -InputFile c:\webster\emailbody.txt -verbose
VERBOSE: 02/01/2014 09:45:00: Retrieving all XenDesktop Catalog names
VERBOSE: 02/01/2014 09:45:00:
VERBOSE: 02/01/2014 09:45:00:
VERBOSE: 02/01/2014 09:45:00: Using Controller   : xd71studio1
VERBOSE: 02/01/2014 09:45:00: XenDesktop version : 7
VERBOSE: 02/01/2014 09:45:00: Smtp Server        : smtp.office365.com
VERBOSE: 02/01/2014 09:45:00: Smtp Port          : 587
VERBOSE: 02/01/2014 09:45:00: Use SSL            : True
VERBOSE: 02/01/2014 09:45:00: From               : Webster@CarlWebster.com
VERBOSE: 02/01/2014 09:45:00: Input File         : c:\webster\emailbody.txt
VERBOSE: 02/01/2014 09:45:00: PoSH version       : 3.0
VERBOSE: 02/01/2014 09:45:00:
VERBOSE: 02/01/2014 09:45:00: Script start       : 02/01/2014 09:45:00
VERBOSE: 02/01/2014 09:45:00:
VERBOSE: 02/01/2014 09:45:00:
VERBOSE: 02/01/2014 09:45:00: Get VMs for Catalog Win7 WC PvD Test
VERBOSE: 02/01/2014 09:45:00:  Processing VM Win7-PvD-01
VERBOSE: 02/01/2014 09:45:01:  Processing VM Win7-PvD-02
VERBOSE: 02/01/2014 09:45:01:  Processing VM Win7-PvD-03
VERBOSE: 02/01/2014 09:45:01: Creating CSV file C:\webster\Win7 WC PvD Test_PvD_Stats.csv
VERBOSE: Performing operation &quot;Export-Csv&quot; on Target &quot;C:\webster\Win7 WC PvD Test_PvD_Stats.csv&quot;.
VERBOSE: 02/01/2014 09:45:01: Creating Summary CSV file C:\webster\Summary_PvD_Stats.csv
VERBOSE: Performing operation &quot;Export-Csv&quot; on Target &quot;C:\webster\Summary_PvD_Stats.csv&quot;.
VERBOSE: 02/01/2014 09:45:01: Sending emails
VERBOSE: 02/01/2014 09:45:14:  Sending email to webster@carlwebster.com
VERBOSE: 02/01/2014 09:45:19: CSV Processing complete
VERBOSE: 02/01/2014 09:45:19: Start creating Excel file and worksheets
VERBOSE: 02/01/2014 09:45:19: Setup Excel
VERBOSE: The object written to the pipeline is an instance of the type
&quot;Microsoft.Office.Interop.Excel.ApplicationClass&quot; from the component's primary interop assembly. If this type exposes
different members than the IDispatch members, scripts written to work with this object might not work if the primary
interop assembly is not installed.
VERBOSE: 02/01/2014 09:45:19: Get Summary CSV file
VERBOSE: 02/01/2014 09:45:21:  Adding summary row for Win7-PvD-02
VERBOSE: 02/01/2014 09:45:22: Deleting C:\webster\Summary_PvD_Stats.csv
VERBOSE: Performing operation &quot;Remove file&quot; on Target &quot;C:\webster\Summary_PvD_Stats.csv&quot;.
VERBOSE: 02/01/2014 09:45:22: Summary sheet completed
VERBOSE: 02/01/2014 09:45:22: Start processing catalogs
VERBOSE: 02/01/2014 09:45:23: Get CSV file for Catalog Win7 WC PvD Test
VERBOSE: 02/01/2014 09:45:24:  Adding row for Win7-PvD-01
VERBOSE: 02/01/2014 09:45:25:  Adding row for Win7-PvD-02
VERBOSE: 02/01/2014 09:45:25:  Adding row for Win7-PvD-03
VERBOSE: 02/01/2014 09:45:26: Deleting C:\webster\Win7 WC PvD Test_PvD_Stats.csv
VERBOSE: Performing operation &quot;Remove file&quot; on Target &quot;C:\webster\Win7 WC PvD Test_PvD_Stats.csv&quot;.
VERBOSE: 02/01/2014 09:45:26: Processing worksheets is complete
VERBOSE: 02/01/2014 09:45:26: Saving Excel file
VERBOSE: Performing operation &quot;Remove variable&quot; on Target &quot;Name: Excel&quot;.
VERBOSE: 02/01/2014 09:45:26: Excel file C:\webster\PvDStats_2014-02-01.xlsx is ready for use
VERBOSE: Performing operation &quot;Stop-Process&quot; on Target &quot;EXCEL (3324)&quot;.
VERBOSE: 02/01/2014 09:45:26: Script started: 02/01/2014 09:45:00
VERBOSE: 02/01/2014 09:45:26: Script ended: 02/01/2014 09:45:26
VERBOSE: 02/01/2014 09:45:26: Elapsed time: 0 days, 0 hours, 0 minutes, 26.5 seconds
PS C:\webster&gt;
</pre>
<p>What happens if you are supposed to use SSL and you don&#8217;t?</p>
<pre class="brush: plain; title: ; notranslate">
VERBOSE: 02/01/2014 09:47:43: Sending emails
VERBOSE: 02/01/2014 09:47:52:  Sending email to webster@carlwebster.com
Send-MailMessage : The SMTP server requires a secure connection or the client was not authenticated. The server
response was: 5.7.1 Client was not authenticated
At C:\webster\Get-PvDStatsExcel.ps1:746 char:6
+                     Send-MailMessage -To $emailTo -Subject $emailSubject -Body $emailBody -Smtp ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidOperation: (System.Net.Mail.SmtpClient:SmtpClient) &#x5B;Send-MailMessage], SmtpExcept
ion
+ FullyQualifiedErrorId : SmtpException,Microsoft.PowerShell.Commands.SendMailMessage
</pre>
<p>The rest of the script will continue to run and the Excel file is created and saved.  Only the emails will not be sent.</p>
<p>I believe I have included lots of great help text.</p>
<pre class="brush: plain; title: ; notranslate">
PS C:\webster&gt; get-help .\get-pvdstatsexcel.ps1 -full
NAME
    C:\webster\Get-PvDStatsExcel.ps1

SYNOPSIS
    Creates an Excel spreadsheet containing Citrix XenDesktop Personal vDisk (PvD) usage statistics.

SYNTAX
    C:\webster\Get-PvDStatsExcel.ps1 &#x5B;&#x5B;-XDCatalogName] &lt;String&gt;] &#x5B;&#x5B;-AdminAddress] &lt;String&gt;] &#x5B;&#x5B;-XDVersion] &lt;Int32&gt;] &#x5B;&lt;CommonParameters&gt;]

    C:\webster\Get-PvDStatsExcel.ps1 &#x5B;&#x5B;-XDCatalogName] &lt;String&gt;] &#x5B;&#x5B;-AdminAddress] &lt;String&gt;] &#x5B;&#x5B;-XDVersion] &lt;Int32&gt;] &#x5B;-SmtpServer] &lt;String&gt; &#x5B;&#x5B;-SmtpPort] &lt;Int32&gt;] &#x5B;&#x5B;-UseSSL]] &#x5B;-From] &lt;String&gt; &#x5B;-InputFile] &lt;String&gt; &#x5B;&lt;CommonParameters&gt;]

DESCRIPTION
    Take a XenDesktop Catalog name (or all Catalogs) and gathers PvD usage stats.
    Creates a Summary worksheet with users who have any PvD with &gt; 90% usage.
    Summary worksheet has the user's Active Directory name and email address.

PARAMETERS
    -XDCatalogName &lt;String&gt;
        XenDesktop Catalog name.  If not entered, process all Catalogs.

        Required?                    false
        Position?                    1
        Default value
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -AdminAddress &lt;String&gt;
        Specifies the address of a XenDesktop controller that the PowerShell script will connect to.  This can be provided as a host name or an IP address.

        Required?                    false
        Position?                    2
        Default value
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -XDVersion &lt;Int32&gt;
        Specifies the XenDesktop version.
        5 is for all versions of XenDesktop 5.
        7 is for all versions of XenDesktop 7.
        Default is XenDesktop 7.

        Required?                    false
        Position?                    3
        Default value                7
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -SmtpServer &lt;String&gt;
        Specifies the optional email server to send emails to users on the Summary worksheet.

        Required?                    true
        Position?                    4
        Default value
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -SmtpPort &lt;Int32&gt;
        Specifies the SMTP port.

        Required?                    false
        Position?                    5
        Default value                25
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -UseSSL &#x5B;&lt;SwitchParameter&gt;]
        Specifies whether to use SSL for the SmtpServer.
        Default is False.

        Required?                    false
        Position?                    6
        Default value                False
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -From &lt;String&gt;
        Specifies the username for the From email address.
        If SmtpServer is used, this is a required parameter.

        Required?                    true
        Position?                    7
        Default value
        Accept pipeline input?       false
        Accept wildcard characters?  false

    -InputFile &lt;String&gt;
        The file that contains the text for the body of the email.
        If SmtpServer is used, this is a required parameter.
        Text is treated as HTML.

        Required?                    true
        Position?                    8
        Default value
        Accept pipeline input?       false
        Accept wildcard characters?  false

    &lt;CommonParameters&gt;
        This cmdlet supports the common parameters: Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer and OutVariable. For more information, see
        about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

    INPUTS
        None.  You cannot pipe objects to this script.

    OUTPUTS
        Creates a Microsoft Excel spreadsheet.
        This has only been tested with Microsoft Excel 2010.
        Optional, creates and sends an email for every user on the Summary Worksheet.

    NOTES

        NAME: Get-PvDStatsExcel.ps1
        VERSION: 2.1
        AUTHOR: Carl Webster with help, as usual, from Michael B. Smith
        LASTEDIT: February 1, 2014

    -------------------------- EXAMPLE 1 --------------------------
    PS C:\PSScript &gt;.\Get-PvDStatsExcel.ps1

    Will process all XenDesktop Catalogs.
    AdminAddress is the computer running the script for the AdminAddress.
    Will load Citrix SnapIn for XenDesktop 7.

    -------------------------- EXAMPLE 2 --------------------------
    PS C:\PSScript &gt;.\Get-PvDStatsExcel.ps1 -XDVersion 5

    Will process all XenDesktop Catalogs.
    AdminAddress is the computer running the script for the AdminAddress.
    Will load Citrix SnapIn for XenDesktop 5.

    -------------------------- EXAMPLE 3 --------------------------
    C:\PS&gt;PS C:\PSScript .\Get-PvDStatsExcel.ps1 -XDCatalogName Win7Image1 -AdminAddress DDC01

    Will gather PvD usage stats for the Win7Image1 Catalog
    using a Controller named DDC01 for the AdminAddress.
    Will load Citrix SnapIn for XenDesktop 7.

    -------------------------- EXAMPLE 4 --------------------------
    PS C:\PSScript &gt;.\Get-PvDStatsExcel.ps1 -SmtpServer mail.domain.tld -From XDAdmin@domain.tld -InputFile C:\Scripts\EmailBodyText.txt

    Will process all XenDesktop Catalogs.
    AdminAddress is the computer running the script for the AdminAddress.
    Will load Citrix SnapIn for XenDesktop 7.
    Uses mail.domain.tld as the email server.
    Uses the default SMTP port 25.
    Will not use SSL.
    Uses XDAdmin@domain.tld for the email's Sent From address.
    Reads the contents of C:\Scripts\EmailBodyText.txt and uses the contents as the email body.

    -------------------------- EXAMPLE 5 --------------------------
    PS C:\PSScript &gt;.\Get-PvDStatsExcel.ps1 -SmtpServer smtp.office365.com -SmtpPort 587 -UseSSL -From Webster@CarlWebster.com -InputFile C:\Scripts\EmailBodyText.txt

    Will process all XenDesktop Catalogs.
    AdminAddress is the computer running the script for the AdminAddress.
    Will load Citrix SnapIn for XenDesktop 7.
    Uses smtp.office365.com.
    User SMTP port 587.
    Uses Webster@CarlWebster.com for the email's Sent From address (this must be a valid address on the email system).
    Reads the contents of C:\Scripts\EmailBodyText.txt and uses the contents as the email body.

    -------------------------- EXAMPLE 6 --------------------------
    C:\PS&gt;Sample input file.

    &lt;br /&gt;
    &lt;br /&gt;
    Your Personal vDisk space has reached over 90% of its capacity.   &lt;br /&gt;
    You should resolve this as soon as possible before your Personal &lt;br /&gt;
    vDisk fills up and needs to be reset.  When that happens, you &lt;br /&gt;
    will need to reinstall your applications.&lt;br /&gt;
    &lt;br /&gt;
    You should move your 'User Data' from your C and or PvD drive &lt;br /&gt;
    and it should be kept on your home drive.  The free space on your &lt;br /&gt;
    workstation is to be used for application installs, temp files, &lt;br /&gt;
    and other general system and application configurations.&lt;br /&gt;
    &lt;br /&gt;
    Let us know if you need any help.&lt;br /&gt;
    &lt;br /&gt;
    Thanks&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    The XenDesktop Help Desk Team at CarlWebster.com&lt;br /&gt;

RELATED LINKS

PS C:\webster&gt;
</pre>
<p>I hope you find the changes useful.</p>
<p>If you find any issues, please let me know and I will do my best to get them fixed.</p>
<p><strong>You can always find the most current script by going to </strong><a title="Current Scripts" href="https://www.carlwebster.com/downloads/" target="_blank" rel="noopener noreferrer"><strong>https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</strong></a></p>
<p>Thanks</p>
<p>Webster</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6809</post-id>	</item>
		<item>
		<title>Error in the Provisioning Services 7.0 PowerShell Programmer Guide for Windows 8 and Server 2012</title>
		<link>https://www.carlwebster.com/error-in-the-provisioning-services-7-0-powershell-programmer-guide-for-windows-8-and-server-2012/</link>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Sat, 29 Jun 2013 15:36:44 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PVS]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[pvs7]]></category>
		<category><![CDATA[snap-in]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=5820</guid>

					<description><![CDATA[In updating the PVS documentation script to add support for PVS7, I ran into an issue with getting the McliPSSnapin.dll registered.  This brief article explains how to resolve this issue.&#8230;]]></description>
										<content:encoded><![CDATA[<p>In updating the PVS documentation script to add support for PVS7, I ran into an issue with getting the McliPSSnapin.dll registered.  This brief article explains how to resolve this issue.</p>
<p><span id="more-5820"></span></p>
<p>The Provisioning Services 7.0 PowerShell Programmer Guide is available <a title="Provisioning Services 7.0 PowerShell Programmer Guide " href="http://support.citrix.com/article/CTX138045" target="_blank" rel="noopener">here</a>.</p>
<p>On page 7, the instructions to install the PowerShell Snap-in are not correct for Windows 8 or Server 2012.</p>
<p>The original instructions work for Server 2003, Server 2008, Server 2008 R2, Windows XP, and Windows 7.</p>
<blockquote><p><b>Installation of PowerShell Snap-In</b></p>
<p>The PowerShell snap-in (McliPSSnapIn.dll) can be installed using the Provisioning Server Console install.</p>
<p>If it later needs to be registered in PowerShell, this can be manually done by running one of the following commands at the DOS command prompt:</p>
<p><span style="text-decoration: underline;">F</span><span style="text-decoration: underline;">or 32-bit</span></p>
<p><b><i>%</i></b><b><i>s</i></b><b><i>ystemroot%\Microsoft.NET\Framework\v2.0.50727\installutil.exe McliPSSnapIn.dll</i></b></p>
<p><span style="text-decoration: underline;">For 64-bit</span></p>
<p><b><i>%</i></b><b><i>s</i></b><b><i>ystemroot%\Microsoft.NET\Framework64\v2.0.50727\installutil.exe McliPSSnapIn.dll</i></b></p></blockquote>
<p>The correct instructions for Windows 8 and Server 2012 are:</p>
<p>For 32-bit</p>
<p><b><i>%</i></b><b><i>s</i></b><b><i>ystemroot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe McliPSSnapIn.dll</i></b></p>
<p>For 64-bit</p>
<p><b><i>%</i></b><b><i>s</i></b><b><i>ystemroot%\Microsoft.NET\Framework64\v4.0.30319\installutil.exe McliPSSnapIn.dll</i></b></p>
<p>If you attempt to run the original command, you get:</p>
<figure id="attachment_49455" aria-describedby="caption-attachment-49455" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure1.png"><img decoding="async" class="size-full wp-image-49455" src="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure1.png" alt="Figure 1" width="677" height="343" srcset="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure1.png 677w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure1-530x269.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure1-600x304.png 600w" sizes="(max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49455" class="wp-caption-text">Figure 1</figcaption></figure>
<p>That is because there is nothing in the v2.0.50727 folder.</p>
<figure id="attachment_49457" aria-describedby="caption-attachment-49457" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure2.png"><img loading="lazy" decoding="async" class="size-full wp-image-49457" src="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure2.png" alt="Figure 2" width="677" height="343" srcset="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure2.png 677w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure2-530x269.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure2-600x304.png 600w" sizes="auto, (max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49457" class="wp-caption-text">Figure 2</figcaption></figure>
<p>The InstallUtil.exe utility is in the v4.0.30319 folder.</p>
<figure id="attachment_49458" aria-describedby="caption-attachment-49458" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure3.png"><img loading="lazy" decoding="async" class="size-full wp-image-49458" src="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure3.png" alt="Figure 3" width="677" height="343" srcset="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure3.png 677w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure3-530x269.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure3-600x304.png 600w" sizes="auto, (max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49458" class="wp-caption-text">Figure 3</figcaption></figure>
<p>I am testing with 32-bit Windows 8, so I needed to run:</p>
<p><b><i>%</i></b><b><i>s</i></b><b><i>ystemroot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe McliPSSnapIn.dll</i></b></p>
<figure id="attachment_49459" aria-describedby="caption-attachment-49459" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure4.png"><img loading="lazy" decoding="async" class="size-full wp-image-49459" src="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure4.png" alt="Figure 4" width="677" height="691" srcset="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure4.png 677w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure4-294x300.png 294w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure4-600x612.png 600w" sizes="auto, (max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49459" class="wp-caption-text">Figure 4</figcaption></figure>
<p>Now I can configure a remote connection to my PVS7 server and run an MCLI PowerShell command.</p>
<figure id="attachment_49460" aria-describedby="caption-attachment-49460" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure5.png"><img loading="lazy" decoding="async" class="size-full wp-image-49460" src="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure5.png" alt="Figure 5" width="677" height="343" srcset="https://www.carlwebster.com/wp-content/uploads/2013/06/Figure5.png 677w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure5-530x269.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/06/Figure5-600x304.png 600w" sizes="auto, (max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49460" class="wp-caption-text">Figure 5</figcaption></figure>
<p>I hope Citrix will correct the PVS7 PowerShell Programmer Guide.</p>
<p>Thanks</p>
<p>Webster</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5820</post-id>	</item>
		<item>
		<title>Using My Citrix PVS PowerShell Documentation Script with Remoting</title>
		<link>https://www.carlwebster.com/using-my-citrix-pvs-powershell-documentation-script-with-remoting/</link>
					<comments>https://www.carlwebster.com/using-my-citrix-pvs-powershell-documentation-script-with-remoting/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Fri, 15 Mar 2013 23:33:46 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PVS]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[remoting]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=5609</guid>

					<description><![CDATA[I needed to figure out how to run my latest PVS documentation script without having Microsoft Word installed on the PVS server.  This turned out to be much simpler than&#8230;]]></description>
										<content:encoded><![CDATA[<p>I needed to figure out how to run my latest PVS documentation script without having Microsoft Word installed on the PVS server.  This turned out to be much simpler than I thought it would be.  There are only four steps involved.</p>
<ol>
<li>From the computer to run the script, start a PowerShell session as Administrator</li>
<li>Add-PSSnapin McliPSSnapin</li>
<li>Mcli-Run SetupConnection -p Server=PVSServerName</li>
<li>.\PVS_Inventory_V2.ps1 -verbose</li>
</ol>
<p>The results of my session on my Windows 7 VM against my Windows Server 2008 R2 PVS 6.1 server VM:</p>
<pre class="brush: plain; title: ; notranslate">
PS C:\webster&gt; $env:computername
WIN7
PS C:\webster&gt; Add-PSSnapin McliPSSnapin
PS C:\webster&gt; Mcli-Run SetupConnection -p Server=PVS61
Run succeeded.
PS C:\webster&gt; .\PVS_Inventory_V2.ps1 -verbose
VERBOSE: checking for McliPSSnapin
VERBOSE: Getting PVS version info
VERBOSE: Build PVS farm values
VERBOSE: Setting up Word
VERBOSE: Create Word comObject. If you are not running Word 2007, ignore the next message.
VERBOSE: The object written to the pipeline is an instance of the type &quot;Microsoft.Office.Interop.Word.ApplicationClass&quot;
from the component's primary interop assembly. If this type exposes different members than the IDispatch members,
scripts written to work with this object might not work if the primary interop assembly is not installed.
VERBOSE: Running Microsoft Word 2010
VERBOSE: Validate company name
VERBOSE: Validate cover page
VERBOSE: Company Name: Webster's Lab
VERBOSE: Cover Page : Motion
VERBOSE: User Name : administrator
VERBOSE: Farm Name : PVS61Farm
VERBOSE: Title : Inventory Report for the PVS61Farm Farm
VERBOSE: Filename : C:\webster\PVS61Farm.docx
VERBOSE: Load Word Templates
VERBOSE: Create empty word doc
VERBOSE: disable spell checking
VERBOSE: insert new page, getting ready for table of contents
VERBOSE: table of contents
VERBOSE: set the footer
VERBOSE: get the footer and format font
VERBOSE: Footer text
VERBOSE: add page numbering
VERBOSE: return focus to main document
VERBOSE: move to the end of the current document
VERBOSE: Processing PVS Farm Information
VERBOSE: Processing Security Tab
VERBOSE: Processing Groups Tab
VERBOSE: Processing Licensing Tab
VERBOSE: Processing Options Tab
VERBOSE: Processing vDisk Version Tab
VERBOSE: Processing Status Tab
VERBOSE: Processing Sites
VERBOSE: Processing Site PVS61Site
VERBOSE: Processing Security Tab
VERBOSE: Processing Options Tab
VERBOSE: Processing vDisk Update Tab
VERBOSE: Processing Servers in Site PVS61Site
VERBOSE: Processing Server PVS61
VERBOSE: Processing General Tab
VERBOSE: Processing Network Tab
VERBOSE: Processing Stores Tab
VERBOSE: Processing Stores for server
VERBOSE: Processing Store Store
VERBOSE: Processing Options Tab
VERBOSE: Processing Logging Tab
VERBOSE: Processing Server Tab on Advanced button
VERBOSE: Processing Network Tab on Advanced button
VERBOSE: Processing Pacing Tab on Advanced button
VERBOSE: Processing Device Tab on Advanced button
VERBOSE: Processing Bootstrap files
VERBOSE: Processing Bootstrap files for Server PVS61
VERBOSE: Processing General Tab
VERBOSE: Processing Options Tab
VERBOSE: Processing all vDisks in site
VERBOSE: Processing vDisk Update Management
VERBOSE: Processing all device collections in site
VERBOSE: Processing Collection PVS61Collection
VERBOSE: Processing General Tab
VERBOSE: Processing Security Tab
VERBOSE: Processing Auto-Add Tab
VERBOSE: Processing each collection process for each device
VERBOSE: Processing all site views in site
VERBOSE: Processing all PVS Farm Views
VERBOSE: Processing Stores
VERBOSE: Processing Store Store
VERBOSE: Processing General Tab
VERBOSE: Processing Servers Tab
VERBOSE: Processing Server PVS61
VERBOSE: Processing Paths Tab
VERBOSE: Finishing up Word document
VERBOSE: Set Cover Page Properties
VERBOSE: Update the Table of Contents
VERBOSE: Save and Close document and Shutdown Word
PS C:\webster&gt;
</pre>
<p>That is it, that is all there is to it.</p>
<p>Hope this help.</p>
<p>Webster</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/using-my-citrix-pvs-powershell-documentation-script-with-remoting/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5609</post-id>	</item>
		<item>
		<title>Documenting a Citrix XenApp 6 Farm with Microsoft PowerShell and Word – Version 3</title>
		<link>https://www.carlwebster.com/documenting-a-citrix-xenapp-6-farm-with-microsoft-powershell-and-word-version-3/</link>
					<comments>https://www.carlwebster.com/documenting-a-citrix-xenapp-6-farm-with-microsoft-powershell-and-word-version-3/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Thu, 21 Feb 2013 11:00:42 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[XenApp]]></category>
		<category><![CDATA[XenApp 6.0]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[Word]]></category>
		<category><![CDATA[word comobject]]></category>
		<category><![CDATA[xenapp 6]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=5481</guid>

					<description><![CDATA[The script to document a Citrix XenApp 6 farm has proven to be very popular.  I had not always wanted to take the time to create a version of the&#8230;]]></description>
										<content:encoded><![CDATA[<p>The script to document a Citrix XenApp 6 farm has proven to be very popular.  I had not always wanted to take the time to create a version of the script that would output to a Microsoft Word document because this script had not been downloaded very much.  But in the last few months, the script has been downloaded several thousands of times.  So I finally decided it was time to create a version of this script that creates a Word document.  Ryan Revord had taken the <a title="Documenting a Citrix XenApp 6 Farm with Microsoft PowerShell" href="https://www.carlwebster.com/documenting-a-citrix-xenapp-6-farm-with-microsoft-powershell/" target="_blank" rel="noopener">XenApp 6.0 version of the script</a> and changed it to create a basic Microsoft Word document.  Ryan saved me a lot of work but I wanted improve on the document created by adding a cover page, Table of Contents and footer.  This article will explain the changes to the script to create a Word document.</p>
<p><span id="more-5481"></span></p>
<p><strong>NOTE: This script is continually updated.  You can always find the most current version by going to <a title="Current Scripts" href="https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/" target="_blank" rel="noopener">https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</a></strong></p>
<p>As much as Microsoft pushes PowerShell for their products and on their users, I find it surprising there is no native PowerShell support for any of the Office products.  For example there is no New_WordDocument, Get-WordDocument or Save-WordDocument.  In order to use Word with PowerShell you must use the Word COM Object model.  Finding detailed information on that subject was not easy.  Fortunately for me, Jeff Hicks had <a title="San Diego 2012 PowerShell Deep Dive Slides and Demos" href="http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/" target="_blank" rel="noopener">blogged about a presentation</a> he did in 2012 where he linked to some sample PowerShell script files.  One of his sample files gave me the start I needed.</p>
<p>The prerequisites to follow along with this article are:</p>
<ul>
<li>A server, physical or virtual, running Microsoft Windows Server 2008 R2 with or without SP1</li>
<li>Citrix XenApp 6 installed with or without HRP01 or HRP02</li>
<li>Word 2007, 2010 or 2013 installed on the computer running the script</li>
</ul>
<p>I tested the script with Hotfix Rollup Pack 02.</p>
<p><strong>Note: </strong>The parts of this script that deal with creating the Word document are derived 100% from the XenApp 6.5 script.  To read the details of the changes to the script that deal with Microsoft Word, please read Documenting a Citrix XenApp 6.5 Farm with Microsoft PowerShell and Word – Version 3.  Several of the bug fixes and issues resolved for Version 3.1 of the XenApp 6.5 script are included in this script.  These include:</p>
<ul>
<li>Several typos were fixed to get rid of my southern drawl.  No more “gettin”, “settin” or “runnin”.</li>
<li>More Write-Verbose statements were added.</li>
<li>Fixed all the issues reported by running the script with Set-StrictMode –Version 2.0 set.</li>
<li>For some users, when Microsoft Word is installed, the HKCU:\Software\Microsoft\Office\Common\UserInfo\CompanyName registry key is set and for some, it is not set. For those users, the HKCU:\Software\Microsoft\Office\Common\UserInfo\Company registry key is set. The script will now check both locations.</li>
<li>Some companies do not install the Microsoft Word Templates. This cause the Cover Page and Table of Contents sections of the script to generate numerous errors. The script now checks to see if the appropriate Word Template file is loaded successfully. If not, then the Cover Page and Table of Contents are skipped. The rest of the report is generated.</li>
<li>Pat Coughlin showed me how to disable Spell Check and Grammar Check while the document is created. For large XenApp 6 Farms, this can substantially speed up the document creation. For those large farms that can generate 1000+ page documents, Word would crash trying to keep track of all the spelling and grammar errors.</li>
<li>In the Load Evaluator section, the Load Throttling and Server User load settings were added.</li>
<li>A user on StackOverflow.com showed me how to indent the Table used for the Citrix Services.</li>
<li>Now that I know how to indent the Word Tables, I added Tables for the Citrix Installed Hotfixes and the Microsoft Hotfixes.</li>
<li>The Table for the Microsoft Hotfixes now lists all the Citrix recommended Microsoft hotfixes and whether the hotfix is Installed or Not Installed.</li>
<li>Before getting information on the Citrix Services and hotfixes, the server is tested to make sure it is reachable.</li>
<li>I received a question as to whether Microsoft Word needed to be installed to create the Word document. The script now verifies that Word is installed. If not, a warning is given and the script exits.</li>
<li>I received reports of the script “crashing” if Word was running before the script was run. The script will now check to see if Word is running and if it is, the script will exit. If the script is run from a XenApp server, the script gets the Session ID of the user running the script. Then the script checks if the WinWord process is running in that session. If it is, a warning is given and the script exits.</li>
<li>Session printers with modified settings are now fully detailed</li>
</ul>
<p>In trying to find resources to figure out how to use PowerShell to create a complex Word document, I found Jeff Hick’s blog post and sample scripts.</p>
<p><a title="San Diego 2012 PowerShell Deep Dive Slides and Demos" href="http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/" target="_blank" rel="noopener">http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/</a></p>
<p>Jeff had a ZIP file with several sample PowerShell scripts.  One of them, Demo-WordReport.ps1, was extremely helpful.</p>
<p>There are three pieces of information the script needs for the Cover Page and Footer:</p>
<ol>
<li>Company Name</li>
<li>Cover Page</li>
<li>User Name</li>
</ol>
<p>Since a digitally signed version of the script is provided, these three pieces of information need to be passed to the script as parameters.  A signed PowerShell script cannot be modified or the script is rendered useless.</p>
<p>These parameters give us $CompanyName, $CoverPage and $UserName.  Each has an alias: CN for CompanyName, CP for CoverPage and UN for UserName.</p>
<p>The default for $CompanyName is read from the registry key where Microsoft Office stores user information.  For some users, when Microsoft Word is installed, the HKCU:\Software\Microsoft\Office\Common\UserInfo\CompanyName registry key is set and for some, it is not set.  For those users, the HKCU:\Software\Microsoft\Office\Common\UserInfo\Company registry key is set.  The script checks both locations.</p>
<p>The default for $CoverPage is Motion.  Motion is a Word Cover Page that comes with both versions of Word, looks good but will require a minor tweak of changing the font used by the date field to a smaller font size.  Some companies do not install the Microsoft Word Templates.  The script checks to see if the appropriate Word Template file is loaded successfully.  If not, then the Cover Page and Table of Contents are skipped.  The rest of the report is generated.</p>
<p>The default for $UserName is taken from the USERNAME environment variable.</p>
<p>The parameter names can be spelled out or the aliases can be used or any combination.  All three of these examples are valid:</p>
<p>-CompanyName “XYC, Inc.” –CoverPage “Grid” –UserName “Joe User”</p>
<p>-CN “XYC, Inc.” –CP “Grid” –UN “Joe User”</p>
<p>-CoverPage “Grid” –UN “Joe User”</p>
<p>For the third example, the default Company Name will be used.</p>
<p>For the Word document to be saved a file name is needed and for the Cover Page, a title is needed.</p>
<p>The filename for the document is the XenApp farm name with the extension DOCX.  The document is stored in the folder where the script is run.</p>
<p>Each version of Word comes with Cover Pages and only two are shared across both versions.  The version of Word installed on the computer running the script needs to be determined.  If a wrong cover page is passed as $CoverPage and that Cover Page is not in the installed version of Word, the script will run but a lot of errors will be returned.  The script validates the $CoverPage against the valid Cover Pages specific to each version of Word.</p>
<p>If an invalid Cover Page is used, the script gives an error, closes Word and exits.</p>
<p>In Version 1 of this script, in order to write out a line of output, my friend Michael B. Smith wrote a <em>Line</em> function.  That function is no longer needed.  Ryan took Michael’s function and modified it to write a line to Word.</p>
<p>The next changes in Version 3 come in the Servers section.  I added Word Tables to hold information on the Citrix services and installed Citrix hotfixes.  I know I can get more data on the services by using WMI Queries but in a large farm with XenApp servers spread geographically; those queries can cause excessive network traffic.  I am using the Get-Service cmdlet because it is native.</p>
<p>Since this script has parameters, I created help text for the script.  Running the following command from the PowerShell prompt will display the full help text.</p>
<pre class="brush: bash; title: ; notranslate">
Get-Help .\XA6_Inventory_v3.ps1 -full
</pre>
<p>You can also use –online to get taken to this article.</p>
<pre class="brush: bash; title: ; notranslate">
Get-Help .\XA6_Inventory_V3.ps1 -online
</pre>
<p>Running the script with –verbose, gives information of the script’s running.</p>
<pre class="brush: bash; title: ; notranslate">
.\xa6_inventory_v3.ps1 -CompanyName &quot;The Accidental Citrix Admin&quot; -CoverPage &quot;Facet&quot; -UserName &quot;Amalgamated Consulting Group&quot; -verbose
</pre>
<p>Sample output.</p>
<pre class="brush: plain; title: ; notranslate">
PS C:\webster&gt; .\xa6_inventory_v3.ps1 -CompanyName &quot;The Accidental Citrix Admin&quot; -CoverPage &quot;Facet&quot; -UserName &quot;Amalgamated Consulting Group&quot; -verbose
VERBOSE: Getting Farm data
VERBOSE: Setting up Word
VERBOSE: Create Word comObject.  If you are not running Word 2007, ignore the next message.
VERBOSE: The object written to the pipeline is an instance of the type &quot;Microsoft.Office.Interop.Word.ApplicationClass&quot;
 from the component's primary interop assembly. If this type exposes different members than the IDispatch members,
scripts written to work with this object might not work if the primary interop assembly is not installed.
VERBOSE: Running Microsoft Word 2013
VERBOSE: Validate company name
VERBOSE: Validate cover page
VERBOSE: Company Name: The Accidental Citrix Admin
VERBOSE: Cover Page  : Facet
VERBOSE: User Name   : Amalgamated Consulting Group
VERBOSE: Farm Name   : NewFarm
VERBOSE: Title       : Inventory Report for the NewFarm Farm
VERBOSE: Filename    : C:\webster\NewFarm.docx
VERBOSE: Load Word Templates
VERBOSE: Create empty word doc
VERBOSE: disable spell checking
VERBOSE: insert new page, getting ready for table of contents
VERBOSE: table of contents
VERBOSE: set the footer
VERBOSE: get the footer and format font
VERBOSE: Footer text
VERBOSE: add page numbering
VERBOSE: return focus to main document
VERBOSE: move to the end of the current document
VERBOSE: Processing Administrators
VERBOSE: Processing Applications
WARNING: Application information could not be retrieved
VERBOSE: Processing Configuration Logging/History Report
VERBOSE: Processing Load Balancing Policies
WARNING: Load balancing policy information could not be retrieved
VERBOSE: Processing Load Evaluators
VERBOSE: Processing Servers
VERBOSE: Testing to see if XA60 is online and reachable
VERBOSE: XA60 is online.  Citrix Services and Hotfix areas processed.
VERBOSE: Processing Citrix services for server XA60
VERBOSE: Create Word Table for Citrix services
VERBOSE: add Citrix services table to doc
VERBOSE: format first row with column headings
VERBOSE: Move table of Citrix services to the right
VERBOSE: return focus back to document
VERBOSE: move to the end of the current document
VERBOSE: Get list of Citrix hotfixes installed
VERBOSE: Processing server XA60
VERBOSE: number of hotfixes is 1
VERBOSE: Create Word Table for Citrix Hotfixes
VERBOSE: add Citrix installed hotfix table to doc
VERBOSE: format first row with column headings
VERBOSE: Move table of Citrix installed hotfixes to the right
VERBOSE: return focus back to document
VERBOSE: move to the end of the current document
VERBOSE: compare Citrix hotfixes to recommended Citrix hotfixes from CTX129229
VERBOSE: Processing Microsoft hotfixes for server XA60
VERBOSE: Create Word Table for Microsoft Hotfixes
VERBOSE: add Microsoft hotfix table to doc
VERBOSE: format first row with column headings
VERBOSE: Move table of Microsoft hotfixes to the right
VERBOSE: return focus back to document
VERBOSE: move to the end of the current document
VERBOSE: Processing Worker Groups
VERBOSE: Processing Zones
VERBOSE: Processing Citrix IMA Policies
VERBOSE: Finishing up Word document
VERBOSE: Set Cover Page Properties
VERBOSE: Update the Table of Contents
VERBOSE: Save and Close document and Shutdown Word
PS C:\webster&gt;
</pre>
<p>How to use this script?</p>
<p>I saved the script as XA6_Inventory_V3.ps1 in the C:\PSScripts folder.  From the PowerShell prompt, change to the C:\PSScripts folder, or the folder where you saved the script.  From the PowerShell prompt, type in:</p>
<p><strong>.\XA6_Inventory_V3.ps1 </strong>and press <em>Enter</em>.</p>
<p><strong>A word about Word</strong></p>
<ol>
<li>Word must be installed</li>
<li>After installation, Word should be opened, at least once, before you run the script</li>
<li>It is better to do File, Options, OK before running the script</li>
</ol>
<p>The script does very strange things if the last two items are not done.  All kinds of errors are generated by the script if Word has not been opened at least once.  The second time the script is run (without Word haven been opened), fewer errors are generated.  The third time the script is run, it runs without errors.</p>
<p>I am assuming there are registry keys and values that need to be set for the Word comObject to operate properly.</p>
<p><strong>Bottom Line:</strong> If you just installed Word, open Word and close Word before running the script.</p>
<p>If you have any suggestions for the script, please let me know.  Send an e-mail to webster@carlwebster.com.</p>
<p><strong>NOTE: This script is continually updated.  You can always find the most current version by going to <a title="Current Scripts" href="https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/" target="_blank" rel="noopener">https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</a></strong></p>
<p>Copies of all the Cover Pages can be found here:</p>
<p><a href="https://carlwebster.sharefile.com/d-s5e9ffd7b1db4a178" target="_blank" rel="noopener">Word 2007</a></p>
<p><a href="https://carlwebster.sharefile.com/d-s309a7ffd0c7430d8" target="_blank" rel="noopener">Word 2010</a></p>
<p><a href="https://carlwebster.sharefile.com/d-sca5ecf61898465bb" target="_blank" rel="noopener">Word 2013</a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/documenting-a-citrix-xenapp-6-farm-with-microsoft-powershell-and-word-version-3/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5481</post-id>	</item>
		<item>
		<title>Documenting a Citrix Provisioning Services Farm with Microsoft PowerShell and Word &#8211; Version 2</title>
		<link>https://www.carlwebster.com/documenting-a-citrix-provisioning-services-farm-with-microsoft-powershell-and-word-version-2/</link>
					<comments>https://www.carlwebster.com/documenting-a-citrix-provisioning-services-farm-with-microsoft-powershell-and-word-version-2/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Wed, 20 Feb 2013 11:00:52 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PVS]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[provisioning services]]></category>
		<category><![CDATA[PVS 5.6]]></category>
		<category><![CDATA[PVS 6.0]]></category>
		<category><![CDATA[PVS 6.1]]></category>
		<category><![CDATA[Word]]></category>
		<category><![CDATA[Word COM Object]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=5402</guid>

					<description><![CDATA[The script to document a Citrix Provisioning Services (PVS) farm has proven to be very popular.  I have always wanted to take the time to create a version of the&#8230;]]></description>
										<content:encoded><![CDATA[<p>The script to document a Citrix Provisioning Services (PVS) farm has proven to be very popular.  I have always wanted to take the time to create a version of the script that would output to a Microsoft Word document.  Ryan Revord had taken the <a title="Documenting a Citrix XenApp 6 Farm with Microsoft PowerShell" href="https://www.carlwebster.com/documenting-a-citrix-xenapp-6-farm-with-microsoft-powershell/" target="_blank" rel="noopener">XenApp 6.0 script</a> and changed it to create a basic Microsoft Word document.  Ryan saved me a lot of work but I wanted improve on the document created by adding a cover page, Table of Contents and footer.  This article will explain the changes to the script to create a Word document.</p>
<p><span id="more-5402"></span></p>
<p><strong>NOTE: This script is continually updated.  You can always find the most current version by going to <a title="Current Scripts" href="https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/" target="_blank" rel="noopener">https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</a></strong></p>
<p>As much as Microsoft pushes PowerShell for their products and on their users, I find it surprising there is no native PowerShell support for any of the Office products.  For example there is no New_WordDocument, Get-WordDocument or Save-WordDocument.  In order to use Word with PowerShell you must use the Word COM Object model.  Finding detailed information on that subject was not easy.  Fortunately for me, Jeff Hicks had <a title="San Diego 2012 PowerShell Deep Dive Slides and Demos" href="http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/" target="_blank" rel="noopener">blogged about a presentation</a> he did in 2012 where he linked to some sample PowerShell script files.  One of his sample files gave me the start I needed.</p>
<p>The prerequisites to follow along with this article are:</p>
<ul>
<li>Word 2007, 2010 or 2013 installed on the computer running the script</li>
<li>PVS 5.6, PVS 6.0 or PVS 6.1</li>
<li>PVS Console PowerShell snap-in registered</li>
</ul>
<p><strong>Note: </strong>The parts of this script that deal with creating the Word document are derived 100% from the XenApp 6.5 script.  To read the details of the changes to the script that deal with Microsoft Word, please read Documenting a Citrix XenApp 6.5 Farm with Microsoft PowerShell and Word – Version 3.  Several of the bug fixes and issues resolved for Version 3.1 of the XenApp 6.5 script are included in this script.  These include:</p>
<ul>
<li>Several typos were fixed to get rid of my southern drawl. No more “gettin”, “settin” or “runnin”.</li>
<li>Write-Verbose statements were added.</li>
<li>Fixed all the issues reported by running the script with Set-StrictMode –Version 2.0 set.</li>
<li>For some users, when Microsoft Word is installed, the HKCU:\Software\Microsoft\Office\Common\UserInfo\CompanyName registry key is set and for some, it is not set. For those users, the HKCU:\Software\Microsoft\Office\Common\UserInfo\Company registry key is set. The script will now check both locations.</li>
<li>Some companies do not install the Microsoft Word Templates. This cause the Cover Page and Table of Contents sections of the script to generate numerous errors. The script now checks to see if the appropriate Word Template file is loaded successfully. If not, then the Cover Page and Table of Contents are skipped. The rest of the report is generated.</li>
<li>Pat Coughlin showed me how to disable Spell Check and Grammar Check while the document is created. For large PVS Farms, this can substantially speed up the document creation. For those large farms that can generate 1000+ page documents, Word would crash trying to keep track of all the spelling and grammar errors.</li>
<li>I received a question as to whether Microsoft Word needed to be installed to create the Word document. The script now verifies that Word is installed. If not, a warning is given and the script exits.</li>
<li>I received reports of the script “crashing” if Word was running before the script was run. The script will now check to see if Word is running and if it is, the script will exit. If the script is run from a XenApp server, the script gets the Session ID of the user running the script. Then the script checks if the WinWord process is running in that session. If it is, a warning is given and the script exits.</li>
</ul>
<p>In trying to find resources to figure out how to use PowerShell to create a complex Word document, I found Jeff Hick’s blog post and sample scripts.</p>
<p><a title="San Diego 2012 PowerShell Deep Dive Slides and Demos" href="http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/" target="_blank" rel="noopener">http://jdhitsolutions.com/blog/2012/05/san-diego-2012-powershell-deep-dive-slides-and-demos/</a></p>
<p>Jeff had a ZIP file with several sample PowerShell scripts.  One of them, Demo-WordReport.ps1, was extremely helpful.</p>
<p>Pat Coughlin showed me how to disable Spell Check and Grammar Check while the document is created.  For large PVS Farms, this can substantially speed up the document creation.  For those large farms that can generate 1000+ page documents, Word would crash trying to keep track of all the spelling and grammar errors.</p>
<p>There are three pieces of information the script needs for the Cover Page and Footer:</p>
<ol>
<li>Company Name</li>
<li>Cover Page</li>
<li>User Name</li>
</ol>
<p>Since a digitally signed version of the script is provided, these three pieces of information need to be passed to the script as parameters.  A signed PowerShell script cannot be modified or the script is rendered useless.</p>
<p>These parameters give us $CompanyName, $CoverPage and $UserName.  Each has an alias: CN for CompanyName, CP for CoverPage and UN for UserName.</p>
<p>The default for $CompanyName is read from the registry key where Microsoft Office stores user information.  For some users, when Microsoft Word is installed, the HKCU:\Software\Microsoft\Office\Common\UserInfo\CompanyName registry key is set and for some, it is not set.  For those users, the HKCU:\Software\Microsoft\Office\Common\UserInfo\Company registry key is set.  The script checks both locations.</p>
<p>The default for $CoverPage is Motion.  Motion is a Word Cover Page that comes with all versions of Word, looks good but will require a minor tweak of changing the font used by the date field to a smaller font size.  Some companies do not install the Microsoft Word Templates.  The script checks to see if the appropriate Word Template file is loaded successfully.  If not, then the Cover Page and Table of Contents are skipped.  The rest of the report is generated.</p>
<p>The default for $UserName is taken from the USERNAME environment variable.</p>
<p>The parameter names can be spelled out or the aliases can be used or any combination.  All three of these examples are valid:</p>
<p>-CompanyName “XYC, Inc.” –CoverPage “Grid” –UserName “Joe User”</p>
<p>-CN “XYC, Inc.” –CP “Grid” –UN “Joe User”</p>
<p>-CoverPage “Grid” –UN “Joe User”</p>
<p>For the third example, the default Company Name will be used.</p>
<p>For the Word document to be saved a file name is needed and for the Cover Page, a title is needed.</p>
<p>The filename for the document is the PVS farm name with the extension DOCX.  The document is stored in the folder where the script is run.</p>
<p>Each version of Word comes with Cover Pages and only two are shared across all versions.  The version of Word installed on the computer running the script needs to be determined.  If a wrong cover page is passed as $CoverPage and that Cover Page is not in the installed version of Word, the script will run but a lot of errors will be returned.  The script validates the $CoverPage against the valid Cover Pages specific to each version of Word.</p>
<p>If an invalid Cover Page is used, the script gives an error, closes Word and exits.</p>
<p>In Version 1 of this script, in order to write out a line of output, my friend Michael B. Smith wrote a <em>Line</em> function.  That function is no longer needed.  Ryan took Michael’s function and modified it to write a line to Word.</p>
<p>In updating this script, I fixed several bugs and logic issues.  For example, the time of “12:00 AM” for various update schedules was incorrectly printed as “012:00 PM”.  An example of a logic fix is For PVS 6.x vDisk Update Management.  I was only processing the Virtualization Hosts and vDisks only if at least one Task had been defined.  The Virtualization Hosts and vDisks are now processed independently of the Tasks.</p>
<p>Since this script has parameters, I created help text for the script.  Running the following command from the PowerShell prompt will display the full help text.</p>
<pre class="brush: bash; title: ; notranslate">

Get-Help .\PVS_Inventory_v2.ps1 -full

</pre>
<p>You can also use –online to get taken to this article.</p>
<pre class="brush: bash; title: ; notranslate">

Get-Help .\PVS_Inventory_V2.ps1 -online

</pre>
<p>Running the script with –verbose, gives information of the script’s running.</p>
<pre class="brush: bash; title: ; notranslate">

.\PVS_inventory_v2.ps1 -CompanyName &amp;amp;quot;The Accidental Citrix Admin&amp;amp;quot; -CoverPage &amp;amp;quot;Motion&amp;amp;quot; -UserName &amp;amp;quot;Amalgamated Consulting Group&amp;amp;quot; -verbose

</pre>
<p>Sample output.</p>
<pre class="brush: plain; title: ; notranslate">
PS C:\webster&amp;amp;gt; .\pvs_inventory_v2.ps1 -CompanyName &amp;amp;quot;The Accidental Citrix Admin&amp;amp;quot; -CoverPage &amp;amp;quot;Contrast&amp;amp;quot; -UserName &amp;amp;quot;Amalgamated Consulting Group&amp;amp;quot; -verbose
VERBOSE: checking for McliPSSnapin
VERBOSE: Getting PVS version info
VERBOSE: Build PVS farm values
VERBOSE: Setting up Word
VERBOSE: Create Word comObject.  If you are not running Word 2007, ignore the next message.
VERBOSE: The object written to the pipeline is an instance of the type “Microsoft.Office.Interop.Word.ApplicationClass&amp;amp;quot;  from the component's primary interop assembly. If this type exposes different members than the IDispatch members, scripts written to work with this object might not work if the primary interop assembly is not installed.
VERBOSE: Running Microsoft Word 2010
VERBOSE: Validate company name
VERBOSE: Validate cover page
VERBOSE: Company Name: The Accidental Citrix Admin
VERBOSE: Cover Page  : Contrast
VERBOSE: User Name   : Amalgamated Consulting Group
VERBOSE: Farm Name   : PVS61Farm
VERBOSE: Title       : Inventory Report for the PVS61Farm Farm
VERBOSE: Filename    : C:\webster\PVS61Farm.docx
VERBOSE: Load Word Templates
VERBOSE: Create empty word doc
VERBOSE: disable spell checking
VERBOSE: insert new page, getting ready for table of contents
VERBOSE: table of contents
VERBOSE: set the footer
VERBOSE: get the footer and format font
VERBOSE: Footer text
VERBOSE: add page numbering
VERBOSE: return focus to main document
VERBOSE: move to the end of the current document
VERBOSE: Processing PVS Farm Information
VERBOSE: Processing Security Tab
VERBOSE: Processing Groups Tab
VERBOSE: Processing Licensing Tab
VERBOSE: Processing Options Tab
VERBOSE: Processing vDisk Version Tab
VERBOSE: Processing Status Tab
VERBOSE: Processing Sites
VERBOSE: Processing Site PVS61Site
VERBOSE: Processing Security Tab
VERBOSE: Processing Options Tab
VERBOSE: Processing vDisk Update Tab
VERBOSE: Processing Servers in Site PVS61Site
VERBOSE: Processing Server PVS61
VERBOSE: Processing General Tab
VERBOSE: Processing Network Tab
VERBOSE: Processing Stores Tab
VERBOSE: Processing Stores for server
VERBOSE: Processing Store PVS61Store
VERBOSE: Processing Options Tab
VERBOSE: Processing Logging Tab
VERBOSE: Processing Server Tab on Advanced button
VERBOSE: Processing Network Tab on Advanced button
VERBOSE: Processing Pacing Tab on Advanced button
VERBOSE: Processing Device Tab on Advanced button
VERBOSE: Processing Bootstrap files
VERBOSE: Processing Bootstrap files for Server PVS61
VERBOSE: Processing General Tab
VERBOSE: Processing Options Tab
VERBOSE: Processing all vDisks in site
VERBOSE: Processing vDisk PVS61vDisk
VERBOSE: Processing Properties General Tab
VERBOSE: Processing Identification Tab
VERBOSE: Processing Auto Update Tab
VERBOSE: Processing vDisk Update Management
VERBOSE: Processing virtual hosts
VERBOSE: Processing virtual host XenServer5
VERBOSE: Processing General Tab
VERBOSE: Processing Advanced Tab
VERBOSE: Processing all Update Managed vDisks for this site
VERBOSE: Processing Managed vDisk PVS61Store\PVS61vDisk
VERBOSE: Processing General Tab
VERBOSE: Processing Personality Tab
VERBOSE: Processing Status Tab
VERBOSE: Processing Logging Tab
VERBOSE: Processing Task Task2
VERBOSE: Processing General Tab
VERBOSE: Processing Schedule Tab
VERBOSE: Processing vDisks Tab
VERBOSE: Processing ESD Tab
VERBOSE: Processing Scripts Tab
VERBOSE: Processing Access Tab
VERBOSE: Processing Task Task3
VERBOSE: Processing General Tab
VERBOSE: Processing Schedule Tab
VERBOSE: Processing vDisks Tab
VERBOSE: Processing ESD Tab
VERBOSE: Processing Scripts Tab
VERBOSE: Processing Access Tab
VERBOSE: Processing all device collections in site
VERBOSE: Processing Collection PVS61Collection
VERBOSE: Processing General Tab
VERBOSE: Processing Security Tab
VERBOSE: Processing Auto-Add Tab
VERBOSE: Processing each collection process for each device
VERBOSE: Processing Device TestVM3
VERBOSE: Processing General Tab
VERBOSE: Processing vDisks Tab
VERBOSE: Processing all bootstrap files for this device
VERBOSE: Processing Authentication Tab
VERBOSE: Processing Personality Tab
VERBOSE: Processing all site views in site
VERBOSE: Processing all PVS Farm Views
VERBOSE: Processing Stores
VERBOSE: Processing Store PVS61Store
VERBOSE: Processing General Tab
VERBOSE: Processing Servers Tab
VERBOSE: Processing Server PVS61
VERBOSE: Processing Paths Tab
VERBOSE: Finishing up Word document
VERBOSE: Set Cover Page Properties
VERBOSE: Update the Table of Contents
VERBOSE: Save and Close document and Shutdown Word
PS C:\webster&amp;amp;gt;
</pre>
<p>How to use this script?</p>
<p>I saved the script as PVS_Inventory_V2.ps1 in the C:\PSScripts folder.  From the PowerShell prompt, change to the C:\PSScripts folder, or the folder where you saved the script.  From the PowerShell prompt, type in:</p>
<p><strong>.\PVS_Inventory_V2.ps1 </strong>and press <em>Enter</em>.</p>
<p><strong>A word about Word</strong></p>
<ol>
<li>Word must be installed</li>
<li>After installation, Word should be opened, at least once, before you run the script</li>
<li>It is better to do File, Options, OK before running the script</li>
</ol>
<p>The script does very strange things if the last two items are not done.  All kinds of errors are generated by the script if Word has not been opened at least once.  The second time the script is run (without Word haven been opened), fewer errors are generated.  The third time the script is run, it runs without errors.</p>
<p>Word 2013 is the worst.  If Word 2013 is installed and never opened before running the script, a popup box is shown asking to set file extension defaults.  It does not matter if <em>Never ask me again</em> is selected and Yes or No is clicked, the popup box will return until Word 2013 is opened and closed.</p>
<p>I am assuming there are registry keys and values that need to be set for the Word comObject to operate properly.</p>
<p><strong>Bottom Line:</strong> If you just installed Word, open Word and close Word before running the script.</p>
<p>If you have any suggestions for the script, please let me know.  Send an e-mail to webster@carlwebster.com.</p>
<p><strong>NOTE: This script is continually updated.  You can always find the most current version by going to <a title="Current Scripts" href="https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/" target="_blank" rel="noopener">https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</a></strong></p>
<p>Copies of all the Cover Pages, from the XenApp scripts, can be found here:</p>
<p><a href="https://carlwebster.sharefile.com/d-s5e9ffd7b1db4a178" target="_blank" rel="noopener">Word 2007</a></p>
<p><a href="https://carlwebster.sharefile.com/d-s309a7ffd0c7430d8" target="_blank" rel="noopener">Word 2010</a></p>
<p><a href="https://carlwebster.sharefile.com/d-sca5ecf61898465bb" target="_blank" rel="noopener">Word 2013</a></p>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/documenting-a-citrix-provisioning-services-farm-with-microsoft-powershell-and-word-version-2/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5402</post-id>	</item>
		<item>
		<title>Using My Citrix XenApp 6.5 PowerShell Documentation Script with Remoting</title>
		<link>https://www.carlwebster.com/using-my-citrix-xenapp-6-5-powershell-doumentation-script-with-remoting/</link>
					<comments>https://www.carlwebster.com/using-my-citrix-xenapp-6-5-powershell-doumentation-script-with-remoting/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Tue, 08 Jan 2013 19:11:09 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[XenApp]]></category>
		<category><![CDATA[XenApp 6.5]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[netsh advfirewall]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[TCP Port 2513]]></category>
		<category><![CDATA[windows firewall]]></category>
		<category><![CDATA[xenapp 6.5]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=5216</guid>

					<description><![CDATA[I received an email from a reader wanting to get my Citrix XenApp 6.5 Farm PowerShell documentation script to work remotely.  After I wrote my original script and article, Citrix&#8230;]]></description>
										<content:encoded><![CDATA[<p>I received an email from a reader wanting to get my <a title="Documenting a Citrix XenApp 6.5 Farm with Microsoft PowerShell" href="https://www.carlwebster.com/downloads/download-info/xenapp-6-5/" target="_blank" rel="noopener">Citrix XenApp 6.5 Farm PowerShell documentation script </a>to work remotely.  After I wrote my original script and article, <a title="XenApp 6.5 Powershell SDK" href="https://carlwebster.sharefile.com/d-s9b9df5f6350489f8" target="_blank" rel="noopener">Citrix updated the XenApp 6.5 PowerShell SDK</a> to support Remoting and a Default Computer Name.  Even using the new –ComputerName parameter, he was still unable to get my script to work.</p>
<p><span id="more-5216"></span></p>
<p><strong>Note:</strong> This article was updated on November 20, 2015. Go to the bottom of this article to see the updated information.</p>
<p>I installed the Citrix XenApp 6.5 PowerShell SDK and Group Policy modules on my lab domain controller.  All my lab servers have the Windows Firewall enabled and Server Manager Remote Management enabled.</p>
<p>I found this information in the SDK help file on <em>Remoting Cmdlets</em>:</p>
<pre class="brush: plain; title: ; notranslate">
This section explains how to invoke the XenApp Commands remotely. In XenApp 6.5 the cmdlets can be remoted using
the -ComputerName parameter.  In order to facilitate running existing scripts remotely without having to make
significant changes, a default computer name can be set in the client machine. To do this a new set of cmdlets
was introduced. When the default computer name is set, all the cmdlets will automatically remote to the server
specified without having to explicitly use the -ComputerName parameter every time.

To set the default computer name:

Set-XADefaultComputerName server1
</pre>
<p>My lab XenApp 6.5 server is named XA65, so I entered on my domain controller.</p>
<pre class="brush: bash; title: ; notranslate">Set-XADefaultComputerName XA65 </pre>
<p>When I ran my documentation script, I received:</p>
<figure id="attachment_49437" aria-describedby="caption-attachment-49437" style="width: 986px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001.png"><img loading="lazy" decoding="async" class="size-full wp-image-49437" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001.png" alt="Figure 1" width="986" height="144" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001.png 986w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001-530x77.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001-900x131.png 900w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001-768x112.png 768w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure001-600x88.png 600w" sizes="auto, (max-width: 986px) 100vw, 986px" /></a><figcaption id="caption-attachment-49437" class="wp-caption-text">Figure 1</figcaption></figure>
<p>I then ran Microsoft’s Sysinternals ProcMon to get a network trace. I found that TCP Port 2513 needed to be opened (Figure 2).</p>
<figure id="attachment_49438" aria-describedby="caption-attachment-49438" style="width: 647px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure002.png"><img loading="lazy" decoding="async" class="size-full wp-image-49438" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure002.png" alt="Figure 2" width="647" height="222" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure002.png 647w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure002-530x182.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure002-600x206.png 600w" sizes="auto, (max-width: 647px) 100vw, 647px" /></a><figcaption id="caption-attachment-49438" class="wp-caption-text">Figure 2</figcaption></figure>
<p>My wife tells me I couldn’t find a 10 gallon (37.8541 Liter) jug of milk on the fridge&#8217;s top shelf!  What does this have to do with anything?  DOH! At the top of the help file, I <em>now</em> see (Figure 3):</p>
<figure id="attachment_49439" aria-describedby="caption-attachment-49439" style="width: 706px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure003.png"><img loading="lazy" decoding="async" class="size-full wp-image-49439" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure003.png" alt="Figure 3" width="706" height="103" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure003.png 706w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure003-530x77.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure003-600x88.png 600w" sizes="auto, (max-width: 706px) 100vw, 706px" /></a><figcaption id="caption-attachment-49439" class="wp-caption-text">Figure 3</figcaption></figure>
<p>The help text says TCP Port 2513 must be opened on both computers, but I found I only needed it opened on the XenApp server.  To me, that is one less port open on my network.</p>
<p>I created a Windows Firewall Rule on my XenApp server to open TCP Port 2513 between the domain controller and my XenApp server (Figure 4).  The “remoteip” will need to be the computer&#8217;s IP address used to run the script.</p>
<pre class="brush: bash; title: ; notranslate"> netsh advfirewall firewall add rule name=&amp;amp;quot;Citrix PoSH TCP Port 2513&amp;amp;quot; dir=in action=allow description=&amp;amp;quot;Allow communication between XenApp and remote computer running PoSH scripts&amp;amp;quot; enable=yes profile=any remoteip=192.168.1.100 protocol=tcp localport=2513 &amp;nbsp;</pre>
<figure id="attachment_49440" aria-describedby="caption-attachment-49440" style="width: 668px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure004-1.png"><img loading="lazy" decoding="async" class="size-full wp-image-49440" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure004-1.png" alt="Figure 4" width="668" height="331" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure004-1.png 668w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure004-1-530x263.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure004-1-600x297.png 600w" sizes="auto, (max-width: 668px) 100vw, 668px" /></a><figcaption id="caption-attachment-49440" class="wp-caption-text">Figure 4</figcaption></figure>
<p>The Windows Firewall GUI shows my new rule created and enabled (Figure 5).</p>
<figure id="attachment_49441" aria-describedby="caption-attachment-49441" style="width: 901px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure005.png"><img loading="lazy" decoding="async" class="size-full wp-image-49441" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure005.png" alt="Figure 5" width="901" height="149" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure005.png 901w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure005-530x88.png 530w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure005-768x127.png 768w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure005-600x99.png 600w" sizes="auto, (max-width: 901px) 100vw, 901px" /></a><figcaption id="caption-attachment-49441" class="wp-caption-text">Figure 5</figcaption></figure>
<p>Now my script runs (Figure 6).</p>
<figure id="attachment_49442" aria-describedby="caption-attachment-49442" style="width: 988px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006.png"><img loading="lazy" decoding="async" class="size-full wp-image-49442" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006.png" alt="Figure 6" width="988" height="631" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006.png 988w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006-470x300.png 470w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006-900x575.png 900w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006-768x490.png 768w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure006-600x383.png 600w" sizes="auto, (max-width: 988px) 100vw, 988px" /></a><figcaption id="caption-attachment-49442" class="wp-caption-text">Figure 6</figcaption></figure>
<p>Now you can use my XenApp 6.5 PowerShell Documentation Script with absolutely no modifications and have it work with remoting.  Thanks, Citrix, for making this so easy.</p>
<p><strong>Update November 20, 2015</strong>:</p>
<p>If you are having an issue connecting, make sure the Citrix XenApp Commands Remoting service is started. I have seen this service in three states at various locations: Manual, Automatic but not Started, and Automatic and Started.  Make sure this service is Started, and then your remote connection should succeed.</p>
<p>Thanks to my Aussie friend Jeremy Saunders for reminding me to update this article with this information.</p>
<figure id="attachment_49443" aria-describedby="caption-attachment-49443" style="width: 820px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure007-1.png"><img loading="lazy" decoding="async" class="size-full wp-image-49443" src="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure007-1.png" alt="Figure 7" width="820" height="616" srcset="https://www.carlwebster.com/wp-content/uploads/2013/01/Figure007-1.png 820w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure007-1-399x300.png 399w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure007-1-768x577.png 768w, https://www.carlwebster.com/wp-content/uploads/2013/01/Figure007-1-600x451.png 600w" sizes="auto, (max-width: 820px) 100vw, 820px" /></a><figcaption id="caption-attachment-49443" class="wp-caption-text">Figure 7</figcaption></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/using-my-citrix-xenapp-6-5-powershell-doumentation-script-with-remoting/feed/</wfw:commentRss>
			<slash:comments>24</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5216</post-id>	</item>
		<item>
		<title>Listing Windows Firewall Rules Using Microsoft PowerShell</title>
		<link>https://www.carlwebster.com/listing-windows-firewall-rules-using-microsoft-powershell/</link>
					<comments>https://www.carlwebster.com/listing-windows-firewall-rules-using-microsoft-powershell/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Fri, 16 Nov 2012 11:00:38 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[windows firewall rules]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=5010</guid>

					<description><![CDATA[At a customer site recently, I needed a way to list all the Enabled Windows Firewall Inbound Rules.  I could not get what I needed by using the Windows netsh&#8230;]]></description>
										<content:encoded><![CDATA[<p>At a customer site recently, I needed a way to list all the Enabled Windows Firewall Inbound Rules.  I could not get what I needed by using the Windows</p>
<pre class="brush: bash; title: ; notranslate">netsh advfirewall monitor show firewall rule name=all dir=in</pre>
<p>command so I turned to using PowerShell.</p>
<p>I found the following article by James O’Neill that helped me get started.</p>
<p><a href="http://blogs.technet.com/b/jamesone/archive/2009/02/18/how-to-manage-the-windows-firewall-settings-with-powershell.aspx" target="_blank" rel="noopener">http://blogs.technet.com/b/jamesone/archive/2009/02/18/how-to-manage-the-windows-firewall-settings-with-powershell.aspx</a></p>
<p>What I needed for a headstart was the following code from James&#8217; article:</p>
<pre class="brush: powershell; title: ; notranslate">
Function Get-FireWallRule
{Param ($Name, $Direction, $Enabled, $Protocol, $profile, $action, $grouping)
$Rules=(New-object –comObject HNetCfg.FwPolicy2).rules
If ($name)      {$rules= $rules | where-object {$_.name     -like $name}}
If ($direction) {$rules= $rules | where-object {$_.direction  -eq $direction}}
If ($Enabled)   {$rules= $rules | where-object {$_.Enabled    -eq $Enabled}}
If ($protocol)  {$rules= $rules | where-object {$_.protocol   -eq $protocol}}
If ($profile)   {$rules= $rules | where-object {$_.Profiles -bAND $profile}}
If ($Action)    {$rules= $rules | where-object {$_.Action     -eq $Action}}
If ($Grouping)  {$rules= $rules | where-object {$_.Grouping -like $Grouping}}
$rules}

Get-firewallRule -enabled $true | sort direction,applicationName,name |
format-table -wrap -autosize -property Name, @{Label=”Action”; expression={$Fwaction&#x5B;$_.action]}},
@{label=&quot;Direction&quot;;expression={ $fwdirection&#x5B;$_.direction]}},
@{Label=&quot;Protocol&quot;; expression={$FwProtocols&#x5B;$_.protocol]}} , localPorts,applicationname
</pre>
<p>I created a script named listfw.ps1 and when I ran the script, I received the output shown in Figure 1.</p>
<figure id="attachment_32378" aria-describedby="caption-attachment-32378" style="width: 988px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001.png" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="wp-image-32378 size-full" src="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001.png" alt="Figure 1" width="988" height="631" srcset="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001.png 988w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001-470x300.png 470w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001-900x575.png 900w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001-768x490.png 768w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure001-600x383.png 600w" sizes="auto, (max-width: 988px) 100vw, 988px" /></a><figcaption id="caption-attachment-32378" class="wp-caption-text">Figure 1</figcaption></figure>
<p>The last column wasn’t formatted properly for me so I thought maybe the “–wrap” parameter of  Format-Table was causing the issue.  So I removed the “-wrap” and reran the script.  I received the output shown in Figure 2.</p>
<figure id="attachment_32379" aria-describedby="caption-attachment-32379" style="width: 988px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002.png"><img loading="lazy" decoding="async" class="size-full wp-image-32379" src="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002.png" alt="Figure 2" width="988" height="631" srcset="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002.png 988w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002-470x300.png 470w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002-900x575.png 900w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002-768x490.png 768w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure002-600x383.png 600w" sizes="auto, (max-width: 988px) 100vw, 988px" /></a><figcaption id="caption-attachment-32379" class="wp-caption-text">Figure 2</figcaption></figure>
<p>OK, still not what I need.  So I thought maybe the “-autosize” was the culprit.  I removed the “-autosize” and reran the script.  I received the output shown in Figure 3.</p>
<figure id="attachment_32380" aria-describedby="caption-attachment-32380" style="width: 988px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003.png" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="wp-image-32380 size-full" src="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003.png" alt="Figure 3" width="988" height="631" srcset="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003.png 988w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003-470x300.png 470w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003-900x575.png 900w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003-768x490.png 768w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure003-600x383.png 600w" sizes="auto, (max-width: 988px) 100vw, 988px" /></a><figcaption id="caption-attachment-32380" class="wp-caption-text">Figure 3</figcaption></figure>
<p>OK, I am getting further away from what I really.  What I want is a way for the Name column and the ApplicationName column to be full width.</p>
<p>Using get-help format-table –full gave me a clue.  The “-property” parameter has some options available:</p>
<pre class="brush: plain; title: ; notranslate">
-- Name (or Label) &lt;string&gt;
-- Expression &lt;string&gt; or &lt;script block&gt;
-- FormatString &lt;string&gt;
-- Width &lt;int32&gt;
-- Alignment  (value can be &quot;Left&quot;, &quot;Center&quot;, or &quot;Right&quot;)
</pre>
<p>I can see in Jame’s original code he is using the “Label” and “Expression” options.  I just need to figure out how to use the “Width” option.  After much trial and error, I came up with the following code:</p>
<pre class="brush: powershell; title: ; notranslate">
$spaces1 = &quot; &quot; * 71
$spaces2 = &quot; &quot; * 64
Get-firewallRule -enabled $true | sort name | `
format-table -property `
@{label=&quot;Name&quot; + $spaces1             ; expression={$_.name}                    ; width=75}, `
@{label=&quot;Action&quot;                      ; expression={$Fwaction&#x5B;$_.action]}       ; width=6 }, `
@{label=&quot;Direction&quot;                   ; expression={$fwdirection&#x5B;$_.direction]} ; width=9 }, `
@{label=&quot;Protocol&quot;                    ; expression={$FwProtocols&#x5B;$_.protocol]}  ; width=8 }, `
@{label=&quot;Local Ports&quot;                 ; expression={$_.localPorts}              ; width=11}, `
@{label=&quot;Application Name&quot; + $spaces2 ; expression={$_.applicationname}         ; width=80}
</pre>
<p>Running the script gives me the output shown in Figure 4.</p>
<figure id="attachment_32381" aria-describedby="caption-attachment-32381" style="width: 988px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004.png" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="wp-image-32381 size-full" src="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004.png" alt="Figure 4" width="988" height="631" srcset="https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004.png 988w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004-470x300.png 470w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004-900x575.png 900w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004-768x490.png 768w, https://www.carlwebster.com/wp-content/uploads/2012/11/Figure004-600x383.png 600w" sizes="auto, (max-width: 988px) 100vw, 988px" /></a><figcaption id="caption-attachment-32381" class="wp-caption-text">Figure 4</figcaption></figure>
<p>DOH! So close.  It seems the output is now limited by the width of the screen.  Looking at the help for Get-Table, I cannot see any option that allows me to make the table wider.  That led me to find this article.</p>
<p><a href="http://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/" target="_blank" rel="noopener">http://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/</a></p>
<p>It appears the solution is very simple.  Use out-string –width nnn.  Using a width of 200 and running the following command, I get what is shown below.</p>
<pre class="brush: bash; title: ; notranslate">.\listfw.ps1 | out-string –width 200 | out-file .\fw.txt</pre>
<p>&nbsp;</p>
<pre class="brush: plain; title: ; notranslate">
Name                                                                        Action Direction Protocol Local Ports Application Name
--------------------------------------------------------------------------- ------ --------- -------- ----------- --------------------------------------------------------------------------------
Citrix ICA (TCP-In)                                                                                   1494
Citrix IMA (TCP-In)                                                                                   2512
Citrix MFCOM (RPC)                                                                                    RPC         C:\Program Files (x86)\Citrix\system32\mfcom.exe
Citrix Print Service (RPC)                                                                            RPC         C:\Program Files (x86)\Citrix\system32\CpSvc.exe
Citrix Remote MFCOM DLLs (RPC)                                                                        RPC         C:\Windows\SysWOW64\dllhost.exe
Citrix Session Reliability (TCP-In)                                                                   2598        C:\Program Files (x86)\Citrix\XTE\bin\xte.exe
Citrix SSL Relay (TCP-In)                                                                             443         C:\Program Files (x86)\Citrix\XTE\bin\xte.exe
Citrix WI Configuration Manager (RPC)                                                                 RPC         C:\Program Files (x86)\Citrix\System32\ConfigMgrSvr.exe
Citrix XML Relay (TCP-In)                                                                             81          C:\Program Files (x86)\Citrix\System32\ctxxmlss.exe
Core Networking - Destination Unreachable (ICMPv6-In)                                                             System
Core Networking - Destination Unreachable Fragmentation Needed (ICMPv4-In)                                        System
Core Networking - DNS (UDP-Out)                                                                       *           C:\Windows\system32\svchost.exe
Core Networking - Dynamic Host Configuration Protocol (DHCP-In)                                       68          C:\Windows\system32\svchost.exe
Core Networking - Dynamic Host Configuration Protocol (DHCP-Out)                                      68          C:\Windows\system32\svchost.exe
Core Networking - Dynamic Host Configuration Protocol for IPv6(DHCPV6-In)                             546         C:\Windows\system32\svchost.exe
Core Networking - Dynamic Host Configuration Protocol for IPv6(DHCPV6-Out)                            546         C:\Windows\system32\svchost.exe
Core Networking - Group Policy (LSASS-Out)                                                            *           C:\Windows\system32\lsass.exe
Core Networking - Group Policy (NP-Out)                                                               *           System
Core Networking - Group Policy (TCP-Out)                                                              *           C:\Windows\system32\svchost.exe
Core Networking - Internet Group Management Protocol (IGMP-In)                                                    System
Core Networking - Internet Group Management Protocol (IGMP-Out)                                                   System
Core Networking - IPHTTPS (TCP-In)                                                                    IPHTTPS     System
Core Networking - IPHTTPS (TCP-Out)                                                                   *           C:\Windows\system32\svchost.exe
Core Networking - IPv6 (IPv6-In)                                                                                  System
Core Networking - IPv6 (IPv6-Out)                                                                                 System
Core Networking - Multicast Listener Done (ICMPv6-In)                                                             System
Core Networking - Multicast Listener Done (ICMPv6-Out)
Core Networking - Multicast Listener Query (ICMPv6-In)                                                            System
Core Networking - Multicast Listener Query (ICMPv6-Out)
Core Networking - Multicast Listener Report (ICMPv6-In)                                                           System
Core Networking - Multicast Listener Report (ICMPv6-Out)
Core Networking - Multicast Listener Report v2 (ICMPv6-In)                                                        System
Core Networking - Multicast Listener Report v2 (ICMPv6-Out)
Core Networking - Neighbor Discovery Advertisement (ICMPv6-In)                                                    System
Core Networking - Neighbor Discovery Advertisement (ICMPv6-Out)
Core Networking - Neighbor Discovery Solicitation (ICMPv6-In)                                                     System
Core Networking - Neighbor Discovery Solicitation (ICMPv6-Out)
Core Networking - Packet Too Big (ICMPv6-In)                                                                      System
Core Networking - Packet Too Big (ICMPv6-Out)
Core Networking - Parameter Problem (ICMPv6-In)                                                                   System
Core Networking - Parameter Problem (ICMPv6-Out)
Core Networking - Router Advertisement (ICMPv6-In)                                                                System
Core Networking - Router Advertisement (ICMPv6-Out)
Core Networking - Router Solicitation (ICMPv6-In)                                                                 System
Core Networking - Router Solicitation (ICMPv6-Out)
Core Networking - Teredo (UDP-In)                                                                     Teredo      C:\Windows\system32\svchost.exe
Core Networking - Teredo (UDP-Out)                                                                    *           C:\Windows\system32\svchost.exe
Core Networking - Time Exceeded (ICMPv6-In)                                                                       System
Core Networking - Time Exceeded (ICMPv6-Out)
DFS Management (DCOM-In)                                                                              135         C:\Windows\system32\svchost.exe
DFS Management (SMB-In)                                                                               445         System
DFS Management (TCP-In)                                                                               RPC         C:\Windows\system32\dfsfrsHost.exe
DFS Management (WMI-In)                                                                               RPC         C:\Windows\system32\svchost.exe
Remote Desktop - RemoteFX (TCP-In)                                                                    3389        C:\Windows\system32\svchost.exe
Remote Desktop (TCP-In)                                                                               3389        System
SQL Server (Citrix IMA)                                                                               *           C:\Program Files (x86)\Microsoft SQL Server\MSSQL10.CITRIX_METAFRAME\MSSQL\Bi...
SQL Server Browser (Citrix IMA)                                                                       *           C:\Program Files (x86)\Microsoft SQL Server\90\Shared\sqlbrowser.exe
Terminal Services - WMI (DCOM-In)                                                                     135         C:\Windows\system32\svchost.exe
Terminal Services - WMI (TCP-In)                                                                      RPC         C:\Windows\system32\svchost.exe
Terminal Services - WMI (WMI-Out)                                                                     *           C:\Windows\system32\svchost.exe
Terminal Services (NP-In)                                                                             445         System
Terminal Services (RPC)                                                                               RPC         C:\Windows\system32\svchost.exe
Terminal Services (RPC-EPMAP)                                                                         RPC-EPMap   C:\Windows\system32\svchost.exe
</pre>
<p>Now I have a report I can use. I can run this script before and after installing XenApp 6.5 and see what changes were made to the Windows Firewall rules.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/listing-windows-firewall-rules-using-microsoft-powershell/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5010</post-id>	</item>
		<item>
		<title>Documenting a Citrix XenDesktop 4 Farm with Microsoft PowerShell</title>
		<link>https://www.carlwebster.com/documenting-a-citrix-xendesktop-4-farm-with-microsoft-powershell/</link>
					<comments>https://www.carlwebster.com/documenting-a-citrix-xendesktop-4-farm-with-microsoft-powershell/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Mon, 12 Mar 2012 09:00:13 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[XenDesktop 5.x]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[xendesktop]]></category>
		<category><![CDATA[xendesktop 4]]></category>
		<guid isPermaLink="false">https://www.carlwebster.com/?p=4783</guid>

					<description><![CDATA[A customer site I was at recently needed their XenDesktop 4 farm documented.  Since I had already created PowerShell scripts to document the various versions of XenApp, I figured a&#8230;]]></description>
										<content:encoded><![CDATA[<p>A customer site I was at recently needed their XenDesktop 4 farm documented.  Since I had already created PowerShell scripts to document the various versions of XenApp, I figured a XenDesktop script should be easy to create.  This article and the script were written for “SR” at the customer site.</p>
<p>This article will focus only on XenDesktop 4.  I am planning on writing articles and scripts for XenDesktop 5.x.<span id="more-4783"></span></p>
<p>The prerequisites to follow along with this article are:</p>
<ul>
<li>A computer, physical or virtual, running Microsoft Windows Server 2003, Server 2008, Server 2008 R2, or Microsoft Windows XP, Vista, or 7 for running the XenDesktop Desktop Delivery Controller SDK.</li>
<li>Citrix XenDesktop 4 Desktop Delivery Controller (DDC) installed with at least one Desktop Group created.</li>
</ul>
<p>In this article, we will be installing the Citrix Delivery Controller SDK.  You can install the SDK from either the XenDesktop 4 installation media or download it from citrix.com.  Since I am at a customer site creating this script on a production network, I do not have access to the installation media.  Therefore, I will be downloading the SDK.</p>
<p>My initial goal was to see if I could walk down the nodes in the Delivery Services Console (DSC) (Figure 1) and see if I could document every nook and cranny.</p>
<figure id="attachment_49414" aria-describedby="caption-attachment-49414" style="width: 282px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure001.png"><img loading="lazy" decoding="async" class="size-full wp-image-49414" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure001.png" alt="Figure 1" width="282" height="403" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure001.png 282w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure001-210x300.png 210w" sizes="auto, (max-width: 282px) 100vw, 282px" /></a><figcaption id="caption-attachment-49414" class="wp-caption-text">Figure 1</figcaption></figure>
<p><del><strong>Note:</strong>  For instructions on how to install the SDK from the XenDesktop 4 installation media, please see http://blogs.citrix.com/2010/08/11/xendesktop-4-powershell-sdk-primer-part-1-getting-started/.</del></p>
<p><strong>Update 7-July-2021: Citrix, obviously, killed these old XD4 links.</strong></p>
<p><strong>For the SDK install, go to <a href="https://carlwebster.sharefile.com/d-s6239e1f90eb043d7a2642fbc61db997a" target="_blank" rel="noopener">https://carlwebster.sharefile.com/d-s6239e1f90eb043d7a2642fbc61db997a</a></strong></p>
<p><strong>For the SDK Welcome, go to <a href="https://carlwebster.sharefile.com/d-s559804f9b3244ff58669263ab1e7dc06" target="_blank" rel="noopener">https://carlwebster.sharefile.com/d-s559804f9b3244ff58669263ab1e7dc06</a></strong></p>
<figure id="attachment_49415" aria-describedby="caption-attachment-49415" style="width: 834px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure002.png"><img loading="lazy" decoding="async" class="size-full wp-image-49415" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure002.png" alt="Figure 2" width="834" height="547" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure002.png 834w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure002-457x300.png 457w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure002-768x504.png 768w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure002-600x394.png 600w" sizes="auto, (max-width: 834px) 100vw, 834px" /></a><figcaption id="caption-attachment-49415" class="wp-caption-text">Figure 2</figcaption></figure>
<p>Click <em>Start</em>, <em>Run</em>, type in <strong>C:\XD4SDK\XenDesktopControllerSDK.msi</strong> and press <em>Enter</em>.</p>
<p>Click <em>Run</em> (Figure 3).</p>
<div class="mceTemp"></div>
<figure id="attachment_49416" aria-describedby="caption-attachment-49416" style="width: 414px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure003.png"><img loading="lazy" decoding="async" class="size-full wp-image-49416" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure003.png" alt="Figure 3" width="414" height="310" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure003.png 414w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure003-401x300.png 401w" sizes="auto, (max-width: 414px) 100vw, 414px" /></a><figcaption id="caption-attachment-49416" class="wp-caption-text">Figure 3</figcaption></figure>
<figure id="attachment_49417" aria-describedby="caption-attachment-49417" style="width: 499px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure004.png"><img loading="lazy" decoding="async" class="size-full wp-image-49417" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure004.png" alt="Figure 4" width="499" height="388" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure004.png 499w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure004-386x300.png 386w" sizes="auto, (max-width: 499px) 100vw, 499px" /></a><figcaption id="caption-attachment-49417" class="wp-caption-text">Figure 4</figcaption></figure>
<p>Select <em>I accept the terms in the License Agreement</em> and click <em>Next</em> (Figure 5).</p>
<div class="mceTemp"></div>
<figure id="attachment_49418" aria-describedby="caption-attachment-49418" style="width: 499px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure005.png"><img loading="lazy" decoding="async" class="size-full wp-image-49418" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure005.png" alt="Figure 5" width="499" height="388" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure005.png 499w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure005-386x300.png 386w" sizes="auto, (max-width: 499px) 100vw, 499px" /></a><figcaption id="caption-attachment-49418" class="wp-caption-text">Figure 5</figcaption></figure>
<figure id="attachment_49419" aria-describedby="caption-attachment-49419" style="width: 499px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure006.png"><img loading="lazy" decoding="async" class="size-full wp-image-49419" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure006.png" alt="Figure 6" width="499" height="388" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure006.png 499w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure006-386x300.png 386w" sizes="auto, (max-width: 499px) 100vw, 499px" /></a><figcaption id="caption-attachment-49419" class="wp-caption-text">Figure 6</figcaption></figure>
<p>Click <em>Install</em> (Figure 7).</p>
<div class="mceTemp"></div>
<figure id="attachment_49420" aria-describedby="caption-attachment-49420" style="width: 499px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure007.png"><img loading="lazy" decoding="async" class="size-full wp-image-49420" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure007.png" alt="Figure 7" width="499" height="388" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure007.png 499w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure007-386x300.png 386w" sizes="auto, (max-width: 499px) 100vw, 499px" /></a><figcaption id="caption-attachment-49420" class="wp-caption-text">Figure 7</figcaption></figure>
<figure id="attachment_49421" aria-describedby="caption-attachment-49421" style="width: 499px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure008.png"><img loading="lazy" decoding="async" class="size-full wp-image-49421" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure008.png" alt="Figure 8" width="499" height="388" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure008.png 499w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure008-386x300.png 386w" sizes="auto, (max-width: 499px) 100vw, 499px" /></a><figcaption id="caption-attachment-49421" class="wp-caption-text">Figure 8</figcaption></figure>
<p>You now have new Start Menu items under <em>All Programs</em>, <em>Citrix</em>.  Windows 7 is shown in Figure 9.</p>
<figure id="attachment_49422" aria-describedby="caption-attachment-49422" style="width: 392px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure009.png"><img loading="lazy" decoding="async" class="size-full wp-image-49422" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure009.png" alt="Figure 9" width="392" height="194" /></a><figcaption id="caption-attachment-49422" class="wp-caption-text">Figure 9</figcaption></figure>
<p>Everything is now set up for us to get started.  The download page for the SDK says to get a listing of the available XenDesktop commands to enter the following command:</p>
<p><strong>Get-Command -psSnapin XdCommands</strong></p>
<p>Typing that line into the PowerShell session returns a list of Citrix XenDesktop PowerShell commands.  A sample is shown in Figure 10.</p>
<figure id="attachment_49423" aria-describedby="caption-attachment-49423" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure010.png"><img loading="lazy" decoding="async" class="size-full wp-image-49423" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure010.png" alt="Figure 10" width="677" height="342" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure010.png 677w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure010-530x268.png 530w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure010-600x303.png 600w" sizes="auto, (max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49423" class="wp-caption-text">Figure 10</figcaption></figure>
<p>To get a list of the Get commands, showing just the Name, where the noun starts with “Xd”, type the following in the PowerShell session (results are shown in Figure 11):</p>
<p><strong>Get-Command –Noun Xd* -Verb Get | Select-Object Name</strong></p>
<figure id="attachment_49424" aria-describedby="caption-attachment-49424" style="width: 550px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure011.png"><img loading="lazy" decoding="async" class="size-full wp-image-49424" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure011.png" alt="Figure 11" width="550" height="221" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure011.png 550w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure011-530x213.png 530w" sizes="auto, (max-width: 550px) 100vw, 550px" /></a><figcaption id="caption-attachment-49424" class="wp-caption-text">Figure 11</figcaption></figure>
<p>Of the eight Get-Xd* commands listed, only three are usable for documenting the Farm:</p>
<ul>
<li>Get-XdFarm</li>
<li>Get-XdController</li>
<li>Get-XdDesktopGroup</li>
</ul>
<p>One feature I like about the XenDesktop PowerShell commands is that you are not required to run them directly on a Controller.  You can use the –AdminAddress parameter to give the name or IP address of a Controller to run the command against.  Since I am developing this script on a production Farm, I am being safe and staying off the customer’s production Controllers.</p>
<p>Typing each of the commands into the PowerShell session gave me the results shown in Figure 12, Figure 13, and Figure 14.</p>
<p><strong>Note:</strong>  I am using a Formatted List (| fl) to see all the properties returned by each command.</p>
<figure id="attachment_49425" aria-describedby="caption-attachment-49425" style="width: 590px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure012.png"><img loading="lazy" decoding="async" class="size-full wp-image-49425" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure012.png" alt="Figure 12" width="590" height="218" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure012.png 590w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure012-530x196.png 530w" sizes="auto, (max-width: 590px) 100vw, 590px" /></a><figcaption id="caption-attachment-49425" class="wp-caption-text">Figure 12</figcaption></figure>
<figure id="attachment_49427" aria-describedby="caption-attachment-49427" style="width: 526px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure013.png"><img loading="lazy" decoding="async" class="size-full wp-image-49427" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure013.png" alt="Figure 13" width="526" height="281" /></a><figcaption id="caption-attachment-49427" class="wp-caption-text">Figure 13</figcaption></figure>
<figure id="attachment_49428" aria-describedby="caption-attachment-49428" style="width: 677px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure014.png"><img loading="lazy" decoding="async" class="size-full wp-image-49428" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure014.png" alt="Figure 14" width="677" height="342" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure014.png 677w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure014-530x268.png 530w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure014-600x303.png 600w" sizes="auto, (max-width: 677px) 100vw, 677px" /></a><figcaption id="caption-attachment-49428" class="wp-caption-text">Figure 14</figcaption></figure>
<p>My goal is to use the same wording as what is seen in the DSC for headings, captions, and text.  In order to do that, I needed a way to format the output text.  Michael B. Smith (MBS) developed a function for me to use called Line.</p>
<pre class="brush: powershell; title: ; notranslate">
Function line
#function created by Michael B. Smith, Exchange MVP
#@essentialexchange on Twitter
#http://TheEssentialExchange.com

{
	Param( &#x5B;int]$tabs = 0, &#x5B;string]$name = ’’, &#x5B;string]$value = ’’, &#x5B;string]$newline = “`n”, &#x5B;switch]$nonewline )

	While( $tabs –gt 0 ) { $global:output += “`t”; $tabs--; }

	If( $nonewline )
	{
		$global:output += $name + $value
	}
	Else
	{
		$global:output += $name + $value + $newline
	}
}
</pre>
<p>Another lesson MBS taught me is to check to see if each cmdlet used returned an error and how to tell the cmdlet how I wanted to proceed if there was an error.  This is done by using –ErrorAction, or –EA.  ErrorAction has four values (Table 1):</p>
<p>Table 1</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="144">Enumeration</td>
<td valign="top" width="48">Value</td>
<td valign="top" width="433">Description</td>
</tr>
<tr>
<td valign="top" width="144">SilentlyContinue</td>
<td valign="top" width="48">0</td>
<td valign="top" width="433">The Windows PowerShell runtime will continue processing without notifying the user that an action has occurred.</td>
</tr>
<tr>
<td valign="top" width="144">Stop</td>
<td valign="top" width="48">1</td>
<td valign="top" width="433">The Windows PowerShell runtime will stop processing when an action occurs.</td>
</tr>
<tr>
<td valign="top" width="144">Continue</td>
<td valign="top" width="48">2</td>
<td valign="top" width="433">The Windows PowerShell runtime will continue processing and notify the user that an action has occurred.</td>
</tr>
<tr>
<td valign="top" width="144">Inquire</td>
<td valign="top" width="48">3</td>
<td valign="top" width="433">The Windows PowerShell runtime will stop processing and ask the user how it should proceed.</td>
</tr>
</tbody>
</table>
<p>For this documentation script, I always use 0.  If an error occurs, I want the rest of the script to continue.</p>
<p>Next, I needed to know how to test to see if an action, like Get-XdFarm, succeeded or had an error.  MBS said to use $? to test if the most recent action succeeded (True) or had an error (False).  For example:</p>
<pre class="brush: powershell; title: ; notranslate">
$farm = Get-XdFarm -EA 0
If( $? )
{
	#success
}
Else
{
	#error
}
</pre>
<p>Because this script does not have to run on a Controller, a parameter is created to allow a Controller name or IP address to be used.</p>
<p>Let’s get started.  We will build the script node by node.  Some of the lines may wrap.</p>
<p>The beginning of the script:</p>
<pre class="brush: powershell; title: ; notranslate">
#Carl Webster, CTP and independent consultant
#webster@carlwebster.com
#@carlwebster on Twitter
#https://www.carlwebster.com
#This script written for &quot;SR&quot;, March 9, 2012
#Thanks to Michael B. Smith, Joe Shock, Jarian Gibson and James Rankin
#for testing and fine-tuning tips

Param(
&#x5B;string]$DDCAddress = &quot;&quot;
)

Function line
#function created by Michael B. Smith, Exchange MVP
#@essentialexchange on Twitter
#http://TheEssentialExchange.com

{
	Param( &#x5B;int]$tabs = 0, &#x5B;string]$name = ’’, &#x5B;string]$value = ’’, &#x5B;string]$newline = “`n”, &#x5B;switch]$nonewline )

	While( $tabs –gt 0 ) { $global:output += “`t”; $tabs--; }

	If( $nonewline )
	{
		$global:output += $name + $value
	}
	Else
	{
		$global:output += $name + $value + $newline
	}
}

#script begins
</pre>
<p>The first node in the DSC is the Farm itself.</p>
<pre class="brush: powershell; title: ; notranslate">
#get farm information
$global:output = &quot;&quot;

If($DDCAddress)
{
	$farm = Get-XdFarm -adminaddress $DDCAddress -EA 0
}
Else
{
	$farm = Get-XdFarm -EA 0
}

If( $? )
{
	line 0 &quot;XenDesktop Farm Name: &quot; $farm.Name
	line 1 &quot;XenDesktop Edition: &quot; -nonewline
	switch ($farm.edition)
	{
		&quot;PLT&quot;   {line 0 &quot;Platinum&quot;  }
		&quot;STD&quot;   {line 0 &quot;VDI&quot;       }
		&quot;ADV&quot;   {line 0 &quot;Advanced&quot;  }
		&quot;ENT&quot;   {line 0 &quot;Enterprise&quot;}
		default {line 0 &quot;Farm Edition could not be determined: $($farm.edition)&quot;}
	}

	line 1 &quot;Base OU: &quot; $farm.BaseOU
	line 1 &quot;License server&quot;
	line 2 &quot;Name: &quot; $farm.LicenseServerName
	line 2 &quot;Port number: &quot; $farm.LicenseServerPort
	line 1 &quot;Session reliability&quot;
	line 2 &quot;Allow users to view sessions during broken connections: &quot; $farm.EnableSessionReliability

	If($farm.EnableSessionReliability)
	{
		line 3 &quot;Port number: &quot; $farm.SessionReliabilityPort
		line 3 &quot;Seconds to keep sessions active: &quot; $farm.SessionReliabilityDurationSeconds
	}
} 
Else 
{
	line 0 &quot;XenDesktop Farm information could not be retrieved&quot;
}
write-output $global:output
$farm = $null
$global:output = $null

$global:output = &quot;&quot;
</pre>
<p>Sample script output:</p>
<pre class="brush: plain; title: ; notranslate">
XenDesktop Farm Name: SAMPLEXD4
        XenDesktop Edition: Platinum
        Base OU: XD4BaseOU
        License server
                Name: CTXLICENSE
                Port number: 0
        Session reliability
                Allow users to view sessions during broken connections: True
                        Port number: 2598
                        Seconds to keep sessions active: 60
</pre>
<p>Even though the license server port number is displayed as 27000 in the console, the Citrix cmdlet returns  0.</p>
<p>The next node in the DSC is Administrators, but Citrix does not provide a way to retrieve any information about the Administrators.</p>
<p>The next node is the Controllers.  Even though Controllers can be in folders, Citrix does not provide a way to retrieve Folder information.</p>
<pre class="brush: powershell; title: ; notranslate">
#get controller information
If($DDCAddress)
{
	$XDControllers = Get-XdController -adminaddress $DDCAddress -EA 0
}
Else
{
	$XDControllers = Get-XdController -EA 0
}

If( $? )
{
	line 0 &quot;Desktop Delivery Controllers:&quot;
	ForEach($XDController in $XDControllers)
	{
		line 1 &quot;Controller: &quot; $XDController.Name
		line 1 &quot;Version: &quot; $XDController.Version
		line 1 &quot;Zone Election Preference: &quot; $XDController.ZoneElectionPreference
		line 1 &quot;License Server&quot;
		If($XDController.UseFarmLicenseServerSettings)
		{
			line 2 &quot;Using Farm Setting&quot;
		}
		Else
		{
			Line 2 &quot;License server&quot;
			line 3 &quot;Name: &quot; $XDController.LicenseServerName
			line 3 &quot;Port number: &quot; $XDController.LicenseServerPort
		}
		line 1 &quot;&quot;
	}
} 
Else 
{
	line 0 &quot;Desktop Delivery Controller information could not be retrieved&quot;
}
write-output $global:output
$XDControllers = $null
$global:output = $null
</pre>
<p>Sample script output:</p>
<pre class="brush: plain; title: ; notranslate">
Desktop Delivery Controllers:
        Controller: DDC1
        Version: 4.0
        Zone Election Preference: Member
        License Server
                Using Farm Setting

        Controller: DDC2
        Version: 4.0
        Zone Election Preference: Member
        License Server
                Using Farm Setting
</pre>
<p>The last node is Desktop Groups. There are different options available depending on if the Desktop Group is Pooled or Assigned.  Instead, I returned the AD Computer Account name as shown in the console, and the cmdlet returns the Machine SID.  Also, not every user account returned a name, but the User SID was always returned.  MBS showed me how to convert a Machine or User Account SID to the Machine or User Name.</p>
<pre class="brush: powershell; title: ; notranslate">
$objSID = New-Object System.Security.Principal.SecurityIdentifier ($Desktop.MachineSid.Value)
$objComputer = $objSID.Translate(&#x5B;System.Security.Principal.NTAccount])
&quot;AD Computer Account: &quot; $objComputer.Value
</pre>
<p>And</p>
<pre class="brush: powershell; title: ; notranslate">
$objSID = New-Object System.Security.Principal.SecurityIdentifier($Desktop.AssignedUserSid.Value)
$objUser = $objSID.Translate(&#x5B;System.Security.Principal.NTAccount])
“Assigned User: “ $objUser.Value
</pre>
<pre class="brush: powershell; title: ; notranslate">
#get desktop group information
$global:output = &quot;&quot;

If($DDCAddress)
{
	$XDGroups = Get-XdDesktopGroup -adminaddress $DDCAddress -EA 0
}
Else
{
	$XDGroups = Get-XdDesktopGroup -EA 0
}

If( $? )
{
	line 0 &quot;Desktop Groups:&quot;
	ForEach($XDGroup in $XDGroups)
	{
		line 1 &quot;Basic&quot;
		line 2 &quot;Desktop Group Name&quot;
		line 3 &quot;Display name: &quot; $XDGroup.Name
		line 3 &quot;Description: &quot; $XDGroup.Description
		line 3 &quot;Desktop Group name: &quot; $XDGroup.InternalName
		line 3 &quot;Disable desktop group: &quot; -nonewline
		If($XDGroup.Enabled)
		{
			line 0 &quot;group is enabled&quot;
		}
		Else
		{
			line 0 &quot;group is disabled&quot;
		}

		line 2 &quot;Assignment Type&quot;
		line 3 &quot;Assignment Behavior: &quot; $XDGroup.AssignmentBehavior

		If($XDGroup.IsHosted)
		{
			line 2 &quot;Hosting infrastructure: &quot; $XDGroup.HostingSettings.HostingServer
		}


		line 2 &quot;Users&quot;
		line 3 &quot;Configured users:&quot;
		ForEach($User in $XDGroup.Users)
		{
			line 4 $User
			#line 4 &quot;SID: &quot; $User.Sid
			line 4 &quot;Group or User: &quot; -nonewline
			If($User.IsSecurityGroup)
			{
				line 0 &quot;Group&quot;
			}
			Else
			{
				line 0 &quot;User&quot;
			}
		}
		line 2 &quot;Virtual Desktops&quot;
		line 3 &quot;Virtual desktops:&quot;
		ForEach($Desktop in $XDGroup.Desktops)
		{
			line 4 &quot;Folder: &quot; $XDGroup.Folder
			line 4 &quot;Virtual Machine: &quot; $Desktop
			$objSID = New-Object System.Security.Principal.SecurityIdentifier ($Desktop.MachineSid.Value)
			$objComputer = $objSID.Translate(&#x5B;System.Security.Principal.NTAccount])
			line 4 &quot;AD Computer Account: &quot; $objComputer.Value
			line 4 &quot;Desktop State: &quot; $Desktop.State
			line 4 &quot;Assigned User: &quot; -nonewline
			If($Desktop.AssignUserName)
			{
				line 0 $Desktop.AssignUserName
			}
			ElseIf($Desktop.AssignedUserSid)
			{
				$objSID = New-Object System.Security.Principal.SecurityIdentifier ($Desktop.AssignedUserSid.Value)
				$objUser = $objSID.Translate(&#x5B;System.Security.Principal.NTAccount])
				line 0 $objUser.Value
			}
			Else
			{
				line 0 &quot;&quot;
			}
			line 4 &quot;Maintenance Mode: &quot; $Desktop.MaintenanceMode
			line 4 &quot;Machine State: &quot; $Desktop.PowerState
			line 4 &quot;Controller: &quot; $Desktop.Controller
			line 4 &quot;Agent Version: &quot; $Desktop.AgentVersion
			line 1 &quot;&quot;
		}
		line 1 &quot;Advanced&quot;
		line 2 &quot;Access Control&quot;

		$test = $XDGroup.AccessGatewayControl.ToString()
		$test1 = $test.replace(&quot;, &quot;,&quot;`n`t`t&quot;)

		line 3 $test1
		line 2 &quot;Access Gateway Conditions: &quot;
		ForEach($Condition in $XDGroup.AccessGatewayConditions)
		{
			line 3 $Condition
		}
		line 2 &quot;Client Options&quot;
		line 3 &quot;Appearance&quot;
		line 4 &quot;Colors: &quot; -nonewline
		switch ($XDGroup.DefaultColorDepth)
		{
			&quot;FourBit&quot;       {line 0 &quot;16 colors&quot;          }
			&quot;EightBit&quot;      {line 0 &quot;256 colors&quot;         }
			&quot;SixteenBit&quot;    {line 0 &quot;High color (16-bit)&quot;}
			&quot;TwentyFourBit&quot; {line 0 &quot;True color (24-bit)&quot;}
			default         {line 0 &quot;Color depth could not be determined: $($XDGroup.DefaultColorDepth)&quot;}

		}
		line 3 &quot;Connection&quot;
		line 4 &quot;Encryption: &quot; -nonewline
		switch ($XDGroup.DefaultEncryptionLevel)
		{
			&quot;Basic&quot;               {line 0 &quot;Basic&quot;                    }
			&quot;LogOnRC5Using128Bit&quot; {line 0 &quot;128-Bit Login Only (RC-5)&quot;}
			&quot;RC5Using40Bit&quot;       {line 0 &quot;40-Bit (RC-5)&quot;            }
			&quot;RC5Using56Bit&quot;       {line 0 &quot;56-Bit (RC-5)&quot;            }
			&quot;RC5Using128Bit&quot;      {line 0 &quot;128-Bit (RC-5)&quot;           }
			default               {line 0 &quot;Encryption level could not be determined: $($XDGroup.DefaultEncryptionLevel)&quot;}

		}
		line 3 &quot;Connection Protocols: &quot;
		ForEach($Protocol in $XDGroup.Protocols)
		{
			line 4 &quot;Name: &quot; $Protocol.Protocol
			line 4 &quot;Enabled: &quot; $Protocol.Enabled
		}

		#only show the next section if the Desktop Group is Pooled
		If($XDGroup.AssignmentBehavior -eq &quot;Pooled&quot;)
		{
			line 2 &quot;Idle Pool Settings&quot;
			line 3 &quot;Business Hours&quot;
			line 4 &quot;Business days &quot;
			ForEach($Day in $XDGroup.HostingSettings.BusinessDays)
			{
				line 5 $Day
			}
			line 4 &quot;Time zone &quot;  $XDGroup.HostingSettings.IdleTimesTimeZone
			IF($XDGroup.HostingSettings.PeakHoursStart)
			{
				line 4 &quot;Day start &quot;  $XDGroup.HostingSettings.PeakHoursStart.ToString()
			}
			If($XDGroup.HostingSettings.PeakHoursEnd)
			{
				line 4 &quot;Peak end &quot;  $XDGroup.HostingSettings.PeakHoursEnd.ToString()
			}
			If($XDGroup.HostingSettings.BusinessHoursEnd)
			{
				line 4 &quot;Day end &quot; $XDGroup.HostingSettings.BusinessHoursEnd.ToString()
			}
			line 3 &quot;Idle Desktop Count&quot;
			line 2 &quot;Business hours &quot; $XDGroup.HostingSettings.BusinessHoursIdleCount
			line 2 &quot;Peak time &quot; $XDGroup.HostingSettings.PeakHoursIdleCount
			line 2 &quot;Out of hours &quot; $XDGroup.HostingSettings.OutOfHoursIdleCount
		}
		
		# I can't find these settings in the console
		line 1 &quot;Other settings&quot;
		line 2 &quot;Allow User Desktop Restart: &quot; $XDGroup.AllowUserDesktopRestart
		line 2 &quot;Tainted Machine Action: &quot; $XDGroup.HostingSettings.TaintedMachineAction
		line 3 &quot;Actions: &quot;
		ForEach($Action in  $XDGroup.HostingSettings.Actions)
		{
			line 4 &quot;Action point: &quot; $Action.ActionPoint
			line 4 &quot;Action: &quot; $Action.Action
			line 4 &quot;Delay: &quot; $Action.Delay
			line 4 &quot;&quot;
		}


		line 1 &quot;&quot;
	}
} 
Else 
{
	line 0 &quot;Desktop Group information could not be retrieved&quot;
}
write-output $global:output
$XDGroups = $null
$test = $null
$test1 = $null
$global:output = $null
</pre>
<p>Sample script output:</p>
<pre class="brush: plain; title: ; notranslate">
Desktop Groups:
Basic
		Desktop Group Name
			Display name: WebstersLab
			Description: Used in Webster’s Lab for writing purposes
			Desktop Group name: WebstersLab
			Disable desktop group: group is enabled
		Assignment Type
			Assignment Behavior: Pooled
		Hosting infrastructure: http://msvirtualcenter.carls.com/sdk
		Users
			Configured users:
				CARLS\TS_XD_Lab
				Group or User: Group
				CARLS\TS_XD_Lab_Admin
				Group or User: Group
		Virtual Desktops
			Virtual desktops:
				Folder: \
				Virtual Machine: CARLS\COMPUTER01$
				AD Computer Account: CARLS\COMPUTER01$
				Desktop State: Available
				Assigned User: 
				Maintenance Mode: False
				Machine State: On
				Controller: DDC1
				Agent Version: 4.0.4522
	
				Folder: \
				Virtual Machine: CARLS\COMPUTER06$
				AD Computer Account: CARLS\COMPUTER06$
				Desktop State: NotRegistered
				Assigned User: 
				Maintenance Mode: False
				Machine State: On
				Controller: 
				Agent Version: 

	Advanced
		Access Control
			AllowGatewayNoConditionsDefined
		AllowGatewayAnyCondition
		Access Gateway Conditions: 
		Client Options
			Appearance
				Colors: High color (16-bit)
			Connection
				Encryption: Basic
			Connection Protocols: 
				Name: ICA30
				Enabled: True
		Idle Pool Settings
			Business Hours
				Business days 
					Sunday
					Monday
					Tuesday
					Wednesday
					Thursday
					Friday
					Saturday
				Time zone (UTC-05:00) Eastern Time (US &amp;amp;amp; Canada)
				Day start 01:00:00
				Peak end 20:30:00
				Day end 23:30:00
			Idle Desktop Count
		Business hours 7
		Peak time 7
		Out of hours 7
	Other settings
		Allow User Desktop Restart: False
		Tainted Machine Action: Restart
			Actions: 
				Action point: Disconnect
				Action: DoNothing
				Delay: 300
				
				Action point: LogOff
				Action: Shutdown
				Delay: 420
		
</pre>
<p>How to use this script?</p>
<p>I saved the script as XD4_Inventory.ps1 in the Z:\ folder.  From the PowerShell prompt, change to the Z:\ folder or the folder where you saved the script.  From the PowerShell prompt, type in:</p>
<p><strong>.\XD4_Inventory.ps1 |out-file Z:\XD4Farm.txt </strong>and press <em>Enter</em>, or</p>
<p><strong>.\XD4_Inventory.ps1 DDCName|out-file Z:\XD4Farm.txt </strong>and press <em>Enter</em>, or</p>
<p><strong>.\XD4_Inventory.ps1 DDCIPAddress|out-file Z:\XD4Farm.txt </strong>and press <em>Enter</em>.</p>
<p>Open XD4Farm.txt in either WordPad or Microsoft Word (Figure 15).</p>
<figure id="attachment_49429" aria-describedby="caption-attachment-49429" style="width: 865px" class="wp-caption alignnone"><a href="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure015-1.png"><img loading="lazy" decoding="async" class="size-full wp-image-49429" src="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure015-1.png" alt="Figure 15" width="865" height="716" srcset="https://www.carlwebster.com/wp-content/uploads/2012/03/Figure015-1.png 865w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure015-1-362x300.png 362w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure015-1-768x636.png 768w, https://www.carlwebster.com/wp-content/uploads/2012/03/Figure015-1-600x497.png 600w" sizes="auto, (max-width: 865px) 100vw, 865px" /></a><figcaption id="caption-attachment-49429" class="wp-caption-text">Figure 15</figcaption></figure>
<p><strong>You can always find the most current script by going to </strong><a title="Current Scripts" href="https://www.carlwebster.com/downloads/" target="_blank" rel="noopener noreferrer"><strong>https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</strong></a></p>
<p>Thanks</p>
<p>Webster</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/documenting-a-citrix-xendesktop-4-farm-with-microsoft-powershell/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4783</post-id>	</item>
		<item>
		<title>How To Digitally Sign a Microsoft PowerShell Script with a Third-Party Code Signing Certificate (Update April 4, 2012)</title>
		<link>https://www.carlwebster.com/how-to-digitally-sign-a-microsoft-powershell-script-with-a-third-party-code-signing-certificate/</link>
					<comments>https://www.carlwebster.com/how-to-digitally-sign-a-microsoft-powershell-script-with-a-third-party-code-signing-certificate/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Fri, 30 Sep 2011 20:00:08 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[XenApp]]></category>
		<category><![CDATA[XenApp 5 for Server 2003]]></category>
		<category><![CDATA[XenApp 5 for Server 2008]]></category>
		<category><![CDATA[XenApp 6.0]]></category>
		<category><![CDATA[XenApp 6.5]]></category>
		<category><![CDATA[code signing]]></category>
		<category><![CDATA[powershell]]></category>
		<guid isPermaLink="false">http://webster.skyrocket.ltd/?p=3705</guid>

					<description><![CDATA[I recently wrote an article on using Microsoft PowerShell to document a Citrix XenApp 6.0 farm.  I am also in the process of finishing up follow-up articles for XenApp 5&#8230;]]></description>
										<content:encoded><![CDATA[<p>I recently wrote an article on using Microsoft PowerShell to document a Citrix XenApp 6.0 farm.  I am also in the process of finishing up follow-up articles for XenApp 5 and XenApp 6.5.  One of the options I wanted to make available is a digitally signed copy of the script used in that article.  As there may be environments where only signed PowerShell scripts are allowed, I want to make signed copies of all my PowerShell scripts available.  I still consider myself a PowerShell rookie, so I wanted to document what I had to go through to sign a PowerShell script.</p>
<p><strong>Update: I now use the Digicert Certificate Utility for Windows to sign all my scripts.</strong></p>
<p><a href="https://www.digicert.com/kb/code-signing/digicert-certificate-utility-to-sign-code.htm" target="_blank" rel="noopener noreferrer">Code Signing with the DigiCert® Certificate Utility for Windows</a></p>
<p>The first thing needed is to request a code signing certificate.  At DigiCert, I clicked on <em>Code Signing Certificates </em>(Figure 1).</p>
<figure id="attachment_20993" aria-describedby="caption-attachment-20993" style="width: 977px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20993" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-2.png" alt="Figure 1" width="977" height="438" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-2.png 977w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-2-530x238.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-2-900x403.png 900w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-2-768x344.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-2-600x269.png 600w" sizes="auto, (max-width: 977px) 100vw, 977px" /><figcaption id="caption-attachment-20993" class="wp-caption-text">Figure 1</figcaption></figure>
<p>I then selected <em>Buy Now</em> (Figure 2).</p>
<figure id="attachment_20995" aria-describedby="caption-attachment-20995" style="width: 746px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20995" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-2.png" alt="Figure 2" width="746" height="552" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-2.png 746w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-2-405x300.png 405w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-2-600x444.png 600w" sizes="auto, (max-width: 746px) 100vw, 746px" /><figcaption id="caption-attachment-20995" class="wp-caption-text">Figure 2</figcaption></figure>
<p>I then selected <em>Code Signing Cert, </em>a <em>Validity Period, </em>and clicked <em>Continue</em> (Figure 3).</p>
<figure id="attachment_20996" aria-describedby="caption-attachment-20996" style="width: 746px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20996" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-2.png" alt="Figure 3" width="746" height="792" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-2.png 746w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-2-283x300.png 283w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-2-600x637.png 600w" sizes="auto, (max-width: 746px) 100vw, 746px" /><figcaption id="caption-attachment-20996" class="wp-caption-text">Figure 3</figcaption></figure>
<p>Next, I selected <em>Microsoft Authenticode</em> and clicked <em>Continue </em>(Figure 4).</p>
<figure id="attachment_20997" aria-describedby="caption-attachment-20997" style="width: 746px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20997" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-2.png" alt="Figure 4" width="746" height="740" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-2.png 746w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-2-302x300.png 302w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-2-150x150.png 150w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-2-100x100.png 100w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-2-600x595.png 600w" sizes="auto, (max-width: 746px) 100vw, 746px" /><figcaption id="caption-attachment-20997" class="wp-caption-text">Figure 4</figcaption></figure>
<p>Next, I filled in my <em>Organization Details</em> and clicked <em>Continue</em> (Figure 5).</p>
<figure id="attachment_20998" aria-describedby="caption-attachment-20998" style="width: 759px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20998" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-2.png" alt="Figure 5" width="759" height="540" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-2.png 759w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-2-422x300.png 422w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-2-600x427.png 600w" sizes="auto, (max-width: 759px) 100vw, 759px" /><figcaption id="caption-attachment-20998" class="wp-caption-text">Figure 5</figcaption></figure>
<p>I then filled in my <em>Contact Details</em> and clicked <em>Continue</em> (Figure 6).</p>
<figure id="attachment_20999" aria-describedby="caption-attachment-20999" style="width: 742px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20999" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-2.png" alt="Figure 6" width="742" height="564" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-2.png 742w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-2-395x300.png 395w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-2-600x456.png 600w" sizes="auto, (max-width: 742px) 100vw, 742px" /><figcaption id="caption-attachment-20999" class="wp-caption-text">Figure 6</figcaption></figure>
<p>I removed the Payment step information.  I selected <em>I agree to the Terms of Service above</em> and clicked <em>Complete Order</em> (Figure 7).</p>
<figure id="attachment_21000" aria-describedby="caption-attachment-21000" style="width: 742px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21000" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure007-1.png" alt="Figure 7" width="742" height="548" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure007-1.png 742w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure007-1-406x300.png 406w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure007-1-600x443.png 600w" sizes="auto, (max-width: 742px) 100vw, 742px" /><figcaption id="caption-attachment-21000" class="wp-caption-text">Figure 7</figcaption></figure>
<p>I then received an e-mail from DigiCert Support asking me to verify that I did request a Code Signing Certificate.  After I replied to the e-mail in the affirmative, I received another e-mail with a link to create the code-signing certificate (Figure 8).</p>
<figure id="attachment_21001" aria-describedby="caption-attachment-21001" style="width: 823px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21001" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure008-1.png" alt="Figure 8" width="823" height="285" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure008-1.png 823w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure008-1-530x184.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure008-1-768x266.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure008-1-600x208.png 600w" sizes="auto, (max-width: 823px) 100vw, 823px" /><figcaption id="caption-attachment-21001" class="wp-caption-text">Figure 8</figcaption></figure>
<p>Clicking the link in the e-mail opens my Internet browser with the following popup (Figure 9).  I clicked <em>Yes</em>.</p>
<figure id="attachment_21002" aria-describedby="caption-attachment-21002" style="width: 415px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21002" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure009-1.png" alt="Figure 9" width="415" height="229" /><figcaption id="caption-attachment-21002" class="wp-caption-text">Figure 9</figcaption></figure>
<p>Which then took me to the web site shown in Figure 10.  I then clicked <em>Generate Certificate</em>.</p>
<figure id="attachment_21003" aria-describedby="caption-attachment-21003" style="width: 824px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21003" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure010-1.png" alt="Figure 10" width="824" height="416" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure010-1.png 824w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure010-1-530x268.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure010-1-768x388.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure010-1-600x303.png 600w" sizes="auto, (max-width: 824px) 100vw, 824px" /><figcaption id="caption-attachment-21003" class="wp-caption-text">Figure 10</figcaption></figure>
<p>Which then took me to the web page shown in Figure 11.</p>
<figure id="attachment_21004" aria-describedby="caption-attachment-21004" style="width: 833px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21004" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure011-1.png" alt="Figure 11" width="833" height="299" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure011-1.png 833w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure011-1-530x190.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure011-1-768x276.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure011-1-600x215.png 600w" sizes="auto, (max-width: 833px) 100vw, 833px" /><figcaption id="caption-attachment-21004" class="wp-caption-text">Figure 11</figcaption></figure>
<p>I verified in Internet Explorer that the certificate is installed (Figure 12 and Figure 13).</p>
<figure id="attachment_21005" aria-describedby="caption-attachment-21005" style="width: 509px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21005" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure012-1.png" alt="Figure 12" width="509" height="464" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure012-1.png 509w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure012-1-329x300.png 329w" sizes="auto, (max-width: 509px) 100vw, 509px" /><figcaption id="caption-attachment-21005" class="wp-caption-text">Figure 12</figcaption></figure>
<figure id="attachment_21006" aria-describedby="caption-attachment-21006" style="width: 408px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21006" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure013-1.png" alt="Figure 13" width="408" height="508" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure013-1.png 408w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure013-1-241x300.png 241w" sizes="auto, (max-width: 408px) 100vw, 408px" /><figcaption id="caption-attachment-21006" class="wp-caption-text">Figure 13</figcaption></figure>
<p>On the computer where the Code Signing Certificate was installed, I started a PowerShell session running as Administrator.  Using the information from Don Jones’ <em>Windows PowerShell 2.0 TFM</em> book on page 149, I entered the following PowerShell command (should be one long line):</p>
<pre class="brush: powershell; title: ; notranslate">
Set-AuthenticodeSignature `
&quot;C:\Users\cwebster\Documents\carlwebster.com\Documenting a Citrix XenApp 6 Farm with Microsoft PowerShell\XA6_Inventory_Signed.ps1&quot; `
-TimestampServer &quot;http://timestamp.digicert.com/&quot; @(Get-Childitem cert:\CurrentUser\My -codesigning)&#x5B;0]
</pre>
<p>Which then returns a successful signing (Figure 14).</p>
<figure id="attachment_21009" aria-describedby="caption-attachment-21009" style="width: 985px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21009" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure014-1.png" alt="Figure 14" width="985" height="214" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure014-1.png 985w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure014-1-530x115.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure014-1-900x196.png 900w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure014-1-768x167.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure014-1-600x130.png 600w" sizes="auto, (max-width: 985px) 100vw, 985px" /><figcaption id="caption-attachment-21009" class="wp-caption-text">Figure 14</figcaption></figure>
<p>Opening my script shows the added signature block (Figure 15).</p>
<figure id="attachment_21008" aria-describedby="caption-attachment-21008" style="width: 835px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21008" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure015-1.png" alt="Figure 15" width="835" height="652" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure015-1.png 835w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure015-1-384x300.png 384w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure015-1-768x600.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure015-1-600x469.png 600w" sizes="auto, (max-width: 835px) 100vw, 835px" /><figcaption id="caption-attachment-21008" class="wp-caption-text">Figure 15</figcaption></figure>
<p>To verify the newly signed script, I went to my XenApp 6 server, copied the signed script to the C:\PSScripts folder, started a PowerShell session as Administrator, and changed to the C:\PSScripts folder.  I then set the PowerShell script execution policy to AllSigned (Figure 16).</p>
<figure id="attachment_21011" aria-describedby="caption-attachment-21011" style="width: 947px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21011" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure016-1.png" alt="Figure 16" width="947" height="126" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure016-1.png 947w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure016-1-530x71.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure016-1-900x120.png 900w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure016-1-768x102.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure016-1-600x80.png 600w" sizes="auto, (max-width: 947px) 100vw, 947px" /><figcaption id="caption-attachment-21011" class="wp-caption-text">Figure 16</figcaption></figure>
<p>I then tried to run the original unsigned script (Figure 17).  The script would not run because it is not digitally signed.</p>
<figure id="attachment_21012" aria-describedby="caption-attachment-21012" style="width: 954px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21012" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure017-1.png" alt="Figure 17" width="954" height="142" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure017-1.png 954w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure017-1-530x79.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure017-1-900x134.png 900w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure017-1-768x114.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure017-1-600x89.png 600w" sizes="auto, (max-width: 954px) 100vw, 954px" /><figcaption id="caption-attachment-21012" class="wp-caption-text">Figure 17</figcaption></figure>
<p>I then tried to run the signed script (Figure 18).</p>
<figure id="attachment_21013" aria-describedby="caption-attachment-21013" style="width: 965px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21013" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure018-1.png" alt="Figure 18" width="965" height="106" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure018-1.png 965w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure018-1-530x58.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure018-1-900x99.png 900w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure018-1-768x84.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure018-1-600x66.png 600w" sizes="auto, (max-width: 965px) 100vw, 965px" /><figcaption id="caption-attachment-21013" class="wp-caption-text">Figure 18</figcaption></figure>
<p>I answered <strong>A</strong> to <em>Always run</em> scripts signed by me (Figure 19) and the script runs successfully.</p>
<figure id="attachment_21014" aria-describedby="caption-attachment-21014" style="width: 988px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21014" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure019-1.png" alt="Figure 19" width="988" height="631" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure019-1.png 988w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure019-1-470x300.png 470w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure019-1-900x575.png 900w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure019-1-768x490.png 768w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure019-1-600x383.png 600w" sizes="auto, (max-width: 988px) 100vw, 988px" /><figcaption id="caption-attachment-21014" class="wp-caption-text">Figure 19</figcaption></figure>
<p>By answering <em>Always run</em> my code signing certificate was installed on the server in the Trusted Publishers store (Figure 20).</p>
<figure id="attachment_21015" aria-describedby="caption-attachment-21015" style="width: 509px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21015" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure020-1.png" alt="Figure 20" width="509" height="464" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure020-1.png 509w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure020-1-329x300.png 329w" sizes="auto, (max-width: 509px) 100vw, 509px" /><figcaption id="caption-attachment-21015" class="wp-caption-text">Figure 20</figcaption></figure>
<p>The next time I run the signed script, the script automatically runs (Figure 21).</p>
<figure id="attachment_21016" aria-describedby="caption-attachment-21016" style="width: 418px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-21016" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure021-1.png" alt="Figure 21" width="418" height="304" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure021-1.png 418w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure021-1-413x300.png 413w" sizes="auto, (max-width: 418px) 100vw, 418px" /><figcaption id="caption-attachment-21016" class="wp-caption-text">Figure 21</figcaption></figure>
<p>What I learned is that digitally signing PowerShell scripts is simple to do.  It is not cheap, but it is simple.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/how-to-digitally-sign-a-microsoft-powershell-script-with-a-third-party-code-signing-certificate/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3705</post-id>	</item>
		<item>
		<title>Where to Get Copies of the Various Scripts</title>
		<link>https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/</link>
					<comments>https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/#comments</comments>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Fri, 30 Sep 2011 19:00:16 +0000</pubDate>
				<category><![CDATA[Active Directory]]></category>
		<category><![CDATA[NetScaler]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[PVS]]></category>
		<category><![CDATA[VMware]]></category>
		<category><![CDATA[XenApp]]></category>
		<category><![CDATA[XenApp 5 for Server 2003]]></category>
		<category><![CDATA[XenApp 5 for Server 2008]]></category>
		<category><![CDATA[XenApp 6.0]]></category>
		<category><![CDATA[XenApp 6.5]]></category>
		<category><![CDATA[XenDesktop 5.x]]></category>
		<category><![CDATA[dhcp]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[provisioning services]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Word]]></category>
		<category><![CDATA[word comobject]]></category>
		<category><![CDATA[xenapp]]></category>
		<category><![CDATA[xendesktop]]></category>
		<guid isPermaLink="false">http://webster.skyrocket.ltd/?p=3741</guid>

					<description><![CDATA[Many people have asked me where they can get copies of the PowerShell documentation scripts.  To make it easier to find, I have linked to all of them in this one article.]]></description>
										<content:encoded><![CDATA[<p><b>NOTE:  All current scripts require PowerShell Version 3 or later.  </b></p>
<p><strong>All current documentation scripts create a Microsoft Word 2010,  2013, or 2016/2019/O365 document.</strong></p>
<p><strong>Word 2016, Word 2019 and the Office 365 version of Word have the same version number of 16. All documentation scripts will work with Word 2019 and Word Office 365 with no changes.</strong></p>
<p><b>*****All the scripts run best on PowerShell Version 5*****</b></p>
<p>Many people have asked me where they can get copies of the various PowerShell documentation scripts. To make it easier to find, I have linked to all of them in this one article.</p>
<p>All scripts have been moved to the new <a title="Script Downloads Page" href="https://www.carlwebster.com/downloads" target="_blank" rel="noopener noreferrer">Downloads page</a>.</p>
<p>I am leaving this landing page here so I don&#8217;t break all the existing links people have to this page.</p>
<p>Thanks</p>
<p>Webster</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.carlwebster.com/where-to-get-copies-of-the-documentation-scripts/feed/</wfw:commentRss>
			<slash:comments>333</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3741</post-id>	</item>
		<item>
		<title>Finding Mismatched Citrix XenApp 5 Servers Using Microsoft PowerShell</title>
		<link>https://www.carlwebster.com/finding-mismatched-xenapp-5-servers-using-powershell/</link>
		
		<dc:creator><![CDATA[Carl Webster]]></dc:creator>
		<pubDate>Wed, 28 Sep 2011 17:30:46 +0000</pubDate>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[XenApp]]></category>
		<category><![CDATA[XenApp 5 for Server 2003]]></category>
		<category><![CDATA[XenApp 5 for Server 2008]]></category>
		<category><![CDATA[citrix]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[xenapp 5]]></category>
		<guid isPermaLink="false">http://webster.skyrocket.ltd/?p=3240</guid>

					<description><![CDATA[Have you ever worked with a customer that had multiple Citrix license servers and product editions?  I worked with a client recently that had upgraded their Citrix XenApp product licenses&#8230;]]></description>
										<content:encoded><![CDATA[<p>Have you ever worked with a customer that had multiple Citrix license servers and product editions?  I worked with a client recently that had upgraded their Citrix XenApp product licenses from Enterprise to Platinum and had moved to a new Citrix license server.  Their problem was that they, over the years, had an unknown number of XenApp servers that had been manually configured to use various license servers and product editions.  Their problem was compounded by having well over 100 XenApp 5 servers.  The XenApp servers were segregated into folders based on Zone name and sub-folders based on application silo name.  Manually checking every XenApp server in the Delivery Services Console would have taken a very long time.  My solution was a Microsoft PowerShell script.</p>
<p>Being fairly new to PowerShell, but having a software development background, I knew this should be a very simple script to produce.  The client simply wanted a list of XenApp servers so they could look at the license server name and product edition.  The basics of the script are shown here (lines may wrap):</p>
<pre>$Farm = Get-XAFarmConfiguration
$Servers = Get-XAServer
ForEach($Server in $Servers)
{
        $ServerConfig = Get-XAServerConfiguration -ServerName $Server.Servername
        Echo "Zone: " $server.ZoneName
        Echo "Server Name: " $server.ServerName
        Echo “Product Edition: “  $server.CitrixEdition
        If( $ServerConfig.LicenseServerUseFarmSettings )
        {
               Echo "License server: " $Farm.LicenseServerName
        }
        Else
        {
               Echo "License server: " $ServerConfig.LicenseServerName
        }
        Echo “”
}</pre>
<p><strong>Note:</strong> This script is only valid for XenApp 5 for both Server 2003 and Server 2008.  In XenApp 5, it is possible to edit each XenApp server and set a specific Citrix license server.  You could, in fact, have every XenApp server in a XenApp farm configured to use its own Citrix license server.  In XenApp 6, you <em>can</em> do the same thing but that would require the use of Citrix Computer polices, one for each server.</p>
<p>While the above script worked, it was almost useless.  With an extremely large number of servers, the output produced was unwieldy.  The customer gave me the product edition and license server name they wanted to validate against.  I updated the script with that new information and needed a way to filter the data.  PowerShell uses the traditional programming “<strong>If</strong>” statement to allow filtering the data as it is processed.  I added a variable for the license server name and an “<strong>If</strong>” statement to the script as shown below (PowerShell uses the <code>character for line continuation. ):<br />
&lt;pre&gt;$LicenseServerName = NEWLICCTX01.WEBSTERSLAB.COM<br />
$Farm = Get-XAFarmConfiguration<br />
$Servers = Get-XAServer<br />
ForEach($Server in $Servers)<br />
{<br />
    $ServerConfig = Get-XAServerConfiguration -ServerName $Server.Servername<br />
    If(($Server.CitrixEdition -ne "Platinum") -or</code><br />
    ($ServerConfig.LicenseServerUseFarmSettings -eq $False `<br />
    &#8211;and $ServerConfig.LicenseServerName -ne $LicenseServerName))<br />
    {<br />
        &lt;snip&gt;<br />
    }<br />
}<br />
The “<strong>If</strong>” statement says:</p>
<ul>
<li><strong>If</strong> the server’s product edition is <strong>not equal</strong> to “Platinum”</li>
<li><strong>Or</strong>, the server is <strong>not</strong> configured to use the farm settings for the license server <strong>and</strong> the server’s license server name is <strong>not equal</strong> to NEWLICCTX01.WEBSTERSLAB.COM</li>
<li>Output the server’s information</li>
<li>If neither condition is met, skip to the next entry in the list of servers</li>
</ul>
<p>The new script allowed me to output just the XenApp servers matching the client’s criteria.</p>
<p>Sample output:</p>
<p>Zone: ZONE1<br />
Server Name: Z1DCCTXSSO01A<br />
Product Edition: Platinum<br />
License server: oldlicctx01<br />
Zone:  ZONE7<br />
Server Name: Z7DCTRMCTX03J<br />
Product edition: Enterprise<br />
License server: NEWLICCTX01.WEBSTERSLAB.COM</p>
<p><strong>Note:</strong>  The license server names shown in the sample output reflect the entry in the License Server name field for each XenApp server.  XenApp allows as valid entries the NetBIOS name, Fully Qualified Domain Name or IP Address.</p>
<p>Sweet, I have what the client needs, now let me just output this to HTML and I am done.</p>
<p>M:\PSScripts\Get-ServerInfo.ps1 | ConvertTo-Html | Out-File M:\PSScripts\MismatchedServers.html</p>
<p>This produced the following:</p>
<table border="0" cellpadding="0">
<tbody>
<tr>
<td>
<p align="center"><strong>*</strong></p>
</td>
</tr>
<tr>
<td>112</td>
</tr>
</tbody>
</table>
<p>What the…?</p>
<p>I needed to find out what was going on here.  I typed in <strong>Get-ServerInfo.ps1 | Get-Member</strong></p>
<pre>TypeName: System.String

Name       MemberType            Definition
----             ----------            ----------
Clone            Method                System.Object Clone()
CompareTo        Method                int CompareTo(System.Object value), int CompareTo(string strB)
Contains         Method                bool Contains(string value)

&lt;snip&gt;</pre>
<p>Next, I typed in <strong>Get-Help ConvertTo-HTML:</strong></p>
<p>PS Z:\&gt; <strong>Get-Help ConvertTo-HTML</strong></p>
<p>NAME<br />
ConvertTo-Html</p>
<p>SYNOPSIS<br />
Converts Microsoft .NET Framework objects into HTML that can be displayed in a Web browser.</p>
<p>&lt;snip&gt;</p>
<p>What I see from these two pieces of information is that my script is outputting <strong>String </strong>(or text) and ConvertTo-Html is expecting an <strong>Object</strong> as input.</p>
<p>Oh, now I get it.  The light-bulb finally went off:  PowerShell wants OBJECTS, not Text.  DOH!!!</p>
<p>OK, so how do I change this script to output objects instead of text?  I found what I needed in Chapter 19 of Don Jones’ book <a href="https://www.manning.com/books/learn-windows-powershell-in-a-month-of-lunches-third-edition"><em>Learn Windows PowerShell in a Month of Lunches</em></a>.  This is going to be a lot easier than I thought because I am only working with four pieces of data.</p>
<p>All I had to do was change:</p>
<pre>Echo "Zone: " $server.ZoneName
Echo "Server Name: " $server.ServerName
Echo “Product Edition: “  $server.CitrixEdition
If( $ServerConfig.LicenseServerUseFarmSettings )
{
       Echo "License server: " $Farm.LicenseServerName
}
Else
{
       Echo "License server: " $ServerConfig.LicenseServerName  
}
Echo “”

To:

$obj = New-Object -TypeName PSObject
$obj | Add-Member -MemberType NoteProperty `
-Name ZoneName -Value $server.ZoneName
$obj | Add-Member -MemberType NoteProperty `
-Name ServerName -Value $server.ServerName
$obj | Add-Member -MemberType NoteProperty `
-Name ProductEdition -Value $server.CitrixEdition
If($ServerConfig.LicenseServerUseFarmSettings)
{
       $obj | Add-Member -MemberType NoteProperty `
    -Name LicenseServer -Value $Farm.LicenseServerName
}
Else
{
       $obj | Add-Member -MemberType NoteProperty `
    -Name LicenseServer -Value $ServerConfig.LicenseServerName                    
}
Write-Output $obj</pre>
<p>Running the command <strong>M:\PSScripts\Get-ServerInfo.ps1 | ConvertTo-Html | Out-File M:\PSScripts\MismatchedServers.html</strong>, now gives me the following results (Figure 1).</p>
<figure id="attachment_20728" aria-describedby="caption-attachment-20728" style="width: 600px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20728" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-1.png" alt="Figure 1" width="600" height="210" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-1.png 600w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure001-1-530x186.png 530w" sizes="auto, (max-width: 600px) 100vw, 600px" /><figcaption id="caption-attachment-20728" class="wp-caption-text">Figure 1</figcaption></figure>
<p>Perfect.  Now that the script is using objects for output, any of the ConvertTo-* or Export-To* cmdlets can be used.  But I wanted to take this adventure one step further.  The script uses a hard-coded license server name and product edition.  I want to turn the script into one that can be used by anyone and also make it an advanced function.</p>
<p>The first thing needed is a name for the function.  The purpose of the function is to Get XenApp Mismatched Servers.  Following the naming convention used by Citrix, Get-XA<em>Noun</em>, the name could be Get-XAMismatchedServer.  Why XAMismatchedServer and not XAMismatchedServers?  PowerShell convention is to use singular and not plural.</p>
<p>Function Get-XAMismatchedServer<br />
{<br />
#PowerShell statements<br />
}</p>
<p>There is more functionality that needs to be added to make this a more useful function.  Additionally, I want to learn how to turn this function into a proper PowerShell advanced function.  Some of the additions needed are:</p>
<ol>
<li>Prevent the function from running on XenApp 6+</li>
<li>Allow the use of a single XenApp Zone to restrict the output</li>
<li>Validate the Zone name entered</li>
<li>Change the function to use parameters instead of hardcoded values</li>
<li>Add debug and verbose statements</li>
<li>Add full help text to explain the function</li>
</ol>
<p>For the basis of turning this simple function into an advanced function, I am using Chapter 48 of <a href="http://www.amazon.com/Windows-PowerShell-2-0-Don-Jones/dp/0982131429"><em>Windows PowerShell 2.0 TFM</em></a> by Don Jones and Jeffery Hicks.</p>
<p>The first thing I need to add to the function is the statement that tells PowerShell this is an advanced function.</p>
<pre>Function Get-XAMismatchedServer
{
    [CmdletBinding( SupportsShouldProcess = $False, `
    ConfirmImpact = "None", DefaultParameterSetName = "" ) ]
}</pre>
<p>Even though all parameters in CmdletBinding() are the defaults, I am including them solely for the learning exercise.</p>
<p>I will also need two “helper” functions.  One to verify the version of XenApp the script is being run under and the other for validating the Zone name entered (if one was entered).  These two functions need to be declared before they are used.  This means they need to be at the top of the script.</p>
<p>The function to verify if the script is running under XenApp 5:</p>
<pre>Function IsRunningXenApp5
{
   Param( [string]$FarmVersion )
   Write-Debug "Starting IsRunningXenApp5 function"
   $XenApp5 = $false
   If($Farm.ServerVersion.ToString().SubString(0,1) -ne "6")
   {
     #this is a XenApp 5 farm, script can proceed
     $XenApp5 = $true
   }
   Else
   {
     #this is a not XenApp 5 farm, script cannot proceed
     $XenApp5 = $false
   }
   Write-Debug "Farm is running XenApp5 is $XenApp5"
   Return $XenApp5
}</pre>
<p>Result of function under XenApp 5 (Figure 2).</p>
<figure id="attachment_20729" aria-describedby="caption-attachment-20729" style="width: 466px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20729" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-1.png" alt="Figure 2" width="466" height="329" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-1.png 466w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure002-1-425x300.png 425w" sizes="auto, (max-width: 466px) 100vw, 466px" /><figcaption id="caption-attachment-20729" class="wp-caption-text">Figure 2</figcaption></figure>
<p>Result of function under XenApp 6 (Figure 3).</p>
<figure id="attachment_20730" aria-describedby="caption-attachment-20730" style="width: 536px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20730" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-1.png" alt="Figure 3" width="536" height="323" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-1.png 536w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure003-1-498x300.png 498w" sizes="auto, (max-width: 536px) 100vw, 536px" /><figcaption id="caption-attachment-20730" class="wp-caption-text">Figure 3</figcaption></figure>
<p>The function to verify that if a zone name is entered, it is valid:</p>
<pre>Function IsValidZoneName
{
   Param( [string]$ZoneName )
   Write-Debug "Starting IsValidZoneName function"
   $ValidZone = $false
   $Zones = Get-XAZone -ErrorAction SilentlyContinue
   If( -not $? )
   {
     Write-Error "Zone information could not be retrieved"
     Return $ValidZone
   }
   ForEach($Zone in $Zones)
   {
     Write-Debug "Checking zone $Zone against $ZoneName"
     Write-Verbose "Checking zone $Zone against $ZoneName"
     If($Zone.ZoneName -eq $ZoneName)
     {
        Write-Debug "Zone $ZoneName is valid $ValidZone"
        $Zones = $null
        $ValidZone = $true
     }
   }
   $Zones = $null
   Return $ValidZone
}</pre>
<p>Result of the function (Figure 4).</p>
<figure id="attachment_20731" aria-describedby="caption-attachment-20731" style="width: 464px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20731" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-1.png" alt="Figure 4" width="464" height="429" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-1.png 464w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure004-1-324x300.png 324w" sizes="auto, (max-width: 464px) 100vw, 464px" /><figcaption id="caption-attachment-20731" class="wp-caption-text">Figure 4</figcaption></figure>
<p>Adding parameters to the main function:</p>
<pre>Function Get-XAMismatchedServer
{
   [CmdletBinding( SupportsShouldProcess = $False,
   ConfirmImpact = "None", DefaultParameterSetName = "" ) ]

   Param( 
   [parameter(Position = 0,Mandatory=$true,
   HelpMessage = "Citrix license server name to match" )]
   [Alias("LS")]
   [string]$LicenseServerName,
   [parameter(Position = 1, Mandatory=$true,
   HelpMessage = "Citrix product edition to match: `
   Platinum, Enterprise or Advanced" )]
   [Alias("PE")]
   [ValidateSet("Platinum", "Enterprise", "Advanced")]
   [string]$ProductEdition,
   [parameter(Position = 2,Mandatory=$false, `
   HelpMessage = "XenApp zone to restrict search.  `
   Blank is all zones in farm." )]
   [Alias("ZN")]
   [string]$ZoneName = '' )
}</pre>
<p>Three parameters have been added: $LicenseServerName, $ProductEdition and $ZoneName.  These parameter names were chosen because they are what the Citrix cmdlets use.</p>
<p>All three parameters are positional.  This means the parameter name is not required.  The function could be called as either:</p>
<p><strong>Get-XAMismatchedServer -LicenseServerName CtxLic01 -ProductEdition Platinum -ZoneName EMEA</strong></p>
<p>Or</p>
<p><strong>Get-XAMismatchedServer CtxLic01 Platinum EMEA</strong></p>
<p>The LicenseServerName and ProductEdition parameters are mandatory (Figure 5).</p>
<figure id="attachment_20732" aria-describedby="caption-attachment-20732" style="width: 759px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20732" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-1.png" alt="Figure 5" width="759" height="211" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-1.png 759w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-1-530x147.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure005-1-600x167.png 600w" sizes="auto, (max-width: 759px) 100vw, 759px" /><figcaption id="caption-attachment-20732" class="wp-caption-text">Figure 5</figcaption></figure>
<p>A help message has been entered so that if a parameter is missing, help text can be requested to tell what needs to be entered (Figure 6).</p>
<figure id="attachment_20733" aria-describedby="caption-attachment-20733" style="width: 734px" class="wp-caption alignnone"><img loading="lazy" decoding="async" class="size-full wp-image-20733" src="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-1.png" alt="Figure 6" width="734" height="297" srcset="https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-1.png 734w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-1-530x214.png 530w, https://www.carlwebster.com/wp-content/uploads/2011/09/Figure006-1-600x243.png 600w" sizes="auto, (max-width: 734px) 100vw, 734px" /><figcaption id="caption-attachment-20733" class="wp-caption-text">Figure 6</figcaption></figure>
<p><strong>Complete function (lines may wrap):</strong></p>
<pre>Function IsRunningXenApp5
{
   Param( [string]$FarmVersion )
   Write-Debug "Starting IsRunningXenApp5 function"
   $XenApp5 = $false
   If($Farm.ServerVersion.ToString().SubString(0,1) -ne "6")
   {
     #this is a XenApp 5 farm, script can proceed
     $XenApp5 = $true
   }
   Else
   {
     #this is not a XenApp 5 farm, script cannot proceed
     $XenApp5 = $false
   }
   Write-Debug "Farm is running XenApp5 is $XenApp5"
   Return $XenApp5
}

Function IsValidZoneName
{
   Param( [string]$ZoneName )
   Write-Debug "Starting IsValidZoneName function"
   $ValidZone = $false
   $Zones = Get-XAZone -ErrorAction SilentlyContinue
   If( -not $? )
   {
     Write-Error "Zone information could not be retrieved"
     Return $ValidZone
   }
   ForEach($Zone in $Zones)
   {
     Write-Debug "Checking zone $Zone against $ZoneName"
     Write-Verbose "Checking zone $Zone against $ZoneName"
     If($Zone.ZoneName -eq $ZoneName)
     {
        Write-Debug "Zone $ZoneName is valid $ValidZone"
        $Zones = $null
        $ValidZone = $true
     }
   }
   $Zones = $null
   Return $ValidZone
}

Function Get-XAMismatchedServer
{
   &lt;#
   .Synopsis
   Find servers not using the correct license server or
   product edition.
   .Description
   Find Citrix XenApp 5 servers that are not using the Citrix license
   server or product edition specified.  Can be restricted to a
   specific XenApp Zone.
   .Parameter LicenseServerName
   What is the name of the Citrix license server to validate servers
   against.  This parameter has an alias of LS.
   .Parameter ProductEdition
   What XenApp product edition should servers be configured to use.
   Valid input is Platinum, Enterprise or Advanced.
   This parameter has an alias of PE.
   .Parameter ZoneName
   Optional parameter.  If no XenApp zone name is specified, all zones
   in the farm are searched.
   This parameter has an alias of ZN.
   .Example
   PS C:\ Get-XAMismatchedServerInfo
   Will prompt for the Citrix license server name and product edition.
   .Example
   PS C:\ Get-XAMismatchedServerInfo -LicenseServerName CtxLic01 -ProductEdition Platinum
   Will search all XenApp zones in the XenApp 5 farm that the current XenApp 5 server
   is a member.  Any XenApp 5 server that is manually configured to use a different license
   server OR product edition will be returned.
   .Example
   PS C:\ Get-XAMismatchedServerInfo -LicenseServerName CtxLic01 -ProductEdition Platinum -ZoneName EMEA
   Will search the EMEA zone in the XenApp 5 farm that the current XenApp 5 server
   is a member.  Any XenApp 5 server that is manually configured to use a different license
   server OR product edition will be returned.
   .Example
   PS C:\ Get-XAMismatchedServerInfo -LS CtxLic01 -PE Enterprise -ZN Russia
   Will search the Russia zone in the XenApp 5 farm that the current XenApp 5 server
   is a member.  Any XenApp 5 server that is manually configured to use a different license
   server OR product edition will be returned.
   .Example
   PS C:\ Get-XAMismatchedServerInfo CtxNCC1701J Enterprise Cardassian
   Will search the dangerous Cardassian zone in the XenApp 5 farm that the current XenApp 5
   server is a member.  Any XenApp 5 server that is manually configured to use an inferior
   license server OR unworthy product edition will be returned (hopefully in one piece).
   .ReturnValue
   [OBJECT]
   .Notes
   NAME:         Get-XAMismatchedServerInfo
   VERSION:      .9
   AUTHOR:       Carl Webster (with a lot of help from Michael B. Smith)
   LASTEDIT:   May 16, 2011
   #Requires -version 2.0
   #Requires -pssnapin Citrix.XenApp.Commands
   #&gt;
   [CmdletBinding( SupportsShouldProcess = $False, ConfirmImpact = "None", DefaultParameterSetName = "" ) ]
   Param(       [parameter(
   Position = 0,
   Mandatory=$true,
   HelpMessage = "Citrix license server name to match" )]
   [Alias("LS")]
   [string]$LicenseServerName,
   [parameter(
   Position = 1,
   Mandatory=$true,
   HelpMessage = "Citrix product edition to match: Platinum, Enterprise or Advanced" )]
   [Alias("PE")]
   [ValidateSet("Platinum", "Enterprise", "Advanced")]
   [string]$ProductEdition,
   [parameter(
   Position = 2,
   Mandatory=$false,
   HelpMessage = "XenApp zone to restrict search.  Blank is all zones in farm." )]
   [Alias("ZN")]
   [string]$ZoneName = '' )
   Begin
   {
     Write-Debug "In the BEGIN block"
     Write-Debug "Retrieving farm information"
     Write-Verbose "Retrieving farm information"
     $Farm = Get-XAFarm -ErrorAction SilentlyContinue
     If( -not $? )
     {
        Write-Error "Farm information could not be retrieved"
        Return
     }
     Write-Debug "Validating the version of XenApp"
     $IsXenApp5 = IsRunningXenApp5 $Farm.ServerVersion
     If( -not $IsXenApp5 )
     {
        Write-Error "This script is designed for XenApp 5 and cannot be run on XenApp 6"
        Return
     }
     If($ZoneName -ne '')
     {
        Write-Debug "Is zone name valid"
        Write-Verbose "Validating zone $ZoneName"
        $ValidZone = IsValidZoneName $ZoneName
        If(-not $ValidZone)
        {
          Write-Error "Invalid zone name $ZoneName entered"
          Return
        }
     }
   }
   Process
   {
     Write-Debug "In the PROCESS block"
     If($ZoneName -eq '')
     {
        Write-Debug "Retrieving server information for all zones"
        Write-Verbose "Retrieving server information for all zones"
        $Servers = Get-XAServer -ErrorAction SilentlyContinue | `
        sort-object ZoneName, ServerName
     }
     Else
     {
        Write-Debug "Retrieving server information for zone $ZoneName"
        Write-Verbose "Retrieving server information for zone $ZoneName"
        $Servers = Get-XAServer -ZoneName $ZoneName -ErrorAction SilentlyContinue | `
        sort-object ZoneName, ServerName
     }
     If( $? )
     {
        ForEach($Server in $Servers)
        {
          Write-Debug "Retrieving server configuration data for server $Server"
          Write-Verbose "Retrieving server configuration data for server $Server"
          $ServerConfig = Get-XAServerConfiguration -ServerName $Server.Servername `
          -ErrorAction SilentlyContinue
          If( $? )
          {
             If($Server.CitrixEdition -ne $ProductEdition -or `
              ($ServerConfig.LicenseServerUseFarmSettings -eq $False -and `
              $ServerConfig.LicenseServerName -ne $LicenseServerName))
             {
               Write-Debug "Mismatched server $server"
               Write-Verbose "Mismatched server $server"
               $obj = New-Object -TypeName PSObject
               $obj | Add-Member -MemberType NoteProperty `
                  -Name ZoneName -Value $server.ZoneName
               $obj | Add-Member -MemberType NoteProperty `
                  -Name ServerName -Value $server.ServerName
               $obj | Add-Member -MemberType NoteProperty `
                  -Name ProductEdition -Value $server.CitrixEdition
               If($ServerConfig.LicenseServerUseFarmSettings)
               {
                  $obj | Add-Member -MemberType NoteProperty `
                    -Name LicenseServer -Value $Farm.LicenseServerName
               }
               Else
               {
                  $obj | Add-Member -MemberType `
                    NoteProperty -Name LicenseServer `
                    -Value $ServerConfig.LicenseServerName
               }
               Write-Debug "Creating object $obj"
               write-output $obj
            }
          }
          Else
          {
             Write-Error "Configuration information for server `
                   $($Server.Servername) could not be retrieved"
          }
        }
     }
     Else
     {
        Write-Error "Information on XenApp servers could not be retrieved"
     }
   }
   End
   {
     Write-Debug "In the END block"
     $servers = $null
     $serverconfig = $null
     $farm = $null
     $obj = $null
   }
}</pre>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3240</post-id>	</item>
	</channel>
</rss>
