private/Get-ManifestDetails.ps1
<#
.SYNOPSIS Retrieves details from an MSIX or APPV package manifest. .DESCRIPTION The Get-ManifestDetail function retrieves details from an MSIX or APPV package manifest. .PARAMETER Filename Specifies the path to the package. .NOTES Function : Get-ManifestDetail Author : John Billekens Copyright: Copyright (c) AppVentiX Version : 1.1 #> function Get-ManifestDetail { [CmdletBinding()] Param ( [ValidateScript({ try { if ((Test-Path -Path "$_") -and ("$_" -like '*.msix' -or "$_" -like '*.appv')) { $true } else { Throw [System.Management.Automation.ItemNotFoundException] "The parameter must be a valid and accessable *.msix or *.appv file!" } } catch { Throw [System.Management.Automation.ItemNotFoundException] "The parameter must be a valid and accessable *.msix or *.appv file!" } })] [System.IO.FileInfo]$Filename ) $packageType = ($Filename.Name.Split('.')[-1]).ToUpper() #Retrieve the manifest from the package [xml]$manifestXml = Get-AppXManifest -Filename $Filename #Gather the package data $appManifest = @{} $appManifest.Name = $manifestXml.Package.Identity.Name $appManifest.Version = $manifestXml.Package.Identity.Version $appManifest.Publisher = $manifestXml.Package.Identity.Publisher $appManifest.PublisherID = Get-PublisherId -Publisher $appManifest.Publisher switch ($packageType) { "MSIX" { $appManifest.Architecture = $manifestXml.Package.Identity.ProcessorArchitecture $appManifest.PackageFullName = Get-PackageFullName @appManifest } "APPV" { $appManifest.PackageId = $manifestXml.Package.Identity.PackageId $appManifest.VersionId = $manifestXml.Package.Identity.VersionId } Default { Write-Warning "Unknown package type: $packageType" } } $appManifest.Type = $packageType $appManifest.FamilyName = '{0}_{1}' -f $manifestXml.Package.Identity.Name, $appManifest.PublisherID $appManifest.DisplayName = $manifestXml.Package.Properties.DisplayName $appManifest.PublisherDisplayName = $manifestXml.Package.Properties.PublisherDisplayName $appManifest.LastUpdated = ([DateTime]$Filename.LastWriteTime).ToString("o").Substring(0, 27) #Gather the application data $appManifest.Applications = @() #Get the package files, treat the package as zip file to extract file entries $packageFiles = [IO.Compression.ZipFile]::OpenRead($Filename) $packageFilesEntries = $packageFiles.Entries #Release the package as soon as possible to remove the lock on the file $packageFiles.Dispose() $appvNumber = 0 ForEach ($application in $manifestXml.Package.Applications.Application) { #Gather the application data $app = @{} switch ($packageType) { "MSIX" { $app.Id = $application.Id $app.AppUserModelID = '{0}!{1}' -f $appManifest.FamilyName, $application.Id $app.Executable = $application.Executable $app.Description = $application.VisualElements.Description $app.FriendlyName = $application.VisualElements.DisplayName $app.AppVentiXExecutable = '{0}#{1}' -f $application.Id, $application.Executable #Select the icon image, this is a bit tricky because the icon image can be in different locations if (-Not [String]::IsNullOrEmpty($($application.VisualElements.Square44x44Logo))) { $imageFilename = Split-Path -Path $application.VisualElements.Square44x44Logo -Leaf $imageExtension = $imageFilename.Split(".")[-1] $imageBase = $imageFilename.Replace(".$($imageExtension)", $null) $imagePath = Split-Path -Path $application.VisualElements.Square44x44Logo -Parent $iconImageNamePath = $packageFilesEntries | Where-Object { $_.Fullname -like "*$($imagePath)/$($imageBase)*.$($imageExtension)" } | Select-Object -ExpandProperty FullName if ([String]::IsNullOrEmpty($iconImageNamePath) -or $iconImageNamePath.Count -gt 1) { $iconImageNamePath = $packageFilesEntries | Where-Object { $_.Fullname -like "*$($imagePath)/$($imageBase)*scale-100*.$($imageExtension)" } | Select-Object -ExpandProperty FullName } } if ([String]::IsNullOrEmpty($iconImageNamePath) -or $iconImageNamePath.Count -gt 1) { $iconImageNamePath = $packageFilesEntries | Where-Object { $_.FullName -like "*Assets*$($application.Id)Square44x44*" } | Select-Object -ExpandProperty FullName } if ($iconImageNamePath.Count -gt 1) { $iconImageNamePath = $iconImageNamePath | Where-Object { $_ -like "*scale-100*" } } if ([String]::IsNullOrEmpty($iconImageNamePath)) { $iconImageNamePath = $packageFilesEntries | Where-Object { $_.FullName -like '*Square44x44Logo.*' -or $_.FullName -like '*Square44x44Logo.scale-100.*' } | Select-Object -ExpandProperty FullName | Select-Object -First 1 | Select-Object -ExpandProperty FullName Write-Warning "Selected a random icon: $($iconImageNamePath)" } if ([String]::IsNullOrEmpty($iconImageNamePath)) { Write-Warning "Cannot set an application image (path), none found" } $app.Iconpath = $iconImageNamePath.Replace('/', '\') $app.IconWindowsPath = [io.path]::combine('C:\Program Files\WindowsApps', $appManifest.PackageFullName, $iconImageNamePath.Replace('/', '\')) $app.IconPackagePath = [io.path]::combine($appManifest.PackageFullName, $iconImageNamePath.Replace('/', '\')) } "APPV" { $app.Number = $appvNumber $app.Executable = $application.Target $app.Id = $application.Id $app.Description = $application.VisualElements.Description $app.FriendlyName = $application.VisualElements.Name $app.Version = $application.VisualElements.Version $app.Iconpath = $application.Target.Replace('[{', $null).Replace('}]', $null) $app.IconWindowsPath = [io.path]::combine('C:\ProgramData\App-V', $appManifest.PackageId, $appManifest.VersionId, 'Root\VFS', $app.Iconpath) $appvNumber++ } Default { Write-Warning "Unknown package type: $packageType" } } $appManifest.Applications += [PSCustomObject]$app.Clone() } #Clear the XML data $manifestXml.RemoveAll() #Return all the gathered data return [PSCustomObject]$appManifest } |