powershell $PSScriptRoot和$MyInvocation之间的功能差异

bksxznpy  于 2023-11-18  发布在  Shell
关注(0)|答案(3)|浏览(219)

问题
我正在使用Jenkins远程部署PowerShell脚本。因此,我试图弄清楚使用$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成为更可行的选择?

vsdwdz23

vsdwdz231#

  1. $PSScriptRoot.GetType().FullName
  2. > System.String
  3. $PSScriptRoot
  4. > C:\Temp

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

  1. $MyInvocation.GetType().FullName
  2. > System.Management.Automation.InvocationInfo
  3. $MyInvocation
  4. > MyCommand : test.ps1
  5. > BoundParameters : {}
  6. > UnboundArguments : {}
  7. > ScriptLineNumber : 0
  8. > OffsetInLine : 0
  9. > HistoryId : 4
  10. > ScriptName :
  11. > Line :
  12. > PositionMessage :
  13. > PSScriptRoot :
  14. > PSCommandPath :
  15. > InvocationName : C:\Temp\test.ps1
  16. > PipelineLength : 2
  17. > PipelinePosition : 1
  18. > ExpectingInput : False
  19. > CommandOrigin : Internal
  20. > DisplayScriptPosition :
  21. $MyInvocation | Get-Member -Force
  22. TypeName: System.Management.Automation.InvocationInfo
  23. Name MemberType Definition
  24. ---- ---------- ----------
  25. pstypenames CodeProperty System.Collections.ObjectModel.Collection`1[[System.String, mscorlib...
  26. psadapted MemberSet psadapted {MyCommand, BoundParameters, UnboundArguments, ScriptLineN...
  27. psbase MemberSet psbase {MyCommand, BoundParameters, UnboundArguments, ScriptLineNumb...
  28. psextended MemberSet psextended {}
  29. psobject MemberSet psobject {BaseObject, Members, Properties, Methods, ImmediateBaseObj...
  30. Equals Method bool Equals(System.Object obj)
  31. GetHashCode Method int GetHashCode()
  32. GetType Method type GetType()
  33. get_BoundParameters Method System.Collections.Generic.Dictionary[string,System.Object] get_Boun...
  34. get_CommandOrigin Method System.Management.Automation.CommandOrigin get_CommandOrigin()
  35. get_DisplayScriptPosition Method System.Management.Automation.Language.IScriptExtent get_DisplayScrip...
  36. get_ExpectingInput Method bool get_ExpectingInput()
  37. get_HistoryId Method long get_HistoryId()
  38. get_InvocationName Method string get_InvocationName()
  39. get_Line Method string get_Line()
  40. get_MyCommand Method System.Management.Automation.CommandInfo get_MyCommand()
  41. get_OffsetInLine Method int get_OffsetInLine()
  42. get_PipelineLength Method int get_PipelineLength()
  43. get_PipelinePosition Method int get_PipelinePosition()
  44. get_PositionMessage Method string get_PositionMessage()
  45. get_PSCommandPath Method string get_PSCommandPath()
  46. get_PSScriptRoot Method string get_PSScriptRoot()
  47. get_ScriptLineNumber Method int get_ScriptLineNumber()
  48. get_ScriptName Method string get_ScriptName()
  49. get_UnboundArguments Method System.Collections.Generic.List[System.Object] get_UnboundArguments()
  50. set_DisplayScriptPosition Method void set_DisplayScriptPosition(System.Management.Automation.Language...
  51. ToString Method string ToString()
  52. BoundParameters Property System.Collections.Generic.Dictionary[string,System.Object] BoundPar...
  53. CommandOrigin Property System.Management.Automation.CommandOrigin CommandOrigin {get;}
  54. DisplayScriptPosition Property System.Management.Automation.Language.IScriptExtent DisplayScriptPos...
  55. ExpectingInput Property bool ExpectingInput {get;}
  56. HistoryId Property long HistoryId {get;}
  57. InvocationName Property string InvocationName {get;}
  58. Line Property string Line {get;}
  59. MyCommand Property System.Management.Automation.CommandInfo MyCommand {get;}
  60. OffsetInLine Property int OffsetInLine {get;}
  61. PipelineLength Property int PipelineLength {get;}
  62. PipelinePosition Property int PipelinePosition {get;}
  63. PositionMessage Property string PositionMessage {get;}
  64. PSCommandPath Property string PSCommandPath {get;}
  65. PSScriptRoot Property string PSScriptRoot {get;}
  66. ScriptLineNumber Property int ScriptLineNumber {get;}
  67. ScriptName Property string ScriptName {get;}
  68. UnboundArguments Property System.Collections.Generic.List[System.Object] UnboundArguments {get;}
  69. Function Example { $MyInvocation } Example
  70. MyCommand : Example
  71. BoundParameters : {}
  72. UnboundArguments : {}
  73. ScriptLineNumber : 8
  74. OffsetInLine : 1
  75. HistoryId : 6
  76. ScriptName : C:\Temp\test.ps1
  77. Line : Example
  78. PositionMessage : At C:\Temp\test.ps1:8 char:1
  79. + Example
  80. + ~~~~~~~
  81. PSScriptRoot : C:\Temp
  82. PSCommandPath : C:\Temp\test.ps1
  83. InvocationName : Example
  84. PipelineLength : 1
  85. PipelinePosition : 1
  86. ExpectingInput : False
  87. CommandOrigin : Internal
  88. DisplayScriptPosition :


$MyInvocation是一个自动变量,有着非常不同的类型,为每个作用域生成。它的成员和实用程序因作用域而异。

  • 在PSv5.1、Windows 7 SP1* 上完成的测试
展开查看全部
kgsdhlau

kgsdhlau2#

记住,这两个变量都指向正在执行的 file。如果没有file,它们就是空的。
在远程处理中,就像使用Invoke-Command -ScriptBlock { }时一样,没有文件。
如果您在远程处理会话中调用模块中的函数,并且该函数使用$PSScriptRoot$MyInvocaton...,则它可能会返回它所在的任何文件。
Jenkins创建了一个临时文件,并从该文件中运行代码,因此该文件将被返回。

qybjjes1

qybjjes13#

虽然(Split-Path -Parent ($MyInvocation.MyCommand.Path))是返回路径的两个命令选项中较长的一个,正如@'Maximilian Burszley'指出的那样,$PSScriptRoot是一个简单的字符串,如果你从一个模块或子脚本中调用,而不是与主脚本位于同一路径中,那么$PSScriptRoot可能会返回一个错误的路径。
更大的陷阱(IMO)是从子作用域调用任何一个命令,就像上面指出的使用Invoke-Command -ScriptBlock { }时一样。

相关问题