6

问题

我正在与 Jenkins 合作远程部署 PowerShell 脚本。因此,我试图弄清楚使用$PSScriptRootover$MyInvocation.MyCommand.Path获取当前脚本根目录是否会出现问题。

细节

一位同事顺便告诉我,使用$PSScriptRoot远程功能不是一个好主意,因为我偶尔会发现它在运行时由于某种原因不会返回预期值,即使它以前有效。但是,无法解释为什么会这样。

在我的研究中,我没有发现任何可以进一步解释这一点或避免此类问题的最佳实践方法是什么。我主要发现这两者基本上是可以互换的;但是,$PSScriptRoot只能PowerShell v3 或更高版本中使用。通过你们中的几个人的帮助,我也开始了解到,它$MyInvocation具有情境差异,可以根据范围和模块进行更改。但我仍然没有发现这是否或为什么会成为 PowerShell Remoting 的问题。

示例 001
所以我在 Jenkins 中有一个 PowerShell 脚本,它$PSScriptRoot用作查找我希望通过相对路径调用的脚本的方法。我能否依靠它来始终为所述脚本提供相同/预期的路径?

示例 002
使用由 Jenkins 启动的 PowerShell 脚本调用的 PowerShell 脚本,我是否能够期望$PSScriptRoot能够为我提供该脚本实际所在的路径,或者它会给我一个基于 Jenkins 的路径?

就个人而言,我希望两者都能$PSScriptRoot为我提供正在运行的脚本的实际物理位置,而不是根据调用它的初始脚本而改变的相对路径。

由于有了这种理解可以帮助我节省很多时间和头痛,我希望像你这样的程序员同行可以帮助我了解如果这是真的,以及为什么会发生这样的问题。

问题

我试图找出使用$PSScriptRoot是否会导致我在 PowerShell Remoting 中出现问题,从而使使用$MyInvocation更可行的选项?

4

2 回答 2

6
$PSScriptRoot.GetType().FullName
> System.String
$PSScriptRoot
> C:\Temp

$PSScriptRoot是一个自动变量,它只保存当前脚本目录的字符串对象。

$MyInvocation.GetType().FullName
> System.Management.Automation.InvocationInfo
$MyInvocation
> MyCommand             : test.ps1
> BoundParameters       : {}
> UnboundArguments      : {}
> ScriptLineNumber      : 0
> OffsetInLine          : 0
> HistoryId             : 4
> ScriptName            : 
> Line                  : 
> PositionMessage       : 
> PSScriptRoot          : 
> PSCommandPath         : 
> InvocationName        : C:\Temp\test.ps1
> PipelineLength        : 2
> PipelinePosition      : 1
> ExpectingInput        : False
> CommandOrigin         : Internal
> DisplayScriptPosition : 

$MyInvocation | Get-Member -Force
   TypeName: System.Management.Automation.InvocationInfo

Name                      MemberType   Definition                                                             
----                      ----------   ----------                                                             
pstypenames               CodeProperty System.Collections.ObjectModel.Collection`1[[System.String, mscorlib...
psadapted                 MemberSet    psadapted {MyCommand, BoundParameters, UnboundArguments, ScriptLineN...
psbase                    MemberSet    psbase {MyCommand, BoundParameters, UnboundArguments, ScriptLineNumb...
psextended                MemberSet    psextended {}                                                          
psobject                  MemberSet    psobject {BaseObject, Members, Properties, Methods, ImmediateBaseObj...
Equals                    Method       bool Equals(System.Object obj)                                         
GetHashCode               Method       int GetHashCode()                                                      
GetType                   Method       type GetType()                                                         
get_BoundParameters       Method       System.Collections.Generic.Dictionary[string,System.Object] get_Boun...
get_CommandOrigin         Method       System.Management.Automation.CommandOrigin get_CommandOrigin()         
get_DisplayScriptPosition Method       System.Management.Automation.Language.IScriptExtent get_DisplayScrip...
get_ExpectingInput        Method       bool get_ExpectingInput()                                              
get_HistoryId             Method       long get_HistoryId()                                                   
get_InvocationName        Method       string get_InvocationName()                                            
get_Line                  Method       string get_Line()                                                      
get_MyCommand             Method       System.Management.Automation.CommandInfo get_MyCommand()               
get_OffsetInLine          Method       int get_OffsetInLine()                                                 
get_PipelineLength        Method       int get_PipelineLength()                                               
get_PipelinePosition      Method       int get_PipelinePosition()                                             
get_PositionMessage       Method       string get_PositionMessage()                                           
get_PSCommandPath         Method       string get_PSCommandPath()                                             
get_PSScriptRoot          Method       string get_PSScriptRoot()                                              
get_ScriptLineNumber      Method       int get_ScriptLineNumber()                                             
get_ScriptName            Method       string get_ScriptName()                                                
get_UnboundArguments      Method       System.Collections.Generic.List[System.Object] get_UnboundArguments()  
set_DisplayScriptPosition Method       void set_DisplayScriptPosition(System.Management.Automation.Language...
ToString                  Method       string ToString()                                                      
BoundParameters           Property     System.Collections.Generic.Dictionary[string,System.Object] BoundPar...
CommandOrigin             Property     System.Management.Automation.CommandOrigin CommandOrigin {get;}        
DisplayScriptPosition     Property     System.Management.Automation.Language.IScriptExtent DisplayScriptPos...
ExpectingInput            Property     bool ExpectingInput {get;}                                             
HistoryId                 Property     long HistoryId {get;}                                                  
InvocationName            Property     string InvocationName {get;}                                           
Line                      Property     string Line {get;}                                                     
MyCommand                 Property     System.Management.Automation.CommandInfo MyCommand {get;}              
OffsetInLine              Property     int OffsetInLine {get;}                                                
PipelineLength            Property     int PipelineLength {get;}                                              
PipelinePosition          Property     int PipelinePosition {get;}                                            
PositionMessage           Property     string PositionMessage {get;}                                          
PSCommandPath             Property     string PSCommandPath {get;}                                            
PSScriptRoot              Property     string PSScriptRoot {get;}                                             
ScriptLineNumber          Property     int ScriptLineNumber {get;}                                            
ScriptName                Property     string ScriptName {get;}                                               
UnboundArguments          Property     System.Collections.Generic.List[System.Object] UnboundArguments {get;} 

Function Example { $MyInvocation } Example

MyCommand             : Example
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 8
OffsetInLine          : 1
HistoryId             : 6
ScriptName            : C:\Temp\test.ps1
Line                  : Example
PositionMessage       : At C:\Temp\test.ps1:8 char:1
                        + Example
                        + ~~~~~~~
PSScriptRoot          : C:\Temp
PSCommandPath         : C:\Temp\test.ps1
InvocationName        : Example
PipelineLength        : 1
PipelinePosition      : 1
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition : 

$MyInvocation是为每个作用域生成的具有非常不同类型的自动变量。它的成员和效用因范围而异。

在 PSv5.1、Windows 7 SP1 上完成的测试

于 2017-08-10T14:09:48.207 回答
3

请记住,这两个变量都指向正在执行的文件。如果没有文件,它们是空的。

在远程处理中,就像您使用时Invoke-Command -ScriptBlock { }没有文件一样。

如果您在远程会话中调用模块中的函数,并且该函数使用$PSScriptRoot$MyInvocaton...在这种情况下它可能会返回它所在的任何文件,它可能会起作用。

在像 Jenkins 这样的情况下,这不是远程处理。Jenkins 创建一个临时文件并从中运行您的代码,因此这就是将返回的文件。

于 2017-08-10T14:15:57.377 回答