diff --git a/Elysium.Common.ps1 b/Elysium.Common.ps1 index 3ae6967..37c9e1b 100644 --- a/Elysium.Common.ps1 +++ b/Elysium.Common.ps1 @@ -1,16 +1,13 @@ -function Restart-WithPwshIfAvailable { +function Invoke-RestartWithExecutable { param( + [string]$ExecutablePath, [hashtable]$BoundParameters, [object[]]$UnboundArguments ) - if ($PSVersionTable.PSVersion.Major -ge 7) { return } - $pwsh = Get-Command -Name 'pwsh' -ErrorAction SilentlyContinue - if (-not $pwsh) { return } + if (-not $ExecutablePath) { return } if (-not $PSCommandPath) { return } - Write-Host ("PowerShell 7 detected at '{0}'; relaunching script under pwsh..." -f $pwsh.Path) - $argList = @('-NoLogo', '-NoProfile', '-File', $PSCommandPath) if ($BoundParameters) { @@ -30,6 +27,44 @@ function Restart-WithPwshIfAvailable { $argList += $UnboundArguments } - & $pwsh.Path @argList + & $ExecutablePath @argList exit $LASTEXITCODE } + +function Restart-WithPwshIfAvailable { + param( + [hashtable]$BoundParameters, + [object[]]$UnboundArguments + ) + + if ($PSVersionTable.PSVersion.Major -ge 7 -or $PSVersionTable.PSEdition -eq 'Core') { return } + $pwsh = Get-Command -Name 'pwsh' -ErrorAction SilentlyContinue + if (-not $pwsh) { return } + Write-Host ("PowerShell 7 detected at '{0}'; relaunching script under pwsh..." -f $pwsh.Path) + Invoke-RestartWithExecutable -ExecutablePath $pwsh.Path -BoundParameters $BoundParameters -UnboundArguments $UnboundArguments +} + +function Restart-WithWindowsPowerShellIfAvailable { + param( + [hashtable]$BoundParameters, + [object[]]$UnboundArguments + ) + + if ($PSVersionTable.PSEdition -eq 'Desktop') { return } + $powershellCmd = Get-Command -Name 'powershell.exe' -ErrorAction SilentlyContinue + $powershellPath = $null + if ($powershellCmd) { + $powershellPath = $powershellCmd.Path + } else { + $defaultPath = Join-Path -Path $env:SystemRoot -ChildPath 'System32\WindowsPowerShell\v1.0\powershell.exe' + if (Test-Path -LiteralPath $defaultPath) { + $powershellPath = $defaultPath + } + } + if (-not $powershellPath) { + Write-Warning 'Windows PowerShell (powershell.exe) was not found; continuing under current host.' + return + } + Write-Host ("Windows PowerShell detected at '{0}'; relaunching script under powershell.exe..." -f $powershellPath) + Invoke-RestartWithExecutable -ExecutablePath $powershellPath -BoundParameters $BoundParameters -UnboundArguments $UnboundArguments +} diff --git a/Extract-NTHashes.ps1 b/Extract-NTHashes.ps1 index 6afd086..aebbce6 100644 --- a/Extract-NTHashes.ps1 +++ b/Extract-NTHashes.ps1 @@ -25,7 +25,7 @@ Set-StrictMode -Version Latest [string]$commonHelper = Join-Path -Path $PSScriptRoot -ChildPath 'Elysium.Common.ps1' if (-not (Test-Path -LiteralPath $commonHelper)) { throw "Common helper not found at $commonHelper" } . $commonHelper -Restart-WithPwshIfAvailable -BoundParameters $PSBoundParameters -UnboundArguments $MyInvocation.UnboundArguments +Restart-WithWindowsPowerShellIfAvailable -BoundParameters $PSBoundParameters -UnboundArguments $MyInvocation.UnboundArguments $scriptRoot = $PSScriptRoot diff --git a/README.md b/README.md index 466c780..eec9322 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Sensitive operations are confined only to the dedicated host. In the third step, This tool is provided in private git repository. Installation and updating is done with cloning and pulling from this repository. During first run, the tool will ask for passphrase that will be used to encrypt/decrypt sensitive content. After installation, edit ElysiumSettings.txt, check all variables and add domains to test. -All scripts automatically relaunch under PowerShell 7 (`pwsh`) when it is installed so that features like parallel transfers are available; if pwsh is missing they continue under Windows PowerShell 5.1 with the legacy single-threaded behavior. +All scripts automatically relaunch under PowerShell 7 (`pwsh`) when it is installed so that features like parallel transfers are available; if pwsh is missing they continue under Windows PowerShell 5.1 with the legacy single-threaded behavior. The two DSInternals-driven workflows (menu options 2 and 3) load the legacy `ActiveDirectory` and `DSInternals` modules, so they automatically fall back to Windows PowerShell even if pwsh is present. ### Update Known-Hashed Database (KHDB) Run script Elysium.ps1 as an administrator and choose option 1 (Update Known-Hashes Database). The updater now pulls a manifest plus individual hash shards (two-hex prefix layout) from the configured storage (Azure Blob or S3-compatible), verifies checksums, replaces only changed shards, and rebuilds `khdb.txt` for local use. Deleted shards listed in the manifest are removed automatically. When PowerShell 7 is available the downloader automatically fetches up to `-MaxParallelTransfers` shards in parallel (default `5`); on Windows PowerShell 5.1 it reverts to the original sequential behavior. Override the concurrency as needed when running the script directly (for example `.\Update-KHDB.ps1 -MaxParallelTransfers 8`). diff --git a/Test-WeakADPasswords.ps1 b/Test-WeakADPasswords.ps1 index e6beed9..69951c7 100644 --- a/Test-WeakADPasswords.ps1 +++ b/Test-WeakADPasswords.ps1 @@ -27,7 +27,7 @@ Set-StrictMode -Version Latest [string]$commonHelper = Join-Path -Path $PSScriptRoot -ChildPath 'Elysium.Common.ps1' if (-not (Test-Path -LiteralPath $commonHelper)) { throw "Common helper not found at $commonHelper" } . $commonHelper -Restart-WithPwshIfAvailable -BoundParameters $PSBoundParameters -UnboundArguments $MyInvocation.UnboundArguments +Restart-WithWindowsPowerShellIfAvailable -BoundParameters $PSBoundParameters -UnboundArguments $MyInvocation.UnboundArguments $VerbosePreference = "SilentlyContinue"