waypoit debuguing

This commit is contained in:
2026-09-25 16:51:04 -06:00
parent 1dbd1ad79b
commit 251c9aa06c
+155 -87
View File
@@ -1,3 +1,13 @@
<#
.SYNOPSIS
Princess Pi's Magical CHECKSUM! - Computes and verifies message digests / file checksums.
.DESCRIPTION
Computes or verifies checksums using cryptographic hash algorithms (SHA256, SHA512, SHA1, MD5, SHA384).
Supports parallel processing, recursive scanning, direct hash matching, and verification file parsing.
.NOTES
Requires PowerShell 7.0 or higher.
#>
[CmdletBinding(DefaultParameterSetName='Generate')] [CmdletBinding(DefaultParameterSetName='Generate')]
param( param(
# File(s) or wildcard pattern to compute checksum for # File(s) or wildcard pattern to compute checksum for
@@ -49,6 +59,13 @@ param(
[switch]$Help [switch]$Help
) )
# --- ENVIRONMENT SANITY CHECK ---
# Ensure PowerShell 7+ is used since ForEach-Object -Parallel is required.
if ($PSVersionTable.PSVersion.Major -lt 7) {
Write-Error "checksum: This script requires PowerShell 7 or higher for parallel execution (-Parallel support). Current version is $($PSVersionTable.PSVersion)."
exit 1
}
begin { begin {
function Show-Help { function Show-Help {
@' @'
@@ -149,7 +166,7 @@ https://linktr.ee/princesspi3
@****#######%**@+*%**#%+++++%##*** #+++++++++++++++++#+++++#****+======*****+ @****#######%**@+*%**#%+++++%##*** #+++++++++++++++++#+++++#****+======*****+
#****##%####@**%+*******@@+++@###**% #+++++++++++++*++++++++++****========****# #****##%####@**%+*******@@+++@###**% #+++++++++++++*++++++++++****========****#
****#####%%*%*%+***@@@%%@*+++@####** *+++++++++++++++++++++#****=======****# ****#####%%*%*%+***@@@%%@*+++@####** *+++++++++++++++++++++#****=======****#
%***####%%**+%%*++*@=##@@%@++++%###*** +++++*+++++++++++#+**************# %***####%%**+%%*++*@=##@@%@++++%###*** ++++*+++++++++++#+**************#
@%%%@@##%%#++++++++==**@@**+++%*###**% +++++++++++#*+++++#*********#### @%%%@@##%%#++++++++==**@@**+++%*###**% +++++++++++#*+++++#*********####
%###%++++++++====**#++++%**##**% @% ++++#+++++++++++++**************# %###%++++++++====**#++++%**##**% @% ++++#+++++++++++++**************#
%###%++++++++++++++++++%**%##**%@###@ %++++++++++++++++***=====******** %###%++++++++++++++++++%**%##**%@###@ %++++++++++++++++***=====********
@@ -174,7 +191,7 @@ https://linktr.ee/princesspi3
@@@@@@@@@@ ++++++++# ******# #++++++# *##@%********% @*@ @@@@@@@@@@ ++++++++# ******# #++++++# *##@%********% @*@
@@+@@@++@@+ ++++++++# ******# #++++++# @## #*********@ #***# @@+@@@++@@+ ++++++++# ******# #++++++# @## #*********@ #***#
@@+@@++@@@++ @@@++++++* @@@%**** #@@++++% +## %#****************% @@+@@++@@@++ @@@++++++* @@@%**** #@@++++% +## %#****************%
@*@**@+++# @@@@+++++ @@@@@@**# @@@@++++# @# %#**************** @*@**@+++# @@@@+++++ @@@@@@**# @@@@@++++# @# %#****************
+#+++++# @@@@@@+++% @@@@@@@@# @@@@@@@++ @ %##************% +#+++++# @@@@@@+++% @@@@@@@@# @@@@@@@++ @ %##************%
#+++** @@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ %###********%* #+++** @@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ %###********%*
@@@@@@@@@@+ @@@@@@@@@@ =@@@@@@@@@ %%#####%% @@@@@@@@@@+ @@@@@@@@@@ =@@@@@@@@@ %%#####%%
@@ -213,31 +230,6 @@ https://linktr.ee/princesspi3
} }
}; };
}; };
function Invoke-ParallelHashing {
param([array]$Items, [string]$Algorithm);
$Items | ForEach-Object -Parallel {
$item = $_
$algo = $using:Algorithm
$hash = (Get-FileHash -Path ($item.FullName) -Algorithm ($algo)).Hash.ToLower();
$relativePath = Resolve-Path -Path ($item.FullName) -Relative -ErrorAction 'SilentlyContinue';
if (-not $relativePath) { $relativePath = $item.Name; };
if ($relativePath.StartsWith(".\") -or $relativePath.StartsWith("./")) {
$relativePath = $relativePath.Substring(2);
};
[PSCustomObject]@{
Item = $item
Hash = $hash
RelativePath = $relativePath
OutputLine = "${hash} ${relativePath}"
ItemOutFile = "$($item.FullName).$($algo.ToLower())"
}
} -ThrottleLimit 16
};
} }
process { process {
@@ -265,6 +257,15 @@ process {
$Algorithm = $Algorithm.ToUpper(); $Algorithm = $Algorithm.ToUpper();
}; };
# Determine if progress bar should display (-r, -c/-Check, or wildcard input '*')
$isWildcardGlobal = $false;
if ($FilePath) {
foreach ($p in $FilePath) {
if ($p -match '\*') { $isWildcardGlobal = $true; }
}
}
$showProgress = $Recursive.IsPresent -or $isWildcardGlobal -or ($PSCmdlet.ParameterSetName -eq 'Verify');
# --- ITEM GATHERING (Generate & Match Modes) --- # --- ITEM GATHERING (Generate & Match Modes) ---
if ($PSCmdlet.ParameterSetName -in @('Generate', 'Match')) { if ($PSCmdlet.ParameterSetName -in @('Generate', 'Match')) {
if (-not $FilePath -or $FilePath.Count -eq 0) { if (-not $FilePath -or $FilePath.Count -eq 0) {
@@ -273,14 +274,12 @@ process {
}; };
$allItems = @(); $allItems = @();
$isWildcardGlobal = $false;
$skipExtensions = @('.md5', '.sha1', '.sha256', '.sha384', '.sha512'); $skipExtensions = @('.md5', '.sha1', '.sha256', '.sha384', '.sha512');
foreach ($pathEntry in ($FilePath)) { foreach ($pathEntry in ($FilePath)) {
$isWildcard = ($pathEntry -match '\*'); $isWildcard = ($pathEntry -match '\*');
if ($isWildcard) { $isWildcardGlobal = $true; };
$resolvedItems = @(); $resolvedItems = @();
if ($Recursive) { if ($Recursive) {
$resolvedItems = Get-ChildItem -Path ($pathEntry) -Recurse -File -ErrorAction 'SilentlyContinue'; $resolvedItems = Get-ChildItem -Path ($pathEntry) -Recurse -File -ErrorAction 'SilentlyContinue';
} else { } else {
@@ -323,9 +322,10 @@ process {
$expectedHash = $Match.Trim().ToLower(); $expectedHash = $Match.Trim().ToLower();
$totalFiles = $allItems.Count; $totalFiles = $allItems.Count;
$currentIndex = [ref]0; $currentIndex = 0;
$results = $allItems | ForEach-Object -Parallel { # Stream parallel results and update progress bar in real time
$allItems | ForEach-Object -Parallel {
$item = $_ $item = $_
$algo = $using:Algorithm $algo = $using:Algorithm
$exp = $using:expectedHash $exp = $using:expectedHash
@@ -339,25 +339,22 @@ process {
TargetFile = $targetFile TargetFile = $targetFile
IsMatch = ($actualHash -eq $exp) IsMatch = ($actualHash -eq $exp)
} }
} -ThrottleLimit 16; } -ThrottleLimit 16 | ForEach-Object {
$currentIndex++
$showProgressMatch = $Recursive.IsPresent -or $isWildcardGlobal; if ($showProgress -and $totalFiles -gt 0) {
Write-Progress -Activity "Matching Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100);
foreach ($res in $results) {
$currentIndex.Value++;
if ($showProgressMatch -and $totalFiles -gt 0) {
Write-Progress -Activity "Matching Checksums ($Algorithm)" -Status "Processing file $($currentIndex.Value) of $totalFiles" -PercentComplete (($currentIndex.Value / $totalFiles) * 100);
} }
if ($res.IsMatch) { if ($_.IsMatch) {
Write-Host "$($res.TargetFile): " -NoNewline; Write-Host "$($_.TargetFile): " -NoNewline;
Write-Host "OK" -ForegroundColor Green; Write-Host "OK" -ForegroundColor Green;
} else { } else {
Write-Host "$($res.TargetFile): " -NoNewline; Write-Host "$($_.TargetFile): " -NoNewline;
Write-Host "FAILED" -ForegroundColor Red; Write-Host "FAILED" -ForegroundColor Red;
} }
}; };
if ($showProgressMatch) {
if ($showProgress) {
Write-Progress -Activity "Matching Checksums ($Algorithm)" -Completed; Write-Progress -Activity "Matching Checksums ($Algorithm)" -Completed;
} }
} }
@@ -428,10 +425,10 @@ process {
} }
$totalFiles = $verifyItems.Count; $totalFiles = $verifyItems.Count;
$currentIndex = [ref]0; $currentIndex = 0;
# Run verification items in parallel # Run verification items in parallel and stream progress live
$verifyResults = $verifyItems | ForEach-Object -Parallel { $verifyItems | ForEach-Object -Parallel {
$item = $_ $item = $_
$algo = $using:fileAlgo $algo = $using:fileAlgo
@@ -459,23 +456,21 @@ process {
IsError = $true IsError = $true
} }
} }
} -ThrottleLimit 16; } -ThrottleLimit 16 | ForEach-Object {
$currentIndex++
foreach ($res in $verifyResults) {
$currentIndex.Value++;
if ($totalFiles -gt 0) { if ($totalFiles -gt 0) {
Write-Progress -Activity "Verifying Checksums ($fileAlgo)" -Status "Processing file $($currentIndex.Value) of $totalFiles" -PercentComplete (($currentIndex.Value / $totalFiles) * 100); Write-Progress -Activity "Verifying Checksums ($fileAlgo)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100);
} }
Write-Host "$($res.DisplayPath): " -NoNewline; Write-Host "$($_.DisplayPath): " -NoNewline;
if ($res.IsError) { if ($_.IsError) {
Write-Host "$($res.Status)" -ForegroundColor Red; Write-Host "$($_.Status)" -ForegroundColor Red;
} elseif ($res.Status -eq "OK") { } elseif ($_.Status -eq "OK") {
Write-Host "OK" -ForegroundColor Green; Write-Host "OK" -ForegroundColor Green;
} else { } else {
Write-Host "FAILED" -ForegroundColor Red; Write-Host "FAILED" -ForegroundColor Red;
} }
} };
Write-Progress -Activity "Verifying Checksums ($fileAlgo)" -Completed; Write-Progress -Activity "Verifying Checksums ($fileAlgo)" -Completed;
}; };
} }
@@ -488,9 +483,6 @@ process {
$wantCustomOut = $PSBoundParameters.ContainsKey('OutFile'); $wantCustomOut = $PSBoundParameters.ContainsKey('OutFile');
$wantAutoOut = $Save.IsPresent; $wantAutoOut = $Save.IsPresent;
# Show progress if wildcard used anywhere in inputs or recursive flag set
$showProgressGen = $Recursive.IsPresent -or $isWildcardGlobal;
if ($wantCustomOut -or $wantAutoOut) { if ($wantCustomOut -or $wantAutoOut) {
# Recursive wildcard auto-saves per directory # Recursive wildcard auto-saves per directory
if ($Recursive -and $isWildcardGlobal) { if ($Recursive -and $isWildcardGlobal) {
@@ -510,17 +502,36 @@ process {
$currentIndex = 0; $currentIndex = 0;
$linesToWrite = @(); $linesToWrite = @();
$parallelResults = Invoke-ParallelHashing -Items $filesInDir -Algorithm $Algorithm; $filesInDir | ForEach-Object -Parallel {
foreach ($res in $parallelResults) { $item = $_
$algo = $using:Algorithm
$hash = (Get-FileHash -Path ($item.FullName) -Algorithm ($algo)).Hash.ToLower();
$relativePath = Resolve-Path -Path ($item.FullName) -Relative -ErrorAction 'SilentlyContinue';
if (-not $relativePath) { $relativePath = $item.Name; };
if ($relativePath.StartsWith(".\") -or $relativePath.StartsWith("./")) {
$relativePath = $relativePath.Substring(2);
};
[PSCustomObject]@{
Item = $item
Hash = $hash
RelativePath = $relativePath
OutputLine = "${hash} ${relativePath}"
ItemOutFile = "$($item.FullName).$($algo.ToLower())"
}
} -ThrottleLimit 16 | ForEach-Object {
$currentIndex++; $currentIndex++;
if ($showProgressGen -and $totalFiles -gt 0) { if ($showProgress -and $totalFiles -gt 0) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Directory: $(Split-Path $dirPath -Leaf) [$currentIndex/$totalFiles]" -PercentComplete (($currentIndex / $totalFiles) * 100); Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Directory: $(Split-Path $dirPath -Leaf) [$currentIndex/$totalFiles]" -PercentComplete (($currentIndex / $totalFiles) * 100);
} }
$linesToWrite += $res.OutputLine; $linesToWrite += $_.OutputLine;
Write-Output $res.OutputLine; Write-Output $_.OutputLine;
} };
if ($showProgressGen) {
if ($showProgress) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed; Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed;
} }
@@ -540,17 +551,36 @@ process {
$currentIndex = 0; $currentIndex = 0;
$linesToWrite = @(); $linesToWrite = @();
$parallelResults = Invoke-ParallelHashing -Items $allItems -Algorithm $Algorithm; $allItems | ForEach-Object -Parallel {
foreach ($res in $parallelResults) { $item = $_
$algo = $using:Algorithm
$hash = (Get-FileHash -Path ($item.FullName) -Algorithm ($algo)).Hash.ToLower();
$relativePath = Resolve-Path -Path ($item.FullName) -Relative -ErrorAction 'SilentlyContinue';
if (-not $relativePath) { $relativePath = $item.Name; };
if ($relativePath.StartsWith(".\") -or $relativePath.StartsWith("./")) {
$relativePath = $relativePath.Substring(2);
};
[PSCustomObject]@{
Item = $item
Hash = $hash
RelativePath = $relativePath
OutputLine = "${hash} ${relativePath}"
ItemOutFile = "$($item.FullName).$($algo.ToLower())"
}
} -ThrottleLimit 16 | ForEach-Object {
$currentIndex++; $currentIndex++;
if ($showProgressGen -and $totalFiles -gt 0) { if ($showProgress -and $totalFiles -gt 0) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100); Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100);
} }
$linesToWrite += $res.OutputLine; $linesToWrite += $_.OutputLine;
Write-Output $res.OutputLine; Write-Output $_.OutputLine;
} };
if ($showProgressGen) {
if ($showProgress) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed; Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed;
} }
@@ -561,17 +591,36 @@ process {
$totalFiles = $allItems.Count; $totalFiles = $allItems.Count;
$currentIndex = 0; $currentIndex = 0;
$parallelResults = Invoke-ParallelHashing -Items $allItems -Algorithm $Algorithm; $allItems | ForEach-Object -Parallel {
foreach ($res in $parallelResults) { $item = $_
$algo = $using:Algorithm
$hash = (Get-FileHash -Path ($item.FullName) -Algorithm ($algo)).Hash.ToLower();
$relativePath = Resolve-Path -Path ($item.FullName) -Relative -ErrorAction 'SilentlyContinue';
if (-not $relativePath) { $relativePath = $item.Name; };
if ($relativePath.StartsWith(".\") -or $relativePath.StartsWith("./")) {
$relativePath = $relativePath.Substring(2);
};
[PSCustomObject]@{
Item = $item
Hash = $hash
RelativePath = $relativePath
OutputLine = "${hash} ${relativePath}"
ItemOutFile = "$($item.FullName).$($algo.ToLower())"
}
} -ThrottleLimit 16 | ForEach-Object {
$currentIndex++; $currentIndex++;
if ($showProgressGen -and $totalFiles -gt 0) { if ($showProgress -and $totalFiles -gt 0) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100); Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100);
} }
Write-Output $res.OutputLine; Write-Output $_.OutputLine;
Set-Content -Path ($res.ItemOutFile) -Value $res.OutputLine -Encoding utf8; Set-Content -Path ($_.ItemOutFile) -Value $_.OutputLine -Encoding utf8;
} };
if ($showProgressGen) {
if ($showProgress) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed; Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed;
} }
}; };
@@ -582,16 +631,35 @@ process {
$totalFiles = $allItems.Count; $totalFiles = $allItems.Count;
$currentIndex = 0; $currentIndex = 0;
$parallelResults = Invoke-ParallelHashing -Items $allItems -Algorithm $Algorithm; $allItems | ForEach-Object -Parallel {
foreach ($res in $parallelResults) { $item = $_
$algo = $using:Algorithm
$hash = (Get-FileHash -Path ($item.FullName) -Algorithm ($algo)).Hash.ToLower();
$relativePath = Resolve-Path -Path ($item.FullName) -Relative -ErrorAction 'SilentlyContinue';
if (-not $relativePath) { $relativePath = $item.Name; };
if ($relativePath.StartsWith(".\") -or $relativePath.StartsWith("./")) {
$relativePath = $relativePath.Substring(2);
};
[PSCustomObject]@{
Item = $item
Hash = $hash
RelativePath = $relativePath
OutputLine = "${hash} ${relativePath}"
ItemOutFile = "$($item.FullName).$($algo.ToLower())"
}
} -ThrottleLimit 16 | ForEach-Object {
$currentIndex++; $currentIndex++;
if ($showProgressGen -and $totalFiles -gt 0) { if ($showProgress -and $totalFiles -gt 0) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100); Write-Progress -Activity "Computing Checksums ($Algorithm)" -Status "Processing file $currentIndex of $totalFiles" -PercentComplete (($currentIndex / $totalFiles) * 100);
} }
Write-Output $res.OutputLine; Write-Output $_.OutputLine;
} };
if ($showProgressGen) {
if ($showProgress) {
Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed; Write-Progress -Activity "Computing Checksums ($Algorithm)" -Completed;
} }
}; };