Calling Powershell with WshShell.Exec() method hangs the script - powershell

I am trying to call Powershell with the Exec method of the WshShell object. I am writing the script in JScript, but I have reproduced the problem in VBScript as well. Both of the following short test scripts will cause WSH to hang indefinitely:
test.js
var shell = new ActiveXObject("WScript.Shell");
WScript.Echo(shell.exec("powershell -Command $Host.Version; Exit").StdOut.ReadAll());
test.vbs
dim shell
set shell = CreateObject("WScript.Shell")
WScript.Echo shell.exec("powershell -Command $Host.Version; Exit").StdOut.ReadAll
Am I doing something wrong, or am I running into or a limitation/incompatibility? The Run method works very well, but I need to capture output, which it's not capable of doing.
Edit: I forgot to mention that my platform is Windows 7 Pro, 64-bit with PowerShell 3. I've tested on Windows XP with PowerShell 1 as well.
Edit 2: I've updated the test scripts that I'm running to fit with x0n's answer. Unfortunately, I'm still having trouble. Here are my current tests:
test.js:
var shell = new ActiveXObject("WScript.Shell");
WScript.Echo(shell.exec('powershell -noninteractive -noprofile -Command "& { echo Hello_World ; Exit }"').StdOut.ReadAll());
test.vbs:
dim shell
set shell = CreateObject("WScript.Shell")
WScript.Echo shell.exec("powershell -noninteractive -noprofile -Command ""& { echo Hello_World ; Exit }""").StdOut.ReadAll

You have to close StdIn:
var shell = new ActiveXObject("WScript.Shell");
var exec = shell.Exec('powershell -noninteractive -noprofile -Command "& { echo Hello_World ; Exit }"');
exec.StdIn.Close();
WScript.Echo(exec.StdOut.ReadAll());
Microsoft said:
StdIn is still open so PowerShell is waiting for input. (This is an
"implementation consideration" that we're hoping to fix in V2. The
PowerShell executable gathers all input before processing.) So
objexec.StdIn.Close() needs to be added.

Use:
powershell.exe -noninteractive -noprofile -command $host.version
as your string. For more complicated groups of commands, use this syntax:
powershell.exe -noninteractive -noprofile -command "& { $host.version; $host.version }"

Related

How To Pass in or Set Environment Variable for Powershell script?

I have a powershell script as part of Azure DevOps pipeline. I also want to run it from windows command line. How can I set them before calling them in windows? Perhaps in a cmd file? Note - these are temporary for a single execution and don't want to set windows environment variables.
I am accessing the environment variables like this in the powershell script:
$tfsAccessToken = If ($serverMode) {$env:SYSTEM_ACCESSTOKEN} else {"somethingelse"}
$tfsBuildDefinitionId = If ($serverMode) {$env:SYSTEM_DEFINITIONID} else {2}
SET command:
Display, set, or remove CMD environment variables. Changes made
with SET will remain only for the duration of the current CMD
session.
Example.
Supposedly, the _foo environment variable isn't defined in a newly opened CMD prompt:
set _foo
Environment variable _foo not defined
powershell -nologo -noprofile -command "& {$env:_foo ; $null -eq $env:_foo}"
True
However, if defined, the _foo environment variable is visible in the child process powershell:
set "_foo=bar"
powershell -nologo -noprofile -command "& {$env:_foo ; $null -eq $env:_foo}"
bar
False
Another example (asynchronous child process powershell):
set "_foo=bar"
start "SO_57237835" powershell -noexit -nologo -noprofile -command "& {$env:_foo;$null -eq $env:_foo}"

Run script using Task Scheduler with user context complete silent with no popup or cmd flash

I have tried to run the script using command
cmd.exe /c Start /min powershell.exe -windowstyle hidden -file <file>.ps1
But getting a CMD window for a fraction of a second. I need it to run completely hidden.
Configure the scheduled task to run whether the user is logged on or not:
and reduce the commandline to this:
powershell.exe -File "C:\path\to\your.ps1"
This makes the task run in the background with no visible window.
I have had this issue and the only way I could fix it was to call the PowerShell script with a simple VBS wrapper:
https://github.com/gbuktenica/PsRun
http://blog.buktenica.com/run-a-powershell-task-silently/
' SYNOPSIS
' Run a PowerShell script in the user context without a script window
' EXAMPLE
' wscript.exe PsRun.vbs MyPsScript.ps1
' AUTHOR
' Glen Buktenica
Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
Dim PSRun
PSRun = "powershell.exe -WindowStyle hidden -ExecutionPolicy bypass -NonInteractive -File " & arg
objShell.Run(PSRun),0

Close Powershell Child Session of my batch file wrapper

