Search code examples
powershellinvoke-command

Get script directory in PowerShell when script is invoked with Invoke-Command


I have a set of PowerShell scripts that include a "common" script, located in the same folder, like this:

# some-script.ps1
$scriptDir = Split-Path -Parent $myinvocation.mycommand.path
. "$scriptDir\script-utils.ps1"

This is fine if the script is called directly, e.g.

.\some-script.ps1

However, if the script is called with Invoke-Command, this does not work:

Invoke-Command -ComputerName server01 -FilePath "X:\some-script.ps1"

In this case, infact, $myinvocation.mycommand contains the contents of the script, and $myinvocation.mycommand.path is null.
How can I determine the script's directory in a way that works also when the script is invoked with Invoke-Command?

NOTE
In the end, this is the solution I actually used:

Invoke-Command -ComputerName server01 `
  {param($scriptArg); & X:\some-script.ps1 $scriptArg } `
  -ArgumentList $something

This also allows passing parameters to the script.


Solution

  • I don't believe you can, from within the invoked script. From get-help invoke-command:

    -FilePath Runs the specified local script on one or more remote computers. Enter the path and file name of the script, or pipe a script path to Invoke-Command. The script must reside on the local computer or in a directory that the local computer can access. Use the ArgumentList parameter to specify the values of parameters in the script.

     **When you use this parameter, Windows PowerShell converts the contents of the specified script file to a script
     block, transmits the script block to the remote computer, and runs it on the remote computer.**
    

    When you use invoke-command using the -filepath parameter, the script is read from the file on the local computer, converted to a script block, and that's what gets passed to the remote computer. The remote computer doesn't have any way of knowing if that script block was read from a file.

    For the remote computer to know what that original file path was, you'll have to tell it. I think the easiest way to do that would be to write a function to do the invocation, and have it pass the filename to the invoked script as a parameter.