GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add PSAvoidUsingNewObject Rule by DrSkillIssue · Pull Request #2109 · PowerShell/PSScriptAnalyzer

Conversation

@DrSkillIssue

@DrSkillIssue Dr. Skill Issue (DrSkillIssue) commented Jun 15, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

PR Summary

#2046

Adds a new built-in rule PSAvoidUsingNewObject that flags usage of the New-Object cmdlet and recommends using type literals with ::new() syntax instead for better performance and more idiomatic PowerShell code.

What Changed

  • New Rule: AvoidUsingNewObject
  • Severity: Warning
  • Scope: Flags New-Object -TypeName usage while preserving New-Object -ComObject (COM objects cannot use type literals)

Key Features

  • Smart COM Object Detection: Excludes New-Object -ComObject calls since they cannot be replaced with type literals
  • Parameter Splatting Support: Handles complex scenarios where parameters are passed via hashtable splatting (New-Object @params)
  • Variable Chain Resolution: Recursively follows variable assignments to determine if splatted parameters contain COM object references
  • Comprehensive AST Analysis: Supports both direct parameter usage and various splatting patterns including $using: variables

PR Checklist

  • PR has a meaningful title
    • Use the present tense and imperative mood when describing your changes
  • Summarized changes
  • Change is not breaking
  • Make sure all .cs, .ps1 and .psm1 files have the correct copyright header
  • Make sure you've added a new test if existing tests do not effectively test the code changed and/or updated documentation
  • This PR is ready to merge and is not Work in Progress.
    • If the PR is work in progress, please add the prefix WIP: to the beginning of the title and remove the prefix when the PR is ready.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

iRon7, andyleejordan, and dan-hughes reacted with thumbs up emoji
All reactions
  • 👍 3 reactions
@DrSkillIssue
feat: PSAvoidUsingNewObject
51ab704
@DrSkillIssue
Dr. Skill Issue (DrSkillIssue) requested review from Andy Jordan (andyleejordan) and Christoph Bergmeister (bergmeister) as code owners June 15, 2025 16:41
@DrSkillIssue

Dr. Skill Issue (DrSkillIssue) commented Jun 15, 2025

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DrSkillIssue Dr. Skill Issue (DrSkillIssue) mentioned this pull request Jun 15, 2025
Rule request: AvoidNewObjectCmdlet #2046
Open
@DrSkillIssue Dr. Skill Issue (DrSkillIssue) changed the title Add PSAvoidUsingNewObject Rule WIP: Add PSAvoidUsingNewObject Rule Jun 15, 2025
@DrSkillIssue
ref: Support variable resolution in hashtables and partial completions
4422b7e
@DrSkillIssue Dr. Skill Issue (DrSkillIssue) changed the title WIP: Add PSAvoidUsingNewObject Rule Add PSAvoidUsingNewObject Rule Jun 15, 2025
@DrSkillIssue
fix: Add missing Documentation
da95630
@DrSkillIssue
Dr. Skill Issue (DrSkillIssue) requested review from Mikey Lombardi (He/Him) (michaeltlombardi) and Sean Wheeler (sdwheeler) as code owners June 16, 2025 18:23
@DrSkillIssue
ref: final restructure
26c779c
@liamjpeters

Liam Peters (liamjpeters) commented Aug 17, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

👋 Hey Dr. Skill Issue (@DrSkillIssue), thanks for putting this together; you've clearly put a lot of thought into the many ways you could try and sneak a -ComObject in 😎.

Some things to look into:

  • When checking for splatting use of ComObject in a hashtable, you dismiss keys that are less than 3 characters. You do this to avoid false positives, but I'm not sure what would lead to a false positive?

    https://github.com/DrSkillIssue/PSScriptAnalyzer/blob/26c779cdf5c42da4ac5e5edc4a09e7954d8f85ad/Rules/AvoidUsingNewObject.cs#L423-L425

    Skipping 1 and 2 character keys does miss the below, which are both valid. New-Object only has 1 parameter starting with a C, so C and Co are both valid (if not ideal) ways to supply the ComObject parameter.

    $Splat = @{
        'C' = 'Word.Application'
    }
    New-Object @Splat
    
    $Splat2 = @{
        'Co' = 'Word.Application'
    }
    New-Object @Splat2
  • When a switch parameter (such as -Strict or -Verbose) precedes -ComObject in the command expression, a violation is still emitted.

    New-Object -Verbose -ComObject 'Word.Application'

    This is probably coming from the HasComObjectParameter function.

    https://github.com/DrSkillIssue/PSScriptAnalyzer/blob/26c779cdf5c42da4ac5e5edc4a09e7954d8f85ad/Rules/AvoidUsingNewObject.cs#L134-L138

    It's looping through the CommandElements of the CommandAst. Each time it encounters a CommandParameterAst it sets waitingForParamValue to true, which skips the next element (assuming it's a parameter value).

    I like to use Jason Shirk's Show-AST to visualise this stuff. CommandParameterAst can be sequential, without a variable expression or constant expression between them.

    image
  • You're getting 2 failing tests (you can run tests locally using .\build.ps1 -Test):

    1. You need to add an entry for your rule into the table in docs/Rules/README.md. The format should be obvious from all the other rules.
    2. You need to increment the rule count of the default rules. With your new rule, there'd be 71.

      PSScriptAnalyzer/Tests/Engine/GetScriptAnalyzerRule.tests.ps1

      Lines 64 to 76 in ea70855

      It "get Rules with no parameters supplied" {
      $defaultRules = Get-ScriptAnalyzerRule
      $expectedNumRules = 70
      if ($PSVersionTable.PSVersion.Major -le 4)
      {
      # for PSv3 PSAvoidGlobalAliases is not shipped because
      # it uses StaticParameterBinder.BindCommand which is
      # available only on PSv4 and above
      $expectedNumRules--
      }
      $defaultRules.Count | Should -Be $expectedNumRules
      }
  • Regarding tests: it's great that you've got so many test cases documented for passing and failing scenarios. It would be so much better if these were all individual tests.

    Currently there are only 3 tests. One for the error message description, one for there being 0 violations in one file, another for there being 20 violations in the other file.

    Small focused tests help pinpoint any future regressions and ensure coverage across edge-cases (rather than a number of violations going from 20 to 19 - it would show which test case has changed).

  • You've changed some formatting in Engine/Commands/InvokeScriptAnalyzerCommand.cs. This formatting change is the only change you're making in that file and it's not related to your new rule or this PR.

I really liked your rule documentation, lots of detail and further reading links. ⭐

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Christoph Bergmeister (bergmeister) added 2 commits December 2, 2025 22:23
@bergmeister
Merge branch 'main' into avoid-new-object
6973dfb
@bergmeister
Merge branch 'main' into avoid-new-object
b4a36e5
@bergmeister
Christoph Bergmeister (bergmeister) requested a review from a team as a code owner January 30, 2026 17:09
@bergmeister

Christoph Bergmeister (bergmeister) commented Jan 30, 2026

Copy link
Copy Markdown
Collaborator

Dr. Skill Issue (@DrSkillIssue) There are 2 test failures, can you please look into fixing them?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bergmeister
Christoph Bergmeister (bergmeister) reviewed Feb 3, 2026
View reviewed changes

@bergmeister Christoph Bergmeister (bergmeister) left a comment

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once my comments are being addressed, I'd be happy to approve, the most important one is that I think rule should not be enabled by default to start with

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Commands/InvokeScriptAnalyzerCommand.cs

@bergmeister Christoph Bergmeister (bergmeister) Dec 2, 2025

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please tidy up diff

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Rules/AvoidUsingNewObject.cs

foreach (var assignment in assignments)
{
if (assignment.Right is CommandExpressionAst cmdExpr)

@bergmeister Christoph Bergmeister (bergmeister) Feb 3, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are a few areas like this one where indentation could be reduced. Here we could e.g. negate statement and continue with next loop member so that other code can just be below at same indentation level: if (assignment.Right is not CommandExpressionAst cmdExpr) { continue; }

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings/PSGallery.psd1

@bergmeister Christoph Bergmeister (bergmeister) Feb 3, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is to replicate setting used by PSGallery to scan code when users upload new module and send email if there are violations. I don't even know whether this file is still in sync as of today but this file should only be updated by PSGallery members who know the rules used by PSGallery (and consider adding new ones).
Can you comment on whether this file is up to date and if not open separate PR to sync please alerickson ?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Engine/Settings/ScriptFunctions.psd1

@bergmeister Christoph Bergmeister (bergmeister) Feb 3, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure what the purpose of this settings file is but until then I'd not recommend touching it please

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Rules/AvoidUsingNewObject.cs
#if !CORECLR
[Export(typeof(IScriptRule))]
#endif
public class AvoidUsingNewObject : IScriptRule

@bergmeister Christoph Bergmeister (bergmeister) Feb 3, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this inheritance rule will run by default but I fear it will cause a big backlash as many people run PSSA in CI. I suggest to inherit from ConfigurableRule so that it's not enabled by default. See this PR for an example of how to: #2124

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bergmeister
Merge branch 'main' into avoid-new-object
3012097
@iRon7

iRon7 commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Despite the nice work already put in this rule, it appears to me that the PR it is stalled on a minor step:

Secondly, we add an entry for our new rule in the docs/Rules/README.md file, in the PSScriptAnalyzer Rules table. We list it as enabled by default and of Warning severity.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@iRon7

iRon7 commented Apr 24, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Dr. Skill Issue (@DrSkillIssue),

Reading more closely through the comments, I see that there is more behind the stall of this PR than thought initially.
Is there any intention to finish this PR?
Otherwise, I will pick this PSAvoidUsingNewObject rule request up by the end of this month and with that, likely start from scratch again.

Please, let me know what you are planned with this pending PR.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

andyleejordan
Andy Jordan (andyleejordan) suggested changes May 4, 2026
View reviewed changes

@andyleejordan Andy Jordan (andyleejordan) left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution Dr. Skill Issue (@DrSkillIssue) — and welcome! The rule itself is one we've previously said we'd accept (#2046), the documentation you wrote is genuinely good (clear examples, real rationale), and the variable-tracking work for splatting/$using: scenarios shows real care. Before this can land there's a mix of correctness, hygiene, and design things to work through.

CI is failing for two real reasons that need fixing:

  • The new rule isn't listed in docs/Rules/README.md. The doc-validation test enforces every rule appearing in that index.
  • Tests/Engine/GetScriptAnalyzerRule.tests.ps1 hardcodes the expected built-in rule count; that needs to bump for the new rule.

Two correctness bugs — both of which Liam Peters (@liamjpeters) already pointed out and are worth fixing with tests:

  • Switch parameters before -ComObject (e.g. New-Object -Verbose -ComObject 'Word.Application') get incorrectly flagged. The waitingForParamValue state machine assumes every CommandParameterAst is followed by a value argument, but switches don't have one — CommandParameterAst.Argument is null in that case and we should detect it.
  • The 3-character minimum length filter on hashtable keys for splat detection rules out valid abbreviations: @{ C = 'Word.App' } and @{ Co = 'Word.App' } both bind to -ComObject because PowerShell accepts any unique prefix, and New-Object only has one parameter starting with C. Removing the length floor and using prefix-based parameter resolution would handle this correctly.

Hygiene cleanup needed:

  • Engine/Commands/InvokeScriptAnalyzerCommand.cs has whitespace-only changes unrelated to the rule — please revert those.
  • Rules/Strings.resx has a few typos introduced into entries unrelated to the new rule (e.g. "equaltiy", "comaprision"). Looks like accidental rebase fallout — please restore those originals.

Design question — and this one I'd really like your view on, plus Christoph Bergmeister (@bergmeister)'s: the rule is currently added to both PSGallery.psd1 and ScriptFunctions.psd1, which means it would be enabled by default the moment we ship it. New-Object is still legitimately used in a lot of production code (especially for COM, for -Property splatting, and in modules that target older PowerShell versions), and turning a Warning on by default for the entire ecosystem is a different commitment than shipping the rule itself. I'd lean toward starting it disabled — either omitted from the default presets, or in a strict/opt-in preset only — and revisiting once we see how it lands. Curious what you think.

Test structure — non-blocking, but worth considering: the bulk-file-with-assertion-count style ($violations.Count | Should -Be 17) makes regressions hard to localize — a count drifting from 17 to 16 doesn't tell you which scenario broke. Splitting the cases into individual It blocks (one per scenario) would pay off the next time someone touches this rule. Up to you whether to do that here or as a follow-up.

Once the CI failures, the two bugs (with regression tests), and the hygiene items are addressed, and we settle the default-on question, I think this is in good shape. Happy to help if you hit anything weird.

— Drafted by Copilot (Claude Opus 4.7)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@iRon7 iRon7 mentioned this pull request May 6, 2026
Add new AvoidDynamicallyCreatingVariableNames rule #2178
Merged
6 tasks done
@bergmeister

Christoph Bergmeister (bergmeister) commented May 7, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the contribution Dr. Skill Issue (@DrSkillIssue) — and welcome! The rule itself is one we've previously said we'd accept (#2046), the documentation you wrote is genuinely good (clear examples, real rationale), and the variable-tracking work for splatting/$using: scenarios shows real care. Before this can land there's a mix of correctness, hygiene, and design things to work through.

CI is failing for two real reasons that need fixing:

  • The new rule isn't listed in docs/Rules/README.md. The doc-validation test enforces every rule appearing in that index.
  • Tests/Engine/GetScriptAnalyzerRule.tests.ps1 hardcodes the expected built-in rule count; that needs to bump for the new rule.

Two correctness bugs — both of which Liam Peters (@liamjpeters) already pointed out and are worth fixing with tests:

  • Switch parameters before -ComObject (e.g. New-Object -Verbose -ComObject 'Word.Application') get incorrectly flagged. The waitingForParamValue state machine assumes every CommandParameterAst is followed by a value argument, but switches don't have one — CommandParameterAst.Argument is null in that case and we should detect it.
  • The 3-character minimum length filter on hashtable keys for splat detection rules out valid abbreviations: @{ C = 'Word.App' } and @{ Co = 'Word.App' } both bind to -ComObject because PowerShell accepts any unique prefix, and New-Object only has one parameter starting with C. Removing the length floor and using prefix-based parameter resolution would handle this correctly.

Hygiene cleanup needed:

  • Engine/Commands/InvokeScriptAnalyzerCommand.cs has whitespace-only changes unrelated to the rule — please revert those.
  • Rules/Strings.resx has a few typos introduced into entries unrelated to the new rule (e.g. "equaltiy", "comaprision"). Looks like accidental rebase fallout — please restore those originals.

Design question — and this one I'd really like your view on, plus Christoph Bergmeister (@bergmeister)'s: the rule is currently added to both PSGallery.psd1 and ScriptFunctions.psd1, which means it would be enabled by default the moment we ship it. New-Object is still legitimately used in a lot of production code (especially for COM, for -Property splatting, and in modules that target older PowerShell versions), and turning a Warning on by default for the entire ecosystem is a different commitment than shipping the rule itself. I'd lean toward starting it disabled — either omitted from the default presets, or in a strict/opt-in preset only — and revisiting once we see how it lands. Curious what you think.

Test structure — non-blocking, but worth considering: the bulk-file-with-assertion-count style ($violations.Count | Should -Be 17) makes regressions hard to localize — a count drifting from 17 to 16 doesn't tell you which scenario broke. Splitting the cases into individual It blocks (one per scenario) would pay off the next time someone touches this rule. Up to you whether to do that here or as a follow-up.

Once the CI failures, the two bugs (with regression tests), and the hygiene items are addressed, and we settle the default-on question, I think this is in good shape. Happy to help if you hit anything weird.

— Drafted by Copilot (Claude Opus 4.7)

as previously commented I think we should not touch the settings preset files. we should just worry about defaults when running invoke-scriptanalyzer. It's up to PSGallery team to maintain this settings file, which they run when someone uploads a module to Gallery. The other file I am not sure who uses and classify it as legacy

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@iRon7 iRon7 mentioned this pull request Jun 9, 2026
Add new AvoidUsingNewObject rule #2186
Open
6 tasks done
@DrSkillIssue Dr. Skill Issue (DrSkillIssue) closed this by deleting the head repository Aug 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@bergmeister Christoph Bergmeister (bergmeister) bergmeister left review comments
@sdwheeler Sean Wheeler (sdwheeler) Awaiting requested review from sdwheeler
@michaeltlombardi Mikey Lombardi (He/Him) (michaeltlombardi) Awaiting requested review from michaeltlombardi michaeltlombardi is a code owner
+1 more reviewer
@andyleejordan Andy Jordan (andyleejordan) andyleejordan requested changes
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@DrSkillIssue @liamjpeters @bergmeister @iRon7 @andyleejordan
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.