I have a problem to use a powershell script plugin, with my nagios agent (NRPE_NT.exe).
To solve this problem I've create underlying wrap batch file:
#ECHO OFF
SET SCRIPTPATH=%~d0%~p0check_process_mem.ps1
SET ARGS=%*
IF [%ARGS%] NEQ [] GOTO ESCAPE_ARGS
:POWERSHELL
PowerShell.exe -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Unrestricted -Command "& { $ErrorActionPreference = 'Stop'; & '%SCRIPTPATH%' #args; EXIT $LASTEXITCODE }" %ARGS%
EXIT /B %ERRORLEVEL%
:ESCAPE_ARGS
SET ARGS=%ARGS:"=\"%
SET ARGS=%ARGS:`=``%
SET ARGS=%ARGS:'=`'%
SET ARGS=%ARGS:$=`$%
SET ARGS=%ARGS:{=`{%
SET ARGS=%ARGS:}=`}%
SET ARGS=%ARGS:(=`(%
SET ARGS=%ARGS:)=`)%
SET ARGS=%ARGS:,=`,%
SET ARGS=%ARGS:^%=%
GOTO POWERSHELL
Now, if I run it as dialog user, I haven't any problem, but if I run it with SYSTEM user, powershell session doesn't close, and I have to kill it, from tasklist.
What can I do, for solve this problem?
I can't update NRPE_NT.exe agent to NSClient+ (powershell compliance).
i've solve this problem with powershell plugin, without wrap batch file. I've declaire nrpe.cfg in this way:
command[check_X]=cmd /c echo C:\nrpe\libexec\check_process_mem.ps1 $ARG1$ -VM_w "$ARG2$" -VM_c "$ARG3$" ; exit $($LastExitCode) | powershell.exe -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Unrestricted -command -
and now it works correctly. Exit code and output of script is correct.

Vbscript valid path

I'm trying to have a scheduler to run a Vbscript, which it will run a Powershell script.
Basically here is my Vbscript
command = "powershell.exe -nologo -command C:\Users\someuser\Desktop\appAPIMonitor.ps1"
set shell = CreateObject("WScript.Shell")
shell.Run command,0
When I run above script, it worked. But when I place the script at my preferred path, the script wont run as before. So it must be the path not valid. Here is my new script
command = "powershell.exe -nologo -command C:\Users\someuser\My Work\App\Project\My.API.App\Scripts\appAPIMonitor.ps1"
set shell = CreateObject("WScript.Shell")
shell.Run command,0
Can somebody point what is wrong with my path? Is it the whitespace in My Work? Or the dot in My.Api.App?
This is the solution I managed to get.
command = "powershell.exe -nologo -file ""C:\Users\someuser\My Work\App\Project\My.API.App\Scripts\appAPIMonitor.ps1"" "
set shell = CreateObject("WScript.Shell")
shell.Run command,0
Give the last quote some white space and change -command to -file should do the trick. I solve this in my case. Hopefully help anybody in future. By the way, thanks to those who spent their precious time to answer my question.

Calling a powershell function using a .bat file

I would like to know how to call a powershell function using a .Bat file.
I have this simple function:
(Script.ps1)
function testfunction
{
Write-Log "Calling from Bat file"
}
and I would like to call the function testfunction within the .Bat File.
powershell .\Script.ps1 ...
I noticed that there is a switch -ExecutionPolicy ByPass which allows the batch file to run using Powershell. This works here, taken from the answer by vonPryz.
#echo off
:: Create a test script file
echo function test { write-host "Called from %~f0" } > s.ps1
powershell -ExecutionPolicy ByPass -command ". "%cd%\s.ps1"; test;"
del s.ps1
pause
Start Powershell with -command switch, include the script and call the function. You need to dot source the script before its function can be called.
:: Create a test script file
C:\temp>echo function test { write-host "Called from .bat" } > c:\temp\s.ps1
C:\temp>powershell -command ". c:\temp\s.ps1; test;"
:: Output
Called from .bat
Also, take a look at some samples.
I know this is very old but I was recently trying to do this same thing and it took me a long time to find out what to do. The answer is amazingly simple
In BatchFile (RunMe)
powershell -command ". Script.ps1; Set-SomeFunction %1 %2 %3 %4 %5"
Then you can call the batch like
RunMe -SomeParm val -SomeParm2 val -SomeSwitch -SomeBool $true
also, to run as admin
powershell -command "Start-Process -verb runas powershell" "'-noexit -command ". Script.ps1; Set-SomeFunction %1 %2 %3 %4 %5 %6 %7 %8 %9'"
I usually do it like that:
powershell {Set-ExecutionPolicy unrestricted}
powershell.exe -executionpolicy ByPass ./script/powerhsell-script.ps1 %par1% %par2%
powershell {Set-ExecutionPolicy Restricted}
Hope you need that :)
I've done it using
powershell.exe -ExecutionPolicy Bypass -file ".\Write_date.ps1"
Seems similar to what others have written but I'm not sure what vonPryz meant by needing the dot source the script before calling the script. The above worked on a Win7 with executionpolicy set to restricted.