diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f46a7b0..75f04c7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,8 +25,8 @@ jobs: & powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\ParallelKit.Harness.ps1 exit $LASTEXITCODE - # PowerShell 7 isn't a supported target. This job is informational, to see - # whether the kit keeps working there; it isn't a required check. + # PowerShell 7 on Windows is supported alongside 5.1, so this is a required + # check too. harness-pwsh: name: Harness (PowerShell 7) runs-on: windows-latest diff --git a/ParallelKit.ps1 b/ParallelKit.ps1 index 34b84c1..8522838 100644 --- a/ParallelKit.ps1 +++ b/ParallelKit.ps1 @@ -1,6 +1,10 @@ # ParallelKit - parallel runspace jobs, bounded external-process dispatch, and # graceful Ctrl+C/window-close handling for Windows PowerShell 5.1. # +# Version 2.0 - https://github.com/HalRiveria/PowerShell-ParallelKit +# Copyright (c) 2026 HalRiveria. MIT License: keep this notice with any copy; +# the full text is in LICENSE in the repository. +# # Use: . "\ParallelKit.ps1" (dot-source it; do NOT Import-Module it) # Read README.md first - the two worker-code rules there are what keep this # from hanging or crashing. diff --git a/README.md b/README.md index d79ee65..8a9c78a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Tests](https://github.com/HalRiveria/PowerShell-ParallelKit/actions/workflows/tests.yml/badge.svg)](https://github.com/HalRiveria/PowerShell-ParallelKit/actions/workflows/tests.yml) -Run thousands of command-line programs, or blocks of PowerShell code, in parallel from Windows PowerShell 5.1, and stop cleanly when you press Ctrl+C. One file, nothing to install. +Run thousands of command-line programs, or blocks of PowerShell code, in parallel from Windows PowerShell 5.1 (or PowerShell 7 on Windows), and stop cleanly when you press Ctrl+C. One file, nothing to install. - **Process dispatch** - run many external programs, a set number at a time, with their output captured. - **Runspace jobs** - run a PowerShell worker script many times in parallel. @@ -64,7 +64,7 @@ Wrap any of them in `Invoke-PkRun { ... }` to get graceful Ctrl+C. (For `Invoke- For running PowerShell code in parallel, most of these are fine and some are simpler. ParallelKit is mainly about running external programs, and about what happens when a run is stopped partway through. -- **PowerShell 7's `ForEach-Object -Parallel`.** The easy answer if you can use PowerShell 7. ParallelKit is for scripts and machines that are stuck on 5.1. +- **PowerShell 7's `ForEach-Object -Parallel`.** The easy answer for plain parallel PowerShell code if you can use PowerShell 7. ParallelKit was built for scripts and machines stuck on 5.1, though it runs on 7 too, where it still adds the external-program handling and graceful Ctrl+C. - **`Start-Job`.** Built in, but each job is a whole new `powershell.exe` process, so every job costs noticeable startup time and memory, and what it returns comes back as serialized copies (properties only, no methods). 5.1's `Start-Job` has no throttle either, so you write the wait-for-a-free-slot loop yourself. Fine for a handful of long jobs, poor for thousands of short ones. - **ThreadJob (`Start-ThreadJob`).** Runs jobs as runspaces in the same process, with a `-ThrottleLimit`. On 5.1 it's the best fit for plain parallel scriptblocks, if you can install a module from the PowerShell Gallery (it ships with PowerShell 7, not 5.1). - **PoshRSJob (`Start-RSJob`).** A community module from the Gallery, also runspace-based, with a `-Throttle` limit and a job-style interface. For this purpose it has the same strengths and gaps as ThreadJob. @@ -82,7 +82,7 @@ What none of them do for you: ## Setup -Requires Windows and Windows PowerShell 5.1. Copy `ParallelKit.ps1` into your project and dot-source it: +Requires Windows, with Windows PowerShell 5.1 or PowerShell 7. Download `ParallelKit.ps1` from the [Releases page](https://github.com/HalRiveria/PowerShell-ParallelKit/releases) (this README describes version 2.0 and later), put it in your project, and dot-source it from your script: ```powershell . "$PSScriptRoot\ParallelKit.ps1" @@ -93,6 +93,8 @@ If you downloaded the file, Windows marks it as coming from the internet and you It works whether or not your script uses `Set-StrictMode`. +The version is in the comment block at the top of the file, so a copy kept in your project still says which one it is. That block also carries the licence notice; keep it with the file. + Dot-source it; don't `Import-Module` it. As a module it couldn't see the functions you list in `-SharedFunctionNames`. The kit's functions are also defined globally, so they stay available for the rest of that PowerShell session, and a `.GetNewClosure()` block can call them however your script was started. @@ -296,7 +298,7 @@ Other pieces: `Request-PkAbort` triggers the same abort from code. `Test-PkAbort ## Limits -- Windows PowerShell 5.1, Windows only (console and Job Object APIs). +- Windows only (console and Job Object APIs). Built for Windows PowerShell 5.1; PowerShell 7 on Windows passes the same test suite. - Run it in a PowerShell console window or an editor's terminal (graceful Ctrl+C tested in Windows Terminal and Visual Studio's built-in terminal). The Windows PowerShell ISE isn't supported: tested there, the kit loads and runs, but the ISE has no console, so Ctrl+C stops the script outright, with no graceful drain and no cleanup callbacks. - It needs FullLanguage mode, since it compiles a little C# with `Add-Type` when loaded. On a machine locked down to Constrained Language Mode (usually by AppLocker or Windows Defender Application Control), loading it fails with a message saying so. Some endpoint security products also flag scripts that compile code calling Windows APIs at runtime; if yours blocks the kit, that's the likely reason. - After changing `ParallelKit.ps1` itself, start a new PowerShell window. A session keeps the kit's compiled parts until it closes; the kit tells you if it finds an older copy loaded. @@ -316,7 +318,7 @@ powershell -NoProfile -File .\ParallelKit.Harness.ps1 It uses real runspaces and real child processes (`cmd.exe`, `ping.exe`), with nothing mocked, so it takes about a minute. It prints a `[PASS]`/`[FAIL]` line per check and exits 0 only if everything passed. A few `message handler failed` lines in the output are expected: some checks break the message handler on purpose to test the fallback. -GitHub runs the same harness on Windows PowerShell 5.1 for every pull request and every change to `main`. +GitHub runs the same harness on Windows PowerShell 5.1 and on PowerShell 7 for every pull request and every change to `main`. ## FAQ @@ -330,7 +332,7 @@ It hasn't been tested with them. The cause is in PowerShell itself, not in this **Does it work in PowerShell 7, or on Linux or macOS?** -It's written for and tested on Windows PowerShell 5.1 only. Ctrl+C handling, child-process cleanup and keep-awake all use Windows APIs, so Linux and macOS are out. On PowerShell 7 for Windows it isn't tested, and `ForEach-Object -Parallel` covers most needs there anyway. +PowerShell 7 on Windows, yes: Windows PowerShell 5.1 is the main target, but the full test suite runs on both for every change. Linux and macOS are out, since Ctrl+C handling, child-process cleanup and keep-awake all use Windows APIs. On 7, `ForEach-Object -Parallel` is simpler for plain parallel PowerShell code; the kit is still useful for running external programs and for stopping cleanly on Ctrl+C. **Does it need admin rights?**