Citrix Receiver unattended installation with PowerShell is a must in automated environments. Also, Citrix Receiver requires some additional configuration to make it run smoothly in your environment. This article explains and automates the most important ones.
Note: Citrix Receiver has been replaced by Citrix Workspace App. For detailed information on how to install and configure Citrix Workspace App, see the article Citrix Workspace App unattended installation with PowerShell on this website. |
Change Log 24.09.2018: added Prevent an unexpected MSI repair from launching. |
Introduction
The Citrix Receiver is a client component in a Citrix infrastructure that allows a user to launch Citrix XenApp and XenDesktop resources, such as published applications and desktops.
This article is based on Citrix Receiver 4.12 released in June 2018. This is the last version of Receiver. Receiver has been replaced by Citrix Workspace App.
Installing and configuring Citrix Receiver for Windows requires careful planning. You need to decide which components to enable, how to configure the default device access behavior, how to configure the Citrix Receiver group policies, whether or not to allow single sign-on, and more.
For those of you who know my blog, Citrix Receiver is one of the components listed in my article Scripting the complete list of Citrix components with PowerShell, but I decided to create this stand-alone article to allow me to go into more detail.
I strongly suggest you to read the article Receiver / Workspace app 1808 written by Citrix CTP Carl Stalhood. This is the most detailed article on Receiver available.
Installing and configuring Citrix Receiver
Installing and configuring Citrix Receiver is not as straightforward as one might think. Many details can either make or break your deployment. Read and implement the sections below to ensure a smooth and successful deployment.
Summary
- Target device:
Receiver can be installed both on your virtual servers and desktops (alongside the VDA) as well as on the local client device. This all depends on your Citrix infrastructure and your access scenarios. - Installation file name:
CitrixReceiver.exe (or, after renaming, CitrixReceiverWeb.exe) - Version (latest):
4.12 (released in June 2018). This is the last version of Receiver. Receiver has been replaced by Citrix Workspace App. - Installation parameters (command-line switches):
See the section Citrix Receiver command-line switches below. - Uninstallation parameters (command-line switches):
The following two command line switches are required to uninstall Citrix Receiver: /silent /uninstall. The /noreboot parameter is not needed during a silent installation according to the Citrix documentation. - Installation dependencies:
No - Other dependencies:
No - Reboot required:
Yes (for certain components such as Single Sign-on, /includeSSON) - ADMX files:
Yes (see the section on Group Policies at the conclusion of this article) - Ports and firewall:
No (outbound communication only, e.g. port 80, 443, 1494, 2598) - Download location:
Receiver 4.12 for Windows - Reference:
Configure and install Citrix Receiver for Windows using Command Line parameters
Citrix Receiver installation file (CitrixReceiver.exe)
The latest version of Citrix Receiver can be downloaded here. The download contains one file: CitrixReceiver.exe. This file contains several MSI files; one MSI installer per component. This is the list of components for Receiver 4.12:
- AuthManager.msi
- CitrixHDXMediaStreamForFlash-ClientInstall.msi
- DesktopViewer.msi
- GenericUSB.msi
- ICAWebWrapper.msi
- RIInstaller.msi
- SelfServicePlugin.msi
- SSONWrapper.msi
- Vd3dClient.msi
- WebHelper.msi
Note: Use the following command to extract the individual MSI files from the CitrixReceiver.exe installation file: CitrixReceiver.exe /extract %directory% Make sure to create the destination directory beforehand. |
The version is not displayed in the file name, so the file name is the same for each version of Receiver. To see the version of the executable, you have to take a look at the Details tab in the file properties.
The version displayed in the details tab is always a little bit different than the commercial version displayed on the official Citrix download page.
Example:
Version 4.12 of Citrix Receiver has the product version 14.12.0 and file version 14.12.0.17061. You basically should ignore the first “1” in the product version to get to the commercial version.
So why are different numbers used for the same version you may wonder? The exact reason is not known to me, but it most likely has something to do with re-branding. You see, the first 4.x version of Receiver (which was not called Receiver at that time) was released in 1998. In June of 2013, version 4.x resurfaced. Don’t believe me? Check out the official Citrix Receiver for Windows Quick Reference Version List listing all Receiver versions since September 1998. The list seems to miss some newer versions that came after version 4.9 though.
Another thing you should know about the installation file is that renaming it from CitrixReceiver.exe to CitrixReceiverWeb.exe changes the installation behavior. See the section Prevent the Add Account Window for more details.
Citrix Receiver command-line switches
There are various parameters you can parse. For a detailed overview of all parameters please refer to the article Configure and install Citrix Receiver for Windows using Command Line parameters. I strongly suggest reading the entire article before deploying Citrix Receiver.
You can also use the Citrix Receiver Commandline Helper Tool to help you build the exact command line syntax.
It is difficult for me to tell you exactly which command line switches (= parameters) you should use. This all depends on your environment. However, you should be aware of the following:
- Some parameters are required to work together with server-side components, such as enabling bidirectional content redirection.
- Some parameters require local administrator rights, such as /includeSSON to enable single sign-on authentication.
- In some cases, a reboot may be required. For example, USB devices that are in a suspended state when Citrix Receiver for Windows installs are not recognized by Citrix Receiver for Windows until after the user device is restarted (reference).
These are the parameters I use for most environments:
- /silent
All of my deployments are automated, including Citrix Receiver. I therefore need to use the /silent parameter. - /includeSSON
This enables single sign-on (pass-through authentication) so a user does not need to enter authentication information for a second time after logging on to Windows. - /FORCE_LAA=1
This enables Local App Access. - EnableCEIP=false
Do not enable participation in the Citrix Customer Experience Improvement Program (CEIP). CEIP collects anonymous statistics and usage information and sends them to Citrix. - /AutoUpdateCheck = disabled
I prefer to test new versions of Citrix Receiver before implementing them in production (so no automatic updates are allowed). You can also omit this parameter entirely and manage the auto-update behavior using Group Policy. See also the Auto-Update section in Carl Stalhood’s article Receiver / Workspace app 1808.
The /noreboot parameter is not required for silent installations according to the Citrix documentation. If possible, I recommend rebooting the machine before using Citrix Receiver.
Citrix Receiver log files
The installation of Receiver generates multiple log files: one general log file (“Trolley Express”) and one log file per MSI installation, for example:
- TrolleyExpress-%Date%-%Time%.log
- CtxInstall-CitrixHDXMediaStreamForFlash-ClientInstall-%Date%-%Time%.log
- CtxInstall-DesktopViewer-%Date%-%Time%.log
- CtxInstall-SelfServicePlugin-%Date%-%Time%.log
The total number of log files depends on the number of components you install. Each MSI log file represents one component; the more components you install, the more log files will be generated (up to a total of 10).
The installation log files generated by Citrix Receiver are always created in the TEMP folder. The location of the TEMP folder in most environments is one of the following:
- C:\Users\%UserName%\AppData\Local\Temp
This directory is for sure used in many environments. Each user has its temporary directory. - C:\Users\%UserName%\AppData\Local\Temp\%SessionNumber%
This is almost the same directory as the previous one. The difference is that each user has a temporary directory per session. If allowed by the administrator, a user can have multiple sessions on one system.
- C:\Windows\Temp
This is the TEMP of the local SYSTEM account. Software deployment tools such as Microsoft SCCM use the SYSTEM account for installations on the local machine. - C:\Temp
This directory may be used on a FAT client. On a multi-user system, it is not typical to use one temp directory for multiple users.
Of course, the TEMP directory in your environment may be different than the ones listed above. The environment variable %TEMP% will always contain the correct location of the TEMP directory.
Unfortunately, there is no installation (or uninstallation) parameter that allows the log files to be written to another directory besides TEMP. There is no command-line switch like /Logfile or /Log.
The only way to capture the log files in a directory other than TEMP is to copy them from the TEMP folder after the installation has finished.
In the complete installation script below, the script starts by deleting any existing Citrix Receiver log files from the TEMP directory (lines 692 to 701). By using the environment variable %TEMP% the script makes sure that the correct TEMP directory is used.
After the installation (or uninstallation), the script copies the newly created log files to the log directory declared in the variable $LogDir. The log directory ($LogDir) is a combination of the variables $BaseLogDir and $PackageName. You can change these variables in lines 669 and 670.
Configure default device access behavior (Client Selective Trust)
As per Citrix: “With the introduction of Receiver 3.x client, administrators can configure the default behavior for device access when connecting to a Citrix XenDesktop or XenApp environment. By default, the Desktop Viewer client device restrictions are based on the Internet region and this behavior can be changed by creating the Client Selective Trust feature registry keys under the HKEY_LOCAL_MACHINE hive in the registry and by modifying the required values.”
For example, when you allow the user to access files on the local client device, you may see the following security warning:
The security popup can concern the following local resources:
- Client Drives
- Microphones and Webcams
- USB and other Devices
The default behavior of Receiver is to prompt the user. As an administrator, you can define the access level by modifying the registry or by using the ADMX group policy template. There are four access levels:
- 0 = No Access
- 1 = Read Only Access
- 2 = Full Access
- 3 = Prompt User for Access
Please see the Citrix article How to Configure Default Device Access Behavior of Receiver, XenDesktop and XenApp for more information.
I decided to modify the default behavior using the registry. I downloaded the ZIP file from the aforementioned article and modified the file ReceiverCSTRegUpx86.reg. I set all relevant registry entries to 2 (= Full Access) except for the Restricted Sites region/zone (these values remain on 0 = No Access).
Note: yes, I used the file ReceiverCSTRegUpx86.reg even though I installed Receiver on a 64-bit operating system. On a 64-bit operating system, Receiver still installs itself in the folder C:\Program Files (x86) and all processes run in 32-bit. |
You can download a copy of this modified file here:
In the complete installation script below, the script imports the registry file in lines 752 to 756. Please make sure that you copy the actual file to the subdirectory Files. Also, in case you rename the registry file, please make sure to change the file name in the script as well (line 755).
Please be aware that pre-configuring the Client Selective Trust settings does NOT prevent a user from changing these settings! A user can configure his or her connection preferences in the Connection Center under Preferences.
In case you want to prevent the user from changing the preferences, set the value (Default) in the following registry key to false:
HKLM\SOFTWARE\WOW6432Node\Citrix\ICA Client\Client Selective Trust\oidPredefinedSecurityPolicySettings\InstantiatedSecurityPolicyEditable
Like this:
As you can see in the screenshot below, after changing the (Default) value (REG_SZ) to false, the user is no longer able to change the preferences.
You do not even need to close the active session for this setting to work. You only have to close the Preferences window and open it again after changing the registry value. The change is active instantly.
The complete installation script below does NOT change the (Default) registry value. In case you would like to change it, please add the following code:
1 |
DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\WOW6432Node\Citrix\ICA Client\Client Selective Trust\oidPredefinedSecurityPolicySettings\InstantiatedSecurityPolicyEditable" -RegValueName "(Default)" -RegValue "false" -Type "STRING" |
Place it somewhere between lines 750 and 760.
A big thanks to my colleague Wolfgang Thürr for bringing this to my attention.
Prevent the Add Account window from launching
In the Add Account window, as per Citrix “users can […] set up a Citrix Receiver account by entering email address or a server URL. Citrix Receiver determines the NetScaler Gateway, StoreFront server, or AppController virtual appliance associated with the email address and then prompts the user to log on for enumeration.”
The Add Account wizard can be triggered in three ways:
- At the end of the installation by clicking the Add Account button
- At login time
- By double-clicking the Receiver icon in the system tray
By default, at the end of the installation, the Add Account button is shown.
To prevent this button from appearing you can do one of two things:
- Rename the installation file CitrixReceiver.exe to CitrixReceiverWeb.exe (this name has to be exact including camel-case letters).
- Create the registry item EnableX1FTU in the registry key HKLM\SOFTWARE\Wow6432Node\Policies\Citrix with a DWORD value of 0 before running the installation.
The result is that the Add Account button is not shown.
In the complete installation script below, the registry item EnableX1FTU is created before installation, although strictly speaking it is not necessary since the PowerShell script triggers a silent installation (so no GUI is shown anyway).
By default, the Add Account window is also triggered at user logon.
To prevent this window from appearing, there are three options:
- Add the registry item HideAddAccountOnRestart (DWORD) with a value of 1 to the registry key HKCU\Software\Citrix\Receiver. The tick box “Do not show this window automatically at logon” creates the same registry entry. Please be aware that this is a current user setting. I therefore recommend using a Group Policy Preference (the article Configuring the time zone and code page with Group Policy demonstrates how to configure Group Policy Preferences).
- Set the value of the registry item AllowAddStore (REG_SZ) to N in the registry key HKLM\SOFTWARE\WOW6432Node\Citrix\Dazzle. You can also control this setting using a Group Policy.
- Rename the installation file CitrixReceiver.exe to CitrixReceiverWeb.exe (this name has to be exact including camel-case letters).
The complete installation script does not prevent the Add Account window from appearing at user logon. In case you want to prevent this from happening and you do not want to configure a Group Policy Preference, simply rename the CitrixReceiver.exe to CitrixReceiverWeb.exe as stated above.
Note: renaming the CitrixReceiver.exe to CitrixReceiverWeb.exe means that e-mail-based account discovery is no longer supported (reference: Deploy Citrix Receiver for Windows from Receiver for Web). Also, see the official Citrix article How to Suppress the Add Account Window in Citrix Receiver for Windows for more information. |
Prevent an unexpected MSI repair from launching
It may happen that when you try to start a published application, an MSI installer repair of the component “Citrix Online Plug-in” is started.
The exact cause for this behavior is unknown to me, but I can offer you a workaround. To solve this issue, you simply have to delete all data from the registry value WEB_CLIENT (part of the Citrix Online Plug-in MSI). Do not delete the registry value itself! Just remove the data from it (“empty” it) as shown in the screenshot below.
The registry value WEB_CLIENT (string / REG_SZ) is located here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\%ProductGUID%\Features
The product GUID is different for each version of Citrix Receiver:
- AC1889E2C14E5E540855164ACCB19FF3 -> Receiver 4.12
In the complete installation script below, the data in the WEB_CLIENT registry value for Citrix Receiver 4.12 is removed (lines 760 to 768).
Remove Citrix Receiver shortcuts
During installation, Citrix Receiver creates a shortcut in the public (= All Users) Programs folder in the Start Menu:
C:\ProgramData\Start Menu\Programs\Citrix Receiver.lnk
In the complete installation script below, this shortcut is removed (lines 799 to 802).
Note: In the past, Receiver created a shortcut in the public (= All Users) Programs\Startup folder in the Start Menu. This is no longer the case, but the installation script does check for this value and removes it in case it exists. Citrix Receiver automatically starts at logon time by running the command “C:\Program Files (x86)\Citrix\ICA Client\concentr.exe” /startup (HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run -> ConnectionCenter). |
Prevent Windows 10 Game Bar popup (Win+G)
As per Citrix: “When launching published apps or desktops from a Windows 10 OS a […] popup windows briefly appears prompting to press Win + G for the game bar or for the search bar.”
As described in the article, you can disable the game bar with the following registry entry:
- Key: HKLM\SOFTWARE\Policies\Microsoft\Windows\GameDVR
- Item: AllowGameDVR
- Value: 00000000
- Type: DWORD
The complete installation script below sets this registry value (line 778).
Modify the Network Provider order
When you install the Receiver Single Sign-on feature (/includeSSON), an entry is created in the network provider order.
What is the network provider order? Using network providers, Windows can support many different types of network protocols without having to know the network-specific details of each network (reference). By default, Windows ships with the following three network providers in the following order:
In the registry, the list and order of the Microsoft and third-party network providers can be found here: HKLM\System\CurrentControlSet\Control\NetworkProvider. The network provider settings can also be viewed/managed using the GUI: |
Citrix adds the entry PnSson (= Citrix Single Sign-on). Citrix recommends that this entry is listed as number four, after the three default Windows network providers (see the info box above).
With Windows 10 version 1709, two things are important to know:
- There is a known bug with the network provider
- The network provider order is handled differently compared to older operating systems
Let’s start with the bug. As described by Citrix in the article Windows 10 Fall Creators Update (v1709) – Citrix Known Issues, the network provider has a bug (which should be fixed in Windows 10 version 1803). The bug is that no third-party network provider, including Citrix’s PnSson value, is populated under the newly introduced registry key ProviderOrder under HKLM\System\CurrentControlSet\Control\NetworkProvider. This bug causes the error “failed to get network providers” when you try to display the network provider order graphically.
Please be aware that the actual functionality of the network provider still works.
In the past, the order of the network provider was determined by the order of the entries in the registry item ProviderOrder under HKLM\System\CurrentControlSet\Control\NetworkProvider\Order. With Windows 10, this is no longer the case. The order is now determined by the decimal value of the network provider (HKLM\System\CurrentControlSet\Control\NetworkProvider\ProviderOrder). The item with the lowest number is executed first and the item with the highest number last.
In the article Windows 10 Fall Creators Update (v1709) – Citrix Known Issues, Citrix recommends creating the missing item using the decimal DWORD value of 4000. I recommend using a different number, for example, 3001 or 3500. The reason for this is simple; you may have another third-party product that already occupies the number 4000. This is for example the case when you install a product such as Lotus Notes including the Notes Single logon service. The main goal is that the PnSson value is listed as the fourth item, after the three default Microsoft ones. The third Microsoft entry has a value of 3000, so the value PnSson needs to have a higher value (at least 3001 or higher).
In the complete installation script below, the missing network provider registry item is created in lines 782 to 787. The PnSson item is either created or modified.
Performance optimizations
There seem to be a couple of registry values that may improve the performance of Receiver. I did not add these to the complete installation script. In case you experience slow enumerations of (start menu) icons, please test the following registry values:
- InitialRefreshMinMs (REG_SZ) = 1 – minimizes the launch delay before contacting store
- InitialRefreshMaxMs (REG_SZ) = 1 – minimizes the launch delay before contacting store
- MaxSimultaneousFetches (REG_DWORD) = 6 – improves the time of loading icons in Start Menu
- MaxSimultaneousSubscribes (REG_DWORD) = 6 – improves the time of loading icons in Start Menu
See the example in the previous section on how to add these values to the complete installation script.
Complete installation script
I packed the complete Citrix Receiver installation in my installation template. The script below contains the installation and all configurations for Citrix Receiver as described in the previous sections, including detailed logging and error handling. To use this script, please follow these steps:
- Create an installation directory on the local computer or a file share (UNC path). For example C:\Temp\Citrix\Receiver.
- Create a subdirectory called Files.
- Download and copy the Receiver CitrixReceiver.exe to the folder Files in the installation directory.
- Download and copy the registry file (*.reg) containing the Client Selective Trust registry keys and values to the folder Files in the installation directory.
- Copy the complete PowerShell script below to a new PS1 file (e.g. Install_CitrixReceiver.ps1) and add this file to the root of the installation directory (not in the subdirectory Files).
- Optional: modify the location of the log directory in lines 669 and 670.
- Execute the PowerShell script as follows:
powershell.exe -executionpolicy bypass -file C:\Temp\Citrix\Receiver\Install_CitrixReceiver.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
#========================================================================== # # CITRIX RECEIVER FOR WINDOWS # # AUTHOR: Dennis Span (https://dennisspan.com) # DATE : 30.04.2018 # # COMMENT: This script installs and configured Citrix Receiver for Windows 4.12 # This script will also work with older 4.x versions of Receiver for Windows # # This script has been created for Windows 10 version 1709 and higher and Windows Server 2016 version 1607 and higher # This script has been tested on Windows 10 version 1709 # # Change log: # ----------- # 24.09.2018 Dennis Span: added registry value change to prevent unexpected MSI repairs from starting (lines 760 to 768) #========================================================================== # Get the script parameters if there are any param ( # The only parameter which is really required is 'Uninstall' # If no parameters are present or if the parameter is not # 'uninstall', an installation process is triggered [string]$Installationtype ) # define Error handling # note: do not change these values $global:ErrorActionPreference = "Stop" if($verbose){ $global:VerbosePreference = "Continue" } # FUNCTION DS_WriteLog #========================================================================== Function DS_WriteLog { <# .SYNOPSIS Write text to this script's log file .DESCRIPTION Write text to this script's log file .PARAMETER InformationType This parameter contains the information type prefix. Possible prefixes and information types are: I = Information S = Success W = Warning E = Error - = No status .PARAMETER Text This parameter contains the text (the line) you want to write to the log file. If text in the parameter is omitted, an empty line is written. .PARAMETER LogFile This parameter contains the full path, the file name and file extension to the log file (e.g. C:\Logs\MyApps\MylogFile.log) .EXAMPLE DS_WriteLog -InformationType "I" -Text "Copy files to C:\Temp" -LogFile "C:\Logs\MylogFile.log" Writes a line containing information to the log file .Example DS_WriteLog -InformationType "E" -Text "An error occurred trying to copy files to C:\Temp (error: $($Error[0]))" -LogFile "C:\Logs\MylogFile.log" Writes a line containing error information to the log file .Example DS_WriteLog -InformationType "-" -Text "" -LogFile "C:\Logs\MylogFile.log" Writes an empty line to the log file #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][ValidateSet("I","S","W","E","-",IgnoreCase = $True)][String]$InformationType, [Parameter(Mandatory=$true, Position = 1)][AllowEmptyString()][String]$Text, [Parameter(Mandatory=$true, Position = 2)][AllowEmptyString()][String]$LogFile ) begin { } process { $DateTime = (Get-Date -format dd-MM-yyyy) + " " + (Get-Date -format HH:mm:ss) if ( $Text -eq "" ) { Add-Content $LogFile -value ("") # Write an empty line } Else { Add-Content $LogFile -value ($DateTime + " " + $InformationType.ToUpper() + " - " + $Text) } } end { } } #========================================================================== # FUNCTION DS_InstallOrUninstallSoftware #========================================================================== Function DS_InstallOrUninstallSoftware { <# .SYNOPSIS Install or uninstall software (MSI or SETUP.exe) .DESCRIPTION Install or uninstall software (MSI or SETUP.exe) .PARAMETER File This parameter contains the file name including the path and file extension, for example C:\Temp\MyApp\Files\MyApp.msi or C:\Temp\MyApp\Files\MyApp.exe. .PARAMETER Installationtype This parameter contains the installation type, which is either 'Install' or 'Uninstall'. .PARAMETER Arguments This parameter contains the command line arguments. The arguments list can remain empty. In case of an MSI, the following parameters are automatically included in the function and do not have to be specified in the 'Arguments' parameter: /i (or /x) /qn /norestart /l*v "c:\Logs\MyLogFile.log" .EXAMPLE DS_InstallOrUninstallSoftware -File "C:\Temp\MyApp\Files\MyApp.msi" -InstallationType "Install" -Arguments "" Installs the MSI package 'MyApp.msi' with no arguments (the function already includes the following default arguments: /i /qn /norestart /l*v $LogFile) .Example DS_InstallOrUninstallSoftware -File "C:\Temp\MyApp\Files\MyApp.msi" -InstallationType "Uninstall" -Arguments "" Uninstalls the MSI package 'MyApp.msi' (the function already includes the following default arguments: /x /qn /norestart /l*v $LogFile) .Example DS_InstallOrUninstallSoftware -File "C:\Temp\MyApp\Files\MyApp.exe" -InstallationType "Install" -Arguments "/silent /logfile:C:\Logs\MyApp\log.log" Installs the SETUP file 'MyApp.exe' #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$File, [Parameter(Mandatory=$true, Position = 1)][AllowEmptyString()][String]$Installationtype, [Parameter(Mandatory=$true, Position = 2)][AllowEmptyString()][String]$Arguments ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { $FileName = ($File.Split("\"))[-1] $FileExt = $FileName.SubString(($FileName.Length)-3,3) # Prepare variables if ( !( $FileExt -eq "MSI") ) { $FileExt = "SETUP" } if ( $Installationtype -eq "Uninstall" ) { $Result1 = "uninstalled" $Result2 = "uninstallation" } else { $Result1 = "installed" $Result2 = "installation" } $LogFileAPP = Join-path $LogDir ( "$($Installationtype)_$($FileName.Substring(0,($FileName.Length)-4))_$($FileExt).log" ) # Logging DS_WriteLog "I" "File name: $FileName" $LogFile DS_WriteLog "I" "File full path: $File" $LogFile # Check if the installation file exists if (! (Test-Path $File) ) { DS_WriteLog "E" "The file '$File' does not exist!" $LogFile Exit 1 } # Check if custom arguments were defined if ([string]::IsNullOrEmpty($Arguments)) { DS_WriteLog "I" "File arguments: <no arguments defined>" $LogFile } Else { DS_WriteLog "I" "File arguments: $Arguments" $LogFile } # Install the MSI or SETUP.exe DS_WriteLog "-" "" $LogFile DS_WriteLog "I" "Start the $Result2" $LogFile if ( $FileExt -eq "MSI" ) { if ( $Installationtype -eq "Uninstall" ) { $FixedArguments = "/x ""$File"" /qn /norestart /l*v ""$LogFileAPP""" } else { $FixedArguments = "/i ""$File"" /qn /norestart /l*v ""$LogFileAPP""" } if ([string]::IsNullOrEmpty($Arguments)) { # check if custom arguments were defined $arguments = $FixedArguments DS_WriteLog "I" "Command line: Start-Process -FilePath 'msiexec.exe' -ArgumentList $arguments -Wait -PassThru" $LogFile $process = Start-Process -FilePath 'msiexec.exe' -ArgumentList $arguments -Wait -PassThru } Else { $arguments = $FixedArguments + " " + $arguments DS_WriteLog "I" "Command line: Start-Process -FilePath 'msiexec.exe' -ArgumentList $arguments -Wait -PassThru" $LogFile $process = Start-Process -FilePath 'msiexec.exe' -ArgumentList $arguments -Wait -PassThru } } Else { if ([string]::IsNullOrEmpty($Arguments)) { # check if custom arguments were defined DS_WriteLog "I" "Command line: Start-Process -FilePath ""$File"" -Wait -PassThru" $LogFile $process = Start-Process -FilePath "$File" -Wait -PassThru } Else { DS_WriteLog "I" "Command line: Start-Process -FilePath ""$File"" -ArgumentList $arguments -Wait -PassThru" $LogFile $process = Start-Process -FilePath "$File" -ArgumentList $arguments -Wait -PassThru } } # Check the result (the exit code) of the installation switch ($Process.ExitCode) { 0 { DS_WriteLog "S" "The software was $Result1 successfully (exit code: 0)" $LogFile } 3 { DS_WriteLog "S" "The software was $Result1 successfully (exit code: 3)" $LogFile } # Some Citrix products exit with 3 instead of 0 1603 { DS_WriteLog "E" "A fatal error occurred (exit code: 1603). Some applications throw this error when the software is already (correctly) installed! Please check." $LogFile } 1605 { DS_WriteLog "I" "The software is not currently installed on this machine (exit code: 1605)" $LogFile } 1619 { DS_WriteLog "E" "The installation files cannot be found. The PS1 script should be in the root directory and all source files in the subdirectory 'Files' (exit code: 1619)" $LogFile Exit 1 } 3010 { DS_WriteLog "W" "A reboot is required (exit code: 3010)!" $LogFile } default { [string]$ExitCode = $Process.ExitCode DS_WriteLog "E" "The $Result2 ended in an error (exit code: $ExitCode)!" $LogFile Exit 1 } } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_CopyFile #========================================================================== Function DS_CopyFile { <# .SYNOPSIS Copy one or more files .DESCRIPTION Copy one or more files .PARAMETER SourceFiles This parameter can contain multiple file and folder combinations including wildcards. UNC paths can be used as well. Please see the examples for more information. To see the examples, please enter the following PowerShell command: Get-Help DS_CopyFile -examples .PARAMETER Destination This parameter contains the destination path (for example 'C:\Temp2' or 'C:\MyPath\MyApp'). This path may also include a file name. This situation occurs when a single file is copied to another directory and renamed in the process (for example '$Destination = C:\Temp2\MyNewFile.txt'). UNC paths can be used as well. The destination directory is automatically created if it does not exist (in this case the function 'DS_CreateDirectory' is called). This works both with local and network (UNC) directories. In case the variable $Destination contains a path and a file name, the parent folder is automatically extracted, checked and created if needed. Please see the examples for more information.To see the examples, please enter the following PowerShell command: Get-Help DS_CopyFile -examples .EXAMPLE DS_CopyFile -SourceFiles "C:\Temp\MyFile.txt" -Destination "C:\Temp2" Copies the file 'C:\Temp\MyFile.txt' to the directory 'C:\Temp2' .EXAMPLE DS_CopyFile -SourceFiles "C:\Temp\MyFile.txt" -Destination "C:\Temp2\MyNewFileName.txt" Copies the file 'C:\Temp\MyFile.txt' to the directory 'C:\Temp2' and renames the file to 'MyNewFileName.txt' .EXAMPLE DS_CopyFile -SourceFiles "C:\Temp\*.txt" -Destination "C:\Temp2" Copies all files with the file extension '*.txt' in the directory 'C:\Temp' to the destination directory 'C:\Temp2' .EXAMPLE DS_CopyFile -SourceFiles "C:\Temp\*.*" -Destination "C:\Temp2" Copies all files within the root directory 'C:\Temp' to the destination directory 'C:\Temp2'. Subfolders (including files within these subfolders) are NOT copied. .EXAMPLE DS_CopyFile -SourceFiles "C:\Temp\*" -Destination "C:\Temp2" Copies all files in the directory 'C:\Temp' to the destination directory 'C:\Temp2'. Subfolders as well as files within these subfolders are also copied. .EXAMPLE DS_CopyFile -SourceFiles "C:\Temp\*.txt" -Destination "\\localhost\Temp2" Copies all files with the file extension '*.txt' in the directory 'C:\Temp' to the destination directory '\\localhost\Temp2'. The directory in this example is a network directory (UNC path). #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$SourceFiles, [Parameter(Mandatory=$true, Position = 1)][String]$Destination ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Copy the source file(s) '$SourceFiles' to '$Destination'" $LogFile # Retrieve the parent folder of the destination path if ( $Destination.Contains(".") ) { # In case the variable $Destination contains a dot ("."), return the parent folder of the path $TempFolder = split-path -path $Destination } else { $TempFolder = $Destination } # Check if the destination path exists. If not, create it. DS_WriteLog "I" "Check if the destination path '$TempFolder' exists. If not, create it" $LogFile if ( Test-Path $TempFolder) { DS_WriteLog "I" "The destination path '$TempFolder' already exists. Nothing to do" $LogFile } else { DS_WriteLog "I" "The destination path '$TempFolder' does not exist" $LogFile DS_CreateDirectory -Directory $TempFolder } # Copy the source files DS_WriteLog "I" "Start copying the source file(s) '$SourceFiles' to '$Destination'" $LogFile try { Copy-Item $SourceFiles -Destination $Destination -Force -Recurse DS_WriteLog "S" "Successfully copied the source files(s) '$SourceFiles' to '$Destination'" $LogFile } catch { DS_WriteLog "E" "An error occurred trying to copy the source files(s) '$SourceFiles' to '$Destination'" $LogFile Exit 1 } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_DeleteDirectory # Description: delete the entire directory #========================================================================== Function DS_DeleteDirectory { <# .SYNOPSIS Delete a directory .DESCRIPTION Delete a directory .PARAMETER Directory This parameter contains the full path to the directory which needs to be deleted (for example C:\Temp\MyOldFolder). .EXAMPLE DS_DeleteDirectory -Directory "C:\Temp\MyOldFolder" Deletes the directory "C:\Temp\MyNewFolder" #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$Directory ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Delete directory $Directory" $LogFile if ( Test-Path $Directory ) { try { Remove-Item $Directory -force -recurse | Out-Null DS_WriteLog "S" "Successfully deleted the directory $Directory" $LogFile } catch { DS_WriteLog "E" "An error occurred trying to delete the directory $Directory (exit code: $($Error[0])!" $LogFile Exit 1 } } else { DS_WriteLog "I" "The directory $Directory does not exist. Nothing to do." $LogFile } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_DeleteFile # Description: delete one specific file #========================================================================== Function DS_DeleteFile { <# .SYNOPSIS Delete a file .DESCRIPTION Delete a file .PARAMETER File This parameter contains the full path to the file (including the file name and file extension) that needs to be deleted (for example C:\Temp\MyOldFile.txt). .EXAMPLE DS_DeleteFile -File "C:\Temp\MyOldFile.txt" Deletes the file "C:\Temp\MyOldFile.txt" #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$File ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Delete the file '$File'" $LogFile if ( Test-Path $File ) { try { Remove-Item "$File" | Out-Null DS_WriteLog "S" "Successfully deleted the file '$File'" $LogFile } catch { DS_WriteLog "E" "An error occurred trying to delete the file '$File' (exit code: $($Error[0])!" $LogFile Exit 1 } } else { DS_WriteLog "I" "The file '$File' does not exist. Nothing to do." $LogFile } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_CreateRegistryKey #========================================================================== Function DS_CreateRegistryKey { <# .SYNOPSIS Create a registry key .DESCRIPTION Create a registry key .PARAMETER RegKeyPath This parameter contains the registry path, for example 'hklm:\SOFTWARE\MyApp' .EXAMPLE DS_CreateRegistryKey -RegKeyPath "hklm:\SOFTWARE\MyApp" Creates the new registry key 'hklm:\SOFTWARE\MyApp' #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$RegKeyPath ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Create registry key $RegKeyPath" $LogFile if ( Test-Path $RegKeyPath ) { DS_WriteLog "I" "The registry key $RegKeyPath already exists. Nothing to do." $LogFile } else { try { New-Item -Path $RegkeyPath -Force | Out-Null DS_WriteLog "S" "The registry key $RegKeyPath was created successfully" $LogFile } catch{ DS_WriteLog "E" "An error occurred trying to create the registry key $RegKeyPath (exit code: $($Error[0])!" $LogFile DS_WriteLog "I" "Note: define the registry path as follows: hklm:\SOFTWARE\MyApp" $LogFile Exit 1 } } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_DeleteRegistryKey #========================================================================== Function DS_DeleteRegistryKey { <# .SYNOPSIS Delete a registry key .DESCRIPTION Delete a registry key .PARAMETER RegKeyPath This parameter contains the registry path, for example 'hklm:\SOFTWARE\MyApp' .EXAMPLE DS_DeleteRegistryKey -RegKeyPath "hklm:\SOFTWARE\MyApp" Deletes the registry key 'hklm:\SOFTWARE\MyApp' #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$RegKeyPath ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Delete registry key $RegKeyPath" $LogFile if ( Test-Path $RegKeyPath ) { try { Remove-Item -Path $RegkeyPath -recurse | Out-Null DS_WriteLog "S" "The registry key $RegKeyPath was deleted successfully" $LogFile } catch{ DS_WriteLog "E" "An error occurred trying to delete the registry key $RegKeyPath (exit code: $($Error[0])!" $LogFile DS_WriteLog "I" "Note: define the registry path as follows: hklm:\SOFTWARE\MyApp" $LogFile Exit 1 } } else { DS_WriteLog "I" "The registry key $RegKeyPath does not exist. Nothing to do." $LogFile } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_DeleteRegistryValue #========================================================================== Function DS_DeleteRegistryValue { <# .SYNOPSIS Delete a registry value .DESCRIPTION Delete a registry value .PARAMETER RegKeyPath This parameter contains the registry path (for example hklm:\SOFTWARE\MyApp) .PARAMETER RegValueName This parameter contains the name of the registry value that is to be deleted (for example MyValue) .EXAMPLE DS_DeleteRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyValue" Deletes the registry value 'MyValue' from the registry key 'hklm:\SOFTWARE\MyApp' #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$RegKeyPath, [Parameter(Mandatory=$true, Position = 1)][String]$RegValueName ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Delete registry value $RegValueName in $RegKeyPath" $LogFile [string]$RegValueTemp = Get-ItemProperty -Path $RegKeyPath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $RegValueName -ErrorAction SilentlyContinue if ( ($RegValueTemp::IsNullOrEmpty) -Or ($RegValueTemp.Length -eq 0) ) { try { Remove-ItemProperty -Path $RegKeyPath -Name $RegValueName | Out-Null DS_WriteLog "S" "The registry value $RegValueName in $RegKeyPath was deleted successfully" $LogFile } catch { DS_WriteLog "E" "An error occurred trying to delete the registry value $RegValueName in $RegKeyPath (exit code: $($Error[0])!" $LogFile DS_WriteLog "I" "Note: define the registry path as follows: hklm:\SOFTWARE\MyApp" $LogFile Exit 1 } } else { DS_WriteLog "I" "The registry value $RegValueName in $RegKeyPath does not exist. Nothing to do." $LogFile } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_ImportRegFile #========================================================================== Function DS_ImportRegFile { <# .SYNOPSIS Import a registry (*.reg) file into the registry .DESCRIPTION Import a registry (*.reg) file into the registry .PARAMETER FileName This parameter contains the full path, file name and file extension of the registry file, for example "C:\Temp\MyRegFile.reg" .EXAMPLE DS_ImportRegFile -FileName "C:\Temp\MyRegFile.reg" Imports registry settings from the file "C:\Temp\MyRegFile.reg" #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$FileName ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Import registry file '$FileName'" $LogFile if ( Test-Path $FileName ) { try { $process = start-process -FilePath "reg.exe" -ArgumentList "IMPORT ""$FileName""" -WindowStyle Hidden -Wait -PassThru if ( $process.ExitCode -eq 0 ) { DS_WriteLog "S" "The registry settings were imported successfully (exit code: $($process.ExitCode))" $LogFile } else { DS_WriteLog "E" "An error occurred trying to import registry settings (exit code: $($process.ExitCode))" $LogFile Exit 1 } } catch { DS_WriteLog "E" "An error occurred trying to import the registry file '$FileName' (exit code: $($Error[0])!" $LogFile Exit 1 } } else { DS_WriteLog "E" "The file '$FileName' does NOT exist!" $LogFile Exit 1 } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== # FUNCTION DS_SetRegistryValue #========================================================================== Function DS_SetRegistryValue { <# .SYNOPSIS Set a registry value .DESCRIPTION Set a registry value .PARAMETER RegKeyPath This parameter contains the registry path, for example 'hklm:\SOFTWARE\MyApp' .PARAMETER RegValueName This parameter contains the name of the new registry value, for example 'MyValue' .PARAMETER RegValue This parameter contains the value of the new registry entry, for example '1' .PARAMETER Type This parameter contains the type (possible options are: String, Binary, DWORD, QWORD, MultiString, ExpandString) .EXAMPLE DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyStringValue" -RegValue "Enabled" -Type "String" Creates a new string value called 'MyStringValue' with the value of 'Enabled' .Example DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyBinaryValue" -RegValue "01" -Type "Binary" Creates a new binary value called 'MyBinaryValue' with the value of '01' .Example DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyDWORDValue" -RegValue "1" -Type "DWORD" Creates a new DWORD value called 'MyDWORDValue' with the value of 1 .Example DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyQWORDValue" -RegValue "1" -Type "QWORD" Creates a new QWORD value called 'MyQWORDValue' with the value of 1 .Example DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyMultiStringValue" -RegValue "Value1,Value2,Value3" -Type "MultiString" Creates a new multistring value called 'MyMultiStringValue' with the value of 'Value1 Value2 Value3' .Example DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\MyApp" -RegValueName "MyExpandStringValue" -RegValue "MyValue" -Type "ExpandString" Creates a new expandstring value called 'MyExpandStringValue' with the value of 'MyValue' #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position = 0)][String]$RegKeyPath, [Parameter(Mandatory=$true, Position = 1)][String]$RegValueName, [Parameter(Mandatory=$false, Position = 2)][String[]]$RegValue = "", [Parameter(Mandatory=$true, Position = 3)][String]$Type ) begin { [string]$FunctionName = $PSCmdlet.MyInvocation.MyCommand.Name DS_WriteLog "I" "START FUNCTION - $FunctionName" $LogFile } process { DS_WriteLog "I" "Set registry value $RegValueName = $RegValue (type $Type) in $RegKeyPath" $LogFile # Create the registry key in case it does not exist if ( !( Test-Path $RegKeyPath ) ) { DS_CreateRegistryKey $RegKeyPath } # Create the registry value try { if ( ( "String", "ExpandString", "DWord", "QWord" ) -contains $Type ) { New-ItemProperty -Path $RegKeyPath -Name $RegValueName -Value $RegValue[0] -PropertyType $Type -Force | Out-Null } else { New-ItemProperty -Path $RegKeyPath -Name $RegValueName -Value $RegValue -PropertyType $Type -Force | Out-Null } DS_WriteLog "S" "The registry value $RegValueName = $RegValue (type $Type) in $RegKeyPath was set successfully" $LogFile } catch { DS_WriteLog "E" "An error occurred trying to set the registry value $RegValueName = $RegValue (type $Type) in $RegKeyPath" $LogFile DS_WriteLog "I" "Note: define the registry path as follows: hklm:\SOFTWARE\MyApp" $LogFile Exit 1 } } end { DS_WriteLog "I" "END FUNCTION - $FunctionName" $LogFile } } #========================================================================== ################ # Main section # ################ # Disable File Security $env:SEE_MASK_NOZONECHECKS = 1 # Custom variables [edit] $BaseLogDir = "C:\Logs" # [edit] add the location of your log directory here $PackageName = "Citrix Receiver for Windows" # [edit] enter the display name of the software (e.g. 'Arcobat Reader' or 'Microsoft Office') # Global variables $StartDir = $PSScriptRoot # the directory path of the script currently being executed if (!($Installationtype -eq "Uninstall")) { $Installationtype = "Install" } $LogDir = (Join-Path $BaseLogDir $PackageName).Replace(" ","_") $LogFileName = "$($Installationtype)_$($PackageName).log" $LogFile = Join-path $LogDir $LogFileName # Create the log directory if it does not exist if (!(Test-Path $LogDir)) { New-Item -Path $LogDir -ItemType directory | Out-Null } # Create new log file (overwrite existing one) New-Item $LogFile -ItemType "file" -force | Out-Null DS_WriteLog "I" "START SCRIPT - $Installationtype $PackageName" $LogFile DS_WriteLog "-" "" $LogFile ########################################################################### # PRE-CONFIGURATION ########################################################################### # Delete old log folders in the TEMP directory (in case there are any) DS_WriteLog "I" "Delete old log folders" $LogFile $Folders = Get-ChildItem $env:Temp -filter "CTXReceiverInstallLogs*" if ( $Folders.Count -gt 0 ) { Foreach ( $Folder in $Folders ) { DS_DeleteDirectory -Directory $Folder.FullName } } else { DS_WriteLog "I" "No existing log folders were found. Nothing to do." $LogFile } DS_WriteLog "-" "" $LogFile # Only execute the following section during installation, not uninstallation if (! ( $Installationtype -eq "Uninstall" )) { # Prevent the 'Add account' button right after installation # Note 1: this section is not required in case you rename 'CitrixReceiver.exe' to 'CitrixReceiverWeb.exe' (but it also does no harm so you can leave it as it is) # Note 2: 'CitrixReceiverWeb.exe' does NOT set the value 'EnableX1FTU' in the registry: it merely shows a Window at the end of the installation without the 'Add Account' button DS_WriteLog "I" "Prevent the 'Add account' button right after installation" $LogFile DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\Wow6432Node\Policies\Citrix" -RegValueName "EnableX1FTU" -RegValue "00000000" -Type "DWORD" DS_WriteLog "-" "" $LogFile } ########################################################################### # INSTALLATION ########################################################################### # Install or uninstall software $FileName = "CitrixReceiver.exe" # [edit] enter the name of the installation file (e.g. 'MyApp.msi' or 'setup.exe') if ( $Installationtype -eq "Uninstall" ) { $Arguments = "/silent /uninstall" # [edit] enter arguments (for MSI file the following arguments are added by default: /i #File# /qn /norestart / l*v #LogFile#) } else { $Arguments = "/silent /includeSSON /FORCE_LAA=1 EnableCEIP=false /AutoUpdateCheck=disabled" # [edit] enter arguments (for MSI file the following arguments are added by default: /i #File# /qn /norestart / l*v #LogFile#) } $FileSubfolder = "Files" # [edit] enter the name of the subfolder which contains the installation file (e.g. 'Files' or 'MSI') $FileFullPath = Join-Path $StartDir $FileSubfolder # Concatenate the two directories $StartDir and $InstallFileFolder DS_InstallOrUninstallSoftware -File ( Join-Path $FileFullPath $FileName ) -InstallationType $Installationtype -Arguments $Arguments DS_WriteLog "-" "" $LogFile ########################################################################### # POST-CONFIGURATION ########################################################################### if ( $Installationtype -eq "Uninstall" ) { # POST-CONFIGURATION FOR UNINSTALLATIONS # Cleanup remaining registry entries: # Reference: https://docs.citrix.com/en-us/receiver/windows/current-release/install/ica-install-manual.html DS_WriteLog "I" "Cleanup: delete the Citrix Receiver local machine keys" $LogFile DS_DeleteRegistryKey -RegKeyPath "hklm:\SOFTWARE\Policies\Citrix\ICA Client" DS_DeleteRegistryKey -RegKeyPath "hklm:\SOFTWARE\Wow6432Node\Policies\Citrix\ICA Client" DS_DeleteRegistryValue -RegKeyPath "hklm:\SOFTWARE\Wow6432Node\Policies\Citrix" -RegValueName "EnableX1FTU" DS_DeleteRegistryValue -RegKeyPath "hklm:\SYSTEM\CurrentControlSet\Control\NetworkProvider\ProviderOrder" -RegValueName "PnSson" DS_WriteLog "-" "" $LogFile } else { # POST-CONFIGURATION FOR INSTALLATIONS # Import the Client Selective Trust registry keys and values. This prevents annoying security popup message regarding permissions for access to files, microphones, cameras, scanners, etc. in the local intranet and trusted sites. # Reference: How to Configure Default Device Access Behavior of Receiver, XenDesktop and XenApp (https://support.citrix.com/article/CTX133565) DS_WriteLog "I" "Import the Client Selective Trust registry keys and values. This prevents security popup messages during logon" $LogFile $RegFile = Join-Path $StartDir "Files\CitrixReceiver_Client_Selective_Trust_x86_Dennisspan.com.reg" DS_ImportRegFile -FileName $RegFile DS_WriteLog "-" "" $LogFile # Prevent unexpected MSI repairs from starting # -Delete the value data from the WEB_CLIENT registry value (part of the Citrix Online Plug-in MSI) # -Each version of Citrix Receiver has its own product ID: # -AC1889E2C14E5E540855164ACCB19FF3 -> Citrix Receiver 4.12 (this is the latest and last version of Receiver. The replacement for Receiver is Workspace app) $ProductID = "AC1889E2C14E5E540855164ACCB19FF3" DS_WriteLog "I" "Prevent unexpected MSI repairs from starting" $LogFile DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\$($ProductID)\Features" -RegValueName "WEB_CLIENT" -RegValue "" -Type "String" DS_WriteLog "-" "" $LogFile # This section only runs on Windows 10 and higher [int]$WindowsVersion = ([environment]::OSVersion.Version).Major if ( $WindowsVersion -ge 10 ) { # Prevent the Win+G popup on Windows 10 machines # Reference: -https://support.citrix.com/article/CTX226423 # -http://www.carlstalhood.com/receiver-for-windows/#registryvalues DS_WriteLog "I" "Prevent the Win+G popup on Windows 10 machines" $LogFile DS_SetRegistryValue -RegKeyPath "hklm:\SOFTWARE\Policies\Microsoft\Windows\GameDVR" -RegValueName "AllowGameDVR" -RegValue "00000000" -Type "DWORD" DS_WriteLog "-" "" $LogFile # Fix the error ‘Failed to get network providers’ under Advanced Settings of the Network Adaptor when Citrix Receiver with Single Sign-on (SSON) is installed (reference: https://support.citrix.com/article/CTX229052) # Note 1: this issue should be fixed from Windows 10 version 1803 # Note 2: in Windows 10 the provider order is based on the value of the particular item in the registry key 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\ProviderOrder' # By default, each network provider item gets a value of one thousands or higher, always an even 1000 value. For example: 1000, 2000, 3000, etc. DS_WriteLog "I" "Fix the error 'Failed to get network providers' under Advanced Settings of the Network Adapter" $LogFile DS_SetRegistryValue -RegKeyPath "hklm:\SYSTEM\CurrentControlSet\Control\NetworkProvider\ProviderOrder" -RegValueName "PnSson" -RegValue "3001" -Type "DWORD" DS_WriteLog "-" "" $LogFile } # Remove the shortcut from the 'Programs\Startup' folder (if exist) DS_WriteLog "I" "Remove the Citrix Receiver shortcut from the 'Programs\Startup' folder" $LogFile $File = Join-Path $env:AllUsersProfile "Start Menu\Programs\Startup\Receiver.lnk" DS_DeleteFile -File $File DS_WriteLog "-" "" $LogFile # Remove the shortcut from the 'Programs' folder (if exist) DS_WriteLog "I" "Remove the Citrix Receiver shortcut from the 'Programs' folder" $LogFile $File = Join-Path $env:AllUsersProfile "Start Menu\Programs\Citrix Receiver.lnk" DS_DeleteFile -File $File DS_WriteLog "-" "" $LogFile } # Do the following for both installations and uninstallations # Determine the folder name containing the Citrix log files (e.g. C:\Windows\Temp\CTXReceiverInstallLogs-20160218-202413) DS_WriteLog "I" "Copy the log files from the TEMP directory to '$LogDir'" $LogFile $CitrixLogPath = (gci -directory -path $env:Temp -filter "CTXReceiverInstallLogs*").FullName if ( Test-Path ( $CitrixLogPath + "\*.log" ) ) { $Source = Join-Path $CitrixLogPath "*.log" DS_WriteLog "I" "Source files = $Source" $LogFile DS_WriteLog "I" "Destination directory = $LogDir " $LogFile DS_CopyFile -SourceFiles $Source -Destination $LogDir } else { DS_WriteLog "I" "There are no log files in the directory '$CitrixLogPath'. Nothing to copy." $LogFile } ########################################################################### # Enable File Security Remove-Item env:\SEE_MASK_NOZONECHECKS DS_WriteLog "-" "" $LogFile DS_WriteLog "I" "End of script" $LogFile |
To uninstall Receiver, execute the script as follows:
powershell.exe -executionpolicy bypass -file C:\Temp\Citrix\Receiver\Install_CitrixReceiver.ps1 Uninstall
The uninstallation removes any custom configuration the installation may have set as well as the following two registry keys:
- HKLM\Software\Policies\Citrix\ICA Client
- HKLM\Software\Wow6432Node\Policies\Citrix\ICA Client
Removing these two registry keys is recommended by Citrix (see the section Uninstalling Citrix Receiver for Windows in the article Install and Uninstall Citrix Receiver for Windows manually).
Conclusion
Installing and configuring Citrix Receiver can get quite complicated and requires a bit of planning. Also, please be aware of the following:
- There are more settings that can be directly configured during the installation of Citrix Receiver. Most of these configurations concern the Windows registry. Please see the section Registry Values in Carl Stalhood’s article Receiver / Workspace app 1808 for more information. In case you want to add additional configurations to the complete installation script, I recommend copying and reusing existing lines of code. Please be aware that many settings can nowadays be managed using Group Policy.
- Citrix Receiver comes with a large collection of Group Policies settings. Please see the section Receiver Group Policy ADMX Template in Carl Stalhood’s article Receiver / Workspace app 1808 for more information. The actual ADMX files can be downloaded on the Citrix website (in the section Downloads for admins), but they are also included in the installation directory of Receiver (C:\Program Files (x86)\Citrix\ICA Client\Configuration).
- Pass-through authentication (or single sign-on) requires many different settings to be correctly configured, such as Trusted Sites, Trust XML Requests on the Delivery Controller, installing the Single Sign-On component in Receiver, and more. Please see the section Pass-through Authentication in Carl Stalhood’s article Receiver / Workspace app 1808 for a complete overview of what needs to be configured. Citrix Receiver version 4.5 and higher comes with a built-in tool for checking the SSON configuration (see the Citrix article SSON Configuration Checker for Citrix Receiver for Windows).
- The latest version of Receiver is also included in the installation sources of the Virtual Delivery Agent. On a Citrix worker, there are two possible strategies you can follow:
- You install Receiver as a stand-alone installation (as described in this article) and you install the Virtual Delivery Agent excluding Receiver. This is accomplished by using the command line /components VDA as described in the section Citrix Virtual Delivery Agent in my article Scripting the complete list of Citrix components with PowerShell.
- You install the version of Receiver included in the Virtual Delivery Agent installation sources (in this case you do not use the /components parameter).
- When using Skype for Business in your environment, you may want to install the HDX RealTime Media Engine on your client device together with Citrix Receiver. Citrix Receiver is a prerequisite for the Media Engine; without Receiver, Media Engine cannot be installed. To automate the installation of the HDX RealTime Media Engine, please see the section HDX RealTime Media Engine for Windows in my article Scripting the complete list of Citrix components with PowerShell. Also, for extensive information on Skype for Business, Citrix, and the HDX RealTime Optimization Pack, please see the section Skype for Business in Carl Stalhood’s article Receiver / Workspace app 1808. I also highly recommend you to read the article Skype for Business with XenApp & XenDesktop written by Citrix CTP George Spiers.
If you want to go one step further and create an SCCM package as well, please follow the step-by-step explanation in the article Deep dive creating SCCM packages for Citrix.
I hope the information in this article was of some help to you. Happy scripting!
Dennis Span works as a Lead Account Technology Strategist at Cloud Software Group in Vienna, Austria. He holds multiple Citrix certifications (CCE-V). Dennis has been a Citrix Technology Advocate (CTA) since 2017 (+ one year as Citrix Technology Professional, CTP). Besides his interest in virtualization technologies and blogging, he loves spending time with his family as well as snowboarding, playing basketball and rowing. He is fluent in Dutch, English, German and Slovak and speaks some Spanish.
Great Article Dennis
Perfectly described
Alex K.
Thanks a lot Alex!
Amazing …. Good job
Thanks a lot Ray!
What a master piece Dennis ! I’ve rarely seen a such comprehensive article on the subject, you rock !
Yvan
Thanks a lot Yvan! I am happy you like it!
Pingback: EUC Weekly Digest – May 12 ,2018 – Carl Stalhood
Pingback: Detailed Change Log – Carl Stalhood
Pingback: Receiver for Windows 4.12 – Carl Stalhood
Pingback: Citrix Application Probe Agent unattended installation - Dennis Span
Hi, Is there any way to install the Citrix Workspace App with High DPI setting enabled by default ?
Hi Ernest,
Yes, you can configure this via Group Policy. You have to first import the Citrix Workspace app ADMX file. The setting you are looking for is located here: Computer Configuration \ Policies \ Administrative Template \ Citrix Components \ Citrix Receiver \ DPI -> High DPI
HI Dennis,
Can we add Web Interface URL to Citrix Receiver in place of StoreFront during unattended install?
That should not be a problem Srini. If you are in doubt of how to add certain parameters than just use the Citrix Workspace app CommandLine Tool.