Home > database >  "Run without debugging" or "Start debugging" giving different result than runnin
"Run without debugging" or "Start debugging" giving different result than runnin

Time:12-14

The following test sample can be used to reproduce different outcome based on how you run it.
Prerequisites: VSCode with PowerShell extension.

Steps:

  1. Create a new *.ps1 file on your desktop and paste code below into it.
  2. Open file with VSCode, bring up terminal and run ex. .\filename.ps1
$private:PSDefaultParameterValues = @{}
$private:PSDefaultParameterValues.Add("*:ErrorVariable", " ErrorBuffer")

function Test-Variable
{
    [CmdletBinding()]
    param ()

    "Test-Variable private: '$($private:PSDefaultParameterValues | Out-String)'"
    "Test-Variable local: '$($local:PSDefaultParameterValues | Out-String)'"
    "Test-Variable script: '$($script:PSDefaultParameterValues | Out-String)'"
    "Test-Variable global: '$($global:PSDefaultParameterValues | Out-String)'"

    $ErrorBuffer = $PSCmdlet.GetVariableValue("ErrorBuffer")
    "Count of errors is $($ErrorBuffer.Count)"

    Write-Error -Message "sample error"

    "Count of errors is $($ErrorBuffer.Count)"
    $ErrorBuffer.Clear()
}

Test-Variable

Output is this:

> .\filename.ps1
Test-Variable private: ''
Test-Variable local: ''
Test-Variable script: ''
Test-Variable global: ''
Count of errors is 0
Write-Error: C:\Users\User\Desktop\filename.ps1:24:1
Line |
  24 |  Test-Variable
     |  ~~~~~~~~~~~~~
     | sample error
Count of errors is 1

Next, instead of running manually in VSCode select from menu Run -> Run Without Debugging

And here is the new output:

C:\Users\User> . 'c:\Users\User\Desktop\filename.ps1'
Test-Variable private: ''
Test-Variable local: ''
Test-Variable script: '
Name                           Value
----                           -----
*:ErrorVariable                 ErrorBuffer

'
Test-Variable global: '
Name                           Value
----                           -----
*:ErrorVariable                 ErrorBuffer

'
Count of errors is 0
Test-Variable: C:\Users\User\Desktop\filename.ps1:24:1
Line |
  24 |  Test-Variable
     |  ~~~~~~~~~~~~~
     | sample error
Count of errors is 2

Suddenly there are now 2 errors! I understand this is due to PSDefaultParameterValues not being respected, global and script scope variable is set even though I explicitly declare it as private.

You can also try Run -> Start Debugging and the result is same.

I was pulling my hair for hours trying to figure out what's wrong with my code just to discover this.

The question is, what's the issue and how to resolve it?
Is my code wrong or is there some issue with either PS extension or VSCode?

My goal is to have this code produce 1 count of errors no matter how I run it.

If you wonder the reason why I use this method, this is how I implement automated logging in PS without having to specify -ErrorVariable everywhere, the reason why PSDefaultParameterValues is private is because this ensures that only a script being called is seeing it, module scope functions and nested functions will pick it up from the caller (CmdletBinding must exist for this to work).

I don't see any other way around, this is just the smallest reproducible sample of the issue.

CodePudding user response:

The problem is that running your script via the PowerShell extension - whether with or without debugging:

  • runs the script with ., the dot-sourcing operator and ...

  • ... given that the calling scope is the global scope, your script's code effectively runs directly in the global scope.

Therefore, from your function's perspective (which script-internally runs in a child scope), the $script: and the $global: scopes are the same.


Workaround:

Create a helper script alongside your target script, say, debugHelper.ps1, with the following content:

# Call filename.ps1 in a *child* scope.
& $PSScriptRoot/filename.ps1

Then use it as the entry point for running or debugging your code.

  • Related