AFK Macro

Idle Mafia Macro/Source/build.ps1

build.ps1

Builds the exe with the C# compiler that comes with Windows · 64 lines · 4 KB

# Builds IdleMafiaBot.exe with the C# compiler that comes with Windows (.NET Framework 4.x).
# Needs the Windows 10/11 SDK for Windows.winmd (the built-in Windows OCR).
# Usage: powershell -ExecutionPolicy Bypass -File build.ps1 [-Out file.exe]
param([string]$Out = 'IdleMafiaBot.exe')
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
$fx = "$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319"
$csc = "$fx\csc.exe"
$gac = "$env:WINDIR\Microsoft.NET\assembly\GAC_MSIL"
$winmd = Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\UnionMetadata\*\Windows.winmd" -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\\Facade\\' } | Sort-Object FullName -Descending | Select-Object -First 1
if (-not $winmd) { throw 'Windows SDK metadata (Windows.winmd) not found - install the Windows 10/11 SDK.' }
$refs = @(
'System.dll', 'System.Core.dll', 'System.Drawing.dll', 'System.Xaml.dll',
"$fx\WPF\PresentationFramework.dll", "$fx\WPF\PresentationCore.dll", "$fx\WPF\WindowsBase.dll",
"$fx\System.IO.Compression.dll", "$fx\System.IO.Compression.FileSystem.dll",
'System.Security.dll',
$winmd.FullName,
"$gac\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll",
"$gac\System.Runtime.WindowsRuntime\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.WindowsRuntime.dll",
"$gac\System.Runtime.InteropServices.WindowsRuntime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.InteropServices.WindowsRuntime.dll",
"$gac\System.Threading.Tasks\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Threading.Tasks.dll"
) | ForEach-Object { "/r:$_" }
# the window (WPF): src\ui\*.xaml are embedded in the exe and loaded at startup
$resources = @(Get-ChildItem src\ui\*.xaml, src\ui\*.ttf | ForEach-Object { "/resource:$($_.FullName),IdleMafiaBot.ui.$($_.Name)" })
$icon = @('/win32icon:src\ui\app.ico', "/resource:$((Resolve-Path src\ui\app.ico).Path),IdleMafiaBot.ui.app.ico")
$sources = @(Get-ChildItem src\*.cs | ForEach-Object { $_.FullName })
& $csc /nologo /optimize+ /codepage:65001 /target:winexe "/out:$Out" @icon @refs @resources @sources
if ($LASTEXITCODE -ne 0) { throw "compile failed ($LASTEXITCODE)" }
# Same code, same exe byte for byte, so a build can be checked against a release's SHA-256: the compiler writes three
# random things - the build time, the module's ID (MVID) and a type name <PrivateImplementationDetails>{guid}.
# The time and the name are blanked, the ID becomes a hash of the rest.
$b = [IO.File]::ReadAllBytes((Resolve-Path $Out))
$pe = [BitConverter]::ToInt32($b, 0x3C)
[Array]::Clear($b, $pe + 8, 4)
$opt = $pe + 24
$dirs = $opt + $(if ([BitConverter]::ToUInt16($b, $opt) -eq 0x20B) { 112 } else { 96 })
$secs = $opt + [BitConverter]::ToUInt16($b, $pe + 20)
function Off([int]$rva) {
for ($i = 0; $i -lt [BitConverter]::ToUInt16($b, $pe + 6); $i++) {
$s = $secs + 40 * $i; $va = [BitConverter]::ToInt32($b, $s + 12)
if ($rva -ge $va -and $rva -lt $va + [BitConverter]::ToInt32($b, $s + 16)) { return $rva - $va + [BitConverter]::ToInt32($b, $s + 20) }
}
throw "rva $rva not in a section"
}
$md = Off ([BitConverter]::ToInt32($b, (Off ([BitConverter]::ToInt32($b, $dirs + 14 * 8))) + 8))
$p = $md + 16 + [BitConverter]::ToInt32($b, $md + 12); $streams = [BitConverter]::ToUInt16($b, $p + 2); $p += 4
$mvid = -1
for ($i = 0; $i -lt $streams; $i++) {
$at = [BitConverter]::ToInt32($b, $p); $e = $p + 8; while ($b[$e] -ne 0) { $e++ }
if ([Text.Encoding]::ASCII.GetString($b, $p + 8, $e - $p - 8) -eq '#GUID') { $mvid = $md + $at }
$p = ($e + 4) -band -4
}
if ($mvid -lt 0) { throw 'no #GUID stream' }
[Array]::Clear($b, $mvid, 16)
$text = [Text.Encoding]::GetEncoding(28591).GetString($b)
$tag = '<PrivateImplementationDetails>{'
for ($i = $text.IndexOf($tag, [StringComparison]::Ordinal); $i -ge 0; $i = $text.IndexOf($tag, $i + 1, [StringComparison]::Ordinal)) {
[Text.Encoding]::ASCII.GetBytes('00000000-0000-0000-0000-000000000000').CopyTo($b, $i + $tag.Length)
}
[Array]::Copy([Security.Cryptography.SHA256]::Create().ComputeHash($b), 0, $b, $mvid, 16)
[IO.File]::WriteAllBytes((Resolve-Path $Out), $b)
"built $Out"
(Get-FileHash $Out -Algorithm SHA256).Hash