Forum Discussion

Vanbogie1200's avatar
Vanbogie1200
Copper Contributor
Oct 25, 2021

Inspect MSIX Properties via cmd or Powershell

Hi,

As the title suggests, I was wondering if it's possible to inspect the properties of MSIX packages without installing them. Being able to do this would assist in automations I'm attempting to build in Azure.

 

So far I've discovered they can be accessed with the cmdlet 'Expand-AzWvdMsixImage'. This is useful and is being levered at that point in the process. However, earlier on the process before Azure is in play the properties will need to be inspected so various folders and groups can be created or located.

 

The properties I'm most interested in at the moment are:

Name

PackageFullName

PackageFamilyName

Version

 

I suspect others may be of interest later. 

 

 

5 Replies

  • You'd need someone to build a tool to extract out the manifest and then those fields. I'm not aware of any that you'd want.

    A simpler method to accomplish what you want would be to use a file naming convention such as is adopted by some tools that generate MSIX packages. For example, PackageName_Version_Architecture_Hash.msix would allow you construct all of those fields from the filename. If these are all inhouse apps you have control of that, if from third parties you'd have to determine each and rename the files.
    • zkostik's avatar
      zkostik
      Copper Contributor

      TIMOTHY_MANGAN 

      I actually made a simple tool to make it easier to check for MSIX versions. It uses a BAT for a launcher and takes a drap-and-drop MSIX file. I borrowed the .NET code from the interwebs. It is nice as it can extract only a needed file instead of native PowerShell archive command which extracts full archive (which is totally unnecessary here). BAT file calls PowerShell script with same name as it is. This is a simple purpose build script, not some entry into PowerShell proper coding contest, just sayin'. Hope it helps!

       

      You can edit bottom part of the code where it reads XML keys to grab what you need. If your items are in different subkeys, just add multiple commands. Object properties simply follow XML structure at hand. So in this case it is Package -> Identity and Name, Version, ProcessorArchitecture properties.

       

      [Check_MSIX_Version.bat]

       

      @echo off
      REM Passes 1 variable to the powershell script
      REM Var 1: %~dpn0.ps1 calls for powershell script named same as this batch file
      REM Var 2: $~1 path of drag-and-drop file that was sent to this batch file

      powershell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1' '%~1'"

      pause

       

      [Check_MSIX_Version.ps1]

       

      # Input arguments for the script, if none supplued, output usage info
      If ($args[0] -eq $null) {
      Write-Host "No arguments were passed to the script!" -ForegroundColor Red
      Write-Host "Usage: myscript.ps1 [msix path]"
      Write-Host "[msix path] = path to msix file"
      Pause
      Exit 1
      }

      # Input file path from first script argument
      $strFileName = $args[0]

      # Check if argument file path is valid
      If (!(Test-Path $strFileName)) {
      Write-Host "Invalid file path or file does not exist!" -ForegroundColor Red
      Exit 1
      }

      If( !([IO.Path]::GetExtension("$strFileName") -eq '.msix')) {
      Write-Host "Passed file is not correct file type (not MSIX)."
      Exit 1
      }

      # Load required .NET assemblies. Not necessary on PS Core 7+.
      Add-Type -Assembly System.IO.Compression.FileSystem

      $archivePath = $strFileName#"$PSScriptRoot\MSTeams-x64.msix"
      $destinationDir = "$env:TEMP\TeamsManifest"

      # Relative path of file in ZIP to extract.
      # Use FORWARD slashes as directory separator, e. g. 'subdir/test.txt'
      $fileToExtract = 'AppxManifest.xml'

      # Create destination dir if not exist.
      $null = New-Item $destinationDir -ItemType Directory -Force

      # Convert (possibly relative) paths for safe use with .NET APIs
      $resolvedArchivePath = Convert-Path -LiteralPath $archivePath
      $resolvedDestinationDir = Convert-Path -LiteralPath $destinationDir

      # Red archive file
      $archive = [IO.Compression.ZipFile]::OpenRead( $resolvedArchivePath )

      Try {
      # Locate the desired file in the ZIP archive.
      # Replace $_.Fullname by $_.Name if file shall be found in any sub directory.
      If( $foundFile = $archive.Entries.Where({ $_.FullName -eq $fileToExtract }, 'First') ) {

      # Combine destination dir path and name of file in ZIP
      $destinationFile = Join-Path $resolvedDestinationDir $foundFile.Name

      If (Test-Path $destinationFile) {
      Remove-Item $destinationFile -Force
      }

      # Extract the file.
      [IO.Compression.ZipFileExtensions]::ExtractToFile( $foundFile[ 0 ], $destinationFile )
      }
      Else {
      Write-Host "File not found in ZIP: $fileToExtract" -ForegroundColor Red
      }
      }
      Finally {
      # Dispose the archive so the file will be unlocked again.
      If( $archive ) {
      $archive.Dispose()
      }
      }

      # Open xml file
      $xml = [xml](Get-Content $destinationFile)

      # Grab necessary key value
      $xml.Package.Identity | Select Name, Version, ProcessorArchitecture

      #cleanup temp
      If (Test-Path $destinationDir) {
      Remove-Item $destinationDir -Force -Recurse
      }

      Exit 0

       

      [Sample output using Teams package]

       

      Name        Version                       ProcessorArchitecture
      ----            -------                        ---------------------
      MSTeams   24165.1414.2987.41  x64

      • Cool. But actually, I lied.

        I forgot that I did build a tool for this. It is a shell extension that shows that information (and a bit more) in the preview pane of the Windows Explorer!

        I just never released it as I just use it for a fake app in my test lab to verify fixing up the preview pane functionality inside MSIX packages.

Resources