Below is a generalized snippet of some PowerShell that we’ve used to install more complex MSIX files via BigFix provisioned at the System level then installed for each user’s log-on.
I haven’t validated the script is fully functional after removing some of our proprietary libraries/functions/calls but it should be close enough to get someone started if there are errors present.
YMMV & this is provided with no warranty/support so proceed at your own risk. 
#Sample stub PS1 installing an MSIX with or without app dependencies
#Function: CheckProcessorArch
#Usage: CheckProcessorArch
#Purpose: Returns the processor architecture of the device. This data may be useful for installing MSIX architecture specific dependencies among other uses.
function CheckProcessorArch
{
Write-host "Starting CheckProcessorArch..."
$IMAGE_FILE_MACHINE_i386 = 0x014c
$IMAGE_FILE_MACHINE_AMD64 = 0x8664
$IMAGE_FILE_MACHINE_ARM64 = 0xAA64
$IMAGE_FILE_MACHINE_ARM = 0x01c0
$IMAGE_FILE_MACHINE_THUMB = 0x01c2
$IMAGE_FILE_MACHINE_ARMNT = 0x01c4
$MACHINE_ATTRIBUTES_UserEnabled = 0x01
$MACHINE_ATTRIBUTES_KernelEnabled = 0x02
$MACHINE_ATTRIBUTES_Wow64Container = 0x04
# First try to use IsWow64Process2 to determine the OS architecture
try
{
$IsWow64Process2_MethodDefinition = @"
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool IsWow64Process2(IntPtr process, out ushort processMachine, out ushort nativeMachine);
"@
$Kernel32 = Add-Type -MemberDefinition $IsWow64Process2_MethodDefinition -Name "Kernel32" -Namespace "Win32" -PassThru
$Proc = Get-Process -id $pid
$processMachine = New-Object uint16
$nativeMachine = New-Object uint16
$Res = $Kernel32::IsWow64Process2($Proc.Handle, [ref] $processMachine, [ref] $nativeMachine)
if ($Res -eq $True)
{
switch ($nativeMachine)
{
$IMAGE_FILE_MACHINE_i386 { $global:ProcessorArchitecture = "x86" }
$IMAGE_FILE_MACHINE_AMD64 { $global:ProcessorArchitecture = "amd64" }
$IMAGE_FILE_MACHINE_ARM64 { $global:ProcessorArchitecture = "arm64" }
$IMAGE_FILE_MACHINE_ARM { $global:ProcessorArchitecture = "arm" }
$IMAGE_FILE_MACHINE_THUMB { $global:ProcessorArchitecture = "arm" }
$IMAGE_FILE_MACHINE_ARMNT { $global:ProcessorArchitecture = "arm" }
}
}
Write-host " Processor architecture identified as: $ProcessorArchitecture"
}
catch
{
# Ignore exception and fall back to using environment variables to determine the OS architecture
Write-host " Fall back to using ENV to determine architecture"
}
$global:Amd64AppsSupportedOnArm64 = $False
if ($null -eq $ProcessorArchitecture)
{
$global:ProcessorArchitecture = $Env:Processor_Architecture
# Getting $Env:Processor_Architecture on arm64 machines will return x86. So check if the environment
# variable "ProgramFiles(Arm)" is also set, if it is we know the actual processor architecture is arm64.
# The value will also be x86 on amd64 machines when running the x86 version of PowerShell.
if ($ProcessorArchitecture -eq "x86")
{
if ($null -ne ${Env:ProgramFiles(Arm)})
{
$global:ProcessorArchitecture = "arm64"
}
elseif ($null -ne ${Env:ProgramFiles(x86)})
{
$global:ProcessorArchitecture = "amd64"
}
}
Write-host " Processor architecture identified as: $ProcessorArchitecture"
}
elseif ("arm64" -eq $ProcessorArchitecture)
{
# If we successfully determined the OS to be arm64 with the above call to IsWow64Process2 and we're on Win11+
# we need to check for a special case where amd64 apps are supported as well.
if ([Environment]::OSVersion.Version -ge (new-object 'Version' 10,0,22000))
{
try
{
$GetMachineTypeAttributes_MethodDefinition = @"
[DllImport("api-ms-win-core-processthreads-l1-1-7.dll", EntryPoint = "GetMachineTypeAttributes", ExactSpelling = true, PreserveSig = false)]
public static extern void GetMachineTypeAttributes(ushort Machine, out ushort machineTypeAttributes);
"@
$ProcessThreads = Add-Type -MemberDefinition $GetMachineTypeAttributes_MethodDefinition -Name "processthreads_l1_1_7" -Namespace "Win32" -PassThru
$machineTypeAttributes = New-Object uint16
$ProcessThreads::GetMachineTypeAttributes($IMAGE_FILE_MACHINE_AMD64, [ref] $machineTypeAttributes)
# We're looking for the case where the UserEnabled flag is set
if (($machineTypeAttributes -band $MACHINE_ATTRIBUTES_UserEnabled) -ne 0)
{
$global:Amd64AppsSupportedOnArm64 = $True
Write-host "Processor architecture supports amd64 apps"
}
}
catch
{
# Ignore exceptions and maintain assumption that amd64 apps aren't supported on this machine
Write-host "Processor architecture does not support amd64 apps"
}
}
}
Write-host "Finished CheckProcessorArch."
}
#####################################################
##MAIN
CheckProcessorArch
#Provide the name of the folder the MSIX will be staged in (as written must be a sub-folder of c:\programdata)
$AppName = "myApp"
#Provide the name of the MSIX file without a file extension here:
$appfile = "myApp_1.0"
try
{
#Identify dependencies for the application
Write-host "Begin identification of dependencies...."
CheckProcessorArch
#Any Appx or MSIX dependencies should be aligned into the appropriate folders.
#The root dependency directory for any non-Architecture specific ones
#Alternatively if you have files that are platform architecture specific use the following sub-folders as appropriate:
# x86, x64, arm, arm64
$DependencyPackagesDir = "C:\Programdata\$AppName\Dependencies"
$DependencyPackages = @()
if (Test-Path $DependencyPackagesDir)
{
# Get architecture-neutral dependencies
Write-host " Identify Dependencies : Architecture neutral"
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "*.appx") | Where-Object { $_.Mode -NotMatch "d" }
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "*.msix") | Where-Object { $_.Mode -NotMatch "d" }
Write-host " Dependencies identified : Architecture neutral"
Write-host " Check for dependencies for architecture: $ProcessorArchitecture"
# Get architecture-specific dependencies
if (($ProcessorArchitecture -eq "x86" -or $ProcessorArchitecture -eq "amd64" -or $ProcessorArchitecture -eq "arm64") -and (Test-Path (Join-Path $DependencyPackagesDir "x86")))
{
Write-host " Identify Dependencies : Architecture x86"
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "x86\*.appx") | Where-Object { $_.Mode -NotMatch "d" }
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "x86\*.msix") | Where-Object { $_.Mode -NotMatch "d" }
Write-host " Dependencies identified : Architecture x86"
}
if ((($ProcessorArchitecture -eq "amd64") -or ($ProcessorArchitecture -eq "arm64" -and $Amd64AppsSupportedOnArm64)) -and (Test-Path (Join-Path $DependencyPackagesDir "x64")))
{
Write-host " Identify Dependencies : Architecture x64"
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "x64\*.appx") | Where-Object { $_.Mode -NotMatch "d" }
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "x64\*.msix") | Where-Object { $_.Mode -NotMatch "d" }
Write-host " Dependencies identified : Architecture x64"
}
if (($ProcessorArchitecture -eq "arm" -or $ProcessorArchitecture -eq "arm64") -and (Test-Path (Join-Path $DependencyPackagesDir "arm")))
{
Write-host " Identify Dependencies : Architecture arm"
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "arm\*.appx") | Where-Object { $_.Mode -NotMatch "d" }
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "arm\*.msix") | Where-Object { $_.Mode -NotMatch "d" }
Write-host " Dependencies identified : Architecture arm"
}
if (($ProcessorArchitecture -eq "arm64") -and (Test-Path (Join-Path $DependencyPackagesDir "arm64")))
{
Write-host " Identify Dependencies : Architecture arm64"
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "arm64\*.appx") | Where-Object { $_.Mode -NotMatch "d" }
$DependencyPackages += Get-ChildItem (Join-Path $DependencyPackagesDir "arm64\*.msix") | Where-Object { $_.Mode -NotMatch "d" }
Write-host " Dependencies identified : Architecture arm64"
}
}
Write-host "$AppName dependencies have been identified."
}
catch
{
Write-host "$AppName dependencies have NOT been identified."
}
try
{
#Install for all users
Write-host "Begin provisioning of $AppName"
if ($DependencyPackages.FullName.Count -gt 0)
{
Write-host "Found [$($DependencyPackages.FullName.Count)] dependencies to include"
$DependencyPackagesCSV = $DependencyPackages.FullName -join ","
Write-host "Command to execute: [Add-AppProvisionedPackage -online -PackagePath `"C:\Programdata\$AppName\$appfile.msix`" -DependencyPackagePath $DependencyPackages.FullName -SkipLicense]"
$null = Add-AppProvisionedPackage -online -PackagePath "C:\Programdata\$AppName\$appfile.msix" -DependencyPackagePath $DependencyPackages.FullName -SkipLicense
}
else
{
Write-host "No dependencies found to include"
Write-host "Command to execute: [Add-AppProvisionedPackage -online -PackagePath `"C:\Programdata\$AppName\$appfile.msix`" -SkipLicense]"
$null = Add-AppProvisionedPackage -online -PackagePath "C:\Programdata\$AppName\$appfile.msix" -SkipLicense
}
Write-host "$AppName has been Provisioned."
}
catch
{
Write-host "$AppName has NOT been provisioned."
exit -1
}
exit 0