通过带有返回码的 VBS 隐藏 PS 窗口

Gor*_*don 5 vbscript powershell

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

strCMD = strCMD & " > c:\out.txt"
objShell.Run strCMD, 0, True
Run Code Online (Sandbox Code Playgroud)

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

为了完整起见,strCMD 的值是

powershell -noLogo -noProfile -file "C:\Program Files\PragmaticPraxis\Resources\TestMessage.ps1" -message:"I'M ALIVE!!!" -message2:"Me too!"
Run Code Online (Sandbox Code Playgroud)

而 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)
Run Code Online (Sandbox Code Playgroud)

编辑:多亏了 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
Run Code Online (Sandbox Code Playgroud)

这反过来又称之为 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"
}
Run Code Online (Sandbox Code Playgroud)

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

Ult*_*uki 1

您的 powershell 脚本需要通过以下方式返回退出代码

Exit <int>
Run Code Online (Sandbox Code Playgroud)

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

Set WshShell = WScript.CreateObject("WScript.Shell")
Result = WshShell.Run(...
Run Code Online (Sandbox Code Playgroud)

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

WScript.Quit(Result)
Run Code Online (Sandbox Code Playgroud)