PwrPatch.psm1


$nugetConfig = $PSScriptRoot+"\nuget.config"
$netCoreVer = "5.0.11"

function download-nuget()
{
  param($workDir)
  $downloadDir = $workDir
  $webClient = New-Object System.Net.WebClient
  $nugetExe = ($downloadDir+"\nuget.exe")
  $webClient.DownloadFile("https://dist.nuget.org/win-x86-commandline/v5.8.0/nuget.exe", $nugetExe)
  cp $nugetConfig $downloadDir
  set-alias nuget $nugetExe -scope global
}

function Create-PackagesConfig()
{
  param(
    $workDir,
    $csWinRTVersion,
    $winSdkVersion,
    $reunionVer)

  robocopy $PSScriptRoot $workDir /S

  $global:packageConfig = ($workDir+"\packages.config")
  Set-Content -path $global:packageConfig "<packages>"
  Add-Content -path $global:packageConfig " <package id=`"Microsoft.Windows.CsWinRT`" version=`"$csWinRTVersion`" targetFramework=`"native`" />"
  Add-Content -path $global:packageConfig " <package id=`"Microsoft.ProjectReunion`" version=`"$reunionVer`" targetFramework=`"native`" />"
  Add-Content -path $global:packageConfig " <package id=`"microsoft.netcore.app.runtime.win-x64`" version=`"$netCoreVer`" targetFramework=`"native`" />"
  Add-Content -path $global:packageConfig " <package id=`"microsoft.netcore.app.runtime.win-arm64`" version=`"$netCoreVer`" targetFramework=`"native`" />"
  Add-Content -path $global:packageConfig "</packages>"

  $verConfig = ($workDir+"\Versions.props")
  Set-Content -path $verConfig "<Project><PropertyGroup>"
  Add-Content -path $verConfig " <__WinSdkVersion>$winSdkVersion</__WinSdkVersion>"
  Add-Content -path $verConfig " <__CsWinRTVersion>$csWinRTVersion</__CsWinRTVersion>"
  Add-Content -path $verConfig " <__ReunionVersion>$reunionVer</__ReunionVersion>"
  Add-Content -path $verConfig "</PropertyGroup>"
  Add-Content -path $verConfig "<PropertyGroup>"
  Add-Content -path $verConfig " <WindowsSdkPackageVersion>`$(__WinSdkVersion)</WindowsSdkPackageVersion>"
  Add-Content -path $verConfig "</PropertyGroup></Project>"

}

