StdIn.Writeline Fails in ASP sending strings to PowerShell - powershell

I am updating a Classic ASP webpage. It seems that if you try to use StdIn.Writeline to send command to PowerShell it fails. It behaves like the command interpreter only accepts commands as part of creating the session.
Does anyone have any working examples of passing supplemental commands to an open PowerShell execution from a Classic (Not ASP.Net) web page?
Command = "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\Powershell.exe -NoExit -inputformat none -ExecutionPolicy bypass -NonInteractive -noprofile -Command ""& {""$PSVersionTable.PSVersion""; ""Add-PSSnapIn VMware* -ErrorAction SilentlyContinue""; 2>&1} "
Set oExec = WshShell.Exec(Command)
If oExec.Status = 0 Then
oExec.StdIn.Writeline("Dir 2>&1")
oExec.StdIn.Writeline("Exit")
oExec.StdIn.Close()
Do While oExec.StdOut.AtEndOfStream <> True
Response.Write oExec.StdOut.ReadLine
Loop
End If
When I try to keep the command interpreter open and use StdIn.Writeline to send additional commands, including the exit command, it never closes and I have to kill the process on the IIS server.
If I remove the -NoExit switch, it does close after running the string passed, and obviously I can't send additional commands to run.
Any ideas on how to get PowerShell to work like %comspec% does?

Related

PowerShell in Task Manager Shows Window

I am trying to make Task Schedule Task so it is completely invisible that a PowerShell script is running so I created a Task on my Win10 machine configured as follows:
Program/Script:
powershell.exe
Add arguments (optional):
-WindowStyle Hidden -command "& {Out-File 'C:\temp\somefile.txt'}" -NonInteractive -NoLogo -NoProfile
When I run this task the powershell command windows pops up for a split second which I don't want.
You can get around this with an 'Application Host' type wrapper. This is a known issue with powershell as a console-based host.
The most convenient way to do this I've found, is to use WScript.exe and run a VBS script that will invoke the process "invisibly", with no console or task bar flicker.
VBS Code:
On Error Resume Next
ReDim args(WScript.Arguments.Count-1)
For i = 0 To WScript.Arguments.Count-1
If InStr(WScript.Arguments(i), " ") > 0 Then
args(i) = Chr(34) & WScript.Arguments(i) & Chr(34)
Else
args(i) = WScript.Arguments(i)
End If
Next
CreateObject("WScript.Shell").Run Join(args, " "), 0, False
Save the above code in a file with extension '.vbs', and place it somewhere it can be run by the client running the task. This may be in a protected fileshare on the network (if you expect the script it invokes to only run while connected to the network), or locally on the client.
Now when you invoke your console-based script (PowerShell, BAT, CScript, etc.), you invoke this VBS script with WScript explicitly WScript.exe. It also pays to throw on the 'Batch Mode' parameter //B which will suppress script errors & prompts - such as if the wrapper file itself can't be found.
At this point, all you need to do is pass powershell & the command you want powershell to run to this launch sequence:
WScript.exe //B "\\Path\To\Launcher.VBS" powershell.exe -ExecutionPolicy ByPass -file "\\Powershell\Script\To\Run"
I had the same problem, it was resolved at the simple way.
When you create a Task on Windows, just set this configuration:
Open Properties dialog;
Then you check Run whether user is logged on or not;
You can check Do not store password to avoid asking for PC password on Task execution;
In Add arguments (optional): just:
-File 'C:\temp\somefile.txt
This spcript will run without popup the prompt.
Solved in this link below:
https://stackoverflow.com/a/50630717/19926325

Running PowerShell code inside VBS with many nested quotes, in one line

I'm starting to see double here from staring at this so long. I am trying to use an environment variable inside a script path that I'm going to launch from PowerShell, all initiated from a single line inside an mshta command run from a scheduled task on logon.
In case you were wondering, MSHTA can execute HTML/VBS/JS as if a local GUI app.
mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& '\\$env:USERDNSDOMAIN\FOLDER1\FOLDER with Spaces\Folder3\Script-To-Run.ps1'"""""", 0 : window.close")
Premise: I have to do it this way to prevent momentary popups that flash onscreen when running from a scheduled task in user context. I cannot run this script in the System context.
I know that putting anything inside two single quotes gives me a string literal but if I try double quotes it seems to then use the space in the path. I've tried separating the two and concatenating them in all sorts of ways to no avail.
VBS equivalent of $env:USERDNSDOMAIN is
CreateObject("Wscript.Shell").ExpandEnvironmentStrings( "%USERDNSDOMAIN%" )
If the goal/purpose is to execute a PowerShell script without displaying the powershell.exe console window, you can do this by running it from a VBScript script executed by wscript.exe (not cscript.exe).
Example VBScript script:
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File """d:\path name\whatever.ps1"" [parameter [...]]", 0, False
The second parameter of the WshShell object's Run method is 0, so powershell.exe executes from a hidden window.
(Hint: The -File parameter to powershell.exe is generally easier to use than -Command. It must be the last parameter on the powershell.exe command line.)
End result: VBScript script runs the PowerShell script from a hidden window. Also, the VBScript itself has no console window, because you executed it using wscript.exe (the GUI host).

Batch script not calling Powershell

I have a batch script that calls a Powershell file in administration mode. I found this code a while ago, and it's worked great ever since:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command
"& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File %PSFile%' -Verb RunAs}";
This time though, I called the batch script from another program. This program says the process worked, but it didn't actually do anything. Examining the logs from echo, I can see the batch script is being called, but it's not calling Powershell. I tried running the batch script manually, and it calls PS fine, so something with how the batch script is being called by the other program is messing with how it calls PS.
This in mind, I tried changing the batch script to directly run my .ps1 file, instead of starting a new admin instance of powershell to start it. My new .bat file looked like this:
Powershell -File %PSFILE% -Verb RunAs
Calling this from the other program sucessfully calls my Powershell script, but I get a bunch of errors from the PS script, since it's not an admin PS session like it needs to be.
How can I change my batch script to call Powershell as an admin, without using Powershell to call itself (which doesn't seem to work with the program that needs to run it)?
EDIT: After trying a bunch of tweaks, I've found I don't even need to be in admin mode to do what this script does. However, I still get access denied errors when running it through the program (admin or not). So something about running it from the program is making it need more permissions than when I run the batch script manually.
This is what I do (inside the .bat file):
If the .bat is NOT running as admin
powershell.exe -Command "powershell.exe 'C:\path\to\script.ps1' -Verb runAs"
If the .bat is running as admin
powershell.exe -ExecutionPolicy Bypass -Command "C:\path\to\script.ps1"
You could use a small utility I wrote called elevate32.exe/elevate64.exe.
elevate64 -- C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File "d:\path to script\scriptfile.ps1"
elevate32.exe (32-bit version) and elevate64.exe (64-bit version) basically elevate whatever command line you pass to them.
You can get it here (ElevationToolkit1.zip):
http://www.westmesatech.com/misctools.html
An alternative is to use a short WSH script that, when called, provokes elevation. An example is on Aaron Margosis' blog here:
https://blogs.msdn.microsoft.com/aaron_margosis/2007/07/01/scripting-elevation-on-vista/
Script:
// elevate.js -- runs target command line elevated
if (WScript.Arguments.Length >= 1) {
Application = WScript.Arguments(0);
Arguments = "";
for (Index = 1; Index < WScript.Arguments.Length; Index += 1) {
if (Index > 1) {
Arguments += " ";
}
Arguments += WScript.Arguments(Index);
}
new ActiveXObject("Shell.Application").ShellExecute(Application, Arguments, "", "runas");
}
else {
WScript.Echo("Usage:");
WScript.Echo("elevate Application Arguments");
}
The limitations of this approach is that it relies on the WSH command-line parser and can't wait for the program to terminate. These limits may not be a problem in your scenario.
Looks like I was totally off as to the problem source. This was a permissions error on some folders I was editing. The program I was running the scripts through acts as a separate service. I had to add that with modify permissions to the security groups of all the folders I was editing. No elevation required in the scripts, just modifying permissions.

Run Powershell Silently via NSIS

I have a powershell script that I want to run silently.
I am using NSIS script, it's still promoting the powershell command prompt when .exe file is ran..
Is there a way so it will silently.
!include FileFunc.nsh
!include x64.nsh
OutFile "script.exe"
SilentInstall silent
RequestExecutionLevel admin
Function .onInit
SetSilent silent
FunctionEnd
Section
SetOutPath $EXEDIR
File "script.ps1"
IfSilent 0 +2
ExecWait "powershell -ExecutionPolicy Bypass .\script.ps1 -FFFeatureOff"
SectionEnd
Function .onInstSuccess
Delete "script.ps1"
FunctionEnd
There is an example here that uses silent install, but I couldn't get it working when I tried it. http://nsis.sourceforge.net/Examples/silent.nsi
Try this:
ExecWait "powershell -ExecutionPolicy Bypass -WindowStyle Hidden -File .\script.ps1 -FFFeatureOff"
More info: PowerShell.exe Command-Line Help
You can try ExecShell for this, it allows to hide console via SW_HIDE flag:
ExpandEnvStrings $0 "%COMSPEC%"
ExecShell "" '"$0"' "/C powershell -ExecutionPolicy Bypass .\script.ps1 -FFFeatureOff" SW_HIDE
Also, refer to this question:
Exec vs ExecWait vs ExecShell vs nsExec::Exec vs nsExec::ExecToLog vs nsExec::ExecToStack vs ExecDos vs ExeCmd
Powershell.exe is a console application and console applications get a console window by default and the NSIS silent parameter has no impact on console windows created for child processes. A parameter like -WindowStyle Hidden that can be passed to the child process will always cause a console window to be visible on the screen for a short period of time because Windows will create the console window before the child process starts running.
If you need to hide a console window then you should use a plugin. nsExec is part of the default install or you could use a 3rd-party plugin like ExecDos that offers more advanced features like stdin handling.
If you don't need to wait for the child process then you can try ExecShell as suggested by Serge Z...

Powershell equivalent of the "tail" command ALMOST works remotely

I am looking for a Windows 7 equivalent of the "tail" command and thought I had found it with this Powershell equivalent -
C:\>powershell -command "& {Get-Content file.txt | Select-Object -last 100}"
If I use this in the CMD prompt on my own Windows 7 PC, returns the info just fine. I can even input/append it into another file.
However, when I log on remotely to another PC (via openSSH), the command works, but it never drops me back to a command prompt - just hangs after showing me the last 100 lines of the file. Which means this won't work for a batch file I'm trying to edit for about 300 remote Windows 7 PCs.
Any ideas?
After trying MANY different suggestions found all over online, FINALLY found one that worked!
And the answer is within the Batch file itself. My batch file to call this Powershell line was just this:
Powershell.exe -noprofile -executionpolicy Bypass C:\log\Tail.ps1
:end
Again, works great if you're using it on the very PC from which you want it to run/get the information. But not remotely. Finally found you just need to add "< nul" to the end of your call to Powershell in your batch file, just like this
Powershell.exe -noprofile -executionpolicy Bypass C:\log\Tail.ps1 <nul
:end
What the other person wrote is what finally made sense: "My research has shown that PowerShell runs the commands in the script indicated through the -File switch and then waits for additional PowerShell commands from the standard input (my brief experimentation with the -Command switch demonstrated similar behavior). By redirecting the standard input to nul, once PowerShell finishes executing the script and 'reads end-of-file' from the standard input, PowerShell exits."
Found here at this page - Powershell script gets stuck, doesn't exit when called from batch file
so credit actually goes to #Gordon Smith
Since your running the command with -command "...", according to the docs, you need to specify the -noexit flag to stop powershell from exiting after the command is run.
powershell -command "& {Get-Content file.txt | Select-Object -last 100}" -noexit
When you add this to a batch file you'll probably need -noprofile and -noninteractive as well - though for remote commands you might want to spawn a process for better control and error handling. Also, if this doesn't work the problem would probably be with how OpenSSH is handling something (this worked for me on a test-server with remote connect)