A Technique to Run Scripts Asynchronously via AppSense Environment Manager

Whilst AppSense Environment Manager (EM) has a rich set of trigger points, such as logon and reconnect, where you can run built-in actions or scripts, until very recently there was no built-in way of running something say five minutes after logon or every thirty minutes.

I’ve seen techniques that create scheduled tasks, which you can do directly in a PowerShell script rather than having to modify XML task templates, but with these you still have to get the script you want to run onto the local file system. Whilst I came up with a method of embedding any arbitrary file into an AppSense EM configuration, such as image files (see here), that approach is a little cumbersome, particularly if you need to change the embedded script.

I find an easier way to achieve this goal is to write a script inside an EM logon action that takes a copy of itself to a local file and then invokes powershell.exe to run it so that it runs outside of EM thus allowing the logon to finish but the newly launched script is still running as it is hosted inside an asynchronous powershell.exe process. Inside this script you can then wait for any period of time and then perform an action and either exit or loop around ad infinitum, or at least until logoff.

It works by looking to see if the -async option has been specified when the script was run. When EM runs the script, it won’t specify any options so we detect this and make it fire off a copy of the same script, since EM will delete the original when the script it invoked finishes, via powershell.exe which will take a different path through the code because the -async parameter is specified this time.

There’s an example version 10 EM configuration available for download here although the technique will work with any EM version. You will need to put your code into the PowerShell custom action, after the comment line reading “we are now outside of EM so can trigger later”, to perform whatever you need it to do. You might just want it to do something every few minutes or hours or you could put a file system or registry watcher in to trigger when something specifically changes (now there’s an idea for a future post if ever there was one!).

If you need the script to run elevated then simply set the action to run as System in the configuration but remember that environment variables and HKCU will not be for the logged on user but for the System account.

If you are also using AppSense Application Manager to prohibit powershell.exe then as long as you have configured it to ignore restrictions during logon then  it should be ok but you could always add a Process rule for EMUser.exe to allow powershell.exe child processes.

Manipulating autorun logon entries with PowerShell

As I came to manually create a registry value for a script I wanted to run at logon, I thought that I may as well write a script that would ass the item to save people having to remember where to create the entries. It then morphed into something that would list or remove entries too, depending on the command line parameters specified.

The script is available here and can be run in a number of different ways, e.g.:

  • Show all existing autorun entries in the registry for the current user (if -registry is not specified then the file system will be used):
& "C:\Scripts\Autorun.ps1" -list -registry
  • Delete an existing autorun entry for the current user that runs calc.exe either by the name of the entry (the shortcut name or registry value name) or by regular expression matching on the command run:
& "C:\Scripts\Autorun.ps1" -name "Calculator" -remove
& "C:\Scripts\Autorun.ps1" -run Calc.* -remove
  • Add a new autorun entry to the file system that runs calc.exe for the current user:
& "C:\Scripts\Autorun.ps1" -name "Calculator" -run "calc.exe" -description "Calculator" 

The -allusers flag can be used with any of the above to make them operate for all users but the user running the script must have administrative rights.

When creating an autorun item in the file system, the icon for the shortcut can be specified via the -icon option.

Deletions will prompt for confirmation unless you specify -Confirm:$false and it will also prompt for confirmation when creating a new entry if the name of the entry already exists.

Specifying -verify will generate an error if the executable does not exist when creating a new entry.

If you are on a 64 bit system then you can specify the -wow6432node option when using -registry to work in the wow6432node area of the registry.

Exporting validated shortcuts to CSV file

In a recent Citrix XenApp 7.x consulting engagement, the customer wanted to have a user’s start menu on their XenApp desktop populated entirely via shortcuts created dynamically at logon by Citrix Receiver. Receiver has a mechanism whereby a central store can be configured to be used for shortcuts such that when the user logs on, the shortcuts they are allowed are copied from this central share to their start menu. For more information on this see https://www.citrix.com/blogs/2015/01/06/shortcut-creation-for-locally-installed-apps-via-citrix-receiver/

Before not too long there were in excess of 100 shortcuts in this central store so to check these individually by examining their properties in explorer was rather tedious to say the least so I looked to automate it via good old PowerShell. As I already had logon scripts that were manipulating shortcuts, it was easy to adapt this code to enumerate the shortcuts in a given folder and then write the details to a csv file so it could easily be filtered in Excel to find shortcuts whose target didn’t exist although it will also output the details of these during the running of the script.

I then realised that the script could have more uses than just this, for instance to check start menus on desktop machines so decided to share it with the wider community.

The get-help cmdlet can be used to see all the options but in its simplest form, just specify a -folder argument to tell it where the parent folder for the shortcuts is and a -csv with the name of the csv file you want it to write (it will overwrite any existing file of that name so be careful).

It can also check that the shortcut’s target exists on a remote machine. For instance, you can run the script on a Citrix Delivery Controller but have it check the targets on a XenApp server, via its administrative shares, by using the -computername option.

If you run it on a XenApp server with the “PreferTemplateDirectory” registry value set, use the -registry option instead of -folder and it will read this value from the registry and use that folder.

If you’re running it on a desktop to check that there are no bad shortcuts in the user’s own start menu, whether it is redirected or not, or in the all users start menu then specify the options -startmenu or -allusers respectively.

Finally, it can email the resultant csv file via an SMTP mail server using the -mailserver and -recipients options.

The script is available for download here.