Start an App-V 5 Process immediately after Publishing

I have a piece of software that acts as an ‘agent’ sitting in the background (in the System Tray) waiting to intercept print requests.  It needs to be running all the time since it intercepts print requests from ANY desktop application.

The target platforms are a combination of standard desktops and non-persistent VDI desktops.  Making it work with standard desktops wasn’t really the problem – by default the software placed a shortcut in the Startup folder and after publishing, logging off and logging in the background process started.

The trouble with a non-persistent VDI is that when a user logs off and logs back in, they get a completely fresh desktop experience and all the apps get published again.  As a result of this we can’t just lump some logic in a Run key or the Startup folder since the application is published after these features are processed.

Combined with this there were another 2 applications that needed connection-grouping with this agent application.

Unless there’s a more elegant way of achieving this that I’m not aware of, I present my solution forthwith:

Firstly, since we’re publishing to users, I have added a user script at publish time in the AppxManifest.xml file (or you could use the UserConfig.xml file – your choice depending on which version of App-V you’re using):

What’s important to note is that we can’t just point at our background process for 2 reasons:

  1. Because the application is not yet published at this point, and so we can’t access/run it
  2. Even if we could access/run it, the publishing process would stick at running the .exe since the .exe will always be running and the PublishPackage action will never release the handle (unless we manually kill it).  And hence the package would never publish!

Instead we’ve called cmd.exe with the START command.  What this does is launch powershell.exe as a separate process and does NOT wait for it to complete.  Hence the publishing of the app will complete as normal.  Meanwhile in the background, powershell.exe runs a script that I’ve placed in the Scripts folder in the background.  So what does the script do?  In essence it:

  • Loops 10 times maximum, with a 5 second delay between each loop, and attempts to get the package (Get-AppvClientPackage) and ensure it is published to the user (IsPublishedToUser).  We cannot run the process if the package is not published.
  • Loops 10 times maximum, with a 5 second delay between each loop, and attempts to get the connection group (Get-AppvClientConnectionGroup) and ensure it is enabled (IsEnabledToUser).  If using a connection group, we cannot enable a connection group if a package is in use!  So we need to wait until the connection group is enabled before we attempt to start the process.
  • Loops 10 times maximum, with a 5 second delay between each loop, and attempts to start the process (Start-Process).  There’s no reason why it shouldn’t start first time, but I still add in some retries just in case.

Here is the script (runProcess.ps1)

Things to tweak

The variables at the top (package names etc).  Also remember this targets packages published to the user, not the machine.  So you’ll need to tweak things like ‘isEnabledToUser’ and ‘isPublishedToUser’ etc.  Also you may not be using a connection group like me, so you could chop that logic out too.

A note before you commence…

Since the background process is always running, it obviously can’t be unpublished instantly (because the package will be in use).  Luckily we’re running the App-V 5 SP2 client which will set up a pending task to un-publish it when the user logs off and back in.  You may want to consider this before implementing it.

Using Taskkill.exe to Kill Multiple Processes on One Line

I’ve had an issue with my current App-V 5 application.  When I launch an executable called CentralSurveillance.exe, it spawns another two processes called K2DataLogger.exe and K2MSService.exe.  And these remain open even when I close CentralSurveillance.exe.  My first thoughts were that these were child processes, so I added the following to the DeploymentConfig:

Sure enough, when I closed the instance of CentralSurveillance.exe….the instances of K2DataLogger.exe and K2MSService.exe were still running!  So I dug a little deeper – were these actually child processes or not?

I opened up a command prompt and ran:

What this does is list the name, description, command line, process id and parent process id of each running process and outputs it to a text file called processes.txt.  The results (after I’d deleted the irrelevant stuff) were as follows:

We can clearly see that the parent process of K2DataLogger.exe and K2MSService.exe is NOT CentralSurveillance.exe (process id 6120) but instead AppVClient.exe (process id 2664).  And this is probably why TerminateChildProcesses will not work in this instance.  The workaround I used is to run an ExitProcess script so that when we close CentralSurveillance.exe, it kills both K2DataLogger.exe and K2MSService.exe.

I did this like so:

You can see that I can specify multiple command lines to run via CMD.exe by separating each command by an ampersand (& – this needs to be URL encoded in an XML file which is why it would appear as & instead).  In the workaround above I specify two processes.  However by using brackets and nesting commands, I can specify more!  Here’s an example of an argument that kills 4 processes:

