简体   繁体   中英

Difference between Set-Variable foo -Scope Global -Value “bar” and $global:foo = “bar”

What is the difference between Set-Variable foo -Scope Global -Value "bar" and $global:foo = "bar"

I have seen that Set-Variable implements -WhatIf/-Confim so the assignment only happens if these are not set or the action is confirmed whereas the assignment happens regardless. Is there anything else lurking?


UPDATE

Following is an example of how the 2 are different in the presence of -Whatif / -Confirm:

Clear-Variable foo -ErrorAction:SilentlyContinue # just in case
Function repro {
    [CmdletBinding(SupportsShouldProcess)] Param()
    Set-Variable foo -Scope Global -Value "bar"
}
repro -WhatIf
Write-Host "`$global:foo=$($global:foo)"

You should see:

What if: Performing the operation "Set variable" on target "Name: foo Value: bar".
$global:foo=

However:

Clear-Variable foo -ErrorAction:SilentlyContinue # just in case
Function repro {
    [CmdletBinding(SupportsShouldProcess)] Param()
    $global:foo = "bar"
}
repro -WhatIf
Write-Host "`$global:foo=$($global:foo)"

Now you get:

$global:foo=bar

The difference isn't much but the Set-Variable has a few more options available to it than just a regular assignment expression. It's just a matter of how verbose you want to be with your syntax and what you are trying to accomplish.

Assignment Expressions

These are simple, quick variable assignments not much to it.

$foo = "bar"
# If you want to change scope, add it
$global:foo = "bar"
$script:foo = "bar"

Set-Variable CmdLet

As you've pointed out, the Set-Variable Cmdlet has a few more options with it, like -WhatIf and -Confirm . It also has a few other options like setting the type of variable with -Option and -PassThru . -Option allows for the setting of constants, readonly variables, or private scoped variables. -PassThru is pretty useful to and I'll give an example below. A couple more parameters are also available to so review them here

Why PassThru is cool

# PassThru executes your Set-Variable and then continues to
# pass the variable through the pipeline so with it you can 
# assign your variable and then immediately start working with it
Set-Variable -Name "FooArr" -Value @("bar", "baz", "boom") -PassThru | ForEach-Object {
    $_.Value
}
$FooArr # Still assigned
bar
baz
boom

Working with Constants

# Constant
Set-Variable -Name "ImAConstant" -Value "Try to delete me" -Option Constant
Remove-Variable -Name "ImAConstant"
# Error
Remove-Variable : Cannot remove variable ImAConstant because it is constant or 
read-only. If the variable is read-only, try the operation again specifying the Force 
option.
At line:2 char:1
+ Remove-Variable -Name "ImAConstant"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (ImAConstant:String) [Remove-Variable], Ses 
   sionStateUnauthorizedAccessException
    + FullyQualifiedErrorId : VariableNotRemovable,Microsoft.PowerShell.Commands.Remo 
   veVariableCommand

Working with Read only

Set-Variable -Name "ImReadOnly" -Value "Delete me" -Option ReadOnly
Remove-Variable -Name "ImReadOnly" -Force # Removed

These are just a few examples. Pretty cool stuff.

Update to OP Update

In your function repro , you use SupportsShouldProcess in your CmdLetBinding() but you still need to block it up for your assignment with some code for it to run the way you are thinking.

Function repro {
    [CmdletBinding(SupportsShouldProcess)] Param()
    if ($pscmdlet.ShouldProcess('$global:foo', "Sets Variable")){
        $global:foo = "bar"
    }
}

This will produce the same result as your original Set-Variable call with -WhatIf .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM