0

I'm trying to set some global environment variables on a target machine using the following script snippet:

Invoke-Command -ScriptBlock ${function:SetEnvironmentVariableOnTarget} -ArgumentList $location
...
function SetEnvironmentVariableOnTarget($location) 
{
try
{
    [System.Environment]::SetEnvironmentVariable($environmentVarName, $environmentVarValue, $envVarTarget)
    Write-Host "$location - Successfully set $environmentVarName=$env:environmentVarValue in $environmentVarTarget"
}
catch
{
    Write-Host "$location : ERROR: $($Error[0].Exception)"
}    
}

Where the $environmentVarName and $environmentVarValue are both strings, and $envVarTarget is an integer, which I set to 2 (Machine).

However I'm getting the following error:

ERROR: System.Management.Automation.MethodException: Cannot find an overload for "SetEnvironmentVariable" and the argument count: "3".

I have tried to access the target machine remotely, and I am able to successfully execute the above command [System.Environment]::SetEnvironmentVariable("TEST","DEMO", 2) using Powershell command line.

I have also tried to invoke the command on a remote target using [System.EnvironmentVariableTarget]::Machine , but that fails with the same error message.

Not sure why this fails.. thoughts?

RollerMobster
  • 864
  • 1
  • 10
  • 28
  • 2
    "*`$environmentVarName` and `$environmentVarValue` are both strings, and `$envVarTarget`* is an integer", you're not showing this in your [mcve]. I suggest you to confirm that in your `Catch`. Or try: `[System.Environment]::SetEnvironmentVariable([String]$environmentVarName, [String]$environmentVarValue, [Int]$envVarTarget)` – iRon Aug 15 '23 at 07:50
  • 1
    Mathias' answer provides a parameter-based solution, but ultimately your question is a duplicate of https://stackoverflow.com/q/35492437/45375. In short: Because a script block passed to `Invoke-Command -ComputerName ...` executes _remotely_, it knows nothing about the caller's _local_ variables. The simplest way to reference the caller's variable values is with the `$using:` scope. – mklement0 Aug 15 '23 at 12:51

1 Answers1

2

Where the $environmentVarName and $environmentVarValue are both strings, and $envVarTarget is an integer, which I set to 2 (Machine).

That might very well be the case in your local session - but those variables don't exist on the remote machine. That means $null is eventually passed to SetEnvironmentVariable, resulting in the error you observe:

PS ~> [System.Environment]::SetEnvironmentVariable($null, $null, $null)
Cannot find an overload for "SetEnvironmentVariable" and the argument count: "3".
At line:1 char:1
+ [System.Environment]::SetEnvironmentVariable($null, $null, $null)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest

Change your scriptblock to accept the values as parameter arguments:

Invoke-Command -ComputerName $location -ScriptBlock {
  param(
    [string]$location, 
    [string]$environmentVarName,
    [string]$environmentVarValue,
    [int]$envVarTarget)
    try {
        [Environment]::SetEnvironmentVariable($environmentVarName, $environmentVarValue, $envVarTarget)
        Write-Host "${location} - Successfully set ${environmentVarName}=${environmentVarValue} in ${environmentVarTarget}"
    }
    catch {
        Write-Host "$location : ERROR: $($Error[0].Exception)"
    }
} -ArgumentList $location, $environmentVarName, $environmentVarValue, $envVarTarget

(I made the assumption that $location is also the name of the target computer, hence ... -ComputerName $location)

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206