Kae Travis

Scripting Examples for App-V 5 (Updated)

Posted on by in App-V 5.x

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.

**UPDATED WORKAROUND FOR MSIEXEC – Scroll down…**

**ANOTHER UPDATED WORKAROUND FOR MSIEXEC – Scroll (further) down…**

Installing a shim

<MachineScripts>              
<AddPackage>        
<Path>sdbinst.exe</Path>        
<Arguments>/q "[{AppVPackageRoot}]\..\Scripts\ExampleFile.sdb"</Arguments>      
<Wait RollbackOnError="true" Timeout="30"/>      
</AddPackage>   
</MachineScripts>

Running a Powershell script

<MachineScripts>
<AddPackage>
<Path>powershell.exe</Path>
<Arguments>-ExecutionPolicy ByPass -WindowStyle Hidden -File "[{AppVPackageRoot}]\..\Scripts\ExampleFile.ps1"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Running a Powershell command (machine)

<MachineScripts>
<AddPackage>
<Path>powershell.exe</Path>
<Arguments>-ExecutionPolicy ByPass -WindowStyle Hidden -Command  "&amp; { Get-EventLog -LogName security }"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Running a Powershell command (user DPI setting via Powershell registry)

<UserScripts>      
<PublishPackage>
<Path>powershell.exe</Path>
<Arguments>-ExecutionPolicy ByPass -WindowStyle Hidden -Command  "&amp; { If (-Not(Test-Path 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers')) { New-Item -Path 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers' -Force; } New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers' -Name '[{ProgramFilesX86}]\Alkane\Alkane.exe' -PropertyType String -Value '~ DPIUNAWARE' -Force }"</Arguments>
<Wait RollbackOnError="false" Timeout="30"/>
</PublishPackage>   
</UserScripts>

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

<MachineScripts>
<AddPackage>
<Path>cmd.exe</Path>
<Arguments>/c START "" "powershell.exe" -ExecutionPolicy ByPass -WindowStyle Hidden -File "[{AppVPackageRoot}]\..\Scripts\runProcess.ps1"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Running a VBScript (via the CScript engine)

<MachineScripts>
<AddPackage>
<Path>cscript.exe</Path>
<Arguments>"[{AppVPackageRoot}]\..\Scripts\ExampleFile.vbs"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Running a VBScript (via the WScript engine)

<MachineScripts>
<AddPackage>
<Path>wscript.exe</Path>
<Arguments>"[{AppVPackageRoot}]\..\Scripts\ExampleFile.vbs"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Installing an MSI (if this doesn’t work see workarounds below!)

<MachineScripts>
<AddPackage>
<Path>msiexec.exe</Path>
<Arguments>/i "[{AppVPackageRoot}]\..\Scripts\ExampleFile.msi" /qb</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Installing a Driver

<MachineScripts>
<AddPackage>
<Path>pnputil.exe</Path>
<Arguments>/i /a "[{AppVPackageRoot}]\..\Scripts\ExampleFile.inf"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Adding a Registry String Value

<MachineScripts>
<AddPackage>
<Path>reg.exe</Path>
<Arguments>ADD HKLM\SOFTWARE\AlkaneTestKey /f /v AlkaneTestValue /t REG_SZ /d AlkaneTestData</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

Giving Modify Permission to a Directory

<MachineScripts>
<AddPackage>
<Path>icacls.exe</Path>
<Arguments>"C:\AlkaneTest" /grant Users:(OI)(CI)(M) /C /Q</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

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

<MachineScripts>
<AddPackage>
<Path>cmd.exe</Path>
<Arguments>/C MKlink /D C:\AlkaneSolutions "C:\Program Files\AlkaneSolutions"</Arguments>
<Wait RollbackOnError="true" Timeout="30"/>
</AddPackage>
</MachineScripts>

 

**UPDATED WORKAROUND FOR MSIEXEC**

I referred a colleague of mine to this blog today. He was trying to install an MSI from within the Scripts folder of his App-V 5 package. But the example above didn’t work for him!!? Event Viewer stated that MSIEXEC could not locate the MSI!? I ran Process Monitor to confirm this. And then I ran a quick local test.

I created two folders in the root of the C drive – C:\Scripts and C:\Root. As you can probably tell, I was recreating the folder structure of an App-V 5 package to try and recreate the issue.

Essentially when we construct a path in an App-V 5 scripting node such as:

“[{AppVPackageRoot}]\..\Scripts\ExampleFile.msi”

When the package is added to a machine it will resolve to something like:

“C:\ProgramData\App-V\{PackageGUID}\{VersionGUID}\Root\..\Scripts\ExampleFile.msi”

Note how the path starts in the “Root” folder (“[{AppVPackageRoot}]”), goes up a level (“\..\”) and then goes into the Scripts folder.

To replicate this behaviour I placed a sample MSI in C:\Scripts called ExampleFile.msi and then opened up a command prompt and ran:

notepad.exe "c:\Root\..\Scripts\ExampleFile.msi"

The MSI opened in Notepad with no issues (full of gobbledygook as expected). I then ran:

msiexec.exe "c:\Root\..\Scripts\ExampleFile.msi"

Ooops! The exact same path could not be resolved by the MSIEXEC engine! So I assume MSIEXEC cannot handle the double-dot notation to go up one level in the directory structure? As a workaround we had to run the MSI with a slightly different approach:

<MachineScripts>
<AddPackage>
<Path>cmd.exe</Path>
<Arguments>/c cd "[{AppVPackageRoot}]\..\Scripts" &amp; msiexec.exe /i "Example.msi" /qn</Arguments>
<Wait RollbackOnError="false" Timeout="30"/>
</AddPackage>
<RemovePackage>
<Path>cmd.exe</Path>
<Arguments>/c cd "[{AppVPackageRoot}]\..\Scripts" &amp; msiexec.exe /x "Example.msi" /qn</Arguments>
<Wait RollbackOnError="false" Timeout="30"/>
</RemovePackage>
</MachineScripts>

As ever, make a note of the timeout period (in seconds) if your MSI is likely to take longer to (un)install! Also it might be worth setting RollbackOnError to “false” if your MSI is likely to request a (soft) reboot and return a 3010 (non-zero) error code!

ANOTHER UPDATED WORKAROUND FOR MSIEXEC

A few months later, a new client, a new environment and the the workaround above has seemingly stopped working! For some reason when I checked the process monitor logs it wasn’t parsing the arguments correctly (it was passing the scripts folder path to MSIEXEC?). Anyway. I’ve devised another solution using PowerShell that appears to work well, so here it is:

<AddPackage>
<Path>powershell.exe</Path>
<Arguments>-executionpolicy bypass -command "Start-Process msiexec.exe -ArgumentList @('/i',('\"{0}\Alkane.msi\"' -f (Get-Location).path),'/qn') -Wait"</Arguments>
<Wait RollbackOnError="false" Timeout="30"/>
</AddPackage>
<RemovePackage>
<Path>powershell.exe</Path>
<Arguments>-executionpolicy bypass -command "Start-Process msiexec.exe -ArgumentList @('/x',('\"{0}\Alkane.msi\"' -f (Get-Location).path),'/qn') -Wait"</Arguments>
<Wait RollbackOnError="false" Timeout="30"/>
</RemovePackage>

 

Scripting Examples for App-V 5 (Updated)
Scripting Examples for App-V 5 (Updated)

Leave a Reply