Friday, April 6, 2018

Hiding Published Desktop Shortcuts On The Start Menu

Scenario:

Users connect to a XenDesktop 7.13 published desktop that has Citrix Receiver 4.9 LTSR installed to access XenApp published applications. All applications have shortcuts created in the start menu, including published desktop shortcuts.

Problem:

We do not want shortcuts for published desktops to be created as we do not want users starting desktops from within their VDI session.

Solution (Storefront 3.9):

  1. Create a new Store.
  2. Manage Receiver for Web Sites
  3. Select the Web site and click Configure...
  4. From the Client Interface Settings screen, change the Select View value to Show Applications view only, click OK, then click Close
  5. Select Configure Store SettingsFrom the Advanced Settings screen, click on Filter resources by type and select Citrix.MPS.Application and Citrix.MPS.Document, click OK twice to save changes
  6. Be sure to Propagate Changes
  7. Configure a Receiver GPO that assigns the newly created app store to the VDI desktops which is beyond the scope of this article.
 Now after logging into to a desktop and SSO logs you in to the app store, you should see your assigned app shortcuts in the start menu sans published desktop shortcuts!

The Case of the Disappearing Philips Dictation Microphone in a XenApp-Delivered Application Running In A XenDesktop Virtual Desktop And How To Make It Work

A long title but with amazing results. What do you do when you are asked to fulfill these requirements?

  • User will be using Epic Hyperspace delivered via XenApp 7.x
  • User will be launching Hyperspace from their XenDesktop-delivered Windows 7 desktop
  • User will be launching their VDI desktop from a Dell Wyse Xenith endpoint with a Phillips SpeechMike III attached
  • User must be able to use their SpeechMike in Hyperspace for partial dictation with all buttons functioning
  1. First, make sure you are running a recent Dell/Wyse firmware (I tested on ThinOS Lite 2.4_112 and ThinOS 8.4_112).
  2. Next you will need to set a custom hardware string either in the .ini or your Dell Management Suite group policy->Advamced: Device=vusb ForceRedirect=0x0911,0x0c1c,0x01,0x01,0x00 Type=HDX
  3. After logging in to your published desktop, you will see the Speechmike in audio devices but notice that the default audio device is Citrix HDX Audio for both speakers and microphone. In order for the SpeechMike to work in a XenApp session, the Speechmike must be default.
    1. To accomplish this automatically, you can use Powershell and a 3rd-party utility, nircmdc, to make the change during login.
    2. For the script to work, you must change permissions on
      HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices by first taking ownership of the key and then giving write permissions for Authenticated Users and propagating them down.
    3. Nircmdc uses the Windows generic name (eg. Microphone) and not the device name (Philips Speechmike III). In many cases there will be multiple devices with the same name (eg. Microphone or Speakers) so we need to run a Powershell script to find the Philips microphone and rename it's generic name to DocMic so we can use Nircmdc to set it as default.
      $regcheck = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture"
      $soundcheck = Get-ChildItem -path Registry::$regcheck

      $enabledDevices = foreach($_ in $soundcheck)

          $path = $_.'name'
          Get-ItemProperty -path Registry::$path | ?{$_.DeviceState -eq "1"} | Select-Object pspath | Get-ChildItem | Get-ItemProperty | ?{$_ -match "SpeechMike III"}
      }
      if($enabledDevices)
      {
          $path =  $enabledDevices.pspath
          $key = ($enabledDevices.psobject.properties | ?{$_.Value -match "Microphone"}).name
          set-ItemProperty -path $path -name $key -value DocMic -type string -force
      }
    4. You can modify the Powershell script to also kick off Nircmdc but I've left it separate:
      Nircmdc.exe -setdefaultsounddevice "DocMic"
  4. Now just have these run at user logon. You may need to call a sleep function at the beginning of the script to allow time for Windows to complete the new hardware detection.
  5. If you want to also use the speaker on the dictation mic, you will also need to run a slightly modified version of the above PS script:
    $regcheck = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render"
    $soundcheck = Get-ChildItem -path Registry::$regcheck

    $enabledDevices = foreach($_ in $soundcheck)
    {  
        $path = $_.'name'
        Get-ItemProperty -path Registry::$path | ?{$_.DeviceState -eq "1"} | Select-Object pspath | Get-ChildItem | Get-ItemProperty | ?{$_ -match "SpeechMike III"}
    }
    if($enabledDevices)
    {
        $path =  $enabledDevices.pspath
        $key = ($enabledDevices.psobject.properties | ?{$_.Value -Match "Speakers"}).name
        set-ItemProperty -path $path -name $key -value DocSpeaker -type string -force
    }
    And then modify the nircmdc command to reference "DocSpeaker".
    You can obtain the nircmdc utility here.

Thursday, December 24, 2015

Powershell: Ensuring Values Are Returned As Arrays

It's Christmas Eve and I'm in the office catching up on some work.  This year has flown by pretty quickly and I have realized I have not added any content this year despite being very busy with VDI deployments, scripting, a zero-downtime SAN migration (which really deserved/deserves an article), and other miscellaneous tasks.
When scripting today, I came across an challenge that I remember solving earlier in the year. It took a bit of searching through previous scripts for the answer and I finally found it. I decided to turn it into a post for easier recollection later. I also hope it helps someone that runs across the same issue. Others will read this and probably just shake their head as common knowledge.

The Problem:
I have a function that returns multiple values into an array that I can then run a ForEach loop on.  However, it is possible that the function may only return a single value.  In that case, the variable is no longer an array, but a string or integer (depending on what is returned).
Example:

   $files = Get-ChildItem -Path E:\music –File | Select-Object Name
The example would return all the file names in E:\music as Strings and store it in the variable $files. If there were multiple values returned, the $files variable would be an array but let's say there is only one file in E:\music named mysong.mp3. The output of $files[0] would be:
   m
Not the entire file name. It makes sense when you think about it.  When you only assign one string value to a variable, the variable is going to be a string. Weird, eh?

The Solution:
When you are declaring a variable as an array, you can do something like: 
   $myArray = @( )
So when you are assigning the value of a function to a variable and want to ensure it is stored as an array, you would use:
    $files = @(Get-ChildItem -Path E:\music –File | Select-Object Name)
The result of running $files[0] using the same scenario as above would be:
   mysong.mp3