Using the 'Run Script' operator to run a PowerShell script on a remote Windows machine

Document created by IanRich on Dec 3, 2015Last modified by IanRich on Dec 23, 2015
Version 2Show Document
  • View in full screen mode

Hi Everyone,

 

I have often run into a situation where I have been asked to collect some data or perform a small task on a Windows Server.

 

I don't really like having to install the CAPA Agent on the server just to perform small tasks, as where I work that involves a big pile of paperwork, change controls, and then the future responsibility for maintaining the agent!

 

Once of the ways I have found to avoid having to install agents, is to use PowerShell Remoting to run the action(s) that I am looking for on the remote server.

As there are already lots of articles out there in Google-Land about configuring and setting up PowerShell Remoting, I won't be covering that aspect of the process.

 

Once you know a remote server can be accessed, on the CAPA side, executing a PowerShell Remoting session is really pretty easy.

(I generally develop my PowerShell code locally on my PC, and then add it to the code in CAPA once I know it works (mostly) the way I want it to)

 

While there are several ways to invoke a remote PowerShell session, in this example I will be using the Invoke-Command

 

With Invoke-Command you can either pass a block of script, or a local (to the agent, not the remote host) file name:

-ScriptBlock { **PowerShell Commands Go Here ** }

-FilePath **Path to a local file that contains the PowerShell code**

 

The process is basically two steps:

  1. Create temporary local file(s) on an Agent
  2. Using the Run Script operator to have PowerShell invoke the remote session.

 

I have also built in some basic checks like getting the real server host name (as the Invoke-Command will usually fail when using a DNS alias), and validating the server is responding.

 

Step 1: Create the remote (on the agent) files, for the purposes of this example, I have included two simple PowerShell scripts you can use to see if the remoting works.

 

This one I called "TEST_Working.ps1"

# ** START **

Param(

  [string]$Environmemt

)

$X = "SUCCESS - " + $Environmemt

$X

# ** END **

 

And this one I called: "TEST_Failed.ps1"

# ** START **

Param(

  [string]$Environmemt

)

$x = 5 / 0

$X = "SUCCESS - " + $Environmemt

# ** END **

 

 

Step 2: Insert a Run Script operator

 

  • Change: Script extension to .ps1
  • Assign the following parameters to the script (and don't forget to create/set them in the process).

[0] Process.AD_Username                    The AD Username that has access to the remote server

[1] Process.AD_Password                     The AD Password for the username

[2] Process.DestinationServerName     The FQDN of the server (can be an Alias if you use the GetHostByName func)

[3] Process.PowerShellFileName          The full path & filename to the PS1 file on my Agent/Orchestrator

[4] Process.Remote_Environment         This is just an example variable that I will be passing to the remote script, so it can pass it back in the output.

  • Post output to dataset variable - Checked (since you want to know what is going on)
  • I always also set the Target, under the Execution Settings, to make sure that the Run Script operator will run on the same Agent/Orchestrator Node that I created the file on (when I do it dynamically in-process).

 

Inline Script Code:

# ** Start of Inline Script for Run Script Operator**

Param(

[string]$Remote_Username,

[string]$Remote_Password,

[string]$RemoteComputer,

[string]$LocalTmpPowerShellScriptFile,

[string]$Environment

)

 

$SECURE_Password = convertto-securestring $Remote_Password -asplaintext -force

$Remote_Credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $Remote_Username, $SECURE_Password

 

try

{

    $ServerName = ([System.Net.Dns]::GetHostByName($RemoteComputer)).HostName

}

catch

{

    write-host "Exception: "$_.Exception.Message

    Throw $_.Exception

}

 

 

If (Test-Connection -ComputerName $ServerName -Quiet)

{

    try

        {

            Invoke-Command -Credential $Remote_Credentials -ComputerName $ServerName -ErrorAction Stop -FilePath $LocalTmpPowerShellScriptFile -ArgumentList $Environment

        }

    catch

        {

            write-host "Exception: "$_.Exception.Message

            Throw $_.Exception

        }

}

else

{

    Throw "Failed to connect"

}

# ** End of Inline Script **

 

Step 3: Set your variables, and run the process!

Don't forget, the PowerShellFileName should be the full path to the file on the Agent!

 

If you run TEST_Working.ps1, passing the environment variable of "Production" you should see the following:

If you run TEST_Failed.ps1, passing the environment variable of "Production" you should see the following:

 

If you run either of them, and it fails with one of the following messages, it means the AD_Username/AD_Password are incorrect, or the AD account does not have access to the remote server.

    • Exception:  Connecting to remote server (servername) failed with the following error message : Access is denied. For more information, see the about_Remote_Troubleshooting Help topic. Connecting to remote server (servername) failed with the following error message : Access is denied. For more information, see the about_Remote_Troubleshooting Help topic.
    • Exception:  Connecting to remote server (servername) failed with the following error message : Logon failure: unknown user name or bad password. For more information, see the about_Remote_Troubleshooting Help topic. Connecting to remote server (servername) failed with the following error message : Logon failure: unknown user name or bad password. For more information, see the about_Remote_Troubleshooting Help topic.

 

 

I hope you guys find this little trick will come in handy as much as I do!

 

 

Ian Rich

Sr. Automation Analyst, IT Operations Management

CN Rail

1 person found this helpful

Attachments

    Outcomes