Powershell closes on executing exe - powershell

I am trying to run and .exe in C:programfiles(x86)
I can launch it directly from the filepath. If I run in powershell just closes. No feedback.
Running powershell 5.1.17134 Rev 590
Start-Process -FilePath "C:\Program Files (x86)\App\App.exe"
I tried running powershell -NoExit and then start-process but it returns without any feedback.
If I run it on same machine in Powershell 6.1.0 preview - it runs fine. No issue. How can I track down whats causing this to 1) not run 2)close powershell.
Thanks,

This answer makes a general point. It doesn't solve your problem, if using Start-Process truly crashes the calling PowerShell window.
If C:\Program Files (x86)\App\App.exe is a console application that you want to run in the current console window, do not use Start-Process to invoke it.
Instead, invoke it directly.
Given that its path contains spaces and special characters (( and )), you need to:
quote it
invoke it with &, PowerShell's call operator.
PS> & 'C:\Program Files (x86)\App\App.exe'
Note:
The use of & with a command specified in a quoted string and/or via a variable reference is a syntactic necessity, given that PowerShell has two distinct parsing modes - see about_Parsing.
Invoking a console application directly:
ensures its synchronous execution
That is, control isn't returned to the caller until the application has terminated.
connects its standard output streams - stdout and stderr - to the equivalent PowerShell streams.
That is, you can capture or redirect the application's success output and/or error output, as needed.

You have an interactive shell. You spawn this new process - then your shell closes?
Clearly it is terminating its parent process, and clearly pwsh is doing something different.
I don't think this is truly a powershell question, it's a windows internals one. The suite of tools to use is Sysinternals. The first thing I'd try - and I'd do this on cmd, powershell and pwsh to establish a basis for comparison - is run Process Monitor with a filter on your app's path. Something in its last actions may prove illuminating. Process Explorer may also be useful.
Are you in a corporate environment? I have agents on my machine that kill processes based on heuristics. That can do things like this.
There may be a workaround based on how you invoke the app;
try mklement0's suggestion
try invoking through WMI; this does not provide your powershell process as a parent process: Invoke-WmiMethod -Class win32_process -Name create -ArgumentList "PathToApp.exe"
try invoking via cmd.exe if you are constrained by what's on your target machines
I do think this is off-topic, though.

Related

How to run a batch script without the window flashing?

using suggestions from a previous a question (Kill process after timeout when homonym processes are open - batch) I was able to kill homonym processes after a timeout:
popd
pushd mypath
for /f %%i in ('powershell "(Start-Process myapp.exe -passthru).ID"') do (
timeout /t 180
taskkill /PID %%i
)
However, I would like to start the process without a window displaying (and flashing).
I found many questions, such as: How to run a PowerShell script without displaying a window? but I was not able to combine them to my script. How can I do that?
Thank you for your help
Following Steven's comment I added -WindowStyle Hidden also inside the loop. Here the solution:
pushd mypath
for /f %%i in ('powershell -WindowStyle Hidden -"(Start-Process myapp.exe -passthru -WindowStyle Hidden).ID"') do (
timeout /t 180
taskkill /PID %%i
)
tl; dr
To hide only the console window that results from use of Start-Process with a console application (myapp.exe in your case), use -WindowStyle Hidden, as shown in your answer, but you can also streamline and shorten your code by performing all operations in a single powershell.exe call:
#echo off
powershell.exe -c "if (-not ($ps = Start-Process -WindowStyle Hidden myapp.exe -PassThru).WaitForExit(60000)) { Stop-Process $ps }"
Use cases:
What you wanted is to hide the console window that by default results from PowerShell's Start-Process launching a console application (which isn't normally done, because direct, synchronous execution is by far the most common use case - see this answer):
-WindowStyle Hidden hides this new window; note that you won't be able to see or capture any output, unless you request redirection to files via the
-RedirectStandardOutput and -RedirectStandardError parameters; also, in order to check the exit code you need to use -PassThru so as to obtain an object that represents the newly launched process.
If you want to see the program's output in the current console window - albeit without being able to capture it - use -NoNewWindow, which, however, only makes sense if you also use -Wait, otherwise the asynchronously running program's output will interfere with your display (and if you're waiting anyway, direct, synchronous invocation is the better option).
As an aside: on Unix-like platforms, -WindowStyle isn't supported, and -NoNewWindow is implied, which mostly makes Start-Process only useful for launching GUI programs on Unix (including launching URLs in order to open them in the default web browser; e.g. Start-Process http://example.org)
However, your question's title might lead people to think your intent is to run the batch file itself - or any console application - invisibly:
Windows currently offers no direct mechanism for that; launching a console application invariably creates a visible console for it. A solution therefore requires a GUI-subsystem helper file or mechanism that (a) itself doesn't create a console window and (b) allows hiding the automatically console window when launching the target console application (however, a potential future enhancement is being discussed, conditional allocation of a console, which would allow applications to decide whether or not to allocate a console based on runtime conditions, but note that only applications designed to use this feature would then offer situational no-console launching).
For now, there are several solutions:
Call via mshta.exe:; a simple example that runs powershell.exe itself invisibly and ultimately opens Notepad; you can run it from the Windows Run dialog (Win-R) to verify that no console window is created for PowerShell:
mshta.exe vbscript:(CreateObject("WScript.Shell").Run("powershell -c notepad.exe",0))(Window.Close)
Caveat: AV software may prevent this invocation mechanism.
Use an auxiliary WSH script (*.vbs or *.js) launched via the GUI-subsystem wscript.exe host - see this answer.
Use the third-party RunHiddenConsole project, which offers a generic GUI-subsystem helper executable that you name for your target executable with w appended.
Use Python:
See this answer.
In the context of PowerShell, specifically:
Use a GUI-subsystem wrapper executable for PowerShell scripts that the third-party PS2EXE-GUI script can create for you; see this answer for an example.
Note: The wrapper-generating script must be run in Windows PowerShell and the resulting *.exe too executes via the Windows PowerShell SDK.
The PowerShell (Core) CLI, pwsh.exe, may itself offer a solution in the future, as discussed in GitHub issue #3028, based on the previously linked planned system-level enhancement, conditional console allocation).

PowerShell Start-Process with -ArgumentList doesn't work

A very easy line in a powershell script
Start-Process -FilePath displayswitch -ArgumentList "/extend"
It is supposed to extend my screen. Yet it doesn't work because there is something wrong with the ArgumentList. What is it?
In general, do not use Start-Process to invoke CLIs (command-line interfaces; i.e., programs that accept command-line arguments), unless you explicitly want to launch them asynchronously, in a new window - see this answer for background information.
In the case at hand - for reasons unknown to me[1] - Start-Process additionally seems to prevent the displayswitch.exe executable from functioning properly when arguments are passed (the syntax of your Start-Process command is correct).
However, that is a moot point if you invoke displayswitch.exe directly, which is generally the right choice for CLIs:[2]
displayswitch.exe /extend
[1] The problem may be related to the fact that displayswitch.exe is a GUI-subsystem rather than a console-subsystem application. That is, it doesn't allocate a console window for itself and operates asynchronously when called from an existing console window. Using Start-Process therefore makes the executable run without a console window. That said, running displayswitch.exe /extend from the Windows Run dialog (WinKey-R), where no console window is involved either, works correctly.
[2] Given that displayswitch.exe is a GUI-subsystem application, it will act asynchronously even in direct invocation, but I assume that's not a problem here. If your Start-Process command had worked, it would have been asynchronous too. Adding -Wait to a Start-Process call makes it synchronous, and you can emulate this behavior in direct invocation by piping to Out-Null. However, due to how displayswitch.exe is implemented, even displayswitch.exe /extend | Out-Null doesn't result in fully synchronous operation.

Powershell not running on cmd

I'm trying to run the following command but when I do it the CMD windows closes without the command being executed
the command is
cmd.exe /c powershell.exe (New-Object System.Net.WebClient).DownloadFile(https://site,'%temp%\file.txt');Start-Process '%temp%\file.txt'
You don't need cmd here at all¹. You can spawn a process without a shell just as well. Furthermore, it's usually a good idea to quote arguments to avoid surprises with argument parsing (cmd for example has its own meaning for parentheses, which may well interfere here).
powershell -Command "(New-Object System.Net.WebClient).DownloadFile('https://site',$Env:Temp + '\file.txt');Invoke-Item $Env:Temp\file.txt"
I've also added quotes around the URL you want to download, since that wouldn't otherwise work, either. And since cmd is no longer around, environment variables can be expanded by PowerShell as well, with a different syntax.
Start-Process also is for starting processes and Invoke-Item is closer to what you actually want, although I'm sure with ShellExecute behavior, Start-Process could launch Notepad with a text file as well if desired.
¹ If in doubt, it's always a good idea to reduce the number of parts, processes and different wrapped concepts needed. Same reason why you don't use Invoke-Expression in PowerShell to run other programs: Unnecessary, and complicates everything just further by introducing another layer of parsing and interpretation.

-s when using Start-Job in powershell

I am trying to call a Start-Job in powershell. When I do, it spawns a background powershell with the following arguments:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Version 5.0 -s -NoLogo -NoProfile -EncodedCommand [encoded command I want to run in base64]
However, the powershell command never seems to complete, whatever the command I send it.
I tried spawning a powershell instance like this:
powershell.exe -s
And this also seems to create an instance that seems frozen, not executing or doing anything. Looking online, I cannot seem to find any reference to the -s argument.
Does anybody know what it's for or how to get rid of it so that my start-jobs work properly?
Edit: It's possible that -s is the shorthand for -sta, but my command does not freeze using -sta, but it does using -s.
Edit2: I have since found out that -s is a shorthand for -ServerMode, apparently a Legacy Powershell 2.0 option. I have no idea why that is added when using Start-Job.
Edit3: The command I use is:
$deploymentsJobs += Start-Job -InitializationScript { SomeSmallFunction } (AnotherFunction) -ArgumentList $arg1, $arg2, $arg3}
tl;dr:
The -s option is an expected part of the command line used to launch a background job via a new PowerShell process - it puts the new process in server mode, which is required to communicate with the calling process for background job management.
It is not a legacy option, but it isn't documented either, because it is only meant to be used internally by PowerShell.
Given that everything you describe is as expected, the problem is likely with the specific commands you run via -InitializationScript and in the main script block (the implied -ScriptBlock argument).
As you've discovered, a Start-Job call spawns a powershell -s -NoLogo -NoProfile call behind the scenes (discoverable via Task Manager).
That is, a new PowerShell process is created to run the commands in the background.
An -EncodedCommand parameter with a Base64-encoded command string is only present if you invoked Start-Process with the -Initialization parameter - the main script block (the (implied) -ScriptBlock argument) is not passed via the command line (see below).
-s is used PowerShell-internally - always - to invoke background jobs, and -s, as you've also discovered, is an alias for the -servermode switch. (Given that only -STA is documented, one would expect -s to be short for -STA, but it is not).
-s / -servermode is an implementation detail, used only by PowerShell itself, which is why it isn't documented.
This location in the PowerShell Core source code on GitHub shows you how the command line for the background process is constructed.
Server mode is the mode the background process must be in in order to communicate with the calling process via its standard streams (stdin, stdout, stderr): That is, the command to execute in the background is sent to the background process through its stdin stream, and the background process reports its output via its stdout and stderr streams.[1]
Note that XML-based serialization / deserialization happens during this inter-process communication, using the same infrastructure as PowerShell remoting - see this answer for more information.
[1] Ohad Schneider points out that it is possible to accidentally disrupt this communication if the main script block contains commands such as Start-Process -NoNewWindow with a console program that directly write to the background process' stdout stream - see this answer.

How to get Hudson CI to execute a Powershell script?

I'm using Hudson version 1.324 for CI and have a couple of issues:
Environment:
Windows Server 2008
Powershell v1.0
Hudson 1.324 running as a service
Hudson Powershell Plugin installed
Psake (aka. "Powershell Make/Rake" available from Github) 0.23
(All current/latest versions as of this initial post)
I have a Powershell (PS) script that works to compile, run NUnit tests, and if successful, create a 7z file of the output. The PS script works from the command line, on both my local development box as well as the CI server where Hudson is installed.
1) Execution Policy with Powershell.
I initially ran a PS console on the server, ran Set-ExecutionPolicy Unrestricted, which allows any script to be run. (Yes, I realize the security concerns here, I'm trying to get something to work and Unrestricted should remove the security issues so I can focus on other problems.)
[This worked, and allowed me to fire off the PS build script from Hudson yesterday. I then encountered another problem, but we'll discuss that more in item #2.]
Once Hudson could fire off a PS script, it complained with the following error:
"C:\Windows\system32\WindowsPowerShell\v1.0\powershell "&
'OzSystems.Tools\psake\psake.ps1' '.\oz-build.ps1'" The term
'OzSystems.Tools\psake\psake.ps1' is not recognized as a cmdlet, funct
ion, operable program, or script file. Verify the term and try again.
At line:1 char:2
+ & <<<< 'OzSystems.Tools\psake\psake.ps1' '.\oz-build.ps1'"
Using the same command line, I am able to successfully execute the PS script from the command line manually. However Hudson is unable to get PS to do the same. After looking at additional PS documentation I also tried this:
"& 'OzSystems.Tools\psake\psake.ps1' '.\oz-build.ps1'"
and got a similar error. There does not appear to be any documentation for the Powershell plugin for Hudson. I've gone through all the Powershell plugin files and don't see anything that's configurable. I can't find a log file for Hudson to get additional information.
Can anyone help me past this?
2) I spent yesterday wrestling with #1. I came in this AM and tried to dig in again, after restarting the Hudson server/service, and now it appears that the ExecutionPolicy has been reset to Restricted. I did what worked yesterday, opened a PS console and Set-ExecutionPolicy to Unrestricted. It shows Unrestricted in the PS console, but Hudson says that it doesn't have rights to execution PS scripts. I reopened a new PS console and confirmed that the ExecutionPolicy is still Unrestriced -- it is. But Hudson evidently is not aware of this change. Restarting Hudson service again does not change Hudson's view of the policy.
Does anyone know what's going on here?
Thanks, Derek
I just ran into the problem of running powershell scripts in hudson. The thing is that you are running a 32-bit process of Java, and you've configured Hudson for 64-bit but not for 32-bit. See the following thread we created at microsoft.
http://social.technet.microsoft.com/Forums/en/winserverpowershell/thread/a9c08f7e-c557-46eb-b8a6-a19ba457e26d
If your lazy.
1. Start powershell (x86) from the start menu as administrator
2. Set the execution policy to remotesigned
Run this once and your homefree.
When Running PowerShell from a scheduled task or Hudson you want to:
Specify the -ExecutionPolicy parameter (in your case: -Ex Unrestricted)
Specify that command using either -Command { ... } or -File NOT BOTH and not without specifying which you mean.
Try this (except that I don't recommend using relative paths):
PowerShell.exe -Ex Unrestricted -Command "C:\Path\To\OzSystems.Tools\psake\psake.ps1" ".\oz-build.ps1"
To be clear, this will work too:
PowerShell.exe -Ex Unrestricted -Command "&{&'OzSystems.Tools\psake\psake.ps1' '.\oz-build.ps1'}"
The first string after -Command is interpreted as THE NAME OF A COMMAND, and every parameter after that is just passed to that command as a parameter. The string is NOT a script, it's the name of a command (in this case, a script file)... you cannot put "&'OzSystems.Tools\psake\psake.ps1'" but you can put "OzSystems.Tools\psake\psake.ps1" even if it has spaces.
To quote from the help (run PowerShell -?) emphasis mine:
-Command
Executes the specified commands (and any parameters) as though they were
typed at the Windows PowerShell command prompt, and then exits, unless
NoExit is specified. The value of Command can be "-", a string. or a
script block.
If the value of Command is "-", the command text is read from standard
input.
If the value of Command is a script block, the script block must be enclosed
in braces ({}). You can specify a script block only when running PowerShell.exe
in Windows PowerShell. The results of the script block are returned
to the parent shell as deserialized XML objects, not live objects.
If the value of Command is a string, Command must be the last parameter
in the command , because any characters typed after the command are
interpreted as the command arguments.
I have been having the same problems as you (as you've seen from my comments). I have given up on the powershell launcher and moved to running things using the batch file launcher. Even though I had set the system to unrestricted that setting didn't seem to matter to hudson's launcher. I don't know if it runs in some other context or something, even adding things to the global profile.ps1 didn't seem to help. What I ended up doing was running
powershell " set-executionpolicy Unrestricted; & 'somefile.ps1'"
which does what I need, although it isn't ideal. I've e-mailed the plugin author about this and will update.
For question #1, try this (assuming you are using PowerShell 2.0):
"C:\Windows\system32\WindowsPowerShell\v1.0\powershell -executionPolicy Unrestricted -file OzSystems.Tools\psake\psake.ps1 C:\{path}\oz-build.ps1"
You are using "." for the path to oz-build.ps1. I suspect you will need to provide the full path to your oz-build.ps1 file to make this work. Unless the infrastructure that executes the command above happens to have the current dir set correctly. And even if it is set correctly for the "process", that only matters to .NET/Win32 API calls and not to PowerShell cmdlets. Current dir in PowerShell is tracked differently than the process's current dir because PowerShell can have multiple runspaces running simultaneously. That sort of global, mutable value doesn't work in this concurrent scenario.
As for question #2, what account does the Hudson service run under? Make sure that account has executed Set-ExecutionPolicy RemoteSigned (or unrestricted).
I just got through this exact problem. What a pain!
If you are running a 32-bit JVM on a 64-bit Windows, make sure that you set the execution policy for the 32-bit Powershell interface. I found my 32 bit executable here:
C:\Windows\syswow64\Windowspowershell\v1.0\powerhsell.exe
The 32- and 64-bit Powershell environments are completely distinct so setting the execution policy in one has no effect on the other.