Using RunVirtual to Present Excel Addins

I’ve recently been having a look at the best way to present Excel Add Ins using our locally installed instance of Microsoft Excel and our virtualised Add Ins.

The easiest approach is probably to create an additional shortcut in your package called ‘Microsoft Excel 2010 with XXX Add In’ which points to your local instance of Excel.exe.  Running this shortcut will launch the local instance of Excel.exe inside the virtual bubble, and you should then see your virtualised Add Ins when the application is loaded.

The trouble with this approach is that users will generally head straight to the main shortcut to Microsoft Excel (the shortcut to the local instance) and wonder why they can’t see their Add In.  On top of this, using the approach above could mean that we have multiple ‘Microsoft Excel 2010 with XXX Add In’ shortcuts, which can look quite untidy.

An alternative approach is presented by the RunVirtual registry key introduced in App-V 5 .  What this feature enables us to do is to launch the shortcut to the locally installed version of Excel and drag this process (Excel.exe) instance inside the virtual bubble of a specified package.

Again, I won’t go into too much detail here since there’s a great blog about how RunVirtual works here and also a mention of an important update for App-V 5 SP3 here, which enables us to target packages published to the User.

Anyway, I’m babbling a bit so we’ll crack on….

In my opinion RunVirtual is ALMOST great.  Ideally we would be able to create a RunVirtual reference to a local application like so (Microsoft Excel in this example):

HKEY_CURRENT_USER\Software\Microsoft\AppV\Client\RunVirtual\Excel.exe

and then list multiple virtualised Addins underneath that (by specifying their PackageId and VersionId).  Unfortunately we can only specify one virtual package under this key.

What this limitation means is that we will need to specify one ’empty’ virtual package which maintains a static PackageID and VersionId.  This package will NEVER change.  We will then use a Connection Group to connect this single package to our multiple virtualised Add In packages.  What this essentially means is that when we launch the local version of Excel.exe, it will launch our associated RunVirtual package (our ’empty’ package) which in turn will launch all of its connected packages.

In honesty though, and before we continue, you would really require App-V 5 SP3 as a minimum.  Why?  Because the schema for connection groups has changed and it now enables us to specify OPTIONAL packages (i.e, if a connected package is not published just ignore it and don’t throw an error!) and to automatically use the latest published version of a package.  For me, the ‘optional’ addition is the most important.  After all, our Add Ins aren’t necessarily for all users!  We may have one Add In policied to a specific group of users, and another Add In policied to another specific group of users.  And membership of these policied AD Groups may very well be mutually exclusive!  The optional attribute saves us a great headache in that sense and provides us with a flexibility that helps to reduce the management overhead.

Am I still babbling?  Ok.  An example….

Step 1.  Create an ‘Empty’ Package

We will link to this from the RunVirtual key.  This package isn’t entirely empty – make sure you add a dummy file to the package otherwise it will throw an error when you’re adding the package (presumably because there is no VFS to mount).

Also, ensure you allow Named Objects and COM objects to interact with the local system.  They’re not both required for this example (although I think Named Objects IS required), but we need to think ahead.  If we are packaging a COM Add In for Excel, this may well be required.

Finally follow this guide.  This guide lets us dynamically add the relevant RunVirtual key from our AppxManifest.xml.  In this example we are going to add RunVirtual in the HKCU key, since we are publishing the package to the User and NOT the machine.

Note to SCCM 2012 Virtual Environment users (and this part is all untested by myself):

As mentioned in the comments section below, when using SCCM 2012 Virtual Environments it is not a requirement that you specify a dummy package. Instead you can specify the AppConnectionGroupId and VersionId of the connection group. The problem with this approach is that the connection group gets dynamically generated on each client, which means that the AppConnectionGroupId and VersionId of the connection group is different for each client. I have suggested that to set the RunVirtual registry value dynamically you can use the approach documented here, so long as the dynamically generated connection group has a static name (I can’t verify this because I don’t have the environment to test with)!!

The alternative approach is to use a dummy package like I have suggested in this blog, whereby the PackageId and VersionId of the dummy package remains static.

Another Note:

As Tim Mangan has mentioned in the comments section below, delivery via an App-V server differs from SCCM 2012 Virtual Environments in that it requires at least one non-optional package.

Step 2.  Sequence Two Add In Packages

Each package will contain a different Excel Add In.  For this proof of concept I Googled for free XLA files and created a package for each one.  I simply lumped the XLA file into the following location, and that was that:

%AppData%\Microsoft\Excel\XLSTART

(You can alternatively copy it here for a per-machine install)
C:\Program Files\Microsoft Office\Office14\XLSTART

Again, ensure you allow Named Objects and COM objects to interact with the local system.  We need to ensure that all of our connected packages contain the same setting for COM and Named Objects, otherwise we may get errors when launching the connection group such as:

The Application Failed to Launch.  This may be due to a network failure
or
The connection group {xxx} version {xxx} could not be published because the virtual COM settings of the individual packages conflict.
Verify that the virtual COM settings are the same for all member packages and try again.

Step 3 – Create Connection Group for Local Testing

Create a connection group using this tool.  You should add the ’empty’ package as being mandatory (i.e, NOT optional).  The version shouldn’t matter since this package will NEVER change.

The other two Add In packages should be marked as Optional and Ignore Version.

Connection Group(Note that in your live environment you will probably just use your App-V publishing server to manage this connection group and its settings)

Step 4 – Local Testing

Ensure scripting is enabled on your machine

Add and Publish all your packages (since our RunVirtual key should be installing to HKCU, we publish our packages to the User and NOT the machine)

Add and Enable our Connection Group

Launch the local Excel version, and see your Add Ins appear!

As a further test, try un-publishing just one of the Add In packages and then launch Excel again.  You will notice 2 things:

1)  You don’t get an error, even though the package is not published!  This is due to the Optional attribute in our connection group.  So that works well.

2)  You will notice that the Add In still appears in the Excel Add In tab!  Doh.  Why has this happened?

Well.  Putting App-V aside for a second.  You will notice that when you lump your XLA file into %AppData%\Microsoft\Excel\XLSTART and then launch Excel, the date modified of the XLA file changes!  Close Excel and the Date Modified reverts back to its original Date Modified date.  So what I believe is happening here is that App-V detects a modification to the file, and writes it to a Copy on Write location.

Importantly, it doesn’t write it to the Copy on Write location of the Add In package but instead to the Copy and Write location of the Connection Group!!

If you copied your XLA file to the per-user location (as in this example), you will find a saved XLA file in this location:

(Copy on Write (COW) Roaming) %AppData%\Microsoft\AppV\Client\VFS\{ConnectionGroupPackageId}\AppData\Microsoft\Excel\XLSTART

If you copied your XLA file to the per-machine location, you will find a saved XLA file in this location:

(Copy on Write (COW) Local) %LocalAppData%\Microsoft\AppV\Client\VFS\{ConnectionGroupPackageId}\ProgramFilesX86\Microsoft Office\Office14\XLSTART

So in essence, when you un-publish your Add In packages you will need to add some logic to delete this file.

Configuring RunVirtual Registry from the AppxManifest.xml

To configure the RunVirtual key from an App-V package we needed to add a registry key/value to the local machine via an App-V script.  Since our environment is VDI we are using a new feature in App-V 5 SP3 which enables us to target an App-V application which is published to the user (and not to the machine).

I won’t discuss what RunVirtual is – you can read this if you need to know.

The key reason for this tutorial is because we are performing this logic in the AppxManifest.xml and NOT the UserConfig.xml.  I prefer to add my logic to AppxManifest.xml since it makes my package self-contained with no reliance on external (xml) files – see here.

Why is adding RunVirtual registry logic to the AppxManifest.xml different from adding it to the UserConfig.xml?

Well first a very brief bit of background – the registry key/value we need to add is:

HKCU\SOFTWARE\Microsoft\AppV\Client\RunVirtual\{LocalProcess.exe}

(Default)     REG_SZ     {PackageId}_{VersionId}

By creating a key under RunVirtual with the process name (Excel.exe in this case) we effectively saying “whenever we run Excel.exe I want it to run in the same virtual space as the App-V package with the specified PackageId_VersionId”.  As you’ve probably gathered, this specific package was an Addin for Microsoft Excel.

