From: Max Vilimpoc Date: Wed, 26 Aug 2026 10:33:18 +0000 (+0200) Subject: dotfiles: point git at the Windows SSH client, split out the non-elevated half X-Git-Url: https://vilimpoc.org/repos/dotfiles/commitdiff_plain/2e281421e8cccce19bc1b43bb5bdd7d877870b4e?ds=inline dotfiles: point git at the Windows SSH client, split out the non-elevated half git config core.sshCommand -> %WINDIR%/System32/OpenSSH/ssh.exe, so git shares the Windows ssh-agent that the elevated half enables. Git for Windows otherwise prefers its bundled MSYS2 ssh.exe, which cannot reach that agent (Win32-OpenSSH publishes it on a named pipe the MSYS2 build does not speak), leaving keys added with `ssh-add` invisible to git. The .bat already carried a bare version of this line, but it was inert on a fresh box: `winget install Git.Git` runs a few lines above it, so that cmd session's PATH predates the install and `git config` only printed "not recognized" before carrying on. Resolve git.exe explicitly (PATH, then the standard install roots) before configuring anything. Move the PowerShell-driven per-user work - BinSkim, the WinMerge PATH edit, and the git config - out of the .bat into setup-windows-no-uac.ps1, mirroring setup-windows-with-uac.ps1. It is standalone-runnable, takes -Skip to re-run a subset, runs each step independently (a failure warns, the rest still run, exit 1 if any did), and warns when run elevated, since every step writes per-user state that would otherwise land in the administrator's profile. The .bat is left as winget installs plus two script calls. Two behaviour changes while moving that code: - The git identity is empty strings rather than PLACEHOLDER_NAME, and is skipped when unset instead of being written. The placeholder appeared both in the assignment and in the check that guarded it, so a find/replace over the name - exactly what the README told you to do - silently disabled the guard. - The BinSkim version marker is written on the up-to-date path too. Previously it was written only after a download, so an install predating the marker re-derived its version from BinSkim.exe's ProductVersion on every run. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_019avXmzifMt4wJnJzQDUJCU --- diff --git a/README.md b/README.md index e1e0c87..e10d872 100644 --- a/README.md +++ b/README.md @@ -14,21 +14,24 @@ throwaway VM reachable from a Linux host. | File | Purpose | | --- | --- | -| `setup-windows.bat` | Entry point. Runs the non-elevated, per-user half (winget installs, user `PATH` edits, global git config), then launches the elevated half and prints its log. | +| `setup-windows.bat` | Entry point. Runs the winget installs, then the non-elevated script, then launches the elevated half and prints its log. | +| `setup-windows-no-uac.ps1` | The non-elevated, per-user half: WinMerge and BinSkim on the user `PATH`, and the global git config (identity, plus `core.sshCommand`). Can also be run directly from an ordinary prompt. | | `setup-windows-with-uac.ps1` | The elevated half, started via UAC by the batch file. Enables `ssh-agent`, installs and starts OpenSSH Server, installs `rsync.exe` to the machine `PATH`, then installs Visual Studio 2022 Community with the required components, the WDK, and the Windows Performance Toolkit. Can also be run directly from an Administrator prompt. | ## Usage -1. **Edit `setup-windows.bat` first.** The global git identity near the middle of - the file is placeholder text: +1. **Edit `setup-windows-no-uac.ps1` first.** The global git identity near the + top of the file is empty: - ```bat - git config --global user.name "PLACEHOLDER_NAME" - git config --global user.email "PLACEHOLDER_EMAIL" + ```powershell + $GitUserName = '' # e.g. 'Ada Lovelace' + $GitUserEmail = '' # e.g. 'ada@example.com' ``` - Substitute your own name and email, or comment both lines out to keep your - identity per-repository. + Fill in your own name and email, or leave them empty to keep your identity + per-repository - the script skips `user.name` / `user.email` rather than + writing a placeholder, and says so. Everything else in that script is set + either way. 2. Run it from a normal (non-elevated) prompt: @@ -47,11 +50,27 @@ throwaway VM reachable from a Linux host. - The elevated half writes a transcript to `setup-windows-uac.log` next to the script; the batch file prints it when the elevated window closes. The log is gitignored, as it contains local paths. -- Both halves are idempotent — re-running skips anything already installed. +- **git uses the Windows SSH client.** `setup-windows-no-uac.ps1` sets + `core.sshCommand` to `%WINDIR%/System32/OpenSSH/ssh.exe`. Git for Windows + otherwise prefers its own bundled MSYS2 `ssh.exe`, which cannot reach the + Windows `ssh-agent` service that the elevated half enables - Win32-OpenSSH + publishes the agent on a named pipe the MSYS2 build does not speak. Without + this, keys loaded with `ssh-add` from PowerShell are invisible to `git`, and a + push falls back to hunting for a key file and prompting for its passphrase. + The value uses forward slashes on purpose: git parses `core.sshCommand` with + shell quoting rules, in which a backslash is an escape character. +- All three scripts are idempotent — re-running skips anything already installed. BinSkim in particular checks NuGet for the newest stable version *before* downloading: the package is a self-contained .NET build well over 100 MB, and re-provisioning an up-to-date box should not pay for it. The installed version is tracked in `nupkg-version.txt` beside the tool. +- `setup-windows-no-uac.ps1` runs its steps independently: one failing warns and + the rest still run, and it exits 1 if any did. The `.bat` reports that and + carries on to the elevated half, which is the part worth the UAC prompt. Use + `-Skip` to re-run a subset, e.g. `.\setup-windows-no-uac.ps1 -Skip BinSkim`. + Run it **non-elevated**: it writes per-user state (the `HKCU` `PATH`, the + `.gitconfig` under `%USERPROFILE%`), so an elevated run would configure the + administrator's profile instead. It warns if you do. - **Remote access.** OpenSSH Server is installed from the Windows on-demand capability (10/1809+), set to start automatically, and given an inbound TCP 22 firewall rule on *all* profiles — a VM's host-only or bridged adapter is diff --git a/setup-windows-no-uac.ps1 b/setup-windows-no-uac.ps1 new file mode 100644 index 0000000..e1d5beb --- /dev/null +++ b/setup-windows-no-uac.ps1 @@ -0,0 +1,269 @@ +<# + setup-windows-no-uac.ps1 + Non-elevated portion of the Windows provisioning. Invoked by setup-windows.bat + after its winget installs, or run directly from an ordinary (NOT elevated) + prompt: + + powershell -NoProfile -ExecutionPolicy Bypass -File .\setup-windows-no-uac.ps1 + + Run it non-elevated on purpose. Every step here writes per-user state - the + HKCU PATH and the global .gitconfig under $env:USERPROFILE - so running it + elevated would configure the *administrator's* profile instead of yours. + + What this installs / configures: + - WinMerge on the user PATH + - BinSkim (binary hardening analyzer) in %LOCALAPPDATA%\Programs\BinSkim, + on the user PATH + - Global git identity, and core.sshCommand pointed at the Windows OpenSSH + client so git shares the Windows ssh-agent + + FILL IN $GitUserName / $GitUserEmail below before the first run. + + Steps are independent: one failing warns and the rest still run. The exit code + is 1 if any step failed, 0 otherwise. +#> + +[CmdletBinding()] +param( + # Skip individual steps. Note that `powershell -File` cannot pass more than + # one value to an array parameter (neither comma- nor space-separated), so + # for several, dot-call the script or use -Command: + # .\setup-windows-no-uac.ps1 -Skip BinSkim,GitConfig + # powershell -File .\setup-windows-no-uac.ps1 -Skip BinSkim + [ValidateSet('WinMerge', 'BinSkim', 'GitConfig')] + [string[]] $Skip = @() +) + +$ErrorActionPreference = 'Stop' + +# --- Global git identity: FILL THESE IN BEFORE RUNNING --- +# Left empty, Set-GlobalGitConfig skips the identity and says so, rather than +# stamping a placeholder onto your commits. Leaving them empty is a legitimate +# choice - it keeps your identity per-repository. core.sshCommand is set either +# way, so the ssh side works regardless. +$GitUserName = '' # e.g. 'Ada Lovelace' +$GitUserEmail = '' # e.g. 'ada@example.com' + +# BinSkim's win-x64 build, from the NuGet flat container. +$BinSkimPackage = 'microsoft.codeanalysis.binskim' +$BinSkimDir = Join-Path $env:LOCALAPPDATA 'Programs\BinSkim' + +function Write-Step([string]$Msg) { + Write-Host "`n==> $Msg" -ForegroundColor Cyan +} + +function Add-ToUserPath([string]$Dir) { + # HKCU PATH, not the process PATH: this must outlive the script. Idempotent, + # and re-applied on every run so an entry lost to an unrelated PATH edit is + # repaired without re-doing the install that put it there. + $user = [Environment]::GetEnvironmentVariable('Path', 'User') + if (-not $user) { $user = '' } + if (($user -split ';') -contains $Dir) { + Write-Host " $Dir already in user PATH." + return + } + $new = if ($user.Trim()) { $user.TrimEnd(';') + ';' + $Dir } else { $Dir } + [Environment]::SetEnvironmentVariable('Path', $new, 'User') + Write-Host " Added $Dir to user PATH (restart your shell to pick it up)." +} + +function Add-WinMergeToUserPath { + Write-Step 'WinMerge on the user PATH' + $candidates = @( + (Join-Path $env:ProgramFiles 'WinMerge'), + (Join-Path ${env:ProgramFiles(x86)} 'WinMerge'), + (Join-Path $env:LOCALAPPDATA 'Programs\WinMerge') + ) + $dir = $candidates | + Where-Object { Test-Path (Join-Path $_ 'WinMergeU.exe') } | + Select-Object -First 1 + if (-not $dir) { + Write-Warning 'WinMerge not found; user PATH unchanged.' + return + } + Add-ToUserPath $dir +} + +function Install-BinSkim { + # BinSkim checks the exact mitigations the native project enables in + # CMakeLists.txt (CFG/XFG, CET, ASLR/HighEntropyVA, DEP, /GS, stack cookies, + # DEPENDENTLOADFLAG, ...). The NuGet package ships a self-contained win-x64 + # build, so this needs no .NET SDK/runtime: the .nupkg is a zip - extract the + # win-x64 tool folder and put it on the PATH. After restarting the shell: + # binskim analyze path\to\your.exe + # + # VERSION CHECK FIRST. The .nupkg is a large download (well over 100 MB), so + # ask NuGet what the newest stable version is BEFORE fetching anything, and + # skip the download entirely when the installed copy already matches. + # Re-provisioning an up-to-date box should not pay for it. + # + # The installed version is recorded in nupkg-version.txt next to the tool. + # For a copy installed before that marker existed, fall back to BinSkim.exe's + # own ProductVersion; either way the marker is (re)written once we know the + # version, so the fallback runs at most once per install. The + # flat-container URL pins the exact version we checked, + # unlike the v2 /package/ endpoint, which just redirects to whatever is + # newest at the moment of the request. + Write-Step 'BinSkim' + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + $exe = Join-Path $BinSkimDir 'BinSkim.exe' + $marker = Join-Path $BinSkimDir 'nupkg-version.txt' + + $have = $null + if (Test-Path $exe) { + if (Test-Path $marker) { + $have = (Get-Content $marker -Raw).Trim() + } else { + $pv = (Get-Item $exe).VersionInfo.ProductVersion + # NuGet versions carry no build metadata; ProductVersion may ("1.2.3+sha"). + if ($pv) { $have = $pv.Split('+')[0].Trim() } + } + } + + $latest = $null + try { + $index = Invoke-RestMethod -UseBasicParsing ` + -Uri "https://api.nuget.org/v3-flatcontainer/$BinSkimPackage/index.json" + # Versions come back oldest-first; '-' marks a prerelease. + $latest = $index.versions | Where-Object { $_ -notmatch '-' } | Select-Object -Last 1 + } catch { + Write-Warning "BinSkim version check failed: $($_.Exception.Message)" + } + + if (-not $latest) { + if (-not $have) { + Write-Warning 'BinSkim not installed and NuGet unreachable; skipping.' + return + } + Write-Host " BinSkim $have kept (could not reach NuGet to check for a newer one)." + } elseif ($have -and ($have -eq $latest -or $have -eq "$latest.0")) { + Write-Host " BinSkim $have is already the newest stable release; skipping download." + # Records what the ProductVersion fallback just worked out, so the next + # run reads the marker instead of re-deriving it. + Set-Content -Path $marker -Value $latest -Encoding ascii + } else { + if ($have) { + Write-Host " BinSkim $have -> $latest; downloading." + } else { + Write-Host " BinSkim $latest; downloading." + } + $tmp = Join-Path $env:TEMP ('binskim_' + [guid]::NewGuid().ToString('N')) + New-Item -ItemType Directory -Force -Path $tmp | Out-Null + try { + $zip = Join-Path $tmp 'binskim.zip' + Invoke-WebRequest -UseBasicParsing -OutFile $zip ` + -Uri "https://api.nuget.org/v3-flatcontainer/$BinSkimPackage/$latest/$BinSkimPackage.$latest.nupkg" + Expand-Archive -Path $zip -DestinationPath $tmp -Force + + $src = Get-ChildItem -Path $tmp -Recurse -Filter 'BinSkim.exe' | + Where-Object { $_.FullName -match 'win-x64' } | + Sort-Object FullName | Select-Object -Last 1 + if (-not $src) { throw 'BinSkim.exe (win-x64) not found in package.' } + + # Replace wholesale rather than merging over the old tree, so files + # dropped between releases don't linger. + if (Test-Path $BinSkimDir) { Remove-Item -Recurse -Force $BinSkimDir } + New-Item -ItemType Directory -Force -Path $BinSkimDir | Out-Null + Copy-Item -Path (Join-Path $src.Directory.FullName '*') ` + -Destination $BinSkimDir -Recurse -Force + # Written last: the marker must only claim a version that fully landed. + Set-Content -Path $marker -Value $latest -Encoding ascii + Write-Host " BinSkim $latest installed to $BinSkimDir" + } finally { + Remove-Item -Recurse -Force $tmp -ErrorAction SilentlyContinue + } + } + + Add-ToUserPath $BinSkimDir +} + +function Get-GitPath { + # winget installed Git moments ago, but this process inherited its PATH + # before that happened, so Get-Command can miss it on a first run. Prefer a + # git already on PATH, then the usual install roots. + $onPath = Get-Command git.exe -ErrorAction SilentlyContinue + if ($onPath) { return $onPath.Source } + $roots = @( + (Join-Path $env:ProgramFiles 'Git\cmd\git.exe'), + (Join-Path ${env:ProgramFiles(x86)} 'Git\cmd\git.exe'), + (Join-Path $env:LOCALAPPDATA 'Programs\Git\cmd\git.exe') + ) + return $roots | Where-Object { Test-Path $_ } | Select-Object -First 1 +} + +function Set-GlobalGitConfig { + Write-Step 'Global git config' + $git = Get-GitPath + if (-not $git) { + Write-Warning 'git.exe not found; skipping global git config.' + return + } + Write-Host " using $git" + + if (-not $GitUserName -or -not $GitUserEmail) { + Write-Host ' Identity not configured; leaving user.name / user.email alone.' -ForegroundColor Yellow + Write-Host ' Fill in $GitUserName / $GitUserEmail at the top of this script, or set' -ForegroundColor Yellow + Write-Host ' your identity per-repository.' -ForegroundColor Yellow + } else { + & $git config --global user.name $GitUserName + & $git config --global user.email $GitUserEmail + Write-Host " identity: $GitUserName <$GitUserEmail>" + } + + # --- Make git use the Windows OpenSSH client --- + # Git for Windows ships its own MSYS2 ssh.exe and prefers it, and that client + # cannot reach the Windows ssh-agent service that the elevated half enables: + # Win32-OpenSSH publishes the agent on a named pipe the MSYS2 build does not + # speak. So keys added with `ssh-add` from PowerShell stay invisible to git, + # and a push falls back to hunting for a key file and prompting for its + # passphrase. Pointing core.sshCommand at the in-box ssh.exe gives git the + # same client, the same agent, and the same %USERPROFILE%\.ssh\config as + # `ssh` from an ordinary shell. + $winSsh = Join-Path $env:WINDIR 'System32\OpenSSH\ssh.exe' + if (-not (Test-Path $winSsh)) { + Write-Warning "No Windows OpenSSH client at $winSsh. Add the 'OpenSSH Client' optional feature and re-run; until then git uses its own bundled ssh.exe, which cannot see keys held by the Windows ssh-agent service." + return + } + # Forward slashes on purpose: git parses core.sshCommand with shell quoting + # rules, in which a backslash is an escape character. + $value = $winSsh -replace '\\', '/' + & $git config --global core.sshCommand $value + Write-Host " core.sshCommand: $value" +} + +# --------------------------------------------------------------------------- +# Main +# --------------------------------------------------------------------------- +if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( + [Security.Principal.WindowsBuiltInRole]::Administrator)) { + Write-Warning 'Running elevated. The user PATH and .gitconfig changes below will apply to the administrator profile, not yours.' +} + +$steps = [ordered]@{ + WinMerge = { Add-WinMergeToUserPath } + BinSkim = { Install-BinSkim } + GitConfig = { Set-GlobalGitConfig } +} + +$failed = @() +foreach ($name in $steps.Keys) { + if ($Skip -contains $name) { + Write-Host "`n==> $name (skipped)" -ForegroundColor DarkGray + continue + } + try { + & $steps[$name] + } catch { + # One broken step must not cost the others. Collect and report at the end. + Write-Warning "$name failed: $($_.Exception.Message)" + $failed += $name + } +} + +if ($failed) { + Write-Host "`n[setup-windows-no-uac] FAILED: $($failed -join ', ')" -ForegroundColor Red + exit 1 +} +Write-Host "`n[setup-windows-no-uac] All steps completed." -ForegroundColor Green +exit 0 diff --git a/setup-windows.bat b/setup-windows.bat index ff77716..f69eced 100644 --- a/setup-windows.bat +++ b/setup-windows.bat @@ -4,7 +4,7 @@ @rem setup-windows.bat - provision a fresh Windows box for native development @rem --------------------------------------------------------------------------- -@rem --- Non-admin (per-user) installs + git config --- +@rem --- Non-admin (per-user) winget installs --- winget install Anthropic.ClaudeCode winget install Git.Git winget install Microsoft.PowerShell Microsoft.Sysinternals.ProcessExplorer Microsoft.Sysinternals.ProcessMonitor Microsoft.Sysinternals.SDelete Microsoft.VisualStudioCode Microsoft.WindowsTerminal @@ -17,40 +17,20 @@ winget install WiXToolset.WiXCLI @rem which it reads). The installer elevates via UAC. winget install OpenCppCoverage.OpenCppCoverage -@rem --- Add WinMerge to the user PATH (persists to the HKCU environment) --- -@rem Runs non-elevated, so it updates THIS user's PATH (the elevated script runs -@rem as a different account). Idempotent: only appends if not already present. -powershell -NoProfile -Command "$c = @((Join-Path $env:ProgramFiles 'WinMerge'), (Join-Path ${env:ProgramFiles(x86)} 'WinMerge'), (Join-Path $env:LOCALAPPDATA 'Programs\WinMerge')); $d = $c | Where-Object { Test-Path (Join-Path $_ 'WinMergeU.exe') } | Select-Object -First 1; if (-not $d) { Write-Warning 'WinMerge not found; user PATH unchanged.'; exit 0 }; $u = [Environment]::GetEnvironmentVariable('Path','User'); if (-not $u) { $u = '' }; if (($u -split ';') -notcontains $d) { $new = if ($u.Trim()) { $u.TrimEnd(';') + ';' + $d } else { $d }; [Environment]::SetEnvironmentVariable('Path', $new, 'User'); Write-Host ('Added ' + $d + ' to user PATH (restart your shell to pick it up).') } else { Write-Host ($d + ' already in user PATH.') }" - -@rem --- BinSkim (binary hardening analyzer) - per-user install, no admin needed --- -@rem BinSkim checks the exact mitigations we enable in CMakeLists.txt (CFG/XFG, CET, -@rem ASLR/HighEntropyVA, DEP, /GS, stack cookies, DEPENDENTLOADFLAG, etc.). The -@rem Microsoft.CodeAnalysis.BinSkim NuGet package ships a self-contained win-x64 -@rem build, so this needs no .NET SDK/runtime: download the .nupkg (a zip), extract -@rem the win-x64 tool folder to %LOCALAPPDATA%\Programs\BinSkim, and add it to the -@rem user PATH. After restarting the shell: binskim analyze path\to\your.exe +@rem --- Non-elevated PowerShell half --- +@rem WinMerge on the user PATH, BinSkim, and the global git config (identity + +@rem core.sshCommand -> the Windows OpenSSH client, so git shares the Windows +@rem ssh-agent). EDIT THE GIT IDENTITY at the top of setup-windows-no-uac.ps1 +@rem before the first run. @rem -@rem VERSION CHECK FIRST. The .nupkg is a large download (self-contained .NET), so -@rem we ask NuGet what the newest stable version is BEFORE fetching anything, and -@rem skip the download entirely when the installed copy already matches. The -@rem installed version is recorded in nupkg-version.txt next to the tool; for a -@rem copy installed before that marker existed we fall back to BinSkim.exe's own -@rem ProductVersion, which costs at most one more download and then self-heals. -@rem The flat-container URL pins the exact version we checked, unlike the v2 -@rem /package/ endpoint, which just redirects to whatever is newest at the -@rem moment of the request. +@rem Deliberately NOT elevated: every step writes per-user state (the HKCU PATH, +@rem the .gitconfig under %USERPROFILE%), which the elevated half would write to +@rem the administrator profile instead. @rem -@rem The user PATH is refreshed on every run, including the skip path, so a lost -@rem PATH entry is repaired without re-downloading the tool to do it. -@rem A failure here only warns (exit 0) so it never aborts the rest of provisioning. -powershell -NoProfile -Command "try { $ErrorActionPreference='Stop'; [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12; $dest=Join-Path $env:LOCALAPPDATA 'Programs\BinSkim'; $exe=Join-Path $dest 'BinSkim.exe'; $mark=Join-Path $dest 'nupkg-version.txt'; $have=$null; if (Test-Path $exe) { if (Test-Path $mark) { $have=(Get-Content $mark -Raw).Trim() } else { $pv=(Get-Item $exe).VersionInfo.ProductVersion; if ($pv) { $have=$pv.Split('+')[0].Trim() } } }; $latest=$null; try { $idx=Invoke-RestMethod -Uri 'https://api.nuget.org/v3-flatcontainer/microsoft.codeanalysis.binskim/index.json' -UseBasicParsing; $latest=$idx.versions | Where-Object { $_ -notmatch '-' } | Select-Object -Last 1 } catch { Write-Warning ('BinSkim version check failed: '+$_.Exception.Message) }; if (-not $latest) { if ($have) { Write-Host ('BinSkim '+$have+' kept (could not reach NuGet to check for a newer one).') } else { Write-Warning 'BinSkim not installed and NuGet unreachable; skipping.'; exit 0 } } elseif ($have -and ($have -eq $latest -or $have -eq ($latest+'.0'))) { Write-Host ('BinSkim '+$have+' is already the newest stable release; skipping download.') } else { if ($have) { Write-Host ('BinSkim '+$have+' -> '+$latest+'; downloading.') } else { Write-Host ('BinSkim '+$latest+'; downloading.') }; $tmp=Join-Path $env:TEMP ('binskim_'+[guid]::NewGuid().ToString('N')); New-Item -ItemType Directory -Force -Path $tmp | Out-Null; $zip=Join-Path $tmp 'binskim.zip'; Invoke-WebRequest -Uri ('https://api.nuget.org/v3-flatcontainer/microsoft.codeanalysis.binskim/'+$latest+'/microsoft.codeanalysis.binskim.'+$latest+'.nupkg') -OutFile $zip -UseBasicParsing; Expand-Archive -Path $zip -DestinationPath $tmp -Force; $src=Get-ChildItem -Path $tmp -Recurse -Filter 'BinSkim.exe' | Where-Object { $_.FullName -match 'win-x64' } | Sort-Object FullName | Select-Object -Last 1; if (-not $src) { throw 'BinSkim.exe (win-x64) not found in package.' }; if (Test-Path $dest) { Remove-Item -Recurse -Force $dest }; New-Item -ItemType Directory -Force -Path $dest | Out-Null; Copy-Item -Path (Join-Path $src.Directory.FullName '*') -Destination $dest -Recurse -Force; Remove-Item -Recurse -Force $tmp; Set-Content -Path $mark -Value $latest -Encoding ascii; Write-Host ('BinSkim '+$latest+' installed to '+$dest) }; $u=[Environment]::GetEnvironmentVariable('Path','User'); if (-not $u) { $u='' }; if (($u -split ';') -notcontains $dest) { $new = if ($u.Trim()) { $u.TrimEnd(';')+';'+$dest } else { $dest }; [Environment]::SetEnvironmentVariable('Path',$new,'User'); Write-Host ('Added '+$dest+' to user PATH (restart your shell to pick it up).') } else { Write-Host ($dest+' already in user PATH.') } } catch { Write-Warning ('BinSkim install failed: '+$_.Exception.Message); exit 0 }" - -@rem --- Global git identity: EDIT THESE BEFORE RUNNING --- -@rem Replace the placeholders with your own name and email, or comment the two -@rem lines out and set your identity per-repository instead. -git config --global user.name "PLACEHOLDER_NAME" -git config --global user.email "PLACEHOLDER_EMAIL" -git config --global core.sshcommand C:/Windows/System32/OpenSSH/ssh.exe +@rem Non-fatal: these are conveniences, and the elevated half below is the part +@rem worth the UAC prompt. A failure warns and provisioning continues. +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0setup-windows-no-uac.ps1" +if not "%ERRORLEVEL%"=="0" echo [setup-windows] WARNING: setup-windows-no-uac.ps1 reported a failure ^(see above^); continuing. @rem --------------------------------------------------------------------------- @rem No package manager needed for the Windows build