Is it possible to react to a VBScript msgbox from a PowerShell script? - powershell

I've been working to make manual processes more of a one-click process and I've run into an issue with these msgbox popups from a VBScript script.
Essentially, I am using PowerShell and doing something like:
foreach ($loc in $locs):
& cscript $loc
Where the $loc in $locs is a variable holding the path of a .vbs file that needs to be run.
The issue is that one of our developers included two msgbox statements in each of the .vbs files and those pop up and require you to click OK. It would be trivial to edit the VBScript scripts and remove these, but I do not want to change our developers' scripts - so the question is: is it possible to make PowerShell react to the msgbox(s) that are generated from the cscript line?
I'm not sure how I would bring the box into context or react to it via PowerShell.

Run the scripts in batch mode. This will prevent any prompt from stalling execution:
foreach ($loc in $locs){
& cscript //B $loc
}
From the cscript /? usage message:
Usage: CScript scriptname.extension [option...] [arguments...]
Options:
//B Batch mode: Suppresses script errors and prompts from displaying
//D Enable Active Debugging
//E:engine Use engine for executing script
//H:CScript Changes the default script host to CScript.exe
//H:WScript Changes the default script host to WScript.exe (default)
//I Interactive mode (default, opposite of //B)
...

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

PowerShell exiting

I have a script I wrote in PowerShell ISE that works perfectly.
It even works if I copy and paste it into regular PowerShell. However when I run it with regular PowerShell by making it the default program to open it with, then double-clicking, it just opens, displays some red text, and closes.
Is there a way to stop it from closing so I can view the red text or is this a common issue that can be fixed easily?
Try running from cmd prompt using:
powershell -noexit <path to the script>
Additionally, I think the error script may be throwing could be due to execution policy on your machine blocking the script from executing. Otherwise transcript would work. Ensure that the execution policy is set appropriately using Set-ExecutionPolicy cmdlet.
The practice of setting Powershell scripts to run when double clicked is highly discouraged for security reasons. Please ensure you are aware of the risks involved before you proceed.
You cannot simply 'make Powershell as default program' through the Windows Explorer interface. The Run with Powershell context menu option uses the following command:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
The "safest" way (bearing in mind the above caveat) to do what you are trying to achieve is to use Default Programs Editor to set the Run with Powershell context menu option to be the default.

Can't get basic Powershell script running inside Team City

Here's my configuration:
On the build log, I only see the output of the first two lines, and then "Process exited with code 0" as the last output of this build step.
I tried opening a terminal in the build server in the SYSTEM account (using PsTools), since Team City is configured to run under said account. Then, I created a Test.ps1 file with the same content and ran a command just like Team City's:
[Step 1/4] Starting: C:\Windows\system32\cmd.exe /c C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -Command - <C:\TeamCity\buildAgent\temp\buildTmp\powershell5129275380148486045.ps1 && exit /b %ERRORLEVEL%
(except for the path to the .ps1 file and the cmd.exe initial part, of course). I saw the output of the two first lines, and then the terminal disappeared all of a sudden!
Where did I mess up? I'm new to Powershell, by the way.
The stdin command option of Powershell has some weirdness around multiline commands like that.
You script in the following form would work:
write-host "test"
write-host "test2"
if("1" -eq "1"){write-host "test3 in if"} else {write-host "test4 in else"}
The ideal way would be to use the Script : File option in TeamCity which will will run the script you specify using the -File parameter to Powershell.
If you don't want to have a file and having VCS, in the current setup, change Script Execution Mode to Execute .ps1 file with -File argument.
I've had this problem with inline powershell scripts with TeamCity (right up until the current version of 7.1.3). I've found the problem to be the tab character rather than multi-line statements. Try replacing the tab characters with spaces (while still remaining multi-line) and the script should run fine.
You could try putting the brace opening the block on the same line as the If.
I.e.,
If ('1' -eq '1') {
...
}
Else {
...
}
That's the usual styling you see with Powershell, and obviously, putting the braces on the next line can cause problems.

Powershell window disappears before I can read the error message

When I call a Powershell script, how can I keep the called script from closing its command window. I'm getting an error and I'm sure I can fix it if I could just read the error.
I have a Powershell script that sends an email with attachment using the .NET classes. If I call the script directly by executing it from the command line or calling it from the Windows Scheduler then it works fine. If I call it from within another script (IronPython, if that matters) then it fails. All scenarios work fine on my development machine. (I really do have to get that "Works on My Machine" logo!) I've got the call to Powershell happening in a way that displays a command window and I can see a flicker of red just before it closes.
Sorry: Powershell 1.0, IronPython 1.1
Solution: powershell -noexit d:\script\foo.ps1
The -noexit switch worked fine. I just added it to the arguments I pass from IronPython. As I suspected, it's something that I can probably fix myself (execution policy, although I did temporarily set as unrestricted with no effect, so I guess I need to look deeper). I'll ask another question if I run into trouble with that.
Thanks to all for the help. I learned that I need to investigate powershell switches a little more closely, and I can see quite a few things that will prove useful in the future.
Try with the -noexit switch:
powershell -noexit d:\script\foo.ps1
You basically have 3 options to prevent the PowerShell Console window from closing, that I describe in more detail on my blog post.
One-time Fix: Run your script from the PowerShell Console, or launch the PowerShell process using the -NoExit switch. e.g. PowerShell -NoExit "C:\SomeFolder\SomeScript.ps1"
Per-script Fix: Add a prompt for input to the end of your script file. e.g. Read-Host -Prompt "Press Enter to exit"
Global Fix: Change your registry key to always leave the PowerShell Console window open after the script finishes running.
Here are the registry keys to modify for option #3:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Applications\powershell.exe\shell\open\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit \"& \\\"%1\\\"\""
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit \"-Command\" \"if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & \\\"%1\\\"\""
See my blog for more information and a .reg file that will apply these registry changes automatically.
I've needed this before and usually I didn't want to modify the script (typically for scripts fired off from the Task Scheduler). I just wanted to see what was spit out to console.
All you need to do is just append a Read-Host command after the script invocation e.g.:
PowerShell.exe -command { .\foo.ps1; read-host "Press enter key to continue" }
BTW the problem with using Start-Transcript is that it doesn't capture EXE output. And any form of attempted logging in V1 and even V2 with the standard host will not capture the verbose, debug, progress or warning streams. You can only see these by viewing the associated host window.
One cheesy but effective way to capture all script output (stdout, stderr, verbose, warning, debug) is to use another host like cmd.exe e.g.:
cmd.exe /c powershell.exe "$pwd\foo.ps1" > foo.log
I am generaly fine with scripts autoclosing except when an error occurs, where I need to see the error. Assuming you have not changed $ErrorActionPreference away from the default 'Continue', then for the behaviour I described do this at the end of you script
if ($Error)
{
Pause
}
There is no ordinary Try...Catch construction in Powershell; however you can trap exceptions instead and react properly.
I.E:
Function Example() {
trap [Exception] {
write-host "We have an error!";
write-error $("ERROR: " + $_.Exception.Message);
sleep 30;
break;
}
write-host "Hello world!";
throw "Something very bad has happened!";
}
You can also simulate Try...Catch construction:
Function Example2() {
${
write-host "Our try clause...";
throw "...caused an exception! It hurts!";
}
trap [Exception] {
write-error $_.Exception.Message;
sleep 30;
continue;
}
Of course as soon as you will trap an exception, you can log it, sleep, or whatever you want with the error message. My examples just sleep, allowing you to read what happened, but it's much better to log all the errors. (The simplest way is to redirect them with >>).
Look also at:
http://huddledmasses.org/trap-exception-in-powershell/
A quick and dirty solution is to use CTRL+S to halt the scrolling of the display and CTRL+Q to resume it.
You have three options:
Do a catch in the script (if using
Powershell V2)
Write a dummy
script which catches and redirects
stdout which you can then access as a
variable from your IronPython script.
VBS/Wscript Intro An addition to
this is just liberally drop
Read-Host commands everywhere,
and hit return to page through.
Rather than outputting anything to the shell, wrap your powershell script in a second script that redirects all output to a log file.
PS C:> myscript.ps1 |Out-File myscript.log
Create run_ps_script.bat file containing
#PowerShell.exe -command "try { %1 } finally { read-host 'Press ENTER...' }"
and make it default program to open PowerShell scrips.
My solution was to execute the script with a command line from the console window instead of right-clicking the file -> execute with powershell.
The console keeps displaying the error messages,
even though the execution of the script ended.
Have you thought about redirecting stdout and stderr to a file ex:
./ascript.ps1 >logs 2>&1
Note: You can create wrapper script in powershell that calls your powershell script with all necessary redirections.
My .PS1 script ran fine from the Powershell console but when "double-clicking" or "right-click open with powershell" it would exhibit the 'open/close' problem.
The Fix for me was to rename the script folder to a Name Without Spaces.
Then it all worked - Windows couldn't deal with
"C:\This is my folder\myscript.ps1" but
"C:\This_is_my_folder\myscript.ps1" worked just fine
A couple more ideas...You could use the start-sleep cmdlet at the end of you script to give you enough time to review the error.
You might also be able to use start-transcript to record the session to a text file.

Set up PowerShell Script for Automatic Execution

I have a few lines of PowerShell code that I would like to use as an automated script. The way I would like it to be able to work is to be able to call it using one of the following options:
One command line that opens PowerShell, executes script and closes PowerShell (this would be used for a global build-routine)
A file that I can double-click to run the above (I would use this method when manually testing components of my build process)
I have been going through PowerShell documentation online, and although I can find lots of scripts, I have been unable to find instructions on how to do what I need. Thanks for the help.
From http://blogs.msdn.com/b/jaybaz_ms/archive/2007/04/26/powershell-polyglot.aspx
If you're willing to sully your beautiful PowerShell script with a little CMD, you can use a PowerShell-CMD polyglot trick. Save your PowerShell script as a .CMD file, and put this line at the top:
#PowerShell -ExecutionPolicy Bypass -Command Invoke-Expression $('$args=#(^&{$args} %*);'+[String]::Join(';',(Get-Content '%~f0') -notmatch '^^#PowerShell.*EOF$')) & goto :EOF
If you need to support quoted arguments, there's a longer version, which also allows comments. (note the unusual CMD commenting trick of double #).
##:: This prolog allows a PowerShell script to be embedded in a .CMD file.
##:: Any non-PowerShell content must be preceeded by "##"
##setlocal
##set POWERSHELL_BAT_ARGS=%*
##if defined POWERSHELL_BAT_ARGS set POWERSHELL_BAT_ARGS=%POWERSHELL_BAT_ARGS:"=\"%
##PowerShell -ExecutionPolicy Bypass -Command Invoke-Expression $('$args=#(^&{$args} %POWERSHELL_BAT_ARGS%);'+[String]::Join(';',$((Get-Content '%~f0') -notmatch '^^##'))) & goto :EOF
Save your script as a .ps1 file and launch it using powershell.exe, like this:
powershell.exe .\foo.ps1
Make sure you specify the full path to the script, and make sure you have set your execution policy level to at least "RemoteSigned" so that unsigned local scripts can be run.
Run Script Automatically From Another Script (e.g. Batch File)
As Matt Hamilton suggested, simply create your PowerShell .ps1 script and call it using:
PowerShell C:\Path\To\YourPowerShellScript.ps1
or if your batch file's working directory is the same directory that the PowerShell script is in, you can use a relative path:
PowerShell .\YourPowerShellScript.ps1
And before this will work you will need to set the PC's Execution Policy, which I show how to do down below.
Run Script Manually Method 1
You can see my blog post for more information, but essentially create your PowerShell .ps1 script file to do what you want, and then create a .cmd batch file in the same directory and use the following for the file's contents:
#ECHO OFF
SET ThisScriptsDirectory=%~dp0
SET PowerShellScriptPath=%ThisScriptsDirectory%MyPowerShellScript.ps1
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%'"
Replacing MyPowerShellScript.ps1 on the 3rd line with the file name of your PowerShell script.
This will allow you to simply double click the batch file to run your PowerShell script, and will avoid you having to change your PowerShell Execution Policy.
My blog post also shows how to run the PowerShell script as an admin if that is something you need to do.
Run Script Manually Method 2
Alternatively, if you don't want to create a batch file for each of your PowerShell scripts, you can change the default PowerShell script behavior from Edit to Run, allowing you to double-click your .ps1 files to run them.
There is an additional registry setting that you will want to modify so that you can run scripts whose file path contains spaces. I show how to do both of these things on this blog post.
With this method however, you will first need to set your execution policy to allow scripts to be ran. You only need to do this once per PC and it can be done by running this line in a PowerShell command prompt.
Start-Process PowerShell -ArgumentList 'Set-ExecutionPolicy RemoteSigned -Force' -Verb RunAs
Set-ExecutionPolicy RemoteSigned -Force is the command that actually changes the execution policy; this sets it to RemoteSigned, so you can change that to something else if you need. Also, this line will automatically run PowerShell as an admin for you, which is required in order to change the execution policy.
Source for Matt's answer.
I can get it to run by double-clicking a file by creating a batch file with the following in it:
C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe LocationOfPS1File
you can use this command :
powershell.exe -argument c:\scriptPath\Script.ps1