Adding the logic via a UserConfig.xml script is relatively trivial.  We can open the XML file in a text editor and add the following:

However adding a similar change via the AppxManifest.xml is slightly more complex.  Whenever we import a new AppxManifest.xml via the Advanced tab in Edit mode, we need to save the package afterwards for the change to take effect.  And what does this do?  It flips the VersionId of the package!  So we’re left with a situation whereby whenever we update the VersionId in the AppxManifest.xml it becomes redundant as soon as we save the updated package!

Introducing the Powershell approach….

Ignore the slightly different XML syntax for now – this is irrelevant in the context of this tutorial.

The main part to note is the Powershell one-liner, which I’ll explain below:

What we’re doing here is:

  • Getting all locally ADDED packages (Note that Get-AppvClientPackage -Name “Alkane_Package” will return nothing since the package is not published when the PublishPackage event runs!)
  • Looping through them where the Name attribute is the name of my target package (Alkane_Package)
  • We then use foreach because of this
  • And then we can dynamically get the PackageId and VersionId of the package to add it to the registry value

Scripting Examples for App-V 5

Below are a few scripting examples for App-V 5 configuration files (DeploymentConfig, UserConfig and AppxManifest files – the XML syntax varies slightly between these files but the same principle applies).  They’re purely for illustrative purposes and aim to show how we can string together the executable and their arguments to achieve different things.

Installing a shim

Running a Powershell script

Running a Powershell command

Running an EXE (For example, Powershell) without waiting for execution to complete

Running a VBScript (via the CScript engine)

Running a VBScript (via the WScript engine)

Installing an MSI

Installing a Driver

Adding a Registry String Value

Giving Modify Permission to a Directory

Creating a Symbolic Link (Running a windows command shell internal command – see here)

AppxManifest.xml in place of DeploymentConfig.xml and UserConfig.xml

There’s a new feature in the App-V 5.1 Sequencer which enables us to export and import a file called AppxManifest.xml:

App-V 5.1 Sequencer Import/Export ManifestI’ve been using this approach recently to add custom scripting logic to my packages (I used ACE to make my life slightly easier).  What it means is that I can import my App-V package straight into the App-V Management Server and it works straight away with my custom changes – that is, I do not have to manually specify any Deployment/User config files using the approach below:

Appv-5 Overwrite ConfigIt also means that when I’m testing my application in standalone mode I do not have to specify DynamicUserConfigurationPath or DynamicDeploymentConfigurationPath parameters to apply the configurations to my package on the Powershell command line.

 

Common App-V 5 Powershell Commands

The following posts contains common App-V 5 Powershell commands.  Assuming a package consisting of the following:

Package Name: AlkaneSolutions
AlkaneSolutions.appv
AlkaneSolutions_DeploymentConfig.xml
AlkaneSolutions_UserConfig.xml

and a connection group consisting of:

Package Name: AlkaneSolutions_ConnectionGroup
AlkaneSolutions_ConnectionGroup.xml

General Commands

Import the App-V 5 module (so we can use the cmdlets below)

Set execution policy to unrestricted (used during testing – should really be set by policy in a live environment)

Enable Package Scripting (can also be done via policy):

Package Commands

Add Package

Add Package with a Deployment Config

Publish Package (-Global will publish globally.  Omitting this will publish to the user)

Mount the package at 100%

Add, Publish and Mount Package on One Line

Add and publish App-V package along with a deployment xml

Add and publish App-V package along with a User Config xml (note how -Global is omitted from this command)

Unpublish package

Delete App-V Package from cache

Connection Group Commands

Add Connection Group

Enable Connection Group (-Global will publish globally. Omitting this will publish to the user)

Add and Enable a Connection Group on One Line

Disable Connection Group

Remove Connection Group

Disable and Remove Connection Group on One Line

 Verification Commands

Get App-V Client Configuration Settings

View all added (not neccessarily published) packages (useful for retrieving names, GUIDs, publishing status etc)

View all added (not neccessarily published) connection groups  (useful for retrieving namesm GUIDs, publishing status etc)

Using Shims with App-V 5

I was working on a package recently called Mead Co ScriptX 7.0.2, and was trying to make it work on Windows 7 x64.  By default when you clicked the shortcut on the Start Menu it did nothing.  However if I ran it in XPSP3 Compatibility Mode it launched.  So I decided to create a compatibility shim.  This post describes using shims with App-V 5:

Step 1 – Install the Windows Assessment Deployment Kit (ADK):

In this instance we’ll install the ADK on our vitual machine (VM).

Go to the Windows Assessment Deployment Kit (ADK) web page – http://www.microsoft.com/en-us/download/details.aspx?id=30652

Click ‘Download’.  The download should commence – run adksetup.exe.  You only need to select the Application Compatibility Toolkit (ACT) feature.

Step 2 – Install the application with the executable you want to shim onto the VM.

In our case, we’ll install Mead Co ScriptX 7.0.2.

Step 3 – Launch the Compatibility Administrator:

From the Start Menu run the Compatibilty Administrator.  If the .exe you want to shim is 32-bit, run the 32-bit version of the Compatibility Administrator.  If the .exe you want to shim is 64-bit, run the 64-bit version of the Compatibility Administrator.

Step 4 – Create the Shim:

Right-click where it says ‘New Database(1) [Untitled 1]’, Click ‘Create New’ and ‘Application Fix’.

Shim Compatibility

Fill in the Name and Vendor for your shim appropriately.  Then navigate to the exe you want to shim.  Click Next.

Shim New Fix

Select the checkbox to run the executable in compatibility mode, and select ‘Windows XP (Service Pack 3)’ from the dropdown list.  Click Next.

XPSP3 Shim

You will notice that because you selected the XPSP3 compatibility option, that 19 of the 367 fixes are automatically applied.  Click Next.

XPSP3 Shim Fixes

Finally we need to select the matchin file attributes.  Thi should be automatically populated from the executable you selected earlier, so just click Finish.

XPSP3 Shim Match File

Now click ‘Save’.  Give the database a name, and then save it.  For example, I called mine MeadCo_ScriptX_703_XPSP3.sdb.

Step 5 – Add the Shim to the App-V 5 package

Open your package in the App-V 5 sequencer.  Go to the ‘Package Files’ tab.  Right-click the ‘Scripts’ folder (it’s on the same level as the ‘Root’ folder) and add your shim file.  Save the package.

Shim Sequencer

Step 6 – Update _DeploymentConfig.xml with a script to install and remove the shim

Amend the package _DeploymentConfig.xml file to install (on AddPackage) and remove (on RemovePackage) the shim using the following commands:

Done!  Add/Publish your package, ensuring that you specify the DynamicDeploymentConfiguration parameter:

Add-AppVClientPackage –Path MeadCo_ScriptX_703.appv -DynamicDeploymentConfiguration MeadCo_ScriptX_703_DeploymentConfig.xml | Publish-AppVClientPackage

To check that your shim is installed you should be able to see it in Programs and Features (and your app should launch!)

A few points to remember:

Be careful if you re-save your sequenced package, since it will overwrite your customized DeploymentConfig.xml file!

Also when you test your package, remember to ensure that scripting is enabled using the following command:

Set-AppVClientConfiguration –EnablePackageScripts 1

 

Running the x64 Powershell from x86 SCCM ConfigMgr

This post describes running the x64 Powershell from x86 SCCM ConfigMgr.  I stumbled upon an issue when I’d created a powershell script to manage App-V 5 packages.  On an x64 platform, we tried to launch the powershell script with the x64 version of Powershell (i.e, the version in %windir%\system32) via an SCCM 2007 program like so:

%windir%\System32\WindowsPowerShell\v1.0\PowerShell.exe .\AV5Admin.ps1 {parameters}

Upon running this program we received the following Powershell error:

The current processor architecture is: x86. The module ‘C:\Program Files\Microsoft Application Virtualization\Client\AppvClient\AppvClient.psd1’ requires the following architecture: Amd64.

This immediately made me think that SCCM was launching the x86 Powershell console as opposed to the x64 one.  But strangely enough, the execmgr log file still said it was running the x64 Powershell at %windir%\System32\WindowsPowerShell\v1.0\PowerShell.exe.  This log file entry was incorrect, and was just spitting out the exact command line in the SCCM program as opposed to what was actually running.

It turns out that the program execution environment in the SCCM 2007 ConfigMgr is 32-bit, and hence the x86 version of Powershell was being launched.  You can find out more information on the redirection process here.  To circumvent this issue, the command line needed to be tweaked to use the SysNative alias like so:

%windir%\Sysnative\windowsPowershell\V1.0\PowerShell.exe .\AV5Admin.ps1 {parameters}

WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access, and should instead use the native system folder. This alias was introduced in Windows Vista and can not be used with x64 applications.  Note that you can ONLY use this alias from 32-bit applications, and it would not be recongnised if, for example, you used it from a 64-bit instance of cmd.exe.

As an example, if you launch cmd.exe on an x86 platform, and run the following command:

%windir%\sysnative\notepad.exe

You will get the error:

The system cannot find the path specified.

Because the Sysnative alias is not supported on x86 platforms.  Also, if you launch the same command on an x64 platform, using the native x64 cmd.exe, you will get the same error because the Sysnative alias is not supported on x64 applications.

However, if you launch an x86 version of cmd.exe on an x64 platform and run the same command, it will launch the native (x64) version of notepad.exe.

Out of interest if you just run the command:

notepad.exe

from the x86 version of cmd.exe on an x64 platform, it will launch the x86  version of notepad.exe.

 

Publishing App-V 5 packages with SCCM 2007

Introduction

At the time of writing this article App-V 5 is not natively supported by SCCM 2007.  Publishing App-V 5 packages with SCCM 2007 requires either deploying the MSI which gets created by the sequencer, or create a custom Powershell script to perform the publishing tasks manually.

The limitation with deploying the MSI is that you cannot handle connection groups, and so you’ll end up with a hybrid approach of deploying MSIs for packages and powershell scripts for connection groups.  On top of this, I don’t believe there is a way (using the MSI) to apply DeploymentConfig and UserConfig files at add/publish time respectively.

To circumvent these issues I’ve created an App-V 5 administration script which can be used with SCCM 2007 programs.

Command Line Parameters are:

Parameter: -av5Verb                        Possible Value(s): “add” “remove”

Parameter: -av5Object                     Possible Value(s): “package” “connectionGroup”

Parameter: -av5PackageName        Possible Value(s): {Package Name – for example “Adobe-Reader-X”}

Parameter: -deploymentConfig         Possible Value(s): “true” “false”

Parameter: -userConfig                     Possible Value(s): “true” “false”

Usage

1.  Put the Powershell script inside the installation source folder, with any associated .appv/.xml files.  In our example we’ll call the script AV5Admin.ps1:

App-v 5 and SCCM 2007

2.  Command lines for the SCCM program are as follows (be careful of the quotes in this blog post!!  See ‘Things to Note’ below for more info!):

Add package (Publishes globally by default)

Add package and apply deployment config xml

Add package and apply user config xml

Remove package

Add connection group (connecting globally published packages)

Add connection group (connecting user published packages)

Remove connection group

Things to Note

  • When creating your connection group XML file, the DisplayName attribute of the AppConnectionGroup tag should be set to the av5PackageName value. In the case of the example above, it should be set to “Adobe-Reader-X”.
  • Be careful of dodgy quotes when copying and pasting. For example:
  • By default, no XML (deployment or user) files are applied. If you specify a “true” value for -deploymentConfig the xx_deploymentConfig.xml file will be applied and the package will be published globally. If you specify a “true” value for -userConfig the xx_UserConfig.xml file will be applied and the package will NOT be published globally.
  • If any XML files are applied, scripting is enabled on the App-V client.
  • *UPDATE – Apparently Configuration Manager 2012 uses -ExecutionPolicy Bypass, as shown here: http://blogs.technet.com/b/virtualvibes/archive/2013/10/02/configuration-manager-2012-sp1-and-app-v-5-0-integration-more-than-meets-the-eye.aspx We have now used this in our command line, whilst also hiding the Powerhell console using -WindowStyle Hidden.
  • Log files get written to C:\Windows\Security\Logs. For example, if you try to publish a connection group and some of the connected packages are not published on the machine, the appropriate error message will be written to a log file called {packagename}_add.log.
  • Checks to see if the AppvClient module exists and is imported.
  • Returns a code of 0 for success, and 1 for an error.
  • **Important**  If running a 32-bit SCCM agent on a 64-bit platform see this post, which explains why we MUST use the Sysnative alias when pointing to the powershell.exe.

The Script