2

I'm trying to set an environment variable via TFS Releasemanagement by invoking a powershell script which should open a remote session on a machine and set the environment variable.

param(
[Parameter(Mandatory=$true)][String]$RemoteComputers,
[Parameter(Mandatory=$true)][String]$UserName,
[Parameter(Mandatory=$true)][String]$Password,
[Parameter(Mandatory=$true)][String]$Environment
)

$credential = New-Object System.Management.Automation.PSCredential($UserName , (ConvertTo-SecureString -String $Password -AsPlainText -Force));
$remoteMachines = $RemoteComputers -split ","

$remoteMachines | ForEach-Object {
    $machineBlock = {
        $machineName = $args[0]
        $credentials = $args[1]

        Write-Host $machineName

        $scriptBlockSetEnvironmentVariable = {
            $environment = $args[0]

            Write-Host "ScriptBlockSetEnvi$environmentVariable $environment"
            [System.Environment]::SetEnvironmentVariable('ASPNETCORE_ENVIRONMENT', $environment , [System.EnvironmentVariableTarget]::Machine)
        }

        Write-Host "========================================================================================"
        Write-Host "@#@#@ Opening remote session to $machineName"
        $session = New-PsSession -ComputerName $machineName -Credential $credentials
        Invoke-Command -Session $session -ScriptBlock $scriptBlockSetEnvironmentVariable -ArgumentList $Environment
        Remove-PSSession -Session $session
        Write-Host "@#@#@ Session Closed"
        Write-Host "========================================================================================"
    }

    Write-Output "Starting job on $_"
    Start-Job -Name $_ -ScriptBlock $machineBlock -ArgumentList $_, $credential
}

Write-Host "Waiting for all jobs to finish"
Wait-Job -Name $remoteMachines
$remoteMachines | ForEach-Object {
    Write-Host "Getting output for $_"
    Receive-Job -Name $_
    Write-Host "------------------------------------------------"
}

When starting the script from my machine like this:

PS C:\temp\ps> .\setEnvVarRemote.ps1 MYSERVER -UserName "MYUSERNAME" -Password "MYPASSWORD" -Environment "Test"

I get the following output

Starting job on MYSERVER

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
9      MYSERVER        BackgroundJob   Running       True            localhost            ...
Waiting for all jobs to finish
1      MYSERVER        BackgroundJob   Completed     False           localhost            ...
3      MYSERVER        BackgroundJob   Completed     False           localhost            ...
5      MYSERVER        BackgroundJob   Completed     False           localhost            ...
7      MYSERVER        BackgroundJob   Completed     False           localhost            ...
9      MYSERVER        BackgroundJob   Completed     True            localhost            ...
Getting output for MYSERVER
MYSERVER
========================================================================================
@#@#@ Opening remote session to MYSERVER
ScriptBlockSetEnvi
@#@#@ Session Closed
========================================================================================
------------------------------------------------

Unfortunately the environment variable is not set and I don't get an error message... what am I doing wrong?

My user has admin rights and the password is correct.

Thanks in advance

4
  • 1
    Why are you running a job on localhost that runs Invoke-Command on a remote host? Just run Invoke-Command -Computer $remoteMachines .... Add -AsJob if required. Also, what makes you think the environment variable is not set? How did you verify? Commented Oct 17, 2019 at 10:32
  • I did check the command that you inported from System.Environment locally and it worked. My question is why do you dont run TFS task of "Run Powershell on target machines" ? It is a built in job that you can entry there the credentials,list of machine names And all job left to done is to fire the SetEnvironment command. Commented Oct 17, 2019 at 11:30
  • As an aside: Please avoid pseudo method syntax: instead of New-Object SomeType(arg1, ...), use New-Object SomeType [-ArgumentList] arg1, ... - PowerShell cmdlets, scripts and functions are invoked like shell commands, not like methods. That is, no parentheses around the argument list, and whitespace-separated arguments (, constructs an array as a single argument, as needed for -ArgumentList). Commented Oct 17, 2019 at 11:56
  • The way you build your credential is insecure. Either ask for input of the credential each time if this is an interactive script ($cred = Get-Credential or $cred = Get-Credential "[email protected]" will suffice), or use Get-Credential to create the credential object, then dump the credential object to disk using Export-CliXml for which can be later read by Import-CliXml by that same user on that same machine for automation later. Commented Oct 21, 2019 at 15:13

1 Answer 1

4

This should be enough, you're over-complicating the code with the use of sessions and your Foreach-Object loop:

$result = Invoke-Command -ComputerName $remoteMachines -Credential $credentials -ArgumentList $Environment {
  [System.Environment]::SetEnvironmentVariable( 'ASPNETCORE_ENVIRONMENT', $args, [System.EnvironmentVariableTarget]::Machine )
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.