How to remotely execute a PS Script that resides on a remote server?

This topic contains 23 replies, has 2 voices, and was last updated by Profile photo of Richard Schaefer Richard Schaefer 8 months ago.

Viewing 15 posts - 1 through 15 (of 24 total)
  • Author
    Posts
  • #34615
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    I'm trying to run a script from my local server where the script resides on the remote target server. I have a UNC path to the remote script so I thought I could just point to it, but that didn't work. I saw a post somewhere about copying the script to a local variable and then use ScriptBlock to run it. The remote script does nothing but echo the parameter passed into a log file that I then copy back. I run this as a test:

    $server='myserver'
    $scriptpath='\\myserver\d$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
    $SDFEnvironment='INT'
    $script=Get-Content $scriptpath
    Invoke-Command -ComputerName $server -ScriptBlock {$script} -ArgumentList($SDFEnvironment)
    

    and it returns to the PS prompt, but when I inspect the target script directory there's no log file. Since the target script does nothing but write to the log file there should be something. Here's what I'm trying to run on the remote server:

    Param
    (
        # SDF Environment
        [Parameter(Position=0)]
        [string]$SDFEnvironment
    )
    if ($PSBoundParameters.ContainsKey('SDFEnvironment')) 
    {
    	"Script Ran Env $SDFEnvironment"|Out-File -FilePath .\$SDFEnvironment"_LogFile.txt" -Encoding ascii -Force
    }
    else
    {
    	"Environment Parameter missing"|Out-File -FilePath .\"ERR_LogFile.txt" -Encoding ascii -Force
    }
    

    Am I missing something basic? How can I tell (aside from script output) whether or not the script is actually running?

    #34617
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Rather than using a UNC, which will engage a second remote access hop, try using a local path. Also, confirm the execution policy of the remote machine.

    And -ArgumentList doesn't work quite that way.

    But mainly, your script block isn't running the script. It's merely getting the content of the script, no?

    #34618
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    How can I use a local path if the script resides on the remote server?

    If ArgumentList doesn't quite work that way, how should I code it to pass the SDFEnvironment variable to the remote script as the 0-th position parameter?

    It's supposed to run the script, but it appears it isn't.

    Note: Clearly I'm a newbie to PS. My company wants me to use it but won't pay for training. I watched three videos on MS Virtual Academy and wrote a number of local scripts that worked very well. This is my first foray into remoting.

    #34620
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    I made this change (removed the {} around the $script variable and added try..catch)

    try
    {
        Invoke-Command -ComputerName $server -ScriptBlock $script -ArgumentList $SDFEnvironment
    }
    catch
    {
        Write-Output "Error running remote script"
    }
    

    and I get this:

    Error running remote script
    

    So it looks like now it's executing the script, I just need to figure out the error which I assume is related to ArgumentList?

    #34621
    Profile photo of Don Jones
    Don Jones
    Keymaster

    – A path that's local for the remote machine. When you ask it to use a UNC, it can't, because that forces remote access and your credential can't be delegated a second time by default, so the UNC access fails.

    – The -ArgumentPath parameter is intended to pass parameters to a Param() block defines in -ScriptBlock. Below, I'm using a v4 technique to pass the local variable values to the remote machine. You'll notice that, before, even your $script variable wouldn't have worked, because $script wasn't defined on the remote machine. -ScriptBlock isn't evaluated for local variables unless you use $using.

    – You weren't trying to execute the script, you were trying to display its contents. Keep in mind that everything in -ScriptBlock is passed literally to the remote computer, which means you were having the remote computer run Get-Content. You weren't having the remote computer run Get-Content, pass the results back to you, and then somehow executing those results as a script.

    Your company's setting you up to fail, unfortunately. PowerShell has a lot of stuff that's non-obvious, and you're going to end up banging your head into it a lot. I'd at least recommend investing in "Learn PowerShell in a Month of Lunches," which is under $40, and in this specific case, "Secrets of PowerShell Remoting," which is free. Pluralsight also has some excellent PowerShell training videos and runs around $30/month. If you're going to make this a part of your career – and you should! – it might be worth a small investment of your own, so that you can eventually go find a better company.

    $server='my server'
    $scriptpath='d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
    $SDFEnvironment='INT'
    Invoke-Command -ComputerName $server -ScriptBlock {$using:script path -SDF $using:sdfenvironment}
    
    #34622
    Profile photo of Don Jones
    Don Jones
    Keymaster

    In your second case, you're now telling YOUR computer to go get the script from a file share, and then pass it to Invoke-Command to run on the remote machine.

    Frankly, there's no need to be using Try/Catch at this point in your experiment. Let it show you the actual error message (which you're suppressing by catching it) so you can see what's happening.

    #34624
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    Using the UNC with Get-Content the $script variable contains the entire remote script in a local variable. I was under the impression I could run the script on the remote machine that way. I'll try your way but I have one question:

    $server='my server'
    $scriptpath='d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
    $SDFEnvironment='INT'
    Invoke-Command -ComputerName $server -ScriptBlock {$using:script path -SDF $using:sdfenvironment}
    

    The "-SDF" – is that supposed to be the parameter designation? I need to pass it positionally. I don't know or have control over the scripts on the remote machines other than to tell them the first (0-th) parameter has to be a string with the Environment name in it. I can't tell them what to call it. I used the same name in my test remote script as my test local script because I wrote them both. It won't always be that way. Can I just leave out the "-SDF" and use:

    $server='my server'
    $scriptpath='d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
    $SDFEnvironment='INT'
    Invoke-Command -ComputerName $server -ScriptBlock {$using:script path  $using:sdfenvironment}
    
    #34625
    Profile photo of Don Jones
    Don Jones
    Keymaster

    "Using the UNC with Get-Content the $script variable contains the entire remote script in a local variable."

    Except, not really, no. You're on Computer A. You're telling Computer B to reach out to Computer B and get the contents of a script located in a file share, and then in a second step telling Computer B to execute that contents of that script. It's overwrought, and it isn't how Remoting works, really. And you're engaging a second authentication hop, which won't work. if you want Computer B running the script, you just tell it to. There's no reason to Get-Content. What you were attempting to do would involve significantly more back-and-forth than needed, even assuming you sorted out the extra (and unnecessary) authentication hop.

    "The "-SDF" – is that supposed to be the parameter designation? I need to pass it positionally."

    Yes, because in your script you defined a parameter with that name. I truncated the name, which PowerShell allows. But, if you want to pass it positionally, that's fine. Just eliminate the "-SDF."

    #34626
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    OK, so this:

    $server='ad1hfdahp802'
    $scriptpath='d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
    $SDFEnvironment='INT'
    Invoke-Command -ComputerName $server -ScriptBlock {$using:scriptpath $using:sdfenvironment}
    

    Results in this:

    At line:5 char:70
    + Invoke-Command -ComputerName $server -ScriptBlock {$using:scriptpath $using:sdfe ...
    +                                                                      ~~~~~~~~~~~
    Unexpected token '$using:sdfenvironment' in expression or statement.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : UnexpectedToken
    

    If I put the "-SDF" back in it barfs on that first. I'm running this in the ISE and in the script editor I'm getting a squiggly under the $using:sdfenvironment and when I hover over it the prompt says "Unexpected token..."

    #34627
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Oh. You're using v2 or v3. Ugh.

    $server='ad1hfdahp802'
    $scriptpath='d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
    $SDFEnvironment='INT'
    Invoke-Command -ComputerName $server -ScriptBlock {
      Param($one,$two) $one $two } -Arg $scriptpath,$sdfenvironment
    

    Which is what we had to do before $using. And, incidentally, how -ArgumentList works ;).

    #34628
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    Nope. Local computer:

    Name                           Value                                                                                                                           
    ----                           -----                                                                                                                           
    PSVersion                      4.0                                                                                                                             
    WSManStackVersion              3.0                                                                                                                             
    SerializationVersion           1.1.0.1                                                                                                                         
    CLRVersion                     4.0.30319.42000                                                                                                                 
    BuildVersion                   6.3.9600.16406                                                                                                                  
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}                                                                                                            
    PSRemotingProtocolVersion      2.2    
    

    and Remote Server:

    Name                           Value                                                                                         
    ----                           -----                                                                                         
    PSVersion                      4.0                                                                                           
    WSManStackVersion              3.0                                                                                           
    SerializationVersion           1.1.0.1                                                                                       
    CLRVersion                     4.0.30319.42000                                                                               
    BuildVersion                   6.3.9600.16406                                                                                
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}                                                                          
    PSRemotingProtocolVersion      2.2  
    

    But I'll try the alternate method anyway. I'm getting a little desperate.

    #34630
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    Here's what I got running the "old version" code:

    At line:5 char:27
    +     Param($one,$two) $one $two } -Arg $scriptpath,$sdfenvironment
    +                           ~~~~
    Unexpected token '$two' in expression or statement.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : UnexpectedToken
    
    #34631
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Well, let's take the variables out of it, because your shell isn't behaving the way I'm used to.

    Invoke-Command -ComputerName ad1hfdahp802 -ScriptBlock {
    d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1 INT
    }
    

    So just one command, all static values. Eliminate complexity.

    #34634
    Profile photo of Richard Schaefer
    Richard Schaefer
    Participant

    OK. That got somewhere. I got back:

    PS C:\users\rs02130\Desktop\Projects\AHP\xml> Invoke-Command -ComputerName ad1hfdahp802 -ScriptBlock {
    d:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1 INT }
    
    Running Script
    
    PS C:\users\rs02130\Desktop\Projects\AHP\xml> 
    

    Which show the output from the Write-Output in the script. I also have a pipe to Out-File that should create a log file on the remote server and that's not getting created. Here's the remote script boiled down to it's simplest

    Param
    (
        # SDF Environment
        [Parameter(Position=0)]
        [string]$SDFEnvironment
    )
    Write-Output "Running Script"
    "Script Ran Env $SDFEnvironment"|Out-File -FilePath .\$SDFEnvironment"_LogFile.txt" -Encoding ascii -Force
    
    #34651
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Inside your script, you're using a relative path. I wouldn't do that. You don't necessarily know what path the shell is going to default to (it won't necessarily be the path the script is located within) when it runs.

    Also, I'm not sure this:

    .\$SDFEnvironment"_LogFile.txt"

    Is producing the results you expect.

    ".\$SDFEnvironment_LogFile.txt"

    Would work better, I suspect.

Viewing 15 posts - 1 through 15 (of 24 total)

You must be logged in to reply to this topic.