Improvements.

This commit is contained in:
Vasyl Palamarchuk
2026-09-06 20:30:20 -07:00
parent 738c482e72
commit 67e3153b0e
7 changed files with 102 additions and 36 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{
"Local": ["Projects\\Tuning\\Original", "Projects\\Tuning\\Modified", "Projects\\Tuning\\Checksums", "Projects\\Cloning\\ECU", "Projects\\Cloning\\TCU", "Projects\\Cloning\\EEPROM", "Projects\\ReverseEngineering\\Originals", "Projects\\ReverseEngineering\\WorkingCopies", "Projects\\ReverseEngineering\\Disassembly", "Projects\\ReverseEngineering\\Decompiled", "Projects\\ReverseEngineering\\Signatures", "Projects\\ReverseEngineering\\Scripts", "Projects\\ReverseEngineering\\Reports", "Research\\DAMOS", "Research\\A2L", "Research\\Datasheets", "Research\\Notes", "Backups\\ECU", "Backups\\TCU", "Backups\\EEPROM", "Backups\\Coding", "Documentation\\Wiring", "Documentation\\Service", "Documentation\\Procedures", "Drivers\\PassThru", "Drivers\\USB", "Drivers\\CAN", "Exports\\Logs", "Exports\\Reports"],
"SharedData": ["Automotive", "Automotive\\DAMOS", "Automotive\\A2L", "Automotive\\FlashFiles", "Automotive\\Projects", "Automotive\\VehicleLogs", "Automotive\\Reports", "Automotive\\Backups\\ECU", "Automotive\\Backups\\TCU", "Automotive\\Backups\\EEPROM", "Automotive\\Backups\\Coding", "Automotive\\Documentation\\Wiring", "Automotive\\Documentation\\Service", "Automotive\\Documentation\\Procedures", "Automotive\\BMW\\ISTA", "Automotive\\BMW\\PSdZData", "Automotive\\BMW\\CodingBackups", "Automotive\\BMW\\VehicleLogs", "Automotive\\Porsche\\PIWIS", "Automotive\\Porsche\\VehicleLogs", "Automotive\\VAG\\ODIS", "Automotive\\Mercedes\\Xentry", "Automotive\\Workstations\\DailyTech-Tuning", "Automotive\\Workstations\\ODIS-XENTRY", "Automotive\\Workstations\\PIWIS-ISTA", "Exchange\\DailyTech-Tuning", "Exchange\\ODIS-XENTRY", "Exchange\\PIWIS-ISTA"],
"SharedPortable": ["PortableApps", "PortableApps\\Automotive", "PortableApps\\Automotive\\CommercialTools", "PortableApps\\CAN", "PortableApps\\Editors", "PortableApps\\FileTools", "PortableApps\\Networking", "PortableApps\\SystemTools", "PortableApps\\USBTools", "PortableApps\\Development", "PortableApps\\Documentation", "PortableApps\\Security", "PortableApps\\Database", "PortableApps\\Media", "PortableApps\\Capture", "PortableApps\\CommandLine", "PortableApps\\WebTools", "PortableApps\\Launchers", "PortableApps\\Icons", "Installers\\DailyTech-Tuning", "Installers\\ODIS-XENTRY", "Installers\\PIWIS-ISTA", "Config\\DailyTech-Tuning", "Config\\ODIS-XENTRY", "Config\\PIWIS-ISTA", "Manifests", "Manifests\\Cache", "Manifests\\Hashes", "Manifests\\Inventory", "Logs"]
"SharedPortable": ["PortableApps", "PortableApps\\Automotive", "PortableApps\\Automotive\\CommercialTools", "PortableApps\\CAN", "PortableApps\\Editors", "PortableApps\\FileTools", "PortableApps\\Networking", "PortableApps\\SystemTools", "PortableApps\\USBTools", "PortableApps\\Development", "PortableApps\\Documentation", "PortableApps\\Security", "PortableApps\\Database", "PortableApps\\Media", "PortableApps\\Capture", "PortableApps\\CommandLine", "PortableApps\\WebTools", "PortableApps\\Launchers", "PortableApps\\Icons", "Install\\DailyTech-Tuning", "Install\\ODIS-XENTRY", "Install\\PIWIS-ISTA", "Config\\DailyTech-Tuning", "Config\\ODIS-XENTRY", "Config\\PIWIS-ISTA", "Manifests", "Manifests\\Cache", "Manifests\\Hashes", "Manifests\\Inventory", "Logs"]
}
+1
View File
@@ -18,4 +18,5 @@
{ "Name": "jq", "Type": "GitHubExe", "Repository": "jqlang/jq", "Regex": "(?i)^jq-windows-amd64\\.exe$", "Folder": "CommandLine\\jq", "Executable": "jq.exe", "Shortcut": true },
{ "Name": "yq", "Type": "GitHubExe", "Repository": "mikefarah/yq", "Regex": "(?i)^yq_windows_amd64\\.exe$", "Folder": "CommandLine\\yq", "Executable": "yq.exe", "Shortcut": true },
{ "Name": "CyberChef Offline", "Type": "GitHubZip", "Repository": "gchq/CyberChef", "Regex": "(?i)^CyberChef(?:_v?|[-_]).*\\.zip$", "Folder": "WebTools\\CyberChef", "Executable": "CyberChef*.html", "Shortcut": true }
,{ "Name": "Google Chrome Portable", "Type": "ChromeForTesting", "Platform": "win64", "Folder": "WebTools\\Chrome", "Executable": "chrome.exe", "Archive": "chrome-win64.zip", "Flatten": true, "Shortcut": true }
]
+11 -1
View File
@@ -19,6 +19,16 @@
- Removed legacy Win1/Win2/Win3 workspace assumptions in favor of the three named workstation profiles.
- Unified the generic portable executable and archive transfer behavior.
- Added optional PowerShell transcripts.
- Disabled USB selective suspend on AC and DC for the active power scheme, then reactivated that scheme. This prevents Windows power management from suspending a connected diagnostic interface during an authorized session.
- Multi-PROG documentation downloads now use `automotive-resources.json`, and the duplicate portable CLI `PATH` update was removed.
## Revalidation Results (2026-09-06)
- PowerShell parser validation completed without errors.
- All seven JSON configuration files completed `ConvertFrom-Json` validation.
- The installer catalog correctly separates portable utilities from licensed/OEM applications and launches vendor installers interactively.
- USB selective-suspend guidance is now backed by an executed configuration step; hibernation remains disabled.
- No live vendor downloads, hardware drivers, or vehicle communication tests were executed during this source revalidation. Those require the intended Windows installation, approved interface, and authorized bench or vehicle.
## Configuration Model
@@ -58,7 +68,7 @@ Each isolated Windows installation uses only local `C:\Automotive`, shared data
- `S:\Automotive\Workstations\<profile>`
- `P:\PortableApps\Config\<profile>`
- `P:\Installers\<profile>`
- `P:\Install\<profile>`
Commercial tool folders and backups are created for MultiPROG, WinOLS, StageX, Flex, PCMFlash, HxD, Ghidra, ImHex, SavvyCAN, and BusMaster. Licensed applications are never downloaded automatically.
+4 -1
View File
@@ -10,6 +10,9 @@
| Licensed OEM tools have unknown prerequisites | Diagnostic tool failure or device risk | No commercial/OEM installer is downloaded automatically. Use vendor-approved installers, supported drivers, a system image, and documented bench/vehicle procedures. |
| Restore uses the latest configuration archive | Restores an unintended backup | Review the archive timestamp in the backup folder before invoking `-RestoreConfiguration`. A future controlled change can add an explicit `-RestoreBackupPath`. |
| Full inventory uses CIM, registry, PnP, and services | Slow final reporting or permission variation | Inventory is captured after setup; a single inventory collection failure is logged through `Invoke-Safe` and does not undo installation work. |
| Interface disconnect or laptop power loss during flashing | ECU/module damage or an incomplete programming session | Preflight AC power, laptop battery, vehicle support voltage, interface connection, and current driver/firmware; use the vendor's approved recovery procedure if a session fails. |
| Windows Update, reboot, sleep, or USB power management interrupts a session | Lost vehicle communication or incomplete programming | Hibernation and USB selective suspend are disabled. Schedule vendor work outside update/restart windows and disable sleep only for the authorized session. |
| Unverified installer or driver content | Supply-chain compromise or incompatible interface behavior | Record SHA256 after download, verify Authenticode publisher and vendor portal provenance, and pin approved hashes/signers before unattended deployment. |
## Deployment Controls
@@ -23,4 +26,4 @@
## Suggested Additional Tools
Consider adding only after validating licensing, hardware compatibility, and operational need: `CANoe/CANalyzer`, `Vehicle Spy`, `PCAN-View`, `UDSonCAN tooling`, `J2534 driver packages`, `DTC databases`, and vendor-specific power-supply monitoring. Keep installer media and configuration exports in the profile-specific `P:\Installers` and `P:\PortableApps\Config` locations.
Consider adding only after validating licensing, hardware compatibility, and operational need: `CANoe/CANalyzer`, `Vehicle Spy`, `PCAN-View`, `UDSonCAN tooling`, `J2534 driver packages`, `DTC databases`, and vendor-specific power-supply monitoring. Keep installer media and configuration exports in the profile-specific `P:\Install` and `P:\PortableApps\Config` locations.
+10
View File
@@ -0,0 +1,10 @@
- [x] Disable hibernation with `powercfg.exe /hibernate off` during setup.
- [x] Save vendor installer downloads under `P:\Install\<profile>`.
- [x] Rename the shared installer root from `P:\Installers` to `P:\Install`.
- [x] Add shared portable Google Chrome for Testing, use `P:\PortableApps\Config\Chrome\User Data` from every Windows installation, and create desktop/Start Menu shortcuts from each workstation setup.
- [x] Download the official Autel Maxi PC Suite ZIP automatically. Extraction and vendor installation remain interactive.
- [x] Disable USB selective suspend on AC and DC power for the active scheme.
- [x] Revalidate PowerShell syntax and all JSON configuration manifests.
- [ ] Add a profile-scoped preflight that verifies AC power, battery charge, free disk capacity, and the expected J2534 interface before an authorized flashing session.
- [ ] Add approved SHA256 values and Authenticode signer expectations for every vendor installer before unattended or production deployment.
- [ ] Add a device/driver verification report for J2534 registry entries, USB hardware IDs, driver versions, and interface firmware after vendor installation.
+1
View File
@@ -16,6 +16,7 @@
- [ ] Confirm hash records were created in `Manifests\Hashes` for portable downloads.
- [ ] Confirm `Installed_Software`, `Portable_Apps`, `VSCode_Extensions`, `Drivers`, `USB_Devices`, `Disk_Inventory`, `Environment_Variables`, and `Services` inventories exist.
- [ ] Confirm each profile-specific workspace, configuration, installer, and backup location exists.
- [ ] Confirm Google Chrome Portable launches from all three Windows installations with the shared `P:\PortableApps\Config\Chrome\User Data` profile.
- [ ] Confirm Xhorse `RESOURCE_CATALOG.md`, `LINK_INDEX.md`, `CHANGELOG.md`, and `README.md` exist under `P:\PortableApps\Automotive\XHorse`.
- [ ] Create and test a configuration backup before vendor diagnostic tools or drivers are installed.
+74 -33
View File
@@ -117,7 +117,7 @@ if ($Profile.Count -ne 1) {
$Profile = $Profile[0]
$ProfileDataRoot = "{0}\Workstations\{1}" -f $SharedDataRoot.TrimEnd('\'), $Profile.Folder
$ProfileConfigRoot = "{0}\Config\{1}" -f $SharedPortableRoot.TrimEnd('\'), $Profile.Folder
$ProfileInstallerRoot = "P:\Installers\{0}" -f $Profile.Folder
$ProfileInstallerRoot = "P:\Install\{0}" -f $Profile.Folder
$Paths = [ordered]@{
Root = $LocalRoot
@@ -428,6 +428,14 @@ function Get-GitHubReleaseAsset {
return $assets[0]
}
function Get-ChromeForTestingAsset {
param([Parameter(Mandatory)][string]$Platform)
$metadata = Invoke-RestMethod -Uri 'https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json' -Headers @{ 'User-Agent' = 'Automotive-Workstation-Setup' }
$asset = @($metadata.channels.Stable.downloads.chrome | Where-Object { $_.platform -eq $Platform } | Select-Object -First 1)
if ($asset.Count -ne 1) { throw "No stable Chrome for Testing download was found for platform '$Platform'." }
return $asset[0]
}
function Get-HWiNFOPortableUri {
$portableUri = 'https://www.hwinfo.com/files/hwi_852.zip'
Write-Log "Using verified direct HWiNFO portable archive: $portableUri"
@@ -528,14 +536,14 @@ function Test-PortableInstallation {
}
function New-PortableAppShortcut {
param([string]$Name, [string]$Executable, [string]$PortableRoot)
param([string]$Name, [string]$Executable, [string]$PortableRoot, [string]$Arguments = '')
$target = Get-ChildItem -LiteralPath $PortableRoot -Filter $Executable -File -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $target) { throw "Executable not found for shortcut: $Executable" }
$desktopGroup = Join-Path ([Environment]::GetFolderPath('Desktop')) 'Automotive Workstation\Portable Apps'
$startGroup = Join-Path ([Environment]::GetFolderPath('Programs')) 'Automotive Workstation\Portable Apps'
foreach ($group in @($desktopGroup, $startGroup)) {
New-Shortcut -ShortcutPath (Join-Path $group "$Name.lnk") -TargetPath $target.FullName `
-WorkingDirectory $target.DirectoryName -Description "$Name portable"
-Arguments $Arguments -WorkingDirectory $target.DirectoryName -Description "$Name portable"
}
}
@@ -700,6 +708,22 @@ if (-not (Test-Administrator)) {
throw 'Run this script from Windows PowerShell or PowerShell as Administrator.'
}
Invoke-Safe 'Configuration' 'Disable hibernation' {
$powerProcess = Start-Process -FilePath 'powercfg.exe' -ArgumentList '/hibernate', 'off' -Wait -PassThru -NoNewWindow
if ($powerProcess.ExitCode -ne 0) { throw "powercfg.exe /hibernate off failed with exit code $($powerProcess.ExitCode)." }
} | Out-Null
Invoke-Safe 'Configuration' 'Disable USB selective suspend' {
foreach ($powerArguments in @(
@('/setacvalueindex', 'SCHEME_CURRENT', 'SUB_USB', 'USBSELECTIVE', '0'),
@('/setdcvalueindex', 'SCHEME_CURRENT', 'SUB_USB', 'USBSELECTIVE', '0'),
@('/setactive', 'SCHEME_CURRENT')
)) {
$powerProcess = Start-Process -FilePath 'powercfg.exe' -ArgumentList $powerArguments -Wait -PassThru -NoNewWindow
if ($powerProcess.ExitCode -ne 0) { throw "powercfg.exe $($powerArguments -join ' ') failed with exit code $($powerProcess.ExitCode)." }
}
} | Out-Null
if ($RestoreConfiguration) {
Invoke-Safe 'Recovery' 'Restore workstation configuration' { Restore-WorkstationConfiguration } | Out-Null
$Results | Export-Csv -LiteralPath $SummaryFile -NoTypeInformation -Encoding UTF8
@@ -841,7 +865,16 @@ if (-not $SkipDownloads) {
Write-Log "$($configuredApp.Name) release lookup skipped because its portable installation is already validated." 'INFO'
continue
}
if ($isGitHub) {
if ($appType -eq 'ChromeForTesting') {
Invoke-Safe 'PortableResolve' $configuredApp.Name {
$asset = Get-ChromeForTestingAsset -Platform $configuredApp.Platform
$PortableDefinitions.Add([pscustomobject]@{
Name=$configuredApp.Name; Type='Zip'; Uri=$asset.url; Folder=$configuredApp.Folder;
Executable=$configuredApp.Executable; Archive=$configuredApp.Archive; Flatten=[bool]$configuredApp.Flatten; Shortcut=$createShortcut
})
} | Out-Null
}
elseif ($isGitHub) {
Invoke-Safe 'PortableResolve' $configuredApp.Name {
$asset = Get-GitHubReleaseAsset -Repository $configuredApp.Repository -AssetRegex $configuredApp.Regex
$PortableDefinitions.Add([pscustomobject]@{
@@ -882,7 +915,13 @@ if (-not $SkipDownloads) {
if (-not $SkipShortcuts -and $app.Shortcut -and (Test-Path -LiteralPath $destination)) {
Invoke-Safe 'PortableShortcut' $app.Name {
New-PortableAppShortcut -Name $app.Name -Executable $app.Executable -PortableRoot $destination
$shortcutArguments = ''
if ($app.Name -eq 'Google Chrome Portable') {
$chromeProfileRoot = Join-Path $PortableRoot 'Config\Chrome\User Data'
$null = New-Item -ItemType Directory -Path $chromeProfileRoot -Force
$shortcutArguments = '--user-data-dir="{0}"' -f $chromeProfileRoot
}
New-PortableAppShortcut -Name $app.Name -Executable $app.Executable -PortableRoot $destination -Arguments $shortcutArguments
} | Out-Null
}
}
@@ -967,7 +1006,17 @@ $apps = Get-ChildItem -LiteralPath $root -Filter *.exe -File -Recurse |
Sort-Object BaseName
$choice = $apps | Select-Object @{Name='Application';Expression={$_.BaseName}}, FullName |
Out-GridView -Title 'Portable Applications' -PassThru
if ($choice) { Start-Process -FilePath $choice.FullName -WorkingDirectory (Split-Path $choice.FullName -Parent) }
if ($choice) {
$workingDirectory = Split-Path $choice.FullName -Parent
if ($choice.FullName -match '\\WebTools\\Chrome\\chrome\.exe$') {
$chromeProfile = Join-Path $root 'Config\Chrome\User Data'
$null = New-Item -ItemType Directory -Path $chromeProfile -Force
Start-Process -FilePath $choice.FullName -ArgumentList ('--user-data-dir="{0}"' -f $chromeProfile) -WorkingDirectory $workingDirectory
}
else {
Start-Process -FilePath $choice.FullName -WorkingDirectory $workingDirectory
}
}
'@ | Set-Content -LiteralPath $launcher -Encoding UTF8
if (-not $SkipShortcuts) {
$desktop = Join-Path ([Environment]::GetFolderPath('Desktop')) 'Automotive Workstation\Portable Apps Launcher.lnk'
@@ -993,11 +1042,7 @@ if ($choice) { Start-Process -FilePath $choice.FullName -WorkingDirectory (Split
$multiProgBackups = Join-Path $multiProgRoot 'Backups'
$null = New-Item -ItemType Directory -Path $multiProgDocs,$multiProgTemplates,$multiProgLibraries,$multiProgExamples,$multiProgReleased,$multiProgTestData,$multiProgBackups -Force
$manuals = @(
@{ Name='Multi-PROG-Script-Function-Manual-EN.pdf'; Uri='https://www.xhorsevvdi.com/upload/pro/24040217120425363837.pdf' },
@{ Name='Multi-PROG-User-Manual-EN.pdf'; Uri='https://www.xhorsevvdi.com/upload/pro/23122817038226585731.pdf' }
)
foreach ($manual in $manuals) {
foreach ($manual in $Configuration.Automotive.Manuals) {
$manualPath = Join-Path $multiProgDocs $manual.Name
Invoke-ReliableDownload -Name $manual.Name -Uri $manual.Uri -Destination $manualPath
if ((Get-Item -LiteralPath $manualPath).Length -lt 100KB) { throw "Documentation validation failed: $($manual.Name)" }
@@ -1330,7 +1375,7 @@ Multi-PROG for the selected device, and preserve multiple verified original back
# activation, and dongle pairing themselves. Opt in with -InstallXhorseSoftware.
if ($InstallXhorseSoftware) {
Invoke-Safe 'AutomotiveTooling' 'Xhorse Multi-PROG software installer' {
$multiProgSoftwareRoot = Join-Path $Paths.Downloads 'Xhorse\Multi-PROG'
$multiProgSoftwareRoot = Join-Path $ProfileInstallerRoot 'Xhorse\Multi-PROG'
$null = New-Item -ItemType Directory -Path $multiProgSoftwareRoot -Force
$installerPath = Join-Path $multiProgSoftwareRoot 'Multi-PROG.exe'
Invoke-ReliableDownload -Name 'Xhorse Multi-PROG installer' -Uri $Configuration.Automotive.Installers[0].Uri -Destination $installerPath
@@ -1341,7 +1386,7 @@ Multi-PROG for the selected device, and preserve multiple verified original back
} | Out-Null
Invoke-Safe 'AutomotiveTooling' 'Xhorse MVCI PRO software installer' {
$mvciSoftwareRoot = Join-Path $Paths.Downloads 'Xhorse\MVCI-PRO'
$mvciSoftwareRoot = Join-Path $ProfileInstallerRoot 'Xhorse\MVCI-PRO'
$null = New-Item -ItemType Directory -Path $mvciSoftwareRoot -Force
$installerPath = Join-Path $mvciSoftwareRoot 'MVCI_PRO-J2534.exe'
# Xhorse's MVCI PRO CDN rejects HTTPS (403); HTTP is the vendor's only working transport for this asset.
@@ -1367,7 +1412,7 @@ Multi-PROG for the selected device, and preserve multiple verified original back
$mvci = $communicationSoftware | Where-Object { $_.Name -eq 'MVCI PRO J2534' } | Select-Object -First 1
if ($mvci) {
Invoke-Safe 'AutomotiveTooling' 'MVCI PRO J2534 communication software' {
$mvciRoot = Join-Path $Paths.Downloads $mvci.Folder
$mvciRoot = Join-Path $ProfileInstallerRoot $mvci.Folder
$null = New-Item -ItemType Directory -Path $mvciRoot -Force
$mvciPath = Join-Path $mvciRoot $mvci.FileName
Invoke-ReliableDownload -Name $mvci.Name -Uri $mvci.Uri -Destination $mvciPath
@@ -1381,12 +1426,20 @@ Multi-PROG for the selected device, and preserve multiple verified original back
$autel = $communicationSoftware | Where-Object { $_.Name -eq 'Autel Maxi PC Suite' } | Select-Object -First 1
if ($autel) {
Invoke-Safe 'AutomotiveTooling' 'Autel Maxi PC Suite download' {
$autelRoot = Join-Path $Paths.Downloads $autel.Folder
$autelRoot = Join-Path $ProfileInstallerRoot $autel.Folder
$null = New-Item -ItemType Directory -Path $autelRoot -Force
$autelPath = Join-Path $autelRoot $autel.FileName
Invoke-ReliableDownload -Name $autel.Name -Uri $autel.Uri -Destination $autelPath
if ((Get-Item -LiteralPath $autelPath).Length -lt [int64]$autel.MinimumBytes) { throw 'Autel Maxi PC Suite download is unexpectedly small.' }
Unblock-File -LiteralPath $autelPath -ErrorAction SilentlyContinue
$autelExtractRoot = Join-Path $autelRoot 'Extracted'
Remove-Item -LiteralPath $autelExtractRoot -Recurse -Force -ErrorAction SilentlyContinue
Expand-Archive -LiteralPath $autelPath -DestinationPath $autelExtractRoot -Force
$autelInstaller = Get-ChildItem -LiteralPath $autelExtractRoot -Filter '*.exe' -File -Recurse -ErrorAction SilentlyContinue |
Where-Object { $_.Name -match '(?i)(setup|install|maxipcsuite)' } |
Select-Object -First 1
if (-not $autelInstaller) { throw 'Autel Maxi PC Suite installer executable was not found in the downloaded ZIP.' }
Unblock-File -LiteralPath $autelInstaller.FullName -ErrorAction SilentlyContinue
$autelReadme = Join-Path $autelRoot 'INSTALLATION.txt'
@"
Autel Maxi PC Suite
@@ -1395,33 +1448,21 @@ Profile: $WorkstationProfile
Downloaded package:
$autelPath
Extracted installer:
$($autelInstaller.FullName)
Official support page:
$($autel.DownloadPage)
Extract and install Maxi PC Suite from the downloaded package on this Windows installation.
Complete Autel licensing, device registration, USB driver, firmware, and vehicle-interface setup
according to the vendor instructions. Do not use a third-party mirror.
"@ | Set-Content -LiteralPath $autelReadme -Encoding UTF8
Write-Log "Autel Maxi PC Suite downloaded to $autelPath. Extract and launch the package installer for this Windows installation." 'WARN'
Write-Log "Autel Maxi PC Suite extracted to $autelExtractRoot. Launching the package installer for this Windows installation." 'WARN'
Start-Process -FilePath $autelInstaller.FullName -WorkingDirectory $autelInstaller.DirectoryName
} | Out-Null
}
}
# Add portable command-line tool folders to the current user's PATH once.
Invoke-Safe 'PortableConfig' 'Portable command-line PATH' {
$cliFolders = @(
(Join-Path $PortableRoot 'CommandLine\jq'),
(Join-Path $PortableRoot 'CommandLine\yq')
) | Where-Object { Test-Path -LiteralPath $_ }
$currentUserPath = [Environment]::GetEnvironmentVariable('Path', 'User')
$pathParts = @($currentUserPath -split ';' | Where-Object { $_ })
foreach ($folder in $cliFolders) {
if ($pathParts -notcontains $folder) { $pathParts += $folder }
}
[Environment]::SetEnvironmentVariable('Path', ($pathParts -join ';'), 'User')
$env:Path = (($env:Path -split ';' | Where-Object { $_ }) + $cliFolders | Select-Object -Unique) -join ';'
} | Out-Null
# Save a manifest for auditing and reproducing the setup in the other isolated workstations.
$manifestRoot = if (Test-Path 'P:\Manifests') { 'P:\Manifests' } else { $Paths.Config }
$PortableDefinitions | Select-Object Name, Type, Uri, Folder, Executable, Shortcut |
@@ -1492,7 +1533,7 @@ Invoke-Safe 'Configuration' 'Local TEMP workspace' {
Recommended manual checks after setup:
1. Create a full system image before installing OEM diagnostic suites or interface drivers.
2. Keep every other Windows installation offline and without a drive letter in this OS; use only C:, S:, and P:.
3. Disable USB selective suspend only if a specific diagnostic interface requires it.
3. USB selective suspend is disabled by this setup for diagnostic-interface reliability.
4. Exclude project folders from antivirus only when the vendor explicitly requires it.
5. Never flash/code a vehicle while Windows Update is applying changes.
6. Use a stable power supply for the laptop and a regulated vehicle support charger.