How to Automate App-V 5 to MSIX Conversion

Written by Horatiu Vladasel · November 3rd, 2022

#APPV #MSIX

IT professionals are now considering switching from App-V to MSIX technology more than ever, since main-stream support for App-V ended a few years back and extended support is due to end in a few years (April 14, 2026). However, as it happens with change, this shift comes with many challenges when converting App-V packages to MSIX.

The good news is that most tools now offer either manual or automatic conversion options for App-V packages.

While manually converting from App-V 5 to MSIX may seem like a fairly simple process, it is almost impossible to convert hundreds or even thousands of packages manually.

In this article, I am going to show you how to automate your App-V 5 to MSIX conversion. Let's see how you can avoid all the hassle.

How to use MSIX Packaging Tool to automatically convert an App-V 5 to MSIX?

With the Command Line Input (CLI) support in the Microsoft MSIX Packaging Tool, you can automate the conversion from App-V 5 to MSIX.

Before we begin converting your App-V 5 packages with the MSIX Packaging tool, we need to make sure that all of the prerequisites are met.

What are the prerequisites to automating your App-V 5 to MSIX Conversion?

To automate the conversion of your App-V 5 package to MSIX, you need the following:

  • The MSIX Packaging Tool installed on your machine;
  • SignTool.exe;
  • The digital signing certificate that you will use to sign the converted MSIX packages.

Once you’ve met the above requirements, you may begin automating your App-V 5 to MSIX conversion. Let’s see how.

Choosing your conversion template file for your conversion

Open your Command prompt window as an Administrator amd enter the following command

MsixPackagingTool.exe create-package –template <path to the conversion template file>.

This command will lead you to the conversion template file. The conversion template file is an XML file containing all the package information and settings you need for the conversion.

To get a conversion template file that suits your needs, you have two options:

1. You can use a conversion template file generated from one of your packages. They are saved next to the MSIX package by default (unless the save location was changed).

Check this image:

Conversion Template File

NoteYou will notice that after you choose a conversion template file, you will still need to perform minor changes based on what you want the output of each conversion to be.

2. The second option is to use the sample conversion template file available on the Microsoft website and update it as you need.

Regardless of the option you choose, you may find here the complete list of parameters that you can use in the conversion template file.

Now we’ll go through an example of a template file that we are going to use going forward to convert our App-V 5 packages to MSIX.

<MsixPackagingToolTemplate    xmlns="http://schemas.microsoft.com/appx/msixpackagingtool/template/2018"    xmlns:mptv2="http://schemas.microsoft.com/msix/msixpackagingtool/template/1904">
   <Installer Path="[Installer]"/>
   <SaveLocation PackagePath="[SaveLocation]" />
   <PackageInformation
       PackageName="[PackageName]"
       PackageDisplayName="[PackageDisplayName]"
       PublisherName="[PublisherName]"
       PublisherDisplayName="[PublisherDisplayName]"
       Version="1.0.0.0">
   </PackageInformation>
</MsixPackagingToolTemplate>

You can use this template file as it is or customize it.

Starting the automation of App-V 5 to MSIX

The automation of your App-V 5 to MSIX conversion was first addressed by Microsoft a while back in the MSIX – Batch Conversion of Your App-V 5 Packages article, where they shared a PowerShell script to perform the bulk conversion.

However, you will notice that you need to modify the original PowerShell script to copy the conversion log file for each package you want to convert.

Here’s what it should look like:

$MyAppvPackagesContentStore = "C:\Users\HoratiuVladasel\Desktop\MyAppvPackagesContentStore"
$MyMsixPackagesContentStore = "C:\Users\HoratiuVladasel\Desktop\MyMSIXPackagesContentStore"   #if blank, it takes the path as currentdirectory
$PublisherName = "CN=WLD Software"
$PublisherDisplayName = "MyCompany"
$CertificateFilePath = "C:\Users\HoratiuVladasel\Desktop\WLD Software.pfx"
$CertificatePassword = "********"
$TimestampingURL = ""
$SignToolFilePath = ""   #if blank, it takes the path as currentdirectory
$MsixPackagingToolTemplateFilePath =  ""   #if blank, it takes the path as currentdirectory
#----------------------- Do NOT modify bellow this line ---------------------
$executingScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
If (!$MsixPackagingToolTemplateFilePath)
{
    $MsixPackagingToolTemplateFilePath = "$executingScriptDirectory\MsixPackagingToolTemplate.xml"
}
If (!$SignToolFilePath) 
{
    $SignToolFilePath = "$executingScriptDirectory\signtool.exe"
}
function Run_MainProcessing($AppVFilePath)
{
    $AppVPackageFilePath = $AppVFilePath.FullName
    $AppVPackageFileName = $AppVFilePath.BaseName
    # MSIX package name cannot contain spaces, dashes or dots, so replacing these
    $MsixPackageName = $AppVPackageFileName -replace '\s+', ''  -replace '_', '-'
    #Creating the folder where the MSIX package is saved
    If (!$MyMsixPackagesContentStore) 
    {
        $SaveLocationPath = "$(Split-Path -Path $AppVPackageFilePath)\MSIX"    
    }
    else
    {
        $SaveLocationPath = (Split-Path -Path $AppVPackageFilePath).Replace("$MyAppvPackagesContentStore","$MyMsixPackagesContentStore")
    }
    New-Item -Force -Type Directory $SaveLocationPath
    # Generate the template XML file
    [String]$MsixPackagingToolTemplateXmlContent = Get-Content -path "$MsixPackagingToolTemplateFilePath" | Out-String
    $MsixPackagingToolTemplateXmlContent = $MsixPackagingToolTemplateXmlContent.Replace("[Installer]", "$AppVPackageFilePath")
    $MsixPackagingToolTemplateXmlContent = $MsixPackagingToolTemplateXmlContent.Replace("[SaveLocation]", "$SaveLocationPath")
    $MsixPackagingToolTemplateXmlContent = $MsixPackagingToolTemplateXmlContent.Replace("[PackageName]", "$MsixPackageName")
    $MsixPackagingToolTemplateXmlContent = $MsixPackagingToolTemplateXmlContent.Replace("[PackageDisplayName]", "$AppVPackageFileName")
    $MsixPackagingToolTemplateXmlContent = $MsixPackagingToolTemplateXmlContent.Replace("[PublisherName]", "$PublisherName")
    $MsixPackagingToolTemplateXmlContent = $MsixPackagingToolTemplateXmlContent.Replace("[PublisherDisplayName]", "$PublisherDisplayName")
    $MsixPackagingToolTemplateXmlContent | out-File "$("$($SaveLocationPath)\MsixPackagingToolTemplate.xml")" -Encoding Ascii -Force
    # Starting the conversion  NOTE: Packaging tool does not accept putting template filepath in quotes -- so no spaces allowed!!!
    $MsixPackagingToolCommand = MsixPackagingTool.exe create-package --template "$($SaveLocationPath)\MsixPackagingToolTemplate.xml"
    $ConvertedToMsix = $false
    ForEach ($line in $MsixPackagingToolCommand)
    {
        #Get the MSIX Package path
        If ($line -like "Package created under: *")
        {
            $ConvertedToMsix = $true
            $MsixFilePath = $line.replace("Package created under: ","").replace("%UserProfile%","$env:USERPROFILE")           
        }
        #Get the MSIX Conversion Log File Path   
        If ($line -like "Log file is located under: *")
        {
            $LogFilePath = $line.replace("Log file is located under: ","")
        }
    }
    #$MsixFileName = $MsixFilePath.replace("$SaveLocationPath\","").replace(".msix","")
    If ($ConvertedToMsix -eq $true)
    {
        $DefaultPackageName = $MsixFilePath.replace("$SaveLocationPath\","").replace(".msix","")
    }
    else
    {
        $DefaultPackageName = $AppVPackageFileName             
    }
    #Copy the MSIX Conversion Log File Path next to the MSIX Package
    $LogFilePath = $LogFilePath.replace("%UserProfile%","$env:USERPROFILE")
    Copy-Item "$LogFilePath" -Destination "$SaveLocationPath\$DefaultPackageName.log"
    #Rename the MsixPackagingToolTemplate.xml
    Move-Item -Path "$($SaveLocationPath)\MsixPackagingToolTemplate.xml" -Destination "$($SaveLocationPath)\$DefaultPackageName.xml" -Force
    #Sign the MSIX Package
    $cmd = "`"" + $SignToolFilePath + "`""
    $args = "sign /a /v  /f " + "`"" + $CertificateFilePath + "`"" + " /p `"" + $CertificatePassword + "`" /fd SHA256 " + "`"" + $MsixFilePath + "`""
    Start-Process $cmd -Wait -ArgumentList  $args
}
# Get all the App-V packages from the MyAppsContentStore and convert them.
Get-ChildItem $MyAppvPackagesContentStore -Recurse | Where-Object { $_.extension -eq ".appv" } | ForEach-Object{
    $err = Run_MainProcessing $_ *>&1
}

As you can see, the script above goes through the list of App-V 5 packages (located under $MyAppvPackagesContentStore) and converts them to MSIX.

Apart from $MyAppvPackagesContentStore and $MyAMSIXPackagesContentStore (optional), you also need to specify:

  • $PublisherName
  • $PublisherDisplayName
  • $CertificateFilePath
  • $CertificatePassword

After completing all of the previous steps, your App-V 5 packages should be successfully converted to MSIX.

How to use Advanced Installer to automate the conversion of App-V 5 to MSIX?

When it comes to Advanced Installer, performing the App-V 5 to MSIX conversion is quite straightforward since it has its own built-in CLI support.

What do you need to convert App-V 5 to MSIX with Advanced Installer?

  • A machine with Advanced Installer installed on it
  • The digital signing certificate you will use to sign the converted MSIX packages.

Unlike MSIX Packaging Tool, we don’t need any conversion template file since Advanced Installer has its own built-in CLI support to do the App-V 5 to MSIX conversion.

Starting the automation of your App-V 5 packages in Advanced Installer

To convert an App-V 5 package to MSIX, you can use the following set of commands:

AdvancedInstaller.com /newproject <path to AI project file> -type architect
AdvancedInstaller.com /edit <path to AI project file> /ImportAppv5x <path to App-Vfile> -res_folder <path to resource folder>
AdvancedInstaller.com /edit <path to AI project file> /SetSig
AdvancedInstaller.com /edit <path to AI project file> /SetDigitalCertificateFile -file <path to pfx file> -password <password>
AdvancedInstaller.com /edit <path to AI project file> /AddBuild -name MSIX -type MSIX
AdvancedInstaller.com /edit <path to AI project file> /SetUwpAppxBuildOutput -name MSIX -output_folder <output folder> -output_name <output MSIX file name>
AdvancedInstaller.com /build <path to AI project file> -buildslist MSIX

As you can see below, the process is pretty simple:

  1. It starts by importing the App-V 5 package to a newly created Advanced Installer project
  2. It enables and sets the digital signature details
  3. It adds the MSIX build and sets the output folder and the output MSIX file name
  4. It builds the MSIX package.

And here’s what the PowerShell script should look like:

$AdvancedInstallerComFilePath = "C:\Program Files (x86)\Caphyon\Advanced Installer 19.9 - 2940\bin\x86\AdvancedInstaller.com"
$MyAppvPackagesContentStore = "C:\Users\HoratiuVladasel\Desktop\MyAppvPackagesContentStore"
$MyMsixPackagesContentStore = "C:\Users\HoratiuVladasel\Desktop\MyMSIXPackagesContentStore"
$CertificateFilePath = "C:\Users\HoratiuVladasel\Desktop\WLD Software.pfx"
$CertificatePassword = "zaq12wsx"
#----------------------- Modifications should only be needed above this line ---------------------
function Run_MainProcessing($AppVFilePath)
{
    $AppVPackageFilePath = $AppVFilePath.FullName
    $AppVPackageFileName = $AppVFilePath.BaseName
    # MSIX package name cannot contain spaces, dashes or dots, so replacing these
    #$MsixPackageName = $AppVPackageFileName -replace '\s+', ''  -replace '_', '-'
    #Creating the folder where the MSIX package is saved
    If (!$MyMsixPackagesContentStore) 
    {
        $SaveLocationPath = "$(Split-Path -Path $AppVPackageFilePath)\MSIX"    
    }
    else
    {
        $SaveLocationPath = (Split-Path -Path $AppVPackageFilePath).Replace("$MyAppvPackagesContentStore","$MyMsixPackagesContentStore")
    }
    New-Item -Force -Type Directory $SaveLocationPath
    New-Item -Force -Type Directory $SaveLocationPath\AI_Resources
    New-Item -Force -Type Directory $SaveLocationPath\AI_Resources\Res_Folder
    New-Item -Force -Type Directory $SaveLocationPath\Logs    
    $CreateAIProjectArgs = "/newproject " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " -type architect"
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList  $CreateAIProjectArgs
    $ImportAppV5xPackageArgs = "/edit " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " /ImportAppv5x " + "`"" + $AppVPackageFilePath + "`"" + " -res_folder " + "`"" + "$SaveLocationPath\AI_Resources\Res_Folder" + "`""
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList $ImportAppV5xPackageArgs -RedirectStandardOutput "$SaveLocationPath\Logs\$AppVPackageFileName_ImportAppV5xPackage.log"
    $EnableDigitalSignatureArgs = "/edit " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " /SetSig"
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList  $EnableDigitalSignatureArgs
    $SetDigitalSignatureArgs = "/edit " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " /SetDigitalCertificateFile -file " + "`"" + $CertificateFilePath + "`"" + " -password $CertificatePassword"
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList  $SetDigitalSignatureArgs
    $AddMSIXBuildArgs = "/edit " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " /AddBuild -name MSIX -type MSIX"
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList  $AddMSIXBuildArgs
    $SetMSIXBuildArgs = "/edit " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " /SetUwpAppxBuildOutput -name MSIX -output_folder " + "`"" + $SaveLocationPath + "`"" + " -output_name $AppVPackageFileName"
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList  $SetMSIXBuildArgs
    $BuildMSIXPackageArgs = "/build " + "`"" + "$SaveLocationPath\AI_Resources\$AppVPackageFileName.aip" + "`"" + " -buildslist MSIX"
    Start-Process $AdvancedInstallerComFilePath -Wait -ArgumentList  $BuildMSIXPackageArgs -RedirectStandardOutput "$SaveLocationPath\Logs\$AppVPackageFileName_BuildMSIXPackage.log"
}
# Get all the App-V packages from the MyAppsContentStore and convert them.
Get-ChildItem $MyAppvPackagesContentStore -Recurse | Where-Object { $_.extension -eq ".appv" } | ForEach-Object{
    $err = Run_MainProcessing $_ *>&1
}

The PowerShell script logic is the same as the one used with MSIX Packaging Tool - it goes through the list of App-V 5 packages and converts them to MSIX.

All you need to specify is the location of the App-V packages to be converted and the location of the code signing certificate.

The script also saves the logs and the Advanced Installer project (.aip) file in case they need to be reviewed or reopened.

What are the limitations of automating the conversion from App-V 5 to MSIX?

Automation is without a doubt a popular topic within every single enterprise as it saves time and costs. Automating the conversion from App-V 5 to MSIX is no exception, especially when dealing with hundreds or thousands of packages.

However, you must be prepared for some limitations with MSIX.

Although most of the MSIX limitations can be bypassed with the Package Support Framework (PSF), there is no way to add it as part of the conversion process when using MSIX Packaging Tool.

This means that even if a conversion is successful, the resulting MSIX package might not work as expected.

Some of those limitations are:

  • Start Menu entries limitations - MSIX Start Menu entries have no native support for shortcuts that have
  • Current working directory
  • Command line arguments
  • Non-executable files set as the target application
  • Scripts – all the scripts included into App-V package are ignored during the conversion process
  • MSIX package root folder permission - files located under the package root folder and its subfolders are not writable by default.
  • Virtual File System (VFS) files redirection – there might be scenarios when the application fails to write, and sometimes to read, data from files located under the VFS folder.

When it comes to Advanced Installer, StartMenu entries limitations are automatically fixed when and if they are detected.

NoteIf you want to know more about this topic, you can check out our article: The most common MSIX Start Menu limitations and how to fix them with the Package Support Framework (PSF).

Although both App-V 5 and MSIX may run scripts, the events that trigger the script differ between the two technologies and cannot be converted automatically. You can find a comparison between App-V and MSIX scripting in the Custom Actions in MSIX vs. MSI vs. App-V Scripting - A quick comparison article.

Conclusion

As we see in this article, there are a lot of benefits to automating the conversion of your App-V packages to MSIX - namely when it comes to saving time and money. But, that doesn't mean it's all bells and whistles.

We still need to test. Just because a package was converted successfully does not necessarily mean that the application is fully functional and works as expected. This is why testing is so important for each converted package.

We hope you found this article useful. Do you have any questions? Leave them below.

Subscribe to Our Newsletter

Sign up for free and be the first to receive the latest news, videos, exclusive How-Tos, and guides from Advanced Installer.

Comments: