Powershell write to stdout (no newline) - powershell

I need something absolutely simple but apparently totaly impossible. I need to write something to stdout in powershell.
So far I found only write-output but this unfortunately appends linefeed. I tried to somehow "hack" it by getting stdout from .net but I always get host stream which doesnt do what I want.
Do anyone knows a way how can I write for example 1 to stdout so when I pipe the script exactly 1 is on stdin of other script? I accept any kind of hack but I dont want to do redirection on invocation like ()sth>&1 | script.

I was going crazy trying to capture PowerShell output from a PowerShell command I executed from within a Python script. And it did not work because PowerShell does not properly write to STDOUT.
But I found some ways...
First is using the PowerShell command Write-Information:
Write-Information -Message "This goes to Stdout" -InformationAction Continue
The other is starting PowerShell with cmd and capture the output of cmd:
cmd.exe /C "powershell.exe -command "Write-Host 'This goes to Stdout'"

Related

How to execute string as batch script in PowerShell

I have a string in PowerShell that I want to have executed as a batch script.
Something like:
cmd /c $batch_script
I am working with a giant cluster%!&$ software suite called Oracle Hyperion (with which most knowledge of how it operates appears to be lost - even within Oracle), so the reasons I want to do this are complex and require specific knowledge to understand, so I really just want to know if this is possible or not.
You can run a .bat file with & and then path to the bat file.
& D:\BatScripts\Example.bat
You can then also pipe that info to a string and assign it to a variable to compare against expected output etc.
$batOutput = & D:\BatScripts\Example.bat | Out-String
if($batOutput -like '*The operation completed successfully.*'){
Write-Host ("Job Complete")
} else{
Write-Host ("Job Failed")
}
Hope that helps.
Old question, but for anyone searching for the answer - this might work. Still somewhat new to PS myself, but it appears you can execute EXE files just by typing them in. But SET is an internal BATCH command, not an executable file. So executing CMD, and passing it SET, seems to work.
$Cmd = "SET"
CMD.EXE /C "$Cmd"
You should be able to build any string you want in the $Cmd variable and execute it. Not sure if the quotes around $Cmd are actually seen by CMD.EXE, so you may run into some issues where you have add quotes into the string.

Powershell Script not working out of ISE

I have a powershell Script that runs fine in the ISE, but when I run it directly from the .ps1 file it stops at this point:
Write-Host "Attempting to start FFMPEG Process with arguments:$ArgumentList::::" -ForegroundColor Green
Start-Process $SCRIPT:FFMPEGLocation $ArgumentList -Wait
I get the Write-Host printout, with the correct Argument List, but no window pops up for the start-process or anything. I made sure to use the SCRIPT scope variable for anything that is outside the function. It runs fine in ISE just not when I run it in Console. No errors either, and the $SCRIPT:FFMPEGLocation variable is a direct path to the exe to be executed.
Any help would be greatly appreciated, and if you need more let me know.
PSVersion 5.1.14393.1066
OSVersion 10.0.14393
As per comments, check the value passed to Start-Process to ensure it contains what you expect as the issue is likely to be with $SCRIPT:FFMPEGLocation.
The difference between the ISE and Console with regard to scope can be frustrating.
See this SuperUser post which explains the behaviour further
. You may also find this post helpful;
BartekB explains that F5 in the ISE actually dot-sources the script instead of calling it, and provides a function to run a clean session.
An alternative method which will also wait on the process that needs to be run:
& $EXE /arg 1 /arg 2 -etc 2>&1 | % { $_ }
This will execute the command and pass the args, redirect any errors to the output stream and then print that output (for some reason, I've had bad luck with actually getting output from commands)

Is Out-Host buffering?

I ha a function, where I call an application with the & operator. The application produces several line command line output, downloads some files, and returns a string:
& "app.exe" | Out-Host
$var = ...
return $var
It seems, that on the console appears the output produced by app.exe only after app.exe terminates. The user does not have any real time information which file is downloading. Is there a way to continuously update the console when app.exe is running?
Many console applications buffer theirs output stream, if it known to be redirected. Actually, it is standard behavior of C library. So, buffering done by app.exe, because of redirection, but not by Out-Host.
Solution would be to not to redirect output of app.exe, even when outer command redirected. For than you should know exact condition, when PowerShell not redirect output stream of console application and link it directly to their own output stream, which would be console for interactive PowerShell.exe session. The conditions is:
Command is last item in pipeline.
Command is piped to Out-Default.
Solution would be wrap command into script block, and pipe that script block to Out-Default:
& { & "app.exe" } | Out-Default
The other solution would be to use Start-Process cmdlet with -NoNewWindow and -Wait parameters:
Start-Process "app.exe" -NoNewWindow -Wait

Powershell 2: Easy way to direct every bit of output to a file?

I have a script that generates output of various forms - mostly standard output and error channels.
I have tried things like:
script.ps1 > $somefile 2>&1
script.ps1 | tee-object <args>
script.ps1 | out-file <args>
I've also tried start-transcript / stop-transcript. All of these methodologies have their drawbacks, or just don't plain seem to work.
What is the closest powershell equivalent of the UNIX-style invocation:
myScript.ps1 > $somefile 2>&1
When I try the above command in powershell, I see all output on console, and a 0-length file called 'output' is left behind. What gives?
EDIT: Okay, I believe most of my problem lies in the fact I'm using Write-Host, which I think bypasses the standard output stream. However, I am very worried that if I switch my Write-Host statements to Write-Output, then I'll end up corrupting the return values of all of my functions, or seriously screwing my script up some other way.
What is my most prudent option of dealing with the Write-Host entries so that I can reliably capture all output and errors to the same file? Also, I'm using colorization capabilities from Write-Host... I'm guessing I'll have to give that up if I'm looking to dump to log files.
Or even better, is it possible to set up a command-line argument, say, '-console' that controls whether Write-Host or something else is used? My script is initially being run dozens of times a day manually and interactively. It will then run once an hour every day for years to come, where logs of all output/errors will be desired.
Instead of doing
myScript.ps1 > $somefile
You can do
powershell myScript.ps1 > $somefile
I'd focus my efforts on start and stop transcript. I use it in a 3-tier system involving a client calling a script on a server that proxies a call to another server via PSRemote, and it does a splendid job for me. The output is clean and easily parsed.
It fails with native commands, unless you pipe its output to Out-Default. And you can't get to fancy with it. One transcript is all you get at a time, but one's enough.

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.