Created
March 17, 2025 06:13
-
-
Save jonwis/dd5c33737d5e02b35dfbe53074b28122 to your computer and use it in GitHub Desktop.
Deploy WASDK with python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import sys | |
import subprocess | |
import urllib.request | |
import argparse | |
from pathlib import Path | |
wasdk = { | |
"name": "Microsoft.WindowsAppSDK", | |
"version": "1.7.250127003-experimental3", | |
} | |
abiwinrt = { | |
"name": "Microsoft.Windows.AbiWinRT", | |
"version": "2.0.210330.2", | |
} | |
def find_nuget(): | |
"""Find nuget.exe in PATH or common locations""" | |
# Check if nuget is in PATH | |
try: | |
subprocess.run(["nuget", "help"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) | |
return "nuget" | |
except FileNotFoundError: | |
pass | |
# Check common locations | |
common_locations = [ | |
os.path.join(os.environ.get("ProgramFiles(x86)", ""), "NuGet", "nuget.exe"), | |
os.path.join(os.environ.get("ProgramFiles", ""), "NuGet", "nuget.exe"), | |
os.path.join(os.environ.get("LOCALAPPDATA", ""), "NuGet", "nuget.exe"), | |
os.path.join(os.path.expanduser("~"), ".nuget", "nuget.exe"), | |
] | |
for location in common_locations: | |
if os.path.exists(location): | |
return location | |
# Go download it to ~/.nuget | |
destination = os.path.join(os.path.expanduser("~"), ".nuget") | |
os.makedirs(destination, exist_ok=True) | |
nuget_path = os.path.join(destination, "nuget.exe") | |
if not os.path.exists(nuget_path): | |
print(f"nuget.exe not found in common locations. Downloading to {destination}...") | |
urllib.request.urlretrieve("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", nuget_path) | |
return nuget_path | |
def install_wasdk(nuget_path, output_dir): | |
"""Install the latest Windows App SDK using nuget""" | |
print(f"Installing latest Windows App SDK to {output_dir}...") | |
# Create output directory if it doesn't exist | |
os.makedirs(output_dir, exist_ok=True) | |
# Use nuget to install the package | |
cmd = [ | |
nuget_path, | |
"install", "Microsoft.WindowsAppSDK", | |
"-OutputDirectory", output_dir, | |
"-ExcludeVersion" | |
] | |
try: | |
result = subprocess.run(cmd, capture_output=True, text=True, check=True) | |
print("Windows App SDK installed successfully!") | |
print(f"Package installed to: {os.path.join(output_dir, 'Microsoft.WindowsAppSDK')}") | |
return True | |
except subprocess.CalledProcessError as e: | |
print(f"Error installing Windows App SDK: {e}") | |
print(f"NuGet output: {e.stdout}") | |
print(f"NuGet error: {e.stderr}") | |
return False | |
def fetch_packages(output_dir): | |
"""Fetch the Windows App SDK and AbiWinRT packages""" | |
nuget_path = find_nuget() | |
cmd = [ | |
nuget_path, | |
"install", wasdk["name"], | |
"-Version", wasdk["version"], | |
"-OutputDirectory", output_dir, | |
"-ExcludeVersion" | |
] | |
result = subprocess.run(cmd, capture_output=True, text=True, check=False) | |
if result.returncode != 0: | |
print(f"Error installing {wasdk['name']}: {result.stderr}") | |
sys.exit(1) | |
cmd = [ | |
nuget_path, | |
"install", abiwinrt["name"], | |
"-Version", abiwinrt["version"], | |
"-OutputDirectory", output_dir, | |
"-ExcludeVersion" | |
] | |
result = subprocess.run(cmd, capture_output=True, text=True, check=False) | |
if result.returncode != 0: | |
print(f"Error installing {abiwinrt['name']}: {result.stderr}") | |
sys.exit(1) | |
def winmds_in_path(path): | |
"""Check if any WinMD files are in the specified path""" | |
for root, dirs, files in os.walk(path): | |
for file in files: | |
if file.endswith(".winmd"): | |
return True | |
return False | |
def project_abi_package(output_dir, sdk_dir, sdk_version): | |
"""Project the Windows App SDK package""" | |
sdk_references = os.path.join(sdk_dir, "References", sdk_version) | |
abi_output_path = os.path.join(output_dir, "abi") | |
# Grab all the WinMDs, recursively, from output_dir and {sdk_dir}/References/{sdk_version} | |
winmds_in = Path(output_dir).rglob("*.winmd"); | |
winmds_refs = Path(sdk_references).rglob("*.winmd") | |
# Write those to a .rsp file along with the other arguments to abiwinrt | |
rsp_file = os.path.join(output_dir, "abiwinrt.rsp") | |
with open(rsp_file, "w") as f: | |
f.write(f"-output \"{abi_output_path}\"\n") | |
for winmd in winmds_in: | |
f.write(f"-in \"{winmd}\"\n") | |
for winmd in winmds_refs: | |
f.write(f"-ref \"{winmd}\"\n") | |
# Use the abiwinrt tool to project the WinMDs. Search under the output_dir\abiwinrt for abi.exe | |
abiwinrt_tool = list(Path(output_dir).rglob("abi.exe")).pop() | |
if (not abiwinrt_tool) or (not os.path.exists(abiwinrt_tool)): | |
print("abiwinrt tool not found in the output directory") | |
sys.exit(1) | |
result = subprocess.run(f"{abiwinrt_tool} @{rsp_file}", capture_output=True, text=True, check=False) | |
if result.returncode != 0: | |
print(f"Error projecting WinMD ABI: {result.stderr}") | |
sys.exit(1) | |
def guess_winsdk_version_and_dir(): | |
"""Guess the Windows SDK version and directory""" | |
# Read the "KitsRoot10" under the "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots" | |
# registry key to find the Windows SDK installation directory | |
import winreg | |
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\\WOW6432Node\\Microsoft\\Windows Kits\\Installed Roots") as key: | |
kits_root = winreg.QueryValueEx(key, "KitsRoot10")[0] | |
sdk_dir = os.path.join(kits_root, "10") | |
# Enumerate the versions under the sdk_dir\Include directory, whose names | |
# are dotted four part versions like "10.0.22621.0". Pick the latest one. | |
include_dir = os.path.join(sdk_dir, "Include") | |
versions = os.listdir(include_dir) | |
versions.sort(reverse=True) | |
sdk_version = versions[0] | |
return sdk_dir, sdk_version | |
def main(): | |
parser = argparse.ArgumentParser(description="Install Windows App SDK using NuGet") | |
parser.add_argument("output_dir", help="Directory to install the Windows App SDK package") | |
parser.add_argument("sdk_dir", help="Directory where the Windows SDK is installed") | |
parser.add_argument("sdk_version", help="Version of the Windows SDK to use") | |
args = parser.parse_args() | |
output_dir = os.path.abspath(args.output_dir) | |
if not args.sdk_dir or not args.sdk_version: | |
args.sdk_dir, args.sdk_version = guess_winsdk_version_and_dir() | |
fetch_packages(output_dir) | |
project_abi_package(output_dir, args.sdk_dir, args.sdk_version) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment