The outputs below come from running each step against the example script. What you need:
- DetentShell, open. The transforms ship with the app; if the dialog reports the feature unavailable, the transforms module is missing from the install.
Press Ctrl+N and paste this. It works, and it has the problems reviewers flag: parameters accept anything, failures are unhandled, and the deletion runs with no safety net.
function Clear-OldLogs {
param(
[Parameter(Mandatory)]
$LogFolder,
$DaysToKeep = 30
)
$cutoff = (Get-Date).AddDays(-$DaysToKeep)
$old = Get-ChildItem -Path $LogFolder -Filter *.log |
Where-Object { $_.LastWriteTime -lt $cutoff }
foreach ($file in $old) {
Remove-Item $file.FullName
}
Write-Output "Removed $($old.Count) old log files from $LogFolder"
}
Put the caret inside the function and pick Edit > Quick Fix (right-click works too). A dialog lists the five transforms. Each row is either applicable, with a Preview, or declined, with its reason stated in a sentence. Your script hasn’t changed; the analysis ran against a copy.
Open the preview for try/catch wrapping: your function on the left, the proposed version on the right. On this script it wraps three statements and leaves one alone. The Remove-Item call comes back like this:
# wrapped by Add-MWTryCatch v1.24.0
try {
Remove-Item $file.FullName
}
catch [System.IO.FileNotFoundException] { throw }
catch [System.IO.DirectoryNotFoundException] { throw }
catch [System.UnauthorizedAccessException] { throw }
catch [System.IO.IOException] { throw }
catch { throw }
Two things to notice. The catch blocks are typed for the failures a file operation can produce, so you can later handle a missing file differently from a permissions problem. And Write-Output was skipped, with the reason recorded: it’s on the always-safe list, and wrapping it would add noise without protection.
Click Apply. The change splices into the enclosing function and nothing else in your buffer moves. Cancel, at any point in this dialog, leaves the buffer byte-identical to how you found it.
- Strict mode inserts
Set-StrictMode -Version Latestat line 1. This is the one transform that considers your whole file rather than just the function. - Parameter validation adds
[ValidateNotNullOrEmpty()]above the mandatory$LogFolder, and declines$DaysToKeepwith the reason that it has no[Parameter(Mandatory)]attribute. Mandatory parameters are the scope of this transform in the current version. - Dangerous-command guard reports nothing to guard here. It watches for command-execution risks:
Invoke-Expression, dynamicInvoke-Command, andAdd-Typewith inline type definitions. When it finds one, it injects a warning above the call site. - Secure error messages reports there are no catch blocks to secure in the original script. It acts when a catch block echoes exception detail into output, where it can leak paths or connection information.
On a function that passes user text to Invoke-Expression, the guard’s injected line looks like this:
Write-Warning "DangerousCmdlet: Invoke-Expression at line 3 -- review before shipping (MWGUARD)"
A transform reporting “nothing to do” is a result, not a failure. The list tells you where your script already stands.
Open a new tab and paste:
Set-StrictMode -Off
function Get-LooseValue {
param($Name)
$settings = @{ Retries = 3 }
return $settings[$Name]
}
Run Quick Fix. The strict-mode row declines, and its reason reads:
This script explicitly turns strict mode off; that looks deliberate, so this won’t override it.
There’s no do-it-anyway on this one; if you want strict mode here, remove the -Off line yourself. Other refusals, where overriding is reasonable, carry a do-it-anyway row so the choice stays yours.
Every applied change carries a comment naming the tool and version that made it, like the # wrapped by Add-MWTryCatch v1.24.0 line in step 3. In a code review or a diff six months from now, tool-applied hardening stays distinguishable from hand-written logic, which is exactly what a reviewer wants to know.
- The dialog reports the feature unavailable: the transforms module (ModuleWorkshop.Transforms) is missing from the install.
- Your wrap counts differ: expected, if your function differs from the example. Statements already wrapped, and cmdlets on the always-safe list, are left alone with the reason recorded.
The Quick Fix wiki page covers the feature per audience, and the blog series has a post on why every transform previews before it applies.
PS> Start-Process "https://detentpoint.com/detentshell/download"
# Coming soon — ships once the installer is code-signed
Coming soon. DetentShell launches at $29.99 in the Microsoft Store for its first two weeks. The regular price that follows is not final yet and will be published here first; volume licensing for teams is handled separately.