Skip to content

Add -Path parameter to Invoke-Formatter #775

Open

Description

@kapilmb

Invoke-Formatter takes only a ScriptDefinition parameter. The user should be able to point the cmdlet to a file for formatting. However, the following things need to be preserved when formatting a file:

  • file encoding
  • new line characters
  • indentation type {tab, space}

Activity

  1. Kriegel commented on Feb 21, 2018

    @Kriegel

    I had even no luck with Get-Content :-(
    The following produces only chaos with or without -readcount
    Invoke-Formatter -ScriptDefinition (Get-Content -Path 'C:\MyFile.ps1' -ReadCount 0)

  2. bergmeister commented on Feb 21, 2018

    @bergmeister
    Collaborator

    Peter Kriegel (@Kriegel) You need to use the -Raw option instead because -ScriptDefinition expects a string:

    Invoke-Formatter -ScriptDefinition (Get-Content -Path 'C:\MyFile.ps1' -Raw)
  3. Kriegel commented on Feb 21, 2018

    @Kriegel

    Christoph Bergmeister (@bergmeister)
    Thank you! -raw does it!

    This works even fine fo me:

    # Replace whole text in current file with formatted text
    $psise.CurrentFile.Editor.Text = Invoke-Formatter $psise.CurrentFile.Editor.Text
    

    testing with VSCode .......

  4. bergmeister commented on Feb 21, 2018

    @bergmeister
    Collaborator

    Peter Kriegel (@Kriegel) You're welcome. I had many cases in the past where -Raw was the better option and recently even when having to write tests that not only work with PowerShell 5 but also older versions like PowerShell 4 and blogged about it here:
    https://bracketsandbraces.blogspot.co.uk/2018/02/gotcha-when-developing-powershell-that.html

  5. bergmeister commented on Mar 11, 2018

    @bergmeister
    Collaborator

    I see that this issue has quite a few upvotes. Can anyone please provide details of a use case? Because VSCode has already integrated Invoke-Formatter, I do not understand why people want to use it this way, especially since using Get-Content -Raw and Set-Content in PowerShell seems to be OK as a workaround. I think stuff like preserving the encoding right, is going to be super hard.

  6. Kriegel commented on Mar 12, 2018

    @Kriegel

    I can now live with Get-Content -Raw but it is ugly and was not intuitively to find out.

    I work often with code found on the Internet even with Modules which have more then one .ps1 file.
    and i have a repository of my own old scripts

    Or you handover scripts from one Team to another ...
    Or the Team formatting rules are changed ...
    with -Path we can batch format and standardize those.

    without a -Path Parameter Invoke-Formatter seems to be intended to be used interactive in a Editor only and not made for automating (batch runs).

    Invoke-ScriptAnalyzer has a -Path Parameter as the main parameter so lets make the interfaces consistent.

    because we can....

  7. bergmeister commented on Mar 16, 2018

    @bergmeister
    Collaborator

    Peter Kriegel (@Kriegel) Thanks for the feedback. This sounds more like we could at least document an automation snippet because gluing stuff together is what PowerShell is for. The reason why implementing this is hard is because the requirements (preservation of encoding, tabs/spaces) are quite difficult to achieve, I already struggled to preserve the encoding in all cases for the -Fix switch on Invoke-ScriptAnalyzer, which re-uses some of the low-level internals of Invoke-Formatter. Applying the formatting is quite quick and easy to do for one file via Ctrl+A and Ctrl+K+F in VSCode, whereas fixing individual warnings was a pain to do manually.
    At the end of the day, you still need to validate what the formatter did (never trust software, see e.g. issue 826 for an example of a formatter bug, the formatter is a relatively new feature in PSSA), therefore applying the correction is still much less work compared to validating the correction.
    Feel free to give it a go implementing it yourself though, PRs are very welcome.

  8. Kriegel commented on Mar 28, 2018

    @Kriegel

    see: Default Encoding for PowerShell 6.0 is UTF-8 without a BOM except for New-ModuleManifest

    So i think to Support the UTF-8 without a BOM is enough, if the file is not of this encoding throw an Error and all is done.

    without batchfile Support Invoke-Formatter is in my Point of view a poor automating tool ...
    So I have the Impression that PSScriptAnalyzer only adresses in Editor (GUI) support.
    I suggest to widen it for CLI Support, because there is Need and possibility ....

    PRs ? Sorry I am IT-Pro no C-sharpy ...

    Offtopic:
    i am seeing many PowerShell Modules which are stale and have no or no good Support by the community because C# is a bunker silo for many IT-pros and most C# devlopers do not Need or avoid PowerShell.
    The development strategie of PowerShell Modules should be: less C# as possible and much PowerShell Code as possible.
    See for example the module Plaster. File structure scaffolding with XML and C# instead use of the Item-xxx cmdlets are mental crazy!
    so it is stale ...

    the support to create custom rules with PowerShell script code in this module project, is well hidden and bad documented.
    I think this Project can get much more contributions with a better support for PowerShell script code rules.

  9. felixfbecker commented on Jun 15, 2018

    @felixfbecker

    It's important to have a way to check if all files in a folder are formatted in CI, and fail the build if some are not. Every formatter I've used had this feature.

    Something like:

    Get-ChildItem -Recurse '*.ps*' |
    Get-Content -Raw |
    ForEach-Object { Compare-Object $_ (Invoke-Formatter -ScriptDefinition $_) }
  10. bergmeister commented on Jun 15, 2018

    @bergmeister
    Collaborator

    Felix Becker (@felixfbecker) You can, Invoke-ScriptAnalyzer supports that, the most common way is to use Pester integration in CI for PSSA checks. Either specify your custom format in a PSSA setting file and point the -Settings parameter to it or if you tab complete on this parameter you also get the option of choosing one of the built in ones that you know from VSCode.

  11. joaoe commented on Dec 1, 2019

    @joaoe

    Hi.

    Regarding support for InvokeFormatter -Path ....

    1. The default behavior should be to output the formatted content as a string, to avoid accidentally overwrite the file.
    2. Add an InPlace parameter to modify the file in place, instead of outputting the formatted contents, like sed.
    3. Add a Diff, DryRun or Test parameter that DOES NOT format anything but instead returns $True if any modifications would be done, or $False otherwise. This can then be used in git hooks, to verify the file was formatted before committing, or used in a CI job to check all modified files are properly formatted.

    Thank you :)

  12. metablaster commented on Jun 16, 2020

    @metablaster

    Christoph Bergmeister (@bergmeister)
    I see that this issue has quite a few upvotes. Can anyone please provide details of a use case?

    I'm also upvoting on this issue, and here is the reason why current implementation of InvokeFormatter isn't really useful.

    1. I have a bunch of scripts in my project, cca 100 of them,
    2. I want to execute formatter on entry project for all scripts. (ex. with -Recurse parameter) just like you execute Invoke-ScriptAnalyzer .\ -Recurse you also do Invoke-Formatter .\ -Recurse
    3. Expected behavior is that all scripts are recursively formatted according to settings in PSScriptAnalyzerSettings.psd1

    I don't understand why anyone would like to want to retain anything as suggested in previous posts here, ie. indentation or encoding, these things should be configurable in PSScriptAnalyzerSettings.psd1 and the formatter runs according to these rules with no exceptions.

    Yes there is default formatter in VSCode but but it's not recursive,
    This project makes use of PSScriptAnalyzerSettings.psd1 which is far superior to default formatter if you are able to apply it recursively.

    This issue is about -Path parameter, but if this is implemented then -Recurse should be implemented as well. both do the same thing anyway.

  13. bergmeister commented on Jun 16, 2020

    @bergmeister
    Collaborator

    metablaster Invoke-Formatter has a -Settings switch already. As mentioned before, you could still script it yourself at the moment with something like

    Get-ChildItem -Recurse '*.ps*' |
         ForEach-Object { Set-Content -Path $_.FullName -Value (Invoke-Formatter -ScriptDefinition (Get-Content -Raw -Path $_.FullName) ) }

    If you had the option: Would you prefer a Path option in Invoke-Formatter or rather a built in command into the vs-code extension as the latter might be easier to achieve?
    Due to the layering in the engine internals, it's actually not that straightforward to add a -Path parameter set to it. Maybe something to be considered for PSSA v2 Rob Holt (@rjmholt) ?

  14. metablaster commented on Jun 16, 2020

    @metablaster

    I'll try out the option with Get-ChildItem thanks, it's still better than manually checking formatting for each file.

    I believe it's the same (depends on context) whether the recursive formatting is built into extension or into module, what matters is that there is a default way to actually do it when you need it.

    Maybe I'm wrong but PSScriptAnalyzerSettings.psd1 seems to have more (or some unique) options than vs-code extension, so it would be natural to prefer Invoke-Formatter.

  15. bergmeister commented on Jun 16, 2020

    @bergmeister
    Collaborator

    The vs-code extension basically has individual settings for (most) settings of the formatting rules that you can specify in the psd1, therefore I consider them equivalent. People use the settings file usually for code analysis rules (same for the settingsPath setting in the extension), hence why having a Format all documents in addition to the already existing Format Document vs-code command could potentially be useful to a wider audience.

  16. metablaster commented on Aug 22, 2020

    @metablaster

    I just want to input my discovery that might help some people.

    In VSCode use search function and search for word that is located inside ALL files, examples such as:
    .SYNOPSIS, Copyright or regex Get-\w+

    Then simply use "replace all" to replace all occurrences of that word, and repeat it once again to revert of course.

    What will happen is that formatter will be invoked on your entry repository formatting all your scripts.
    Requirement is that you have your PSScriptAnalzerSettings.psd1 in place and filled with settings.

    Of course to minimize errors while doing so, add new comment into every script in your repository such as:

    ### PSScriptAnalyzerInvokeFormatter

    Now use search function and replace all occurrences with:

    ## PSScriptAnalyzerInvokeFormatter

    I find this so cool.

  17. Jiehong commented on Aug 18, 2023

    @Jiehong

    Christoph Bergmeister (@bergmeister)

    If you had the option: Would you prefer a Path option in Invoke-Formatter or rather a built in command into the vs-code extension as the latter might be easier to achieve? Due to the layering in the engine internals, it's actually not that straightforward to add a -Path parameter set to it. Maybe something to be considered for PSSA v2 Rob Holt (@rjmholt) ?

    Not everyone uses vscode, and I think people are used to having a formatter that can fix the files for you in other languages (eg: go fmt /path/to/dir, cargo fmt, even non programming projects do that such as caddy with caddy fmt --override)

    I think there is somewhat easy way to handle that: provide a new cmdlet named Invoke-ScriptFormatter, aligned with Invoke-ScriptAnalyzer.

    Invoke-ScriptFormatter could just have its own strict limitations to avoid dealing with them:

    • force utf8;
    • override by default, unless -Dry-Run is provided;
    • delegate to Invoke-Formatter the actual formatting.

    Just a QoL wrapper that woudn't require any change to Invoke-Formatter, and people could use if they want.

  18. tribals commented on Apr 9, 2025

    @tribals

    Nice to still NOT have this in 2k25!

  19. kilasuit commented on Sep 29, 2026

    @kilasuit
    Contributor

    Ideally we do need a Path Parameter, so that script formatting can be done in 1 command programmatically without larger overhead of knowing all these quirks to work through this that have been mentioned above.

    Whilst this is something longer time PowerShell Scripters/developers would be aware of, I can't see many newcomers thinking of this

    Get-ChildItem -Recurse '*.ps*' |
         ForEach-Object { Set-Content -Path $_.FullName -Value (Invoke-Formatter -ScriptDefinition (Get-Content -Raw -Path $_.FullName) ) }
    

    when, even though we "have options" I feel that the full end user experience's should be

    1. To cover current dump of content out to screen - I think this would keep the current downstream implementations bug free today but allow this to also be UI led too.

    Invoke-Formatter -Path $ScriptPath -Settings $FormattingSettings

    1. To cover a full in place replacement for multiple files - Keeping Encoding intact.

    Invoke-Formatter -Path $ScriptPath -Settings $FormattingSettings -Recurse -Overwrite

    1. Outing to a new path - still keeping encoding intact.

    Invoke-Formatter -Path $ScriptPath -Settings $FormattingSettings -OutPath $NewScriptPath

    1. Out to a new path with any dotnet available encoding. (which well utf-17 isn't as far as I know 😜)

    Invoke-Formatter -Path $ScriptPath -Settings $FormattingSettings -OutPath $NewScriptPath -OutEncoding utf-17

    Path as well as LiteralPath should be supported, here for completeness with other cmdlets that implement these parameters.

    The last two allow people that aren't source code savvy still (and even those that are), to be able to do visual side by side inspections, as opposed to needing to use file diffing tooling or even the I want to keep original source left well alone usecase.

    VSCode/PSES driven experiences would also benefit from you being able to right click a file/folder and point it to run formatting from that user experience path and whilst out scope here, is doable in there once this is added.

    As would tooling like Superlinter which is why I was looking for exactly this so that could (selfishly) more easily actually complete this PR than what the current implementation would allow for.

    My back and forth with copilot on this

    Looking at the issue, the original ask was already recognised as more than just "add a parameter" because file encoding, newline preservation, and indentation settings need handling correctly. One maintainer explicitly called out that preserving encoding would be "super hard".github

    Based on your expanded proposal, I'd split it into tiers:

    Scope Human (familiar with PSSA) Human (new to codebase) Copilot + strong reviewer
    Simple -Path for a single file, returns formatted text 1-2 hours 4-8 hours 15-30 mins
    -Path + -LiteralPath + parameter set design + tests 4-8 hours 1-2 days 1-3 hours
    In-place formatting preserving newlines and encoding 1-2 days 3-5 days 4-8 hours
    -Recurse, file discovery, filtering .ps1/.psm1/.psd1 0.5-1 day 1-2 days 2-4 hours
    -OutPath + -OutEncoding support 0.5-1 day 1-2 days 2-4 hours
    Production-quality feature ready for merge (tests, docs, edge cases, review feedback) 2-5 days 1-2 weeks 1-3 days with human supervision

    For the exact feature set you've described:

    PowerShell

    Invoke-Formatter -Path ...

    Invoke-Formatter -LiteralPath ...

    Invoke-Formatter -Recurse

    Invoke-Formatter -OutPath ...

    Invoke-Formatter -OutEncoding ...

    Show more lines

    plus:

    • encoding preservation
    • newline preservation
    • test coverage
    • cmdlet help updates
    • parameter set design
    • review comments

    I'd estimate:

    Experienced PSScriptAnalyzer contributor

    • ~16-30 hours total

    Experienced PowerShell developer but new to PSSA

    • ~24-50 hours total

    GitHub Copilot (GPT-4.1 / Claude Sonnet-class assistance) with a human driving

    • Initial implementation: 2-6 hours
    • Mergeable implementation: 8-16 hours

    GPT-5/Copilot-level capability with full repository context

    • Prototype PR: 1-3 hours
    • Review-ready PR: 4-12 hours

    The biggest uncertainty is actually not the -Path parameter itself. That's probably only a few hours of work. The majority of effort is deciding expected behaviour:

    • Should formatting be in-place by default?
    • What files count as PowerShell files?
    • How should BOMs be preserved?
    • What about mixed encodings?
    • Should -WhatIf and -Confirm be supported?
    • Should -PassThru exist?

    I'd argue in your GitHub comment that 80% of the user value comes from the first 20% of implementation effort. A minimal implementation that mirrors Invoke-ScriptAnalyzer -Path would probably be a sub-day change for a maintainer, while the full UX vision you describe is realistically a small feature project rather than a simple parameter addition.github+1

    Honestly, if a maintainer gave me this issue today and accepted "match Invoke-ScriptAnalyzer UX where sensible", I'd budget around 2-3 working days for a high-quality community PR. The actual coding would likely be under a day; tests, edge cases, and review feedback would consume the rest.

    Provide your feedback on BizChat

    Favicon typeFavicon type

    Sources

    You said:

    replace -force with -Overwrite instead I think makes sense doesn't it

    Copilot said:

    I actually think -Overwrite is the better name here.

    -Force in PowerShell tends to mean:

    • Override restrictions
    • Include hidden/system items
    • Suppress prompts
    • Access something that would otherwise be blocked

    It generally does not imply "replace the contents of a file".

    Consider these examples:

    PowerShell

    Remove-Item -Force

    Copy-Item -Force

    Move-Item -Force

    Show more lines

    In each case, -Force is really about bypassing safeguards.

    Whereas with Invoke-Formatter, you're effectively choosing between:

    PowerShell

    # Return formatted text

    Invoke-Formatter -Path script.ps1

    # Write back to original file

    Invoke-Formatter -Path script.ps1 -Overwrite

    # Write to another file

    Invoke-Formatter -Path script.ps1 -OutPath script.formatted.ps1

    Show more lines

    That reads very naturally.

    I'd probably even make it impossible to combine:

    PowerShell

    -Overwrite

    -OutPath

    Show more lines

    via parameter sets because they represent mutually exclusive actions.

    The only thing I'd challenge is whether -Overwrite should even be necessary.

    Many formatters default to modifying files:

    Shell

    prettier --write

    dotnet format

    gofmt -w

    black file.py

    Show more lines

    so a PowerShell-style design could be:

    PowerShell

    Invoke-Formatter -Path .\script.ps1

    Show more lines

    returns formatted text (current behaviour)

    PowerShell

    Invoke-Formatter -Path .\script.ps1 -Overwrite

    Show more lines

    updates file in place

    PowerShell

    Invoke-Formatter -Path .\script.ps1 -OutPath .\new.ps1

    Show more lines

    writes elsewhere

    PowerShell

    Invoke-Formatter -Path .\scripts -Recurse -Overwrite

    Show more lines

    bulk formats a tree

    That's probably the most PowerShell-esque design because it preserves backwards compatibility while making file operations explicit.

    If you raise this on the issue, I'd phrase it as:

    Rather than -Force, I think -Overwrite better communicates the intent. -Force is typically used throughout PowerShell to bypass restrictions or prompts, whereas the behaviour here is specifically replacing the contents of existing files with their formatted representation. -Overwrite and -OutPath would also naturally form separate parameter sets and make the resulting action clearer to users reading the command.

  20. linked a pull request that will close this issueAdd file-path support to Invoke-Formatter #2230on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions