Appx-Backup icon indicating copy to clipboard operation
Appx-Backup copied to clipboard

You don't need Visual Studio, just Windows 10 SDK

Open NotSoCheezy opened this issue 4 years ago • 10 comments

https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/

NotSoCheezy avatar Sep 19 '20 00:09 NotSoCheezy

I just tried this, unfortunately even with all options checked it did not download MakeAppx.exe etc. required for this script.

xtcrefugee avatar Dec 24 '20 12:12 xtcrefugee

I just tried this, unfortunately even with all options checked it did not download MakeAppx.exe etc. required for this script.

It is apparently in Windows App Certification Kit https://stackoverflow.com/questions/38755063/what-part-of-windows-10-sdk-do-i-need-to-install-to-get-makeappx-exe

blacklightpy avatar May 20 '21 17:05 blacklightpy

I just tried this, unfortunately even with all options checked it did not download MakeAppx.exe etc. required for this script.

I tried it myself and found the fix!

Made some changes to the script (just changed the locations)

[CmdletBinding()]
param (
	[Parameter(Mandatory=$True)]
	[string] $WSAppPath,

	[Parameter(Mandatory=$True)]
	[string] $WSAppOutputPath,

	[Parameter(Mandatory=$True)]
	[string] $WSTools,
	
	[Parameter(Mandatory=$True)]
	[string] $arch
)

function Run-Process {
	Param ($p, $a)
	$pinfo = New-Object System.Diagnostics.ProcessStartInfo
	$pinfo.FileName = $p
	$pinfo.Arguments = $a
	$pinfo.RedirectStandardError = $true
	$pinfo.RedirectStandardOutput = $true
	$pinfo.UseShellExecute = $false
	$p = New-Object System.Diagnostics.Process
	$p.StartInfo = $pinfo
	$p.Start() | Out-Null
	$output = $p.StandardOutput.ReadToEnd()
	$output += $p.StandardError.ReadToEnd()
	$p.WaitForExit()
	return $output
}

# find tools
$FileExists = Test-Path "$WSTools\App Certification Kit\MakeAppx.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: MakeAppx.exe not found in WSTools path."
	Exit
}
$FileExists = Test-Path "$WSTools\bin\10.0.19041.0\$arch\MakeCert.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: MakeCert.exe not found in WSTools path."
	Exit
}
$FileExists = Test-Path "$WSTools\bin\10.0.19041.0\$arch\Pvk2Pfx.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: Pvk2Pfx.exe not found in WSTools path."
	Exit
}
$FileExists = Test-Path "$WSTools\App Certification Kit\SignTool.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: SignTool.exe not found in WSTools path."
	Exit
}

$WSAppXmlFile="AppxManifest.xml"

# read manifest
Write-Output "Reading ""$WSAppPath\$WSAppXmlFile"""
$FileExists = Test-Path "$WSAppPath\$WSAppXmlFile"
if ($FileExists -eq $False) {
	Write-Output "ERROR: Windows Store manifest not found."
	Exit
}
[xml]$manifest = Get-Content "$WSAppPath\$WSAppXmlFile"
$WSAppName = $manifest.Package.Identity.Name
$WSAppPublisher = $manifest.Package.Identity.Publisher
Write-Output "  App Name : $WSAppName"
Write-Output "  Publisher: $WSAppPublisher"

# prepare
$WSAppFileName = gi $WSAppPath | select basename
$WSAppFileName = $WSAppFileName.BaseName

Write-Output "Creating ""$WSAppOutputPath\$WSAppFileName.appx""."
if (Test-Path "$WSAppOutputPath\$WSAppFileName.appx") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.appx"
}
$proc = "$WSTools\App Certification Kit\MakeAppx.exe"
$args = "pack /d ""$WSAppPath"" /p ""$WSAppOutputPath\$WSAppFileName.appx"" /l"
$output = Run-Process $proc $args
if ($output -inotlike "*succeeded*") {
	Write-Output "  ERROR: Appx creation failed!"
	Write-Output "  proc = $proc"
	Write-Output "  args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Write-Output "Creating self-signed certificates."
Write-Output "  Click NONE in the 'Create Private Key Passsword' pop-up."
if (Test-Path "$WSAppOutputPath\$WSAppFileName.pvk") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.pvk"
}
if (Test-Path "$WSAppOutputPath\$WSAppFileName.cer") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.cer"
}
$proc = "$WSTools\bin\10.0.19041.0\$arch\MakeCert.exe"
$args = "-n ""$WSAppPublisher"" -r -a sha256 -len 2048 -cy end -h 0 -eku 1.3.6.1.5.5.7.3.3 -b 01/01/2000 -sv ""$WSAppOutputPath\$WSAppFileName.pvk"" ""$WSAppOutputPath\$WSAppFileName.cer"""
$output = Run-Process $proc $args
if ($output -inotlike "*succeeded*") {
	Write-Output "ERROR: Certificate creation failed!"
	Write-Output "proc = $proc"
	Write-Output "args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Write-Output "Converting certificate to pfx."
if (Test-Path "$WSAppOutputPath\$WSAppFileName.pfx") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.pfx"
}
$proc = "$WSTools\bin\10.0.19041.0\$arch\Pvk2Pfx.exe"
$args = "-pvk ""$WSAppOutputPath\$WSAppFileName.pvk"" -spc ""$WSAppOutputPath\$WSAppFileName.cer"" -pfx ""$WSAppOutputPath\$WSAppFileName.pfx"""
$output = Run-Process $proc $args
if ($output.Length -gt 0) {
	Write-Output "  ERROR: Certificate conversion to pfx failed!"
	Write-Output "  proc = $proc"
	Write-Output "  args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Write-Output "Signing the package."
$proc = "$WSTools\App Certification Kit\SignTool.exe"
$args = "sign -fd SHA256 -a -f ""$WSAppOutputPath\$WSAppFileName.pfx"" ""$WSAppOutputPath\$WSAppFileName.appx"""
$output = Run-Process $proc $args
if ($output -inotlike "*successfully signed*") {
	Write-Output "ERROR: Package signing failed!"
	Write-Output $output.Length
	Write-Output "proc = $proc"
	Write-Output "args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Remove-Item "$WSAppOutputPath\$WSAppFileName.pvk"
Remove-Item "$WSAppOutputPath\$WSAppFileName.pfx"

Write-Output "Success!"
Write-Output "  App Package: ""$WSAppOutputPath\$WSAppFileName.appx"""
Write-Output "  Certificate: ""$WSAppOutputPath\$WSAppFileName.cer"""
Write-Output "Install the '.cer' file to [Local Computer\Trusted Root Certification Authorities] before you install the App Package."
Exit

And the input statement should be

PS C:\Users\Blacklight> .\Appx-Backup.ps1 -WSAppPath "C:\Program Files\WindowsApps\SpotifyAB.SpotifyMusic_1.158.820.0_x86__zpdnekdrzrea0" -WSAppOutputPath "C:\Users\Blacklight\Onedrive\Desktop\Spotify64\" -WSTools "C:\Program Files (x86)\Windows Kits\10\" -arch "x64"

I added an extra arch parameter to switch between x86 and x64 tools, and also note the change in the WSTools path.

blacklightpy avatar May 20 '21 18:05 blacklightpy

@NotSoCheezyTech is right, please update README.

superbonaci avatar May 30 '21 19:05 superbonaci

I found that all the needed tools (Makeappx.exe, Signtool.exe, and Pvk2pfx.exe) were installed by installing just these 3 packages from the Windows SDK:

Windows SDK Desktop Tools x64-x86_en-us.msi Windows SDK for Windows Store Apps Tools-x86_en-us.msi Windows SDK Signing Tools-x86_en-us.msi

As noted elsewhere, you need to adjust the WSTools path in your command to include the build number. For me (on Windows 11), it was: C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64

DJ8014 avatar Oct 29 '21 19:10 DJ8014

Hey, pardon the newb question here. I'm trying this with an app and don't understand what the arch input should be, could someone fill me in? And besides running the whole script above, where does the Input statement go? Thanks!

PeachPiesky avatar Feb 22 '22 21:02 PeachPiesky

Hey, pardon the newb question here. I'm trying this with an app and don't understand what the arch input should be, could someone fill me in? And besides running the whole script above, where does the Input statement go? Thanks!

I don't remember this exactly, but I think you just have to run the script like I posted, and use the input statement I gave.

blacklightpy avatar Feb 23 '22 08:02 blacklightpy

Hey, pardon the newb question here. I'm trying this with an app and don't understand what the arch input should be, could someone fill me in? And besides running the whole script above, where does the Input statement go? Thanks!

I don't remember this exactly, but I think you just have to run the script like I posted, and use the input statement I gave.

i get ERROR: MakeCert.exe not found in WSTools path.

yeet-dot-org avatar Dec 26 '23 16:12 yeet-dot-org

Hey, pardon the newb question here. I'm trying this with an app and don't understand what the arch input should be, could someone fill me in? And besides running the whole script above, where does the Input statement go? Thanks!

I don't remember this exactly, but I think you just have to run the script like I posted, and use the input statement I gave.

i get ERROR: MakeCert.exe not found in WSTools path.

The latest build of the Windows 10 SDK changes the folder names.

In my case, the code provided targeted: $WSTools\bin\10.0.19041.0\$arch\MakeCert.exe

When it should be: $WSTools\bin\10.0.22621.0\$arch\MakeCert.exe

Since 10.0.22621.0 is the latest versioned folder.

Here is the full updated code:

[CmdletBinding()]
param (
	[Parameter(Mandatory=$True)]
	[string] $WSAppPath,

	[Parameter(Mandatory=$True)]
	[string] $WSAppOutputPath,

	[Parameter(Mandatory=$True)]
	[string] $WSTools,
	
	[Parameter(Mandatory=$True)]
	[string] $arch
)

function Run-Process {
	Param ($p, $a)
	$pinfo = New-Object System.Diagnostics.ProcessStartInfo
	$pinfo.FileName = $p
	$pinfo.Arguments = $a
	$pinfo.RedirectStandardError = $true
	$pinfo.RedirectStandardOutput = $true
	$pinfo.UseShellExecute = $false
	$p = New-Object System.Diagnostics.Process
	$p.StartInfo = $pinfo
	$p.Start() | Out-Null
	$output = $p.StandardOutput.ReadToEnd()
	$output += $p.StandardError.ReadToEnd()
	$p.WaitForExit()
	return $output
}

# find tools
$FileExists = Test-Path "$WSTools\App Certification Kit\makeappx.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: MakeAppx.exe not found in WSTools path."
	Exit
}
$FileExists = Test-Path "$WSTools\bin\10.0.22621.0\$arch\MakeCert.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: MakeCert.exe not found in WSTools path."
	Exit
}
$FileExists = Test-Path "$WSTools\bin\10.0.22621.0\$arch\pvk2pfx.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: Pvk2Pfx.exe not found in WSTools path."
	Exit
}
$FileExists = Test-Path "$WSTools\App Certification Kit\signtool.exe"
if ($FileExists -eq $False) {
	Write-Output "ERROR: SignTool.exe not found in WSTools path."
	Exit
}

$WSAppXmlFile="AppxManifest.xml"

# read manifest
Write-Output "Reading ""$WSAppPath\$WSAppXmlFile"""
$FileExists = Test-Path "$WSAppPath\$WSAppXmlFile"
if ($FileExists -eq $False) {
	Write-Output "ERROR: Windows Store manifest not found."
	Exit
}
[xml]$manifest = Get-Content "$WSAppPath\$WSAppXmlFile"
$WSAppName = $manifest.Package.Identity.Name
$WSAppPublisher = $manifest.Package.Identity.Publisher
Write-Output "  App Name : $WSAppName"
Write-Output "  Publisher: $WSAppPublisher"

# prepare
$WSAppFileName = gi $WSAppPath | select basename
$WSAppFileName = $WSAppFileName.BaseName

Write-Output "Creating ""$WSAppOutputPath\$WSAppFileName.appx""."
if (Test-Path "$WSAppOutputPath\$WSAppFileName.appx") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.appx"
}
$proc = "$WSTools\App Certification Kit\makeappx.exe"
$args = "pack /d ""$WSAppPath"" /p ""$WSAppOutputPath\$WSAppFileName.appx"" /l"
$output = Run-Process $proc $args
if ($output -inotlike "*succeeded*") {
	Write-Output "  ERROR: Appx creation failed!"
	Write-Output "  proc = $proc"
	Write-Output "  args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Write-Output "Creating self-signed certificates."
Write-Output "  Click NONE in the 'Create Private Key Passsword' pop-up."
if (Test-Path "$WSAppOutputPath\$WSAppFileName.pvk") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.pvk"
}
if (Test-Path "$WSAppOutputPath\$WSAppFileName.cer") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.cer"
}
$proc = "$WSTools\bin\10.0.22621.0\$arch\MakeCert.exe"
$args = "-n ""$WSAppPublisher"" -r -a sha256 -len 2048 -cy end -h 0 -eku 1.3.6.1.5.5.7.3.3 -b 01/01/2000 -sv ""$WSAppOutputPath\$WSAppFileName.pvk"" ""$WSAppOutputPath\$WSAppFileName.cer"""
$output = Run-Process $proc $args
if ($output -inotlike "*succeeded*") {
	Write-Output "ERROR: Certificate creation failed!"
	Write-Output "proc = $proc"
	Write-Output "args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Write-Output "Converting certificate to pfx."
if (Test-Path "$WSAppOutputPath\$WSAppFileName.pfx") {
	Remove-Item "$WSAppOutputPath\$WSAppFileName.pfx"
}
$proc = "$WSTools\bin\10.0.22621.0\$arch\pvk2pfx.exe"
$args = "-pvk ""$WSAppOutputPath\$WSAppFileName.pvk"" -spc ""$WSAppOutputPath\$WSAppFileName.cer"" -pfx ""$WSAppOutputPath\$WSAppFileName.pfx"""
$output = Run-Process $proc $args
if ($output.Length -gt 0) {
	Write-Output "  ERROR: Certificate conversion to pfx failed!"
	Write-Output "  proc = $proc"
	Write-Output "  args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Write-Output "Signing the package."
$proc = "$WSTools\App Certification Kit\signtool.exe"
$args = "sign -fd SHA256 -a -f ""$WSAppOutputPath\$WSAppFileName.pfx"" ""$WSAppOutputPath\$WSAppFileName.appx"""
$output = Run-Process $proc $args
if ($output -inotlike "*successfully signed*") {
	Write-Output "ERROR: Package signing failed!"
	Write-Output $output.Length
	Write-Output "proc = $proc"
	Write-Output "args = $args"
	Write-Output ("  " + $output)
	Exit
}
Write-Output "  Done."

Remove-Item "$WSAppOutputPath\$WSAppFileName.pvk"
Remove-Item "$WSAppOutputPath\$WSAppFileName.pfx"

Write-Output "Success!"
Write-Output "  App Package: ""$WSAppOutputPath\$WSAppFileName.appx"""
Write-Output "  Certificate: ""$WSAppOutputPath\$WSAppFileName.cer"""
Write-Output "Install the '.cer' file to [Local Computer\Trusted Root Certification Authorities] before you install the App Package."
Exit

Starworshipp3r avatar May 03 '24 01:05 Starworshipp3r

If you want to contribute, fork this repo, make and test your changes in a new branch in your fork, and then submit a pull request. Any change will need to be backward compatible, so if you want it to be MakeCert version agnostic within 10,0,x,y, you will need to either add code to properly detect the currently installed versions, or perhaps allow the user to specify the version number in a parameter in order to override the default location in the script.

mjmeans avatar May 07 '24 07:05 mjmeans