Home / Archive / Windows

Restore a Deprovisioned Windows 10 In-Box App

2019.03.07 · Windows
Restore a Deprovisioned Windows 10 In-Box App
// Archived record Originally published 2019.03.07. Preserved as written — some references to tools, URLs or a code repository may no longer be maintained. Current work lives in the toolkit.

These days a lot of my blog posts start off with a question on Twitter and this one is no different. At least, this time around the question was relatively simple: How do you restore a modern application which was fully deprovisioned from a Windows 10 installation during OS deployment? Assuming you have the necessary source files handy, the steps involved are relatively straight forward.

First, download the PowerShell script from my GitHub repository.

Next, get the necessary source files. You could use App update OPK or the Windows 10 inbox Apps ISO (available from the VLSC). Personally, I recommend using the Microsoft Store for Business (previously known as Windows Store for Business) as it allows you to download the latest version of an application (which in turn might fix other unrelated issues).

Microsoft Store for Business is a layer that sits on top of the consumer Microsoft Store. Go to the main entry page located at businessstore.microsoft.com. You can do two things there: you can sign-in, if you have used the Store before, or start the sign-up process. Once you are logged in, search for the application...

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

... and acquire it for Offline use.

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

Then, browse to your inventory by clicking the Manage button.

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

Select an application that you have acquired and download all components. Note: Make sure to select the app architecture which matches your target systems.

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

Unfortunately, there is no "Download all", so the process is a little bit messy. Basically, you need the Appx bundle, which is the main application package...

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

... the unencoded license XML file...

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

... and the required frameworks.

Screenshot: Restore a Deprovisioned Windows 10 In-Box App

Once you downloaded all the pieces, you need to put them in the right folder structure, similarly to an application created in Visual Studio. For instance, with the Microsoft Movies & TV app you will end up with the following folder structure:

  • Root folder
    • Install-ProvisionedAppxPackage.ps1
      • AppxBundle
        • Microsoft.ZuneVideo_2019.19021.10411.0_neutral_~_8wekyb3d8bbwe.AppxBundle
        • Microsoft.ZuneVideo_8wekyb3d8bbwe_69f3bcab-8975-c526-30f5-39fa70c77ad9.xml
          • Dependencies
            • x64
              • Microsoft.VCLibs.140.00_14.0.26706.0_x64__8wekyb3d8bbwe.Appx
            • x86

The PowerShell script will locate the Appx bundle, unencoded license file, and dependencies, set the policy to enable sideloading, build the necessary DISM command depending on the detected pieces to provision the application for you, run the DISM command and return the DISM exit code. You can run the script on a client machine either manually or by using your management tool. Ideally, the app will show up in the start menu. By default, the log file will be written to C:\temp\Log - you can adjust the path directly in the script.

So to summarize: download all the pieces, put them in the right folder structure, add the wrapper and run it. It is as simple as that.

Note

If you are not going to deploy private line-of-business apps with the script and stick with the Microsoft Store for Business and Microsoft Store for Education applications which come with a license file, then you may want to remove the sideloading policy from the wrapper because it is not needed.

# Determine where to do the logging 
$logPath = "C:\temp\Logs"
$logFile = "$logPath\$($myInvocation.MyCommand).log"
$ScriptName = $MyInvocation.MyCommand

# Check log path
If (!(Test-Path $logPath)) {
    Write-Output "Log path not found..."
    New-Item -Path $logPath -ItemType Directory -Force
}

# Create Logfile
Write-Output "$ScriptName - Create Logfile" > $logFile
 
Function Logit($TextBlock1){
	$TimeDate = Get-Date
	$OutPut = "$ScriptName - $TextBlock1 - $TimeDate"
	Write-Output $OutPut >> $logFile
}

# Start main code here
. Logit "Make sure policy is set."
Set-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\Appx" -Name "AllowAllTrustedApps" -Value "1" -Force | Out-Null

. Logit "Build the base command line"
# Determine where to check
$AppxBundlePath = $PSScriptRoot + '\AppxBundle'
$AppxBundle = (Get-ChildItem -Path $AppxBundlePath) | where-object {$_.FullName -like "*.AppxBundle"}
$LicensePath = (Get-ChildItem -Path $AppxBundlePath) | where-object {$_.FullName -like "*.xml"}
$DependenciesPath = $AppxBundlePath + "\Dependencies"
$DependenciesList = (Get-ChildItem -Path $DependenciesPath -Recurse) | where-object {$_.FullName -like "*.appx"}
$Dependencies = ""

. Logit "Adding dependencies..."
ForEach ($tmp in $DependenciesList) {
    $Dependencies += " /DependencyPackagePath:" + $tmp.FullName
    }

# Add license
If (!$LicensePath) {
    . Logit "No license file found..."
    $License = " /SkipLicense"
}
Else {
    . Logit "License file found..."
    $License = " /LicensePath:" + $LicensePath.FullName
}

# build command line
$BuildAppxCommand = "/Online /Add-ProvisionedAppxPackage /PackagePath:" + $AppxBundle.FullName + $License + " /NoRestart" + $Dependencies
 
# Launch Command and get return code
. Logit "Installing application $($AppxBundle.Name)"
. Logit "Command line $BuildAppxCommand"
$DISM = Execute-Command -commandTitle "Install AppxProvisionedPackage" -commandPath  DISM.exe -commandArguments $BuildAppxCommand

$ExitCode = $DISM.ExitCode
. Logit "Exit code from command $ExitCode"

Exit $ExitCode