TheGlobalizer: Automatically making user targeted AppV work as Global

Tim SpeakingA treat for you today. You see, today is my day to find out if I am re-awarded as a Microsoft MVP. You get a little nervous waiting for Redmond to wake up and send the email each time. So with a surprise today I find that I am no longer an App-V MVP. Now I’m a “Windows IT Pro” MVP, a category combining move. Whatever; it is my third MVP category over the years (RDS was the other). So in honor of my new recognition, today I have a new technique that IT Pros can use with App-V.

Enjoy!

Problem Description:

A few of the new extensions added to App-V 5 in SP2 require global publishing to work.  This includes some Shell Extensions, Browser Helper Objects, and Active X controls.  Unfortunately, whether using the App-V server, Config Manager, or any other centralized distribution system we typically want to use named user based targeting rather than named machine.   Wouldn’t it be nice if you could target the user but get App-V to use the -global option so that you get all of the features?  While you wouldn’t want that on a shared server (RDS) situation, it would be great for desktop/VDI deployments.

Solution:

I crafted a solution using the Windows Scheduled Tasks.  You see, scheduled tasks can run based on a lot of things other than timers.  For example, the App-V Publishing and Reporting components use scheduled tasks that trigger on both timers and logon events.

You can configure a scheduled task using an XML file.  If you google even a little you can find articles on how to create a scheduled task by triggering on an event that you find in the event viewer.  But the harder part is getting the data elements out.  No worry, I got you covered below.

The solution to globalizing is to trigger on an event that only fires when a user package publishing occurs.  It turns out that the AppV Client Operational log has such an event, 1003, and the data buried in the event includes both the PackageId and VersionId elements of the package.  So this scheduled task pulls those elements out, and then runs PowerShell to republish the same package with the -Global option.

It is OK for a package to be published both to the user and with -global, and the effect is that the user gets the full extensions.  [Note: There are some apps, like browser plug-ins that add toolbars and menus, where you want to clean out the internal registry entries inside the package to keep from getting double items in the browser US (but that problem already exists if you install global and publish to the user or visa versa) But you’d already be aware of that if you took our training class!].  When a management system removes the package, the double publishing doesn’t cause a problem either – removal works even if still published.  The global publishing does have an event also, but it is 1004 so that doesn’t trigger an endless recursion since we don’t trigger on that.

How to Use:

1. Copy the XML below and paste it into a file.  It’s nice to save the file with an xml extension, but it’s ok to use something like txt.

 <?xml version=”1.0″ encoding=”UTF-16″?><Task version=”1.2″ xmlns=”https://schemas.microsoft.com/windows/2004/02/mit/task”><RegistrationInfo><Date>2015-06-30T14:43:47.526978</Date><Author>Tim Mangan</Author><Description>Triggers when a per-user package publishing event occurs. It triggers a global publishing of the package on the machine, allowing extensions that require global publishing to work.</Description></RegistrationInfo><Triggers><EventTrigger>

<Enabled>true</Enabled>

<Subscription>&lt;QueryList&gt;&lt;Query Id=”0″ Path=”Microsoft-AppV-Client/Operational”&gt;&lt;Select Path=”Microsoft-AppV-Client/Operational”&gt;*[System[Provider[@Name=’Microsoft-AppV-Client’] and EventID=1003]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>

<ValueQueries>

<Value name=”ThePackageId”>Event/EventData/Data[@Name=’Package’]</Value>

<Value name=”TheVersionId”>Event/EventData/Data[@Name=’Version’]</Value>

</ValueQueries>

</EventTrigger>

</Triggers>

<Principals>

<Principal id=”Author”>

<UserId>S-1-5-18</UserId>

<RunLevel>LeastPrivilege</RunLevel>

</Principal>

</Principals>

<Settings>

<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>

<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>

<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>

<AllowHardTerminate>true</AllowHardTerminate>

<StartWhenAvailable>false</StartWhenAvailable>

<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>

<IdleSettings>

<StopOnIdleEnd>true</StopOnIdleEnd>

<RestartOnIdle>false</RestartOnIdle>

</IdleSettings>

<AllowStartOnDemand>false</AllowStartOnDemand>

<Enabled>true</Enabled>

<Hidden>false</Hidden>

<RunOnlyIfIdle>false</RunOnlyIfIdle>

<WakeToRun>false</WakeToRun>

<ExecutionTimeLimit>P3D</ExecutionTimeLimit>

<Priority>7</Priority>

</Settings>

<Actions Context=”Author”>

<Exec>

<Command>powershell.exe</Command>

<Arguments>Publish-AppVClientPackage -PackageId $(ThePackageId) -VersionId $(TheVersionId) -Global</Arguments>

</Exec>

</Actions>

</Task>

2. Run the following command as an admin to install the task:

schtasks /CREATE /RU System /TN “Microsoft\AppV\Publishing\TheGlobalizer” /XML “C:\path\to\the\fileyousaved.xml

Obviously you need admin rights to add the scheduled task this way. But you can deploy this as a ConfigManager script, or just add as an AddPackage script to the DeploymentConfig.xml file of an App-V package (like the App-V Client Console package).

By Tim Mangan

Tim is a Microsoft MVP, and a Citrix CTP Fellow. He is an expert in App-V and MSIX.