【问题标题】:Functional differences between $PSScriptRoot and $MyInvocation$PSScriptRoot 和 $MyInvocation 之间的功能差异
【发布时间】:2018-01-18 19:02:07
【问题描述】:

问题

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

详情

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

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

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

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

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

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

问题

我想知道使用 $PSScriptRoot 是否会导致我在 PowerShell 远程处理中出现问题,从而使使用 $MyInvocation 成为更可行的选择?

【问题讨论】:

  • $MyInvocation.MyCommand.Path$PSScriptRoot 之间的区别在于:a) 一个包含文件名,另一个不包含,b) 一个适用于所有 PowerShell 版本,另一个仅适用于 PowerShell v3 及更高版本.期间。
  • 你知道......当你试图“帮助”某人时,你不需要成为一个混蛋。作为对 PowerShell 还有些陌生的人,我问这个问题。我只是在问,因为我目前正在处理一个复杂的问题,有人告诉我使用 $PSScriptRoot 会很糟糕,因为我不会总是得到我期望它提供的路线。
  • @Brandon 再次,正如我在我现在已删除的 cmets 中所说,您需要在此处发布具体问题。 你描述的场景是什么?
  • @briantist 再次编辑了一个更具体的问题
  • @Brandon 1) 你试过看看它会返回什么吗? 2) 认为current script在这种情况下是什么?

标签: powershell powershell-remoting automatic-variable


【解决方案1】:

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

在远程处理中,例如当您使用Invoke-Command -ScriptBlock { } 时,没有文件。

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

对于像 Jenkins 这样的东西,这不是远程处理。 Jenkins 会创建一个临时文件并从中运行您的代码,这就是将要返回的文件。

【讨论】:

  • @TheIncorrigible1 是的,我不确定这与我所说的有何矛盾。你能详细说明你的反对意见吗?
  • @TheIncorrigible1 $PSScriptRoot 也是如此。
  • @TheIncorrigible1 再次,我的回答的哪一部分不准确到值得一票否决的地步?
  • @TheIncorrigible1 OP 没有说明在模块的上下文中使用它。在那种特殊情况下,如果(且仅当)在没有范围修饰符的情况下使用变量时,您会看到差异。除此之外结果是相同的(当然,没有文件名)。
  • @TheIncorrigible1 getting the current scripts root directory 如果您正在执行不受文件支持的代码,则没有当前脚本。
【解决方案2】:
$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 上完成测试

【讨论】:

  • 我明白了。我不知道如何显示这些信息(对于这种编程语言来说仍然有些新),并且我的 PS 的“帮助”文件不存在(系统告诉我安装它们),但作为一台工作 PC,我不知道没有管理员权限这样做。因此,这些信息非常有用。再次感谢您。
猜你喜欢
  • 2018-06-28
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多