Nick's Scripts
PowerShell and shell scripts published via GitHub Pages.
Available downloads
-
Deletes selected junk files and directories from a copied disk tree, with conservative defaults and full WhatIf/Confirm support.
Read more
Clear-DiskJunk scans a target path and removes only the junk categories you explicitly allow.
By default it runs in conservative mode and targets:
- browser-caches
- safe-temp-filesConservative mode avoids deleting generic directory names such as cache, temp, log, or logs unless you explicitly include
DANGEROUS-broad-temp-cache-logs.The function is designed for very large trees. It streams matches as they are found instead of accumulating all results in memory.
Use -PassThru to emit one result object per matched item. Without -PassThru it emits only a final summary object.safe-temp-files deletes:
- *.tmp files older than 30 days
- Office temp files (~$*.??? and ~$*.????)DANGEROUS-broad-temp-cache-logs expands matching to broad generic temp/cache/log locations and broad *.log / *.tmp file cleanup.
.EXAMPLE
Clear-DiskJunk -Path D:\MountedDisk -WhatIfShows what would be deleted using the conservative default categories.
.EXAMPLE
Clear-DiskJunk -Path D:\MountedDisk -IncludeCategory browser-caches,DANGEROUS-broad-temp-cache-logs -ConfirmPrompts before deleting and includes the dangerous broad cleanup category.
.EXAMPLE
Clear-DiskJunk -Path D:\MountedDisk -ExcludePath 'D:\MountedDisk\Users\Nick\AppData\Local\Google\*' -PassThru |
Export-Csv C:\temp\diskjunk-results.csv -NoTypeInformationStreams one result object per matched item and saves them.
.PARAMETER Path
Root path to scan..PARAMETER IncludeCategory
Cleanup categories to include.Allowed values:
- browser-caches
- safe-temp-files
- DANGEROUS-broad-temp-cache-logsDefault:
- browser-caches
- safe-temp-files.PARAMETER ExcludePath
Paths or wildcard patterns to exclude. Matches are tested against both full Windows paths and root-relative forward-slash paths..PARAMETER TmpOlderThanDays
Age threshold for *.tmp deletion in the safe-temp-files category. Default is 30..PARAMETER PassThru
Emits one object per matched item as it is processed. Useful for logging and large-scale runs..OUTPUTS
Without -PassThru:
A summary object.With -PassThru:
One result object per matched item, followed by a final summary object..NOTES
- Supports -WhatIf and -Confirm.
- Intended primarily for copies of Windows disks, not live system cleanup.
- Broad cleanup can remove data you may later want for troubleshooting or forensics. -
Shows a compact, admin-friendly timeline of recent boots, shutdowns,
crashes, and update-related restart signals from the System log.Read more
Use this for first-pass reboot and shutdown triage. It helps answer
whether a recent restart was clean, unexpected, crash-related, planned
by an administrator or process, or associated with Windows Updates..OUTPUTS
Produces one PSCustomObject per matching event:
Level : Event level text.
Time : Event time.
Kind : Event category. One of:
Boot, NormalShutdown, PlannedShutdownOrRestart,
WindowsUpdatesInstallStarted, WindowsUpdatesInstallCompleted,
WindowsUpdatesRestartRequired, WindowsUpdatesRestart
BugCheck, CrashDump, AbnormalShutdown,
UnexpectedShutdownFollowup, Other
Description : First line of the event message with source metadata
appended as "(id <n> from <provider>)".Intentionally excludes noise about Microsoft Defender updates.
-
A collection of helper functions for Domain Controllers
Read more
Search-ADUserAnyProperty
Search Active Directory users by a pattern across multiple common attributes.
Read more
This function wraps Get-ADUser with a wide LDAP filter that checks a user-supplied
pattern against multiple commonly used identifier attributes (e.g. sAMAccountName,
userPrincipalName, displayName, cn, givenName, sn, mail, proxyAddresses).
It's intended as a convenient "search anywhere that matters" for finding users when
you only know part of a name, email, alias, or login.Results include useful profile fields: Display Name, Department, Job Title, State,
Company, OU (derived from DistinguishedName), and all proxyAddresses flattened into
a comma-separated list. Optionally you can also search phone fields and/or restrict
the search scope with -SearchBase..PARAMETER Pattern
The text pattern to search for (wildcards are automatically added at both ends)..PARAMETER SearchBase
Optional LDAP distinguished name to scope the search..PARAMETER IncludePhones
If specified, phone-related attributes are included in the search (makes the search a bit slower).EXAMPLE
# Find any user whose name, alias, or email contains "nick"
Search-ADUserAnyProperty -Pattern 'nick'.EXAMPLE
# Search within a specific OU, also matching phone numbers
Search-ADUserAnyProperty -Pattern '2103' -IncludePhones -SearchBase 'OU=Athens,OU=Users,DC=corp,DC=example,DC=com'.EXAMPLE
# Export results to CSV
Search-ADUserAnyProperty -Pattern 'nick' |
Export-Csv C:\temp\ad-search.csv -NoTypeInformation -Encoding UTF8 -
A collection of helper functions for handling files
Read more
Get-HardLinks
Lists files in the current directory that have >1 hardlink, and shows all link paths
Read more
.EXAMPLE
Get-HardLinks|Format-List -
A collection of helper functions for Networking
Read more
Test-IpReachability
Probe point-in-time ICMP reachability for one or more IP targets.
Read more
Sends one or more ICMP echo attempts to each target and returns one output
object per unique target IP.When a ping attempt cannot be performed due to an internal runtime error,
the target result's lastStatus is set to a string beginning with
"PROGRAM EXCEPTION:"..OUTPUTS
[pscustomobject]
One object per unique target IP with properties:
- ip (string): The target IP string as provided/normalized.
- responded (bool): $true if any attempt succeeded; otherwise $false.
- attempts (int): Number of attempts made for that target.
- respondedOnAttempt (Nullable[int]): Attempt number of first success;
otherwise $null.
- rttMs (Nullable[long]): Round-trip time in milliseconds for the
successful response; otherwise $null.
- lastStatus (string): Final status observed for the target. For runtime
errors, begins with "PROGRAM EXCEPTION:"..PARAMETER Ip
One or more target IPs to probe.Accepts:
- A single value convertible to string.
- An enumerable of values convertible to string.
- A single string containing multiple targets separated by commas and/or
whitespace..PARAMETER Retry
Number of additional attempts per target after the first attempt..PARAMETER TimeoutMs
Timeout in milliseconds for each attempt..EXAMPLE
Test-IpReachability -Ip '10.1.11.50,10.1.11.55 10.1.11.56' `
-Retry 1 -TimeoutMs 500 -VerboseTest-TcpPort
Quickly tests whether a TCP connection can be established.
Read more
Tests TCP connectivity from the current machine to the specified target
and ports, and returns one result object per requested port.The target MAY be specified as an IP address or a hostname. If name
resolution fails, the function throws a terminating error.Ports are accepted in multiple input forms.
The -TimeoutMs value is a single overall time budget (in milliseconds) for
the entire batch of ports, not a per-port timeout..OUTPUTS
System.Management.Automation.PSCustomObjectOne object per normalized port, with these properties:
- port (int) The TCP port tested.
- open (bool) $true if a connection was established; otherwise $false.
- detail (string) "connected" on success; otherwise an error identifier
or "timeout" if the overall time budget was reached.Objects are emitted in ascending port order.
.PARAMETER Target
Target host to test..PARAMETER Ports
Ports to test. Accepts:
- a single integer
- an array of integers
- a string containing one or more port numbers
- an enumerable of values convertible to integers.PARAMETER TimeoutMs
Overall time budget for the entire batch, in milliseconds. Defaults to
200. When the budget is exhausted, remaining ports are reported as
"timeout"..EXAMPLE
Test-TcpPort -Target '10.1.11.1' -Ports 80,443,4444.EXAMPLE
Test-TcpPort -Target 'timesheet-gr.forvismazars.com' -Ports '80,443,4444' `
-TimeoutMs 1000Test-NetConnectivityToHost
Test-NetConnectivityToHost validates that basic network reachability to a target host matches an explicit expectation profile. What it checks - ICMP echo (ping): verifies whether the host responds to pings or not. - TCP ports (optional): - OpenPorts: ports that are expected to accept a TCP connection. - ClosedPorts: ports that are expected to refuse or time out (treated as CLOSED/FILTERED). Output / side effects - Outputs discrepancies using Write-Warning "[<level>] <message>" (<level> can be pass or failure). - If -ReturnTrueFalse is used, the function returns $true/$false and emits no warnings. Notes / interpretation - A TCP port is considered OPEN only if a TCP connect completes successfully within the timeout window. - A TCP port is considered CLOSED/FILTERED if the connect fails or does not complete within the timeout. - If OpenPorts/ClosedPorts are omitted, only the ping expectation is validated. - If -SkipPing is used, only port expectations are validated. Example Test-NetConnectivityToHost -TargetHost 10.30.0.2 -RespondsToPing:$true -OpenPorts @(53,88,135,389,445) -ClosedPorts @(22,3389) -PortTimeoutMs 1000 Example (ports only) Test-NetConnectivityToHost -TargetHost 10.30.0.2 -SkipPing -OpenPorts @(443) -PortTimeoutMs 1000 Example (boolean result only) Test-NetConnectivityToHost -TargetHost 10.30.0.2 -RespondsToPing:$true -ReturnTrueFalse
Split-IpByReachability
Splits input IPs into Alive vs NotAlive based on whether they respond to pings
Read more
Runs Test-IpReachability for the provided targets and returns a single object
containing two string arrays:
- AliveIps: IPs that responded ($true)
- DeadIps: IPs that did not respond ($false) or hit errors/timeouts.INPUTS
Same accepted shapes as Test-IpReachability -Ip..OUTPUTS
[pscustomobject] with:
- AliveIps ([string[]])
- DeadIps ([string[]])
- Results ([pscustomobject[]]) raw per-IP results (handy for lastStatus/rtt)Test-NetConnectivityToNetwork
Assesses reachability of a network by pinging a list of hosts that are known to reply.
Read more
Given a human-friendly network description (e.g. "10.11.x.y/16") and a list of
IP addresses that are expected to respond to ICMP, this function probes them
(using Split-IpByReachability) and outputs the results using:
Write-Warning "[<level>] ..."
(<level> is one of pass, notice, failure)If -ReturnListOfAliveHosts is used, the function does not emit warnings and
instead returns the list of responsive hosts.Test-ShareLikelyUp
QUICKLY tests whether the host of a UNC share is LIKELY reachable over SMB.
Read more
This is a FAST reachability test, not a definitive share-access test. A positive result means the host likely has SMB available. It does not prove that the share exists or that the current user has access to it.
Optionally verifies that at least one configured DNS server falls within an expected CIDR range (prefer to pass it so that you don't spend time on failed DNS resolutions), resolves the host to IPv4 and/or IPv6 addresses, and tests whether any resolved address accepts a TCP connection on port 445 within a short timeout. Supports hostnames, IPv4 UNC hosts, and Windows IPv6-literal UNC hosts.
.PARAMETER SharePath
UNC share path whose host will be tested..PARAMETER DnsCidrs
Optional CIDR ranges. When specified, at least one configured DNS server must fall within one of these ranges or the test returns a negative result..PARAMETER TcpTimeoutMs
For the connection test to TCP port 445 (SMB)..OUTPUTS
A PSCustomObject with the test outcome and discovered details..EXAMPLE
Test-ShareLikelyUp -SharePath '\\server01\share'.EXAMPLE
Test-ShareLikelyUp -SharePath '\\192.168.1.2\foo'.EXAMPLE
Test-ShareLikelyUp -SharePath '\\server01.contoso.local\share' -DnsCidrs '10.30.0.0/16' -
A collection of helper functions for Processes & Tasks
Read more
Quote-Win32Arg
Join-Win32CommandLine
New-ScheduledTaskForPSScript
Registers a Windows Scheduled Task that runs a PowerShell script as SYSTEM.
Read more
Creates or updates a scheduled task that runs the script specified by
-ScriptPath using Windows PowerShell (powershell.exe).The task is registered under -TaskPath and -TaskName (a default name is
chosen when -TaskName is not provided). If a task with the same name
already exists at that path, it is replaced.The task runs as the built-in SYSTEM account with highest run level. Task
settings limit concurrent executions by ignoring new starts while an
instance is already running, and apply -ExecutionTimeLimit to each run.Depending on the script path and provided arguments, the function MAY
create a .cmd wrapper file in the script's folder and configure the task
to execute that wrapper instead of invoking powershell.exe directly.If -ScheduleType is Manual, the task is created without a trigger and
will only run when started manually (or by other tooling).Supports -WhatIf and -Confirm. If confirmation is declined (or -WhatIf is
used), no task is registered and no wrapper file is created..OUTPUTS
Microsoft.Management.Infrastructure.CimInstance
A scheduled task object returned by Register-ScheduledTask when the task
is registered. If ShouldProcess declines the action, no output is
produced..PARAMETER ScriptPath
Path to an existing PowerShell script file. The path MUST exist or the
function throws before making changes..PARAMETER ScheduleType
Selects how (or whether) the task is triggered.Valid values:
- Startup: runs at system startup.
- Daily: runs daily at -Time.
- Weekly: runs weekly on -Day at -Time.
- Hourly: repeats every hour starting shortly after creation time.
- EveryMinute: repeats every minute starting shortly after creation time.
- Manual: no trigger is created..PARAMETER Time
Time of day in HH:mm (24-hour) format. Required for Daily and Weekly..PARAMETER Day
One or more weekdays. Required for Weekly..PARAMETER TaskPath
Scheduled task folder path in Task Scheduler (for example '\enLogic\').
Defaults to '\enLogic\'..PARAMETER TaskName
Scheduled task name. If omitted, a name is derived from the script file
name..PARAMETER ScriptArguments
Argument values passed to the script. Provide either -ScriptArguments or
-RawArgumentsAvoidMe, not both.Elements MAY be $null. How the script receives $null depends on the
invocation mode chosen by the function..PARAMETER RawArgumentsAvoidMe
A raw argument string appended to the invocation. Intended for advanced
cases. Provide either -ScriptArguments or -RawArgumentsAvoidMe, not both..PARAMETER ExecutionTimeLimit
Maximum runtime allowed for each task invocation. Defaults to 2 hours..PARAMETER StartItNow
If set, the function attempts to start the task immediately after it is
registered. If starting fails, the task remains created and an error is
written..EXAMPLE
New-ScheduledTaskForPSScript -ScriptPath 'C:\Ops\Health.ps1' `
-ScheduleType Startup -TaskPath '\enLogic\'.EXAMPLE
New-ScheduledTaskForPSScript -ScriptPath 'C:\Ops\Report.ps1' `
-ScheduleType Daily -Time '02:30' -TaskName 'Daily Report' `
-ScriptArguments @('Full','EU').EXAMPLE
New-ScheduledTaskForPSScript -ScriptPath 'C:\Ops\Cleanup.ps1' `
-ScheduleType Weekly -Day Monday,Thursday -Time '03:00' `
-ExecutionTimeLimit (New-TimeSpan -Minutes 30) -StartItNow.EXAMPLE
New-ScheduledTaskForPSScript -ScriptPath 'C:\Ops\OnDemand.ps1' `
-ScheduleType Manual -TaskName 'Run On Demand'.NOTES
Registers the task to run as SYSTEM with highest privileges, and sets
MultipleInstances to IgnoreNew.For Hourly and EveryMinute schedules, the first run is anchored to a
start time shortly after the function is invoked (not aligned to clock
boundaries).Invoke-DetachedPSScript
Executes a PowerShell script on a remote host as a detached process without leaving a disconnected session after execution completes.
Read more
The script or script block is executed on the remote host. Unlike
`Invoke-Command -InDisconnectedSession` once the execution terminates
it does not leave a disconnected session on the target..OUTPUTS
Produces a PSCustomObject representing the process start result:
ComputerName : The target host name.
ProcessId : The ID of the newly created remote process.
ReturnValue : The system code from the process creation attempt.
Status : The outcome of the initiation (e.g., "Success").
ExecutionPath : The path to the script being executed on the target.Get-ProcessesWithMatchingCommandLine
.DESCRIPTION List processes with command lines matching a like expression (e.g. "*myScript.ps1*") .EXAMPLE Get-ProcessesWithMatchingCommandLine "*myScript.ps1*"
Test-ExeFound
-
A collection of helper functions for handling text files
Read more
Edit-TextFile
Searches and replaces text in files while maintaining the existing text encoding (but will switch ASCII to UTF8 if replacement is unicode).
Read more
Performs an in-place regex (or literal) search/replace on a text file,
while preserving the file's actual encoding. For _really_ hard cases it
may mistake the encoding. In such cases it may fail to find the pattern
and/or change the encoding of the input file.You may pass wildcards like "*.txt" to -File.
To apply one substitution use `-Patern 'a' -Replacement 'b'`. To apply
multiple substitutions use `-ReplaceMap` (see examples).Without -Literal considers Pattern(s) to be a regex pattern.
By default keeps a backup with .bak extension. To skip the Backup
use -Backup "". To change the extension use -Backup "ext".If the sampled bytes are pure 7-bit ASCII and no BOM is present, the
function by default assumes a UTF8 encoding (even though ASCII is also
valid). This is intentional: it allows replacements to introduce Unicode
without changing the reported encoding unexpectedly. Use -DontPreferUTF8
to force ASCII encoding..OUTPUTS
Produces a psCustomObject for each evaluated file:
File = The file path
Changed = True/False
EncodingStr = Human readable encoding.
EncodingObj = The output of Get-TextFileEncoding
Details = Human readable outcome. E.g.:
"Changes made"
"Pattern(s) not found"
"Skipped too big file ..."
"Ignored empty file"
"No files matched pattern".PARAMETER MaxFileSize
Files larger than these many bytes are ignored..PARAMETER PreferISOEncodings
When set, ISO encodings are selected when multiple encodings represent
the text equivalently; otherwise, Windows encodings are selected..EXAMPLE
Edit-TextFile -file .\ansi.txt -Pattern "foo" -Replacement="_FOO_".EXAMPLE
Edit-TextFile -file .\ansi.txt -Pattern "foo?" -Replacement="_FOO_?" -Literal.EXAMPLE
Edit-TextFile -file .\ansi.txt -ReplaceMap ([ordered]@{"foo"="_FOO_"; "bar"="_BAR_"}).NOTES
The operation writes modified content to temporary storage before
replacing the target file. Original files are backed up prior to the
modification. If a terminating error occurs during the file swap, the
target file might remain in its prior state and intermediate temporary
files might remain on the storage volume.Files exceeding the configured maximum size limit or containing no
data are skipped. Substitutions are evaluated sequentially.Get-NewlineStyle
Detect newline style in a decoded string. Returns 'CRLF','LF','CR','Mixed','None','NotChecked'.
Get-TextFileEncoding
Detect (if possible) or guess the encoding of Text Files.
Read more
Uses uchardet (CLI) and simple BOM/ASCII checks.
Returns an object like this:
File : C:\tempansi.txt
Type : NON-ASCII-TEXT
BOMBytes : {}
UCharDetEncoding : ISO-8859-1
EncodingDescription : CP1252
DotNetEncodingObj : System.Text.SBCSCodePageEncoding
NewlineStyle :
BytesRead : 22
UCharDetTimeMs : 0
TotalTimeMs : 55.PARAMETER
-DontPreferUTF8: If the sampled bytes are pure 7-bit ASCII and no BOM
is present, the function returns UTF-8 by default (even though ASCII
is also valid). This is intentional: it allows later writes/replacements
to introduce Unicode without changing the reported encoding unexpectedly.
Use -DontPreferUTF8 to return ASCII instead.
In other words: The default UTF-8 return value is not a strict
"encoding detection" result; it is a compatibility policy for downstream
editing workflows.
-PreferISOEncodings: by default we return Windows encodings instead of ISO ones
WHEN BOTH PRODUCE THE SAME TEXT. This switch overides that behavior..NOTES
- Will fail for pathological files (e.g. BOM indicates UTF-8
but file is UTF-16).
- It consumes RAM to read the file's bytes, possible twice.
(That's why -MaxBytes is by default 512KB)
- It may fail in very hard cases like:
- Files larger than 512KB that appear as ASCII in the first
-MaxBytes and then have some ANSI or UTF-8 bytes.
- Files with ambiguous ASCII encodings (e.g. ISO-8859-1 /
CP1252)
- Respects -ErrorAction by emitting non-terminating errors.
- By default (without -PreferISOEncodings) it will assume a file
is encoded with a Windows(CP) encoding if it can be either
an ISO encoding (e.g. ISO-8859-1) or a windows one (e.g. CP1251)
(Since a lot of these encodings are very similar, a file with plenty
of text but none of the few characters that are encoded
differently between the ISO/CP encodings can be encoded with both giving
exactly the same bytes)For reference these are the default encoding for Notepad,
PS5 & PS7 per windows version:| | PS 5.1 | PS 5.1 | PS 7 either
Operating System | Notepad | > a.txt | Out-File | > or Out-File
2016 (1607 LTSC) | ANSI | ANSI | UTF-16 LE*| UTF-8*
2019 (1809 LTSC) | ANSI | ANSI | UTF-16 LE*| UTF-8*
2022 (21H2 LTSC) | UTF-8* | ANSI | UTF-16 LE*| UTF-8*
2025 (24H2 LTSC) | UTF-8* | ANSI | UTF-16 LE*| UTF-8*
*: UTF-8 always without BOM, UTF-16 always with BOMTODO:
Offer help on how to install uchardet if not found.Remove-TypographyUnicodeFromTextFile
Substitutes Unicode typography characters with ASCII characters in one or more target text files. Mimics the interface of Edit-TextFile.
Read more
Modifies the specified file or files (if you use wildcards like *.txt)
in place. Useful for eliminating unnecessary Unicode typography from code.You may pass wildcards like "*.ps1" to -File.
By default keeps a backup with .bak extension. To skip the Backup
use -Backup "". To change the extension use -Backup "ext"..OUTPUTS
Produces a psCustomObject for each evaluated file:
File = The file path
Changed = True/False
EncodingStr = Human readable encoding.
EncodingObj = The output of Get-TextFileEncoding
Details = Human readable outcome. E.g.:
"Changes made"
"Pattern(s) not found"
"Skipped too big file ..."
"Ignored empty file"
"No files matched pattern".PARAMETER MaxFileSize
Files larger than these many bytes are ignored..PARAMETER PreferISOEncodings
When set, ISO encodings are selected when multiple encodings represent
the text equivalently; otherwise, Windows encodings are selected..NOTES
Why we have to do the changes in three batches instead of all together:
By default, PowerShell hashtables (@{} and [ordered]@{}) use culture-sensitive
linguistic comparison.
Because 0x200B, 0x200C, and 0x200D are invisible formatting characters,
the linguistic comparer gives them a sorting weight of zero. Therefore,
PowerShell evaluates them as the exact same string and throws a "Duplicate keys"
error when building the hashtable.Replace-FileBytesSafely
Replaces a file's contents with specified bytes, optionally retaining a backup.
Read more
Behavior and guarantees:
- Writes the new content to -TmpPath first, then attempts to replace -ResolvedPath with it.
- Primary path uses [IO.File]::Replace(), which is the best option on local NTFS:
* Readers see either the old or the new file, not a partially-written file.
* A backup at -BakPath is created/overwritten as part of the replace.
- If Replace() fails (common on non-NTFS volumes, SMB shares with varying semantics, or transient locks
e.g. AV/OneDrive/indexing), it falls back to Copy-Item + Move-Item with best-effort rollback:
* This fallback is NOT atomic. It is provided for compatibility and "works in more places".
* If the move fails after the backup copy, the function attempts to restore from -BakPath.Backup semantics:
- -BakPath is always used as the safety copy when swapping.
- If -UserBackup is $true, -BakPath is considered caller-visible and is preserved.
- If -UserBackup is $false, -BakPath is a transient safety backup and may be deleted on success.Cleanup:
- Always attempts to delete -TmpPath in a finally block.
- Does not promise preservation of metadata/streams in the fallback path (ACLs, ADS, timestamps, etc.)
beyond what the underlying filesystem/provider naturally keeps..PARAMETER ResolvedPath
The existing target file to be replaced (must be on the same volume as -TmpPath for best behavior)..PARAMETER TmpPath
A temp file path in the same directory as the target (recommended) containing the new bytes to commit..PARAMETER BakPath
Path for the backup copy used during the swap. May be a user-requested backup (kept) or a transient one..PARAMETER UserBackup
Indicates whether -BakPath is user-requested (keep it) or internal/transient (delete on success)..PARAMETER Bytes
The final bytes to be written/committed to the target file..NOTES
- Intended for "in-place update" workflows: generate full new content, then commit in one swap.
- For OneDrive/SMB scenarios, transient failures are normal; callers may want a small retry policy
around the Replace() stage (if not implemented inside this function).Read-FirstBytes
Safe(shared) read of up to Count bytes from the start of a file.
Test-ExeFound
Tests whether an executable can be resolved either as a full path or via PATH/PATHEXT.
Read more
Accepts either:
- A rooted path (e.g. C:\Tools\uchardet or C:\Tools\uchardet.exe), in which case it checks existence and,
if no extension was given, also tries common executable extensions (.exe/.cmd/.bat/.com).
- A bare command name (e.g. uchardet), in which case it resolves it the same way PowerShell would when
launching a process (Get-Command + PATHEXT).
Returns $true if the executable can be found, otherwise $false.Resolve-FileFromPath
Resolve a path to exactly one existing FileSystem file ([IO.FileInfo]) or return $null.
Read more
Accepts a path (or FileInfo/DirectoryInfo) and enforces strict "one real file" semantics:
- Must exist
- Must be FileSystem provider
- Must not be a directory
- If wildcards are used, they must match exactly one itemOn failure, emits a tagged _Write-FunctionError ([RFFP-*]) including both the original input and (when available)
the resolved full path, then returns $null (caller decides whether to stop via -ErrorAction)..OUTPUTS
System.IO.FileInfo or $null.Test-BufferIsValidUtf8
Validates that a byte[] buffer is UTF-8, while intentionally tolerating an incomplete final UTF-8 sequence.
Read more
Returns $true if the buffer contains no invalid UTF-8 sequences in its body.
-
Only relevant to mazars (Install/Update mazars-prepare-laptop-code)
-
Safe* and automatic DISM + SFC repairs made easy.
Read more
Runs CHKDSK, DISM(CheckHealth/RestoreHealth) and SFC with preflight checks, concise console output, and logging.
Designed to minimize risk* and be thourough.*: REGARDING SAFETY
This script is safe to run on Windows installations with no weird customizations,
Don't use it on boxes with OEM-customized, but still WRP-protected components,
or older apps that replace protected system binaries..PARAMETER Source
Optional, one or more DISM sources, e.g. 'WIM:D:\sources\install.wim:1','ESD:E:\sources\install.esd:6'..PARAMETER ScratchDirectory
Optional scratch directory for servicing if supported (offloads staging from C:)..PARAMETER MinFreeSystemGB
Minimum free GB on system drive before running heavy servicing (default 4GB)..PARAMETER MinFreeScratchGB
Minimum free GB on ScratchDirectory if provided. (default 4GB).PARAMETER LimitAccess
Use only -Source and avoid Windows Update (WU/WSUS). Use this along with -Source. PREFER TO AVOID THIS OPTION..EXAMPLE
.\Run-DismSfc.ps1 -Source 'WIM:D:\sources\install.wim:1' -
Minimize copy-pasting and typing while using an LLM like Toula-the-fixer to troubleshoot issues.
Read more
HOW TO USE
Begin by opening a terminal and dot-sourcing this script. E.g.:$p="C:\IT\bin";$f="Start-Copy4Toula.ps1";mkdir $p -force >$null;iwr -useb https://ndemou.github.io/scripts/$f -out $p\$f; . $p\$f
Then repeat these steps:
1. Copy code from the LLM
2. Run `q` in the terminal
3. Go back to the LLM and click to paste the clipboard.Every time you run `q` it:
- Reads code from the clipboard.
- Executes it.
- Automatically copies the output back to the clipboard.It will copy up to 3000 lines by default. Change like this:
$global:SctMaxLinesToCopy = 4000If you run commands directly (without `q`) use `ccc` to copy all output
since the last time you run either `q` or `ccc`.UNDER THE HOOD
The script maintains two transcript files per PowerShell process:
1. `$env:TEMP\Toula-the-fixer-$PID.txt`
Stores the most recent chunk of output.
2. `$env:TEMP\Toula-the-fixer-$PID.full.txt`
Stores the cumulative raw history for the current session..EXAMPLE
. .\Start-Copy4Toula.ps1
q
q -
Prints a detailed warning every time it finds RAM, CPU or Disks are stressed
Read more
There are two modes of operation: monitoring and log file analysis.
In monitor mode (the default) it prints a detailed warning every
time it finds RAM, CPU or Disks are stressed.In monitor mode these switches may be used.
-MonitorVolumes: Will also monitor IO stress of Volumes
-DontMonitorDisks: Will NOT monitor IO stress of disksIn log analysis (invoked if you supply a -LogFile) it creates a
summary report based on the contents of the log file.In log analysis mode these arguments may be used.
-Granularity
-LogsToIgnoreRegex.EXAMPLE
Download & Setup to always run on startup
$bin="C:\IT\bin";$log="C:\it\log"
$f="Test-ForCpuRamDiskStress.ps1";mkdir $bin -force >$null;mkdir $log -force > $null
iwr -useb https://ndemou.github.io/scripts/$f -OutFile $bin\$f$f="helpers-processes.ps1"; iwr -useb https://ndemou.github.io/scripts/$f -OutFile $bin\$f; . $bin\$f
New-ScheduledTaskForPSScript -ScriptPath "$bin\Test-ForCpuRamDiskStress.ps1" -ScheduleType Startup -ScriptArguments "-LogDir",$log
Start-ScheduledTask -TaskPath '\enLogic\' -TaskName 'Execute Test-ForCpuRamDiskStress.ps1'
.EXAMPLE
Get statistics for a particular date
& $bin\Test-ForCpuRamDiskStress.ps1 -Granularity 10m -LogFile C:\it\log\CpuRamDiskStress.2026-01-14.log.EXAMPLE
If you want to run only once:
& C:\IT\bin\Test-ForCpuRamDiskStress.ps1 -LogDir c:\it\log -LogBaseName 'CpuRamDiskStress'.EXAMPLE
What you see if memory is under pressure.
C:\IT\bin\Test-ForCpuRamDiskStress.ps1 | Tee-Object "C:\it\temp\CpuRamDiskStress.log"20:12:47 HIGH <HOSTNAME> Reasons:
- Available memory minimum 0,5% is below the 5% threshold while average Page Reads/sec is 319, above the 150 threshold. Low headroom with active hard faults indicates real stress.
- High classification gate satisfied: Available memory(%) minimum 0,5 is below the 10% gate threshold.
Measurements:
- Time window: 18 secs (9 samples)
- Available memory: average 68,3%, minimum 0,5%
- Committed memory: average 31,9%, maximum 67,0%
- Paging file usage: maximum 73%
- Page Reads/sec (hard faults): average 319, maximum 1.789
- Page Writes/sec: average 23, maximum 203
- Transition Faults/sec: average 1.281, maximum 6.797
- Disk read latency: average 0,0 ms
- Disk write latency: average 0,0 ms
- Disk queue length: average 7,3
- Standby cache memory: Normal 58 MB, Reserve 222 MB, Core 0 MB
- File cache memory: 4 MB
- Modified page list: 134 MB
- Compressed memory: 0 MB -
Installs Windows Updates using the supported WUA COM API, with optional download, controlled reboot (now or scheduled), and detailed logging.
Read more
SPECIAL SHOW UPDATE HISTORY MODE
If -ShowHistory is used, the script does NOT install/download/reboot.
Instead it queries Windows Update history (same source as the GUI "View update history"),
optionally filtered, and then exits.NORMAL INSTALL UPDATES MODE
By default(without -ShowHistory) it installs Windows updates like this:
- Installs already downloaded updates if any.
- With -Download, will also download all required updates.
- With -Reboot, will reboot after installation if needed (or regardless with -RebootAnyway).Batches "normal" updates together; installs "exclusive" updates one-by-one; accepts EULAs.
# Regarding Robustness
- Service start is retried up to 3x with exponential delays (5s, 10s, 20s) before failing.
- Pending reboot detection uses WU `RebootRequired` and CBS `RebootPending`.
- Post-download refresh search has a catch/fallback: if the refresh search throws, proceeds using the initial search results (with a warning).
- Uses only supported, inbox components (no extra modules, no `UsoClient`, PS 5.1-safe syntax).
- Reboot is first tried without /f and after a few minutes with /f.If an update (e.g. Servicing Stack) installs and immediately requires a reboot; subsequent updates will fail with 0x80240030 until reboot. If such failures are detected and the script was run with -Reboot or -RebootAnyway,
the script will ensure continuation of installations after the reboot like this:
- Create a temporary scheduled task that runs this script again
at startup with -XXX_ResumeAfterReboot.
- On that second automated run with -XXX_ResumeAfterReboot: The startup
task is removed and the script continues as normal (install + maybe reboot).# Logging
Logs everything to `WindowsUpdateHelper-YYYY-MM-DD.log`
1. If C:\IT\LOG exists, log is created there.
2. Else if C:\IT\LOGS exists, there.
3. Else in the system temp folder..EXAMPLE
The fastest way to bring a new installation up-to-date:
**CAUTION**: WILL REBOOT WITHOUT WAITING / WITHOUT ASKING
Download & first run
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted -Force
$p="C:\it\bin";mkdir $p -force >$null
$f="WindowsUpdatesHelper.ps1";iwr -useb https://wiki.enlogic.gr/pub/KnowledgeBase/PublicFiles/$f -OutFile $p\$f
& C:\it\bin\WindowsUpdatesHelper.ps1 -Download -Reboot2nd Run (REPEAT UNTIL YOU GET 0 Updates Found)
& c:\it\bin\WindowsUpdatesHelper.ps1 -Download -Reboot -Interactive
It will also install updates that MAY ask you to accept EULAs or make choices
.EXAMPLE
Display the logs from the last 10 executions of this script
& c:\it\bin\WindowsUpdatesHelper.ps1 -ListRecentLogs | %{cat $_.fullname|sls -NotMatch '^(Machine|Host Application|Process ID|Log file|Configuration Name|Username|End time|[A-Z][a-z]*(Versions?|Edition)): '}.EXAMPLE
**CAUTION**: An unfortunate side-effect of this script is that the updates
it installs are not visible in the GUI (Settings -> Windows Updates).
The only way to view them:
& c:\it\bin\WindowsUpdatesHelper.ps1 -ShowHistory | ft
You may add -IncludeAV if you want to also view (the very frequent) Antivirus udpates.PARAMETER Download
Perform online scan and download applicable updates that are not yet downloaded, then proceed to install everything downloaded..PARAMETER Reboot
After installation, reboot only if updates require it (or regardless if -RebootAnyway is also used)..PARAMETER Interactive
If specified, the script will include updates flagged as InstallationBehavior.CanRequestUserInput
(Like some drivers/firmware that show GUI prompts and wait for user actions -- e.g. clicking "Accept").
Without this switch, such updates are skipped.
Alias: -CanRequestUserInput.PARAMETER RebootAnyway
Reboot regardless of whether updates require it (implies -Reboot)..PARAMETER XXX_ResumeAfterReboot
DO NOT USE THIS SWITCH. It is used INTERNALLY to continue installations after a reboot..PARAMETER AbortReboot
Abort a reboot initiated by this script.PARAMETER XXX_RebootNow
DO NOT USE THIS SWITCH. It is used INTERNALLY to force a reboot..PARAMETER XXX_RebootArmedAt
DO NOT USE THIS SWITCH. It is used INTERNALLY to avoid rebooting if a reboot already occured after this time..PARAMETER ShowHistory
List Windows Update history (no install/download/reboot) and exit..PARAMETER MaxResults
(ShowHistory mode) Maximum number of matching history entries to output. Default: 30. Use 0 to return all matches found (within MaxScanEntries)..PARAMETER LastDays
(ShowHistory mode) Only include history entries from the last N days..PARAMETER IncludeAV
(ShowHistory mode) Include KB2267602 (Defender definitions) entries (excluded by default)..PARAMETER MaxScanEntries
(ShowHistory mode) Safety cap: maximum number of history rows to scan. Default: 10000..PARAMETER ListRecentLogs
List this script's log files and exit. Returns FileInfo objects sorted by LastWriteTime (oldest -> newest; most recent last).
By default it returns the most recent 10 log files..PARAMETER ListAll
Used only with -ListRecentLogs. If specified, returns all log files that can be found (instead of only the most recent 10)..PARAMETER InstallOptional
Installs an optional update (needs the update ID).EXAMPLE
Install any already downloaded updates and reboot if needed:
.\WindowsUpdatesHelper.ps1 -Reboot.EXAMPLE
Download, Install and if needed reboot:
.\WindowsUpdatesHelper.ps1 -Download -Reboot.EXAMPLE
Download, Install and reboot regardless of whether updates require it:
.\WindowsUpdatesHelper.ps1 -Download -Reboot -RebootAnyway.EXAMPLE
Show latest Windows Update history entries:
.\WindowsUpdatesHelper.ps1 -ShowHistory.EXAMPLE
Show latest Windows Update history entries, include AV updates:
.\WindowsUpdatesHelper.ps1 -ShowHistory -LastDays 14 -IncludeAV.EXAMPLE
List the most recent 10 log files created by this script (most recent last):
.\WindowsUpdatesHelper.ps1 -ListRecentLogs