我正在尝试使用更新的技术omegastripes提供here来创建帮助程序脚本,以便静默启动PowerShell并获取结果/状态。我做的第一件事是重构,以帮助我理解逻辑。基本上我摆脱了两个函数,一个强制退出,并将它们移动到If / Then / Else。在搜索已识别的窗口时,我还将所有内容都移动到条件中。所以我离开了这个:
Dim strCmd, strRes, objWnd, objParent, strSignature
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
strCmd = "%comspec% /c tasklist"
RunCScriptHidden
WScript.Echo strRes
Sub RunCScriptHidden()
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
End Sub
Sub WshShellExecCmd()
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()
WScript.Quit
End Sub
对此:
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
Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))
objWnd.Quit
objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll()
Exit For
End If
Next
Else
strCmd = "%comspec% /c tasklist"
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
这很有效,而我唯一的问题只是对重构的批评。有什么可以改进的吗?事实上,首先是否存在反对重构的争论?
从那时起,我将strCmd
修改为
strCmd = "powershell.exe -noLogo -noProfile -executionPolicy bypass -file ""\\Mac\Px\Support\Px Tools\Dev 3.3.#\_Spikes\TestMessage.ps1"" -message:""It's ALIVE!"""
哪个调用此PowerShell
param (
[string]$message
)
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") > $null
[System.Windows.Forms.MessageBox]::Show($message) > $null
到目前为止,这么好。现在从PowerShell获取状态。在这里我应该清楚,最终目标是一个通用启动器,我希望能够捕获任何错误,将它们传递回VBS,并从那里写入错误日志或事件。一些潜在的错误包括传递目标PS1中不存在的参数等。 所以,回到返回的信息,我试过了:
Write-Output "Write-Output"
Write-Host "Write-Host"
Out-Host "Out-Host"
这些实际上都没有被返回。那么,我如何输出到标准输出,以便VBS可以访问该信息?我 THINK 一个方面是原始strCmd在处理时发出标准输出,而PowerShell最后会输出。但这只是对这个问题的一个猜测,所以我会问更多的实验,而不是混乱这是否可能,如果是这样,需要做哪些改变?
答案 0 :(得分:0)
这是您链接到的代码的改进版本,从vbs调用cmd.exe。我今天做了。将来自cmd.exe的混乱响应拆分为一个数组,而不是将所有内容都放入一个难以解析的字符串中。
此外,如果在执行cmd.exe的过程中发生错误,则有关该错误的消息将在vbs中变为已知。
好吧... Powershell:
Option Explicit
Sub RunCScriptHidden()
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty strSignature, Me
objShell.Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True
End Sub
Sub WshShellExecCmd()
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() 'simple solution
Set exec = CreateObject("WScript.Shell").Exec(objParent.strCmd)
While exec.Status = WshRunning
WScript.Sleep 20
Wend
Dim err
If exec.ExitCode = WshFailed Then
err = exec.StdErr.ReadAll
Else
output = Split(exec.StdOut.ReadAll,Chr(10))
End If
If err="" Then
objParent.strRes = output(UBound(output)-1) 'array of results, you can: output(0) Join(output) - Usually needed is the last
Else
objParent.wowError = err
End If
WScript.Quit
End Sub
Const WshRunning = 0,WshFailed = 1:Dim cmdExeString,objShell
Dim strCmd, strRes, objWnd, objParent, strSignature, wowError, output, exec
Set objShell = WScript.CreateObject("WScript.Shell"):wowError=False
Dim psCode:psCode="Write-Host 'Hello PS'"
cmdExeString="for /f ""usebackq delims="" %a in (`C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command """ & psCode & """`) do echo %a"
strCmd = "%comspec% /c " & cmdExeString
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
RunCScriptHidden
If wowError=False Then
objShell.popup(strRes)
Else
objShell.popup("Error=" & wowError)
End If