function global:Do-MsBuild()
{
  param($workDir, $arch, $target, $props)

  pushd $workDir

  [string[]]$extraArgs = ""
  if ($null -ne $props) {
    $props.Keys |% {
      $extraArgs += ("/p:"+$_+"="+$props[$_])
    }
    $assemblyName = (Get-Item ("..\msix\"+$arch+"\"+$props["_WinMD"]+"*interop*.dll") | select -first 1).BaseName
    $extraArgs += ("/p:AsmName="+$assemblyName)
  }
  msbuild /p:Configuration=Release /p:Platform=$arch /p:RuntimeIdentifier=win10-$arch /bl:$target.binlog /t:$target $extraArgs

  popd
}

function global:Do-AllMsBuild()
{
  param($workDir, $arch, $out, $props)

  if (test-path ($workDir+"\bin")) { rmdir -Force -Rec ($workDir+"\bin") }
  if (test-path ($workDir+"\obj")) { rmdir -Force -Rec ($workDir+"\obj") }

  Do-Msbuild -workDir $workDir -Arch $arch -Target Restore -props $props
  Do-Msbuild -workDir $workDir -Arch $arch -Target Build -props $props
  Do-Msbuild -workDir $workDir -Arch $arch -Target Publish -props $props

  $outDll = ($workDir+"\bin\"+$arch+"\Release\net5.0*\win10-"+$arch+"\publish\"+$out+"*.dll")
  $outPdb = ($workDir+"\bin\"+$arch+"\Release\net5.0*\win10-"+$arch+"\publish\"+$out+"*.pdb")
  $outDir = ($workDir+"\..\bin")
  cp $outDll $outDir
  cp $outPdb $outDir
  if ($out -eq "Microsoft.Windows.SDK.NET") {
    $outDll = ($workDir+"\bin\"+$arch+"\Release\net5.0*\win10-"+$arch+"\publish\WinRT.Runtime.dll")
    $outPdb = ($workDir+"\bin\"+$arch+"\Release\net5.0*\win10-"+$arch+"\publish\WinRT.Runtime*.pdb")
    cp $outDll $outDir
    cp $outPdb $outDir
  }
}

function global:Do-Patch()
{
  param($workDir, $arch)

  if (!(test-path ($workDir + "\bin")))
  {
    mkdir ($workDir + "\bin")
  }

  $w = $workDir + "\Windows"
  Do-AllMsBuild -workDir $w -arch $arch -out "Microsoft.Windows.SDK.NET"

  $w = $workDir + "\Reunion"
  Do-AllMsBuild -workDir $w -arch $arch -out "Microsoft.WinUI"

  $w = $workDir + "\Interop"

  dir $workDir\msix\x64\*.winmd -exclude Microsoft.* |% {
    Do-AllMsBuild -workDir $w -arch $arch -out $_.BaseName -props @{_WinMD=$_.BaseName;}
  }
}

function global:Extract-WinSDK()
{
  param($workDir,$reunionVer,$arch)

  $tmpDir = ($workDir + "\tmp")

  $reunionPkgs = ($workDir + "\pkgs\Microsoft.ProjectReunion."+$reunionVer+"\tools\MSIX\win10-"+$arch+"\Microsoft.ProjectReunion.*.msix")
  $reunionPkg = (get-item $reunionPkgs | select -first 1).FullName
  makeappx unpack -v -p $reunionPkg /d $tmpDir

  $binDir = ($workDir + "\bin")
  robocopy $tmpDir $binDir /S *.dll *.mui
}

function global:Copy-DotNetSDK()
{
  param($workDir,$arch)

  $tmpDir = ($workDir + "\tmp")

  $pkgs = ($workDir + "\pkgs\microsoft.netcore.app.runtime.win-"+$arch+"."+$netCoreVer+"\runtimes\win-"+$arch+"\native")
  $pkgDir = (get-item $pkgs | select -first 1).FullName

  $binDir = ($workDir + "\bin")
  robocopy $pkgDir $binDir /S *.dll *.mui
}

function global:Patch-MSIX()
{
  param(
    $msixDir,
    $arch="x64",
    $csWinRTVersion="1.3.5",
    $reunionVer="0.8.5",
    $winSdkVersion="10.0.20348.20",
    $workDir=$env:temp)

  if ($null -eq (get-command msbuild*))
  {
    Write-Error "Please run under a developer enviroment"
    return
  }

  $suffix = [datetime]::Now.ToString("yy.MM.dd-HH.mm.ss")
  $workDir += "\" + $suffix
  mkdir $workDir
  $workDir = (get-item $workDir).FullName
  Write-Host ("Working directory "+$workDir)

  $pkgsDir = ($workDir + "\pkgs\")
  Download-Nuget -workDir $workDir
  Create-PackagesConfig -workDir $workDir -csWinRT $csWinRTVersion -reunionVer $reunionVer -winSdkVersion $winSdkVersion
  pushd $workDir
  nuget restore -PackagesDirectory $pkgsDir
  popd

  Extract-WinSDK -workDir $workDir -reunionVer $reunionVer -arch $arch
  Copy-DotNetSDK -workDir $workDir -arch $arch

  $csWinRTDir = ($pkgsDir + "Microsoft.Windows.CsWinRT." + $csWinRTVersion)
  $csWinRTExe = $csWinRTDir + "\csWinRT.exe"
  set-alias cswinrt $csWinRTExe -scope global

  $msiBundle = (get-item $msixDir\*.msixbundle)
  cp $msiBundle.FullName ($workDir+"\msixbundle.zip")
  $msiBundle = (get-item $workDir\msixbundle.zip)
  Expand-Archive $msiBundle.FullName -Destination $workDir\msix

  $msiArch = (get-item $workDir\msix\*$arch*.msix)
  if ($null -eq $msiArch)
  {
     Write-Error "Missing $arch msix"
     return
  }
  mv $msiArch.FullName ($msiArch.FullName+".zip")
  Expand-Archive ($msiArch.FullName+".zip") -Destination $workDir\msix\$arch

  Do-Patch -WorkDir $workDir -Arch $arch

}

Export-ModuleMember -Function Patch-MSIX