【问题标题】:Script runs in ISE but not in Powershell脚本在 ISE 中运行,但不在 Powershell 中
【发布时间】:2019-02-14 06:58:00
【问题描述】:

我有一个powershell script。如果我在 Powershell ISE 中打开此脚本,它运行得非常好,但是,如果我右键单击该文件并单击“使用 powershell 运行”,该脚本会引发错误。

此外,我在之前的帖子中读到以下执行模式为某些人解决了这个问题:

powershell -STA -File script.ps1

在这种情况下,这并没有解决问题,但它确实让我能够阅读错误:

At C:\Users\sancarn\AppData\Local\Temp\script.ps1:20 char:20
+         $parent = [System.Windows.Forms.TreeNode]$global:database.Ite ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unable to find type [System.Windows.Forms.TreeNode].
At C:\Users\sancarn\AppData\Local\Temp\script.ps1:27 char:36
+ ...          [void]$node.nodes.add([System.Windows.Forms.TreeNode]::new(" ...
+                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unable to find type [System.Windows.Forms.TreeNode].
At C:\Users\sancarn\AppData\Local\Temp\script.ps1:33 char:45
+ ... PSCustomObject]IWDBGetChildren([System.Windows.Forms.TreeNode]$node)  ...
+                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unable to find type [System.Windows.Forms.TreeNode].
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : TypeNotFound

话虽如此,我不确定我是否真的可以针对此错误做任何事情...我已经加载了System.Windows.FormsSystem.Drawing...有谁知道如何正确执行此文件?

编辑

尝试解决此问题的其他尝试:

powershell -NoExit -STA -File script.ps1
powershell -NoExit -STA -File script.ps1 -Scope Global

编辑 2

我也试过添加:

Add-Type -AssemblyName System.Windows.Forms

到 powershell 脚本的顶部。然而,这个问题仍未解决。


编辑:

不知道为什么这被标记为重复

  1. 此答案已有推荐答案,并且
  2. 推荐的答案说明了为什么这是不同的。

...

【问题讨论】:

标签: powershell


【解决方案1】:

正如@PetSerAl 在他的评论中所说,答案在https://stackoverflow.com/a/34637458

在执行脚本中的第一条语句之前,每个 PowerShell 脚本都会被完全解析。类定义中无法解析的类型名称标记被视为解析错误。为了解决您的问题,您必须在解析类定义之前加载您的类型,因此类定义必须位于单独的文件中。

最终要解决这个问题,我需要将我的类定义作为单独的文件加载,或者将我的声明存储在一个头文件中,该文件调用类定义(以及脚本的其余部分)。

我很惊讶这甚至是一个问题,但它现在可以工作了,所以这很好......

编辑

在我的情况下,它与解决方案作者链接的帖子有点不同。我实际上正在构建一个用于在 Windows 机器上执行 Powershell 的 ruby​​ 库。目前我不向文件写入数据,也不能保证 here-string/invoke-expression 会起作用。

Invoke-Expression @"
$anotherString=@"
    hello world!
"@    
"@ <--- Powershell will throw an error here!

相反,如果存在标头,我决定对正文进行编码,然后在运行时解码并执行

require 'base64'
if header!=""
    encoded_body = Base64.strict_encode64(body.encode("utf-16le"))
    body = <<-END_TRANSFORMATION
        #{header}

        $encoded_body = "#{encoded_body}"
        Invoke-Expression $([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encoded_body)))
    END_TRANSFORMATION
end

到目前为止,这似乎在所有情况下都有效,不需要外部文件,即使用户在他们的 Powershell 脚本中使用 here-doc 字符串也可以工作!

【讨论】:

  • 您不能在此处嵌套使用相同分隔符的字符串,但如果您使用@'...'@ 作为外部分隔符,则可以使用Invoke-Expression 命令。
  • 确实,这里的问题是 ruby​​ 类是专门设计为允许任何人执行任何 Powershell...我无法预见是否有人会使用 @'...'@ 或 @987654327 @.
  • 因此用户将在传递给Invoke-Expression的here-string中按字面意思键入他们的代码?
  • 是的,非常准确。这是一个用于执行 Powershell 的 Ruby 库。因此,用户将成为开发人员。脚本本身之前只是作为编码命令注入的。所以,是的,他们从字面上输入了传递给 Invoke-Expression 的 here-string。
  • 注意 - 您可以使用powershell.exe -encodedCommand ... 直接执行编码字符串:(当然受行长度限制)。请参阅“powershell.exe -?”获取信息。
猜你喜欢
  • 1970-01-01
  • 2011-05-04
  • 2020-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
  • 2018-06-11
相关资源
最近更新 更多