Home > Blockchain >  Get output from `New-AzResourceGroupDeployment` including `WhatIf`
Get output from `New-AzResourceGroupDeployment` including `WhatIf`

Time:12-06

I want to write a wrapper around New-AzResourceGroupDeployment in PowerShell. So lets assume the following script:

New-AzResourceGroupDeployment `
    -Name 'test' `
    -ResourceGroupName 'rg-test' `
    -TemplateFile .\main.bicep `
    -TemplateParameterFile .\parameters\parameters.json `
    -Verbose `
    -WhatIf

This will output something like this:

VERBOSE: Using Bicep v0.4.1008
...
What if: Performing the operation "Creating Deployment" on target "rg-test".

So the problem here is that I won't get any results from the WhatIf. I guess its because WhatIf runs a different process in the background.

So is there a way to capture the output of the WhatIf?

CodePudding user response:

The output produced by using the common -WhatIf parameter can unfortunately not be captured in-session - it prints directly to the console (host).

The only workaround is to use PowerShell's CLI (powershell.exe for Windows PowerShell, pwsh for PowerShell (Core) 7 )

$whatIfAndVerboseOutput = powershell.exe -c @'
  New-AzResourceGroupDeployment `
    -Name 'test' `
    -ResourceGroupName 'rg-test' `
    -TemplateFile .\main.bicep `
    -TemplateParameterFile .\parameters\parameters.json `
    -Verbose `
    -WhatIf
'@

Not the use of a verbatim here-string (@'<newline>...<newline>'@) to avoid the need for escaping the embedded quote characters.

Caveats:

  • Such a call is expensive.

  • Since a new, independent session that runs in a child process is created, it knows nothing about the state of the caller (except that it inherits environment variables).

    • Assuming the argument data types are simple enough, you can use an expandable string ("...") to embed values from the caller in the command text.

      • Note: As of PowerShell 7.2, PowerShell's CLI, when a command string is passed to -c (-Command) - which is the only option when calling from outside PowerShell - not only sends direct-to-console output to stdout, but all of its output streams there as well - including error - which is problematic: see the bottom section of this answer for details; here, this means that the -Verbose output is captured as well.
    • Alternatively, for better - but not complete - type fidelity, pass a script block ({ ... }) to -c (-Command) instead of a string, to which you can pass values from the caller with -args. Note that using a script block is only an option when also calling from Powershell and that doing so will insert an empty line after each what-if output message.

      • Note: The script-block approach limits the output that is mapped to the caller's success stream (via stdout) to direct-to-console output (such as from -WhatIf) and the command's success-stream output. Output to any of the other streams is mapped to the corresponding streams of the caller, though you can use redirections inside the script block to merge streams into the success output stream.
        In the case at hand, the -Verbose output would be passed through to the caller's verbose stream by default and would therefore not be captured in a variable capturing the command output. However, placing 4>&1 inside the script block would include it.
  • Related