I am trying to use a VBScript helper script to launch a PowerShell script in a hidden window. I have been doing this successfully for some time, but now I want to add getting a return code, and that makes things more complicated.
The usual approach for getting a return code is to use .Exec rather than .Run, but then you lose the ability to hide the command window. I found this thread, and based on that and a known working strCMD
, I tried
strCMD = strCMD & " > c:\out.txt"
objShell.Run strCMD, 0, True
But that doesn't work. Any suggestions where I am going wrong? Or suggestions on a better way to get a hidden Powershell script with return code? FWIW, I have to target PS 2.0. :(
For completeness, the value of strCMD is
powershell -noLogo -noProfile -file "C:\Program Files\PragmaticPraxis\Resources\TestMessage.ps1" -message:"I'M ALIVE!!!" -message2:"Me too!"
And TestMessage.ps1 is simply
[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)
EDIT: Thanks to omegastripes' link, I am trying to implement a more general and PowerShell focused version of this implementation, with some code refactor to eliminate the one time calls to functions and awkward forced exits. What I have is this:
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
Which in turn calls this 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"
}
This works in that it does run the PS1, and it is hidden, but I am having trouble getting results back. I have tried Return, Write-Output and Write-Host and none sends the results from the PS1 back to the VBS. I am also having some issues when passing arguments, and I really don't like the For Each loop with a forced Exit internally, but that is polish. The bigger issue is how to consistently get results back from the PS1.