【问题标题】:Hidden PS window via VBS with return code通过带有返回码的 VBS 隐藏 PS 窗口
【发布时间】:2018-03-12 06:11:54
【问题描述】:

我正在尝试使用 VBScript 辅助脚本在隐藏窗口中启动 PowerShell 脚本。我已经成功地这样做了一段时间,但现在我想添加获取返回码,这使事情变得更加复杂。 获取返回码的常用方法是使用 .Exec 而不是 .Run,​​但这样您就失去了隐藏命令窗口的能力。我找到了this thread,并基于此和一个已知的工作strCMD,我尝试了

strCMD = strCMD & " > c:\out.txt"
objShell.Run strCMD, 0, True

但这不起作用。有什么建议我哪里出错了吗?或者关于获取带有返回码的隐藏 Powershell 脚本的更好方法的建议? FWIW,我必须针对 PS 2.0。 :(

为了完整性,strCMD的值为

powershell -noLogo -noProfile -file "C:\Program Files\PragmaticPraxis\Resources\TestMessage.ps1" -message:"I'M ALIVE!!!" -message2:"Me too!"

TestMessage.ps1 很简单

[CmdletBinding()]
param (
    [string]$message,
    [string]$message2
)

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $null
[System.Windows.Forms.MessageBox]::Show($message)
[System.Windows.Forms.MessageBox]::Show($message2)

编辑: 感谢 omegastripes 的链接,我正在尝试实现一个更通用且以 PowerShell 为中心的实现版本,通过一些代码重构来消除对函数的一次性调用和尴尬的强制退出。我有的是这样的:

Option Explicit
Dim strCmd, strRes, objWnd, objParent, strSignature

If WScript.Arguments.Named.Exists("signature") Then 
    For Each objWnd In CreateObject("Shell.Application").Windows
        If IsObject(objWnd.getProperty(WScript.Arguments.Named("signature"))) Then Exit For
    Next
    Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))

    objWnd.Quit
    objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll()
Else
    strCmd = "powershell.exe -noLogo -noProfile -executionPolicy bypass -file ""\\Mac\Px\Support\Px Tools\Dev 3.3.#\_Spikes\TestMessage.ps1"""
    strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
    GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty strSignature, Me
    CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True

    WScript.Echo strRes
End If

这又称为 PS1

try {
    [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $null
    [System.Windows.Forms.MessageBox]::Show("Message test!") > $null
    Write-Host "Success"
} catch {
    Write-Host "Failure"
}

这是因为它确实运行 PS1,并且它是隐藏的,但我无法返回结果。我已经尝试过 Return、Write-Output 和 Write-Host,但没有一个将 PS1 的结果发送回 VBS。我在传递参数时也遇到了一些问题,我真的不喜欢内部强制退出的 For Each 循环,但这是波兰语。更大的问题是如何始终如一地从 PS1 中获取结果。

【问题讨论】:

  • PowerShell.exe -windowstyle hidden ?
  • Sage,据我所知,它不适用于所有版本的 PowerShell。
  • 好吧,我无法通过 Powershell 2.0 的文档进行确认,尽管我看到提到它应该可以工作,但对于 Powershell 3.0 到 6,它确实可以。 docs.microsoft.com/en-us/powershell/scripting/core-powershell/…
  • 是的,我很确定这是一项新功能,在 2.0 及更早版本中不起作用。不幸的是,我只能支持 Windows7/PS 2.0。虽然也许我应该在旧操作系统和新操作系统上以不同的方式实现这一点。
  • Powershell 2.0 在几周后就被弃用了。因此,如果升级到 PS5 可以解决您的问题,那么您还有另一个理由这样做。 redmondmag.com/articles/2017/07/24/…

标签: powershell vbscript


【解决方案1】:

您的 powershell 脚本需要通过

返回退出代码
Exit <int>

您在 VBS 中的 WScript.Shell 的 Run 方法将返回此代码,因此您需要保存它。

Set WshShell = WScript.CreateObject("WScript.Shell")
Result = WshShell.Run(...

所以 Result 现在包含退出代码,因此您现在可以使用它或再次返回它并退出进程。

WScript.Quit(Result)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    相关资源
    最近更新 更多