App-V 5 Scripting: Change

It is almost easier to pretend you know nothing about App-V 4.x scripting when looking at scripting in 5.0. That is often my first response to many rumblings about difficulty getting scripting set up in 5.0. These rumblings come mostly from users of App-V 4.x. Change is hard, I know, but we have a better set of options and frankly, in my opinion, it’s much better this way in the long run. It is just a paradigm shift that does require somewhat of a translation process for bringing older scripts from 4.x over to 5.0.

No More SCRIPTBODY (Embed in the Package, not the XML)

First of all, there are no more <SCRIPTBODY> elements. Instead of embedding the script inside the XML, the intent is to have the script embedded inside the package in the .\Scripts folder. This is the ideal place for it as it will be one of the default search paths when calling a script. If you have already sequenced a package (or converted a package) and want to add a SCRIPT element into the dynamic configuration, you will need to specify the path to the script interpreter and script file. So in essence you have as the command and argument the script interpreter as the command and the script (and options) as the argument.

Not Enabled by Default

Before you even begin to start testing scripts, you will have to make sure the client is set up to allow for package scripts. The quickest way to do this is through PowerShell using the following

Set-AppvClientConfiguration -EnablePackageScripts $true

You can also do it by GPO or manually in the registry. Always verify this before testing scripts.

Security Context

Some scripts will run in the SYSTEM context or the currently logged on user depending on the scripts package event. Later I’ll discuss workflows that will also help you determine the context (Machine or User) for running the script (which is another new concept in 5.0.) The following table outlines how the security context relates to the package event.

Event

Runs As

When the package is added

Local System

When the package is published globally

Local System

When the package is published to a user

Current User

After a Virtual Environment (Package) is built

Current User

After a virtual application is started

Current User

After a process exits

Current User

When the VE shuts down

Current User

Right before a package is unpublished to a user

Current User

Right before a package is unpublished globally

Local System

Right before a package is removed

Local System

 

Package Events?*

You need to forget the concept of PRE and POST events. Scripts can be called based on specific events in the lifecycle of the package. You will need to know at what point you want the script to be triggered. If your script needs to run in a specific context, this will help determine your event. If you decide your script needs to be triggered during application initialization (at the start of the virtual environment, the start of the process, when a process exits) you will need to also specify the specific application, rollback options, and whether you want to run it inside or outside the virtual environment.

*I so want to call this “event trigger” but it would be confusing.

To explain how the PRE and POST Options of before evolved into Package Event Elements – but not directly – look at the table below:

Package Event

4.6

5.0

When the package is added

N/A

AddPackage

When the package is published globally

N/A

PublishPackage

When the package is published to a user

N/A

PublishPackage

Before a Package is Streamed

PRE STREAM

N/A

After a Package is Streamed

POST STREAM

N/A

After a Virtual Environment (Package) is built

N/A

StartVirtualEnvironment

When a virtual application is started

PRE LAUNCH

N/A – but same effect can be achieved with StartVirtualEnvironment

After a virtual application is started

POST LAUNCH

StartProcess WAIT=TRUE

After a process exits

POST SHUTDOWN

ExitProcess

When the VE shuts down

N/A

TerminateVirtualEnvironment

Right before a package is unpublished to a user

N/A

UnPublishPackage

Right before a package is unpublished globally

N/A

UnPublishPackage

Right before a package is removed

N/A

RemovePackage

The key is to know what package/app event you want to trigger execution: (AddPackage, PublishPackage, StartVirtualEnvironment, StartProcess, ExitProcess, TerminateVirtualEnvironment, UnPublishPackage, RemovePackage)

Wait Options

In addition to the command <Path> and <Arguments> you have your “Wait” options (Wait, RollbackOnError, Timeout.) If you have a <Wait> element with nothing else, it will default to RollbackOnFailure=”True” and Timeout=0.

Element Flow

When we put it all together, you will see the element flow follows this basic process:

    [MACHINE OR USER CONTEXT?]

      [EVENT TO TRIGGER EXECUTION?] [IF VE or Process Event – Also the option of running inside the VE]

        [MY Command Path]

        [MY Command’s arguments]

        [My Wait Options]

          [Optional AppID EXE w/ tokenized path if this is a Process event]

 

Where an example of a machine targeted script looks like this:

 

    <MachineScripts>

      <PublishPackage>

        <Path>PowerShell.exe</Path>

        <Arguments>-f file.ps1 </Arguments>

        <Wait RollbackOnError="true" Timeout="30"/>

      </PublishPackage>

 

As another example, if a script was targeted for a user, set for PRE LAUNCH/ABORTRESULT=1/PROTECTED=TRUE in 4.x, and was only needed for one app, you could call it this way in 5.0 

 

    <UserScripts>

      <StartProcess RunInVirtualEnvironment="true">

        <Path>cscript</Path>

        <Arguments>myscript.vbs</Arguments>

        <Wait RollbackOnError="true"/>

        <ApplicationId>[{AppVPackageRoot}]\Directory\Subdirectory\App.EXE</ApplicationId>

      </StartProcess>

 

Deployment Configuration and Dynamic User Configuration

Many of the problems with testing scripts come with proper placement in deployment and dynamic configuration files and how they are targeting. Scripts that need to be called during package add and global publishing events should be part of the DeploymentConfig.XML file. These scripts will also run in the context of the local system account so scripts that map drives, for example, should not go here. Those need to be called as a <UserScript> element. I use the following visual workflow to help me determine targeting and publishing.

In the case of global publishing, the deployment configuration also has a UserConfiguration element in addition to MachineConfiguration which means that scripts appearing during these events will apply to all users when the package is published globally. This would be the appropriate place to have scripts which map network drives.