verfluecht
verfluecht

Reputation: 513

How can I pass a variable from one PS script to another via VBS?

I am working on a PowerShell script with a GUI with 3 files:

In window1, I enter value1 into textbox1 and click the button.

gui window 1

By clicking it, value1 should be stored into a global variable, so that window2 can pop up (via VBS) and use value1.

code for button in window1:

$button_OnClick= 
{
    $global:value1 = $textBox1.Text
    start-process .\start.vbs
}

start.vbs:

Set objShell = CreateObject("Wscript.Shell")
objShell.run("powershell.exe -nologo -file .\window2.ps1"), 0, True

So far so good. From what I understand, value1 is a global variable and can be used in window2.ps1.

So window2 is an empty window with only a text that should display value1.

$label1.Text = "$value1"

But for some reason, the variable is empty and window2 is empty.

gui window 2

What am I missing? I'm still learning PowerShell and I might be missing a detail.

note: I know the way I open up window2 via .vbs is weird. But that way, the GUI opens up without any PowerShell window in the background.

Upvotes: 3

Views: 572

Answers (1)

Tomalak
Tomalak

Reputation: 338326

A "global variable" is not something that is magically available to every process all over your computer. You're starting two completely separate PowerShell processes. None of their stuff is shared.

You need to give the value as a command line argument to the second PowerShell process if you want to use it there.

And that means you have to give the value your first PowerShell script generates as a command line argument to your intermediary VBScript, because that's a completely separate process, too.

The first PowerShell script calls wscript.exe with two arguments (script name and value):

$button_OnClick= 
{
    $value1 = $textBox1.Text
    Start-Process wscript.exe "window2.vbs","`"$value1`""
}

Assuming the user has entered Hello World!, this will execute the command line (note the quotes, they make sure that values with spaces are not seen as separate arguments):

wscript.exe window2.vbs "Hello World!"

The VBS intermediary can then read Hello World! from it first command line argument (the quotes will have been stripped, so we need to add them back for the next call):

value1 = WScript.Arguments.Unnamed(0)

Set objShell = CreateObject("Wscript.Shell")
objShell.run("powershell.exe -nologo -file .\window2.ps1 """ & value1 & """"), 0, True

now the following command line is executed:

powershell.exe -nologo -file .\window2.ps1 "Hello World!"

The second PowerShell script can then pull Hello World! from its first command line argument, just as the VBScript did (the quotes will have been stripped again):

$label1.Text = $args[0]

I would recommend that you make a VBScript windowless.vbs that can run just about any command windowlessly:

' windowless.vbs
For Each arg In WScript.Arguments
    If InStr(arg, " ") > 0 Then
        cmd = cmd & """" & arg & """ "
    Else
        cmd = cmd & arg & " "
    End If
Next
CreateObject("WScript.Shell").Run(Trim(cmd)), 0, True

and then use it in your PowerShell script

$value1 = "Hello World!"
Start-Process wscript.exe "windowless.vbs","powershell.exe","-nologo","-file window2.ps1","`"$value1`""

which would create this command line

powershell.exe -nologo -file .\window2.ps1 "Hello World!"

which is exactly what we need here, and it can be reused easily for other cases.

Upvotes: 5

Related Questions