Powershell with -noexit does not write errors to stderr - powershell

If I have a powershell script the causes an error, I cannot get the error written to stderr if I use -noexit
For example if I have the following script foo.ps1
Get-Process none
If run this without -noexit the error is written to stderr
PS E:\Play>powershell -file .\foo.ps1 2>Error1.txt
If I use the -noexit param the error is not written to stderr
PS E:\Play>powershell -noexit -file .\foo.ps1 2>Error2.txt
What do I have to do to get the error written to stderr when using -noexit?

Why do you run powershell from PowerShell prompt? Just use
PS E:\Play>.\foo.ps1 2>Error1.txt
or (see Understanding Streams, Redirection, and Write-Host in PowerShell)
PS E:\Play>.\foo.ps1 *>&1 | Tee-Object -FilePath Error1.txt
To run above statements from cmd.exe command prompt, you need to escape some characters to be survived into the powershell (note all ^ carets):
E:\Play>powershell .\foo.ps1 2^>Error1.txt
or
E:\Play>powershell .\foo.ps1 *^>^&1 ^| Tee-Object -FilePath Error1.txt
Omit -file switch and use e.g. -NoExit from command prompt, see powershell /?.

Related

Run Powershell script from WebClient.DownloadString on the Command Prompt

On the Command Prompt, I want to run a PowerShell script that is stored at a URL.
Here is what I have tried:
powershell -c "iex ((New-Object System.Net.WebClient).DownloadString('http://192.X.X.X/Sherlock.ps1'))"
powershell -Command "& iex (New-Object System.Net.WebClient).DownloadString('http://192.X.X.X/Sherlock.ps1')"
powershell -NoProfile -Command "iex ((New-Object System.Net.WebClient).DownloadString('http://192.X.X.X/Sherlock.ps1'))"
powershell.exe -exec Bypass -C "IEX (New-Object Net.WebClient).DownloadString('http://192.X.X.X/Sherlock.ps1')"
I have ran each of them for 5 minutes and nothing really showed the results I wanted. It displays no error but nothing really happen after waiting.
I want to know why the above scripts does not work as intended?
I will achieve the result I want by typing this instead:
echo IEX (New-Object Net.WebClient).DownloadString('http://192.X.X.X/Sherlock.ps1') | powershell -NoProfile -Command -
My question is similar to:
Run Powershell script from URL without temporary file
Other references:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1
https://gist.github.com/jivoi/c354eaaf3019352ce32522f916c03d70
There is more than one method, but here's a quick one-liner that should do the trick from the command prompt:
powershell -ExecutionPolicy Bypass -Command "[scriptblock]::Create((Invoke-WebRequest "https://gist.githubusercontent.com/ChrisKibble/afea9880a184cd2b2445e5d8408715af/raw/41cbbf042af07136132f09395e4664ffab33e310/gistfile1.txt").Content).Invoke();"
This creates a script block based on the content of a file hosted at a URL.
As to why yours don't work, it's tough to say without debugging it or doing some process monitoring, but my first guess would be something wrong with your PS1 file (try something simple like just a Write-Host).

How do I call an elevated PowerShell from Windows command prompt to execute commands and a PowerShell script file?

The following script works fine in Powershell:
Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Webrequest
'https://blah.blob.core.windows.net/laps/AutoAutoPilot.ps1' -OutFile
C:\script.ps1; C:\script.ps1
I'm trying to convert it so that it runs as a CMD/BAT file. I simply need to double click to run it. I need the CMD/BAT file to run Powershell as administrator and from there, it will run the script from above. Here's what I have. It'll just quit straight away without doing anything.
powershell -ExecutionPolicy Bypass -c Start-Process -Verb RunAs -Wait
powershell.exe '-ExecutionPolicy Bypass -Noexit -c Set-Location
"\"\\\"%CD%\\\"\""; -c "& Invoke-Webrequest
\"https://blah.blob.core.windows.net/laps/AutoAutoPilot.ps1\"
-OutFile C:\script.ps1; C:\script.ps1" '
Update:
I got it working now. The full output looks like this:
powershell -Command "& ({Start-Process powershell -Verb RunAs -ArgumentList '-ExecutionPolicy Bypass -NoExit -Command Invoke-WebRequest -Uri https://blah.blob.core.windows.net/laps/AutoAutoPilot.ps1 -OutFile C:\script.ps1; C:\script.ps1'})"
If you use the -NoExit parameter when starting powershell.exe PowerShell should not close after the script has finished running. Afterwards if you do not see errors, you can look at the $error variable, to see any errors which occurred when running your script.
You are trying to run your PowerShell code, using PowerShell.exe from command prompt, so you should be able to use the same code as you did before, when you were running your code directly in PowerShell before.
To my understanding you want to run powershell code in a batch-file.well Depending upon your preference there are multiple solutions to this problem(well i haven't checked any of them):
Solution:1
make a batch file and give your powershell script to it as a parameter.
Without Admin access:
#ECHO OFF
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'"
PAUSE
With Admin access:
#ECHO OFF
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -Verb RunAs}"
PAUSE
Solution:2
If you don't want an external .ps1 file,then you can try this.just save it as something.bat
powershell -command if ($true)^
Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Webrequest 'https://blah.blob.core.windows.net/laps/AutoAutoPilot.ps1' -OutFile C:\script.ps1; C:\script.ps1^
This should do the trick:
powershell -Command "& {Start-Process powershell -Verb RunAs -ArgumentList '-ExecutionPolicy Bypass -NoExit -Command Set-Location -Path C:\whatever\working\directory\you\need; Invoke-WebRequest -Uri https://blah.blob.core.windows.net/laps/AutoAutoPilot.ps1 -OutFile C:\script.ps1; C:\script.ps1'}"
Explanation:
When executing commands in PowerShell using the -Command argument, ExecutionPolicies do not apply as your are executing a single command and not a script. Even the execution of a scriptblock consisting of multiple commands counts as the execution of a single command. That's why you can directly call PowerShell from the command prompt like this (without anything else):
powershell -Command ...
-Command expects - to read from stdin or a scriptblock (read more). Scriptblocks have to be enclosed in curly braces ({...}). If you pass a scriptblock from the command prompt to PowerShell, you also have to add the call operator &:
powershell -Command "& {...}"
As you need an elevated PowerShell, you start a new PowerShell process from the previous PowerShell with Start-Process in combination with the -Verb RunAs argument. You add all arguments that you want to pass to the elevated PowerShell to the -ArgumentList argument:
... Start-Process powershell -Verb RunAs -ArgumentList '...' ...
As you want to call a script file, you now need the corresponding ExecutionPolicy. If you don't want to change it on the system, you can bypass the ExecutionPolicy with -ExecutionPolicy Bypass as you already did. And you also add -NoExit here. To pass your desired PowerShell commands, you use the -Command argument again. This time, you don't need the call operator and you can also omit the curly braces as we are now in PowerShell and not in the command prompt anymore.
... -ExecutionPolicy Bypass -NoExit -Command Set-Location -Path C:\whatever\working\directory\you\need; Invoke-WebRequest -Uri https://blah.blob.core.windows.net/laps/AutoAutoPilot.ps1 -OutFile C:\script.ps1; C:\script.ps1 ...

Why can't I tail a log in powershell when I run it from the run Window?

If I open a Power Shell window and run the following command it works fine...
get-content -Path C:\Users\user\AppData\Local\Temp\90\tmpDF49.tmp -wait
But if I open the run menu (WINKEY+R) and then run it like this:
powershell -command 'get-content -Path C:\Users\user\AppData\Local\Temp\90\tmpDF49.tmp -wait'
it opens a powershell window and then just closes...
I've also tried the same thing from a powershell script and it just closes up...just like with the run menu:
[Diagnostics.Process]::Start("powershell.exe", "-command `"get-content -Path $($tmpFile) -wait`"")
Shouldn't it keep waiting and trying to tail the log?
You need to run the following from the run line:
powershell -NoExit -command "Get-Content -Path C:\Users\user\AppData\Local\Temp\90\tmpDF49.tmp -wait"
The -command switch is designed to run the provided command and exit unless -NoExit is specified. -NoExit must come before the -command parameter by design as well.
Running PowerShell.exe -Help will divulge this information. I have been told that not all of the information is accurate, but the statements above appear to be.

How to Run Long Powershell script from Windows Command Prompt (CMD)

I tried to launch a long powershell script with the name "long name here.ps1" from command prompt. But I am also trying to ensure that it runs as an administrator command in powershell. I have all execution policies in powershell set accordingly I used the ss64 set-executionpolicy command guide for powershell to get powershell working. But I am trying to use the solution from another stackoverflow question that talks about running commands as administrator. I am running a batch script that needs to execute a powershell script (.ps1) as admin, and I don't mind if the user is prompted by UAC or for the password. I am currently using the following command:
powershell.exe -command "&{ Start-Process powershell -ArgumentList '-noprofile -file "C:\long name here.ps1"' -verb RunAs}"
I found this command at https://ss64.com/ps/powershell.html at the bottom where there are details on how to run a powershell command as administrator. The problem with that code is that my powershell script 1. has arguments, and 2. has a long name. I have tried many different iterations of this command with no success, and the ones that DON'T work are listed below:
powershell.exe -command "&{ Start-Process powershell -ArgumentList '-noprofile -file C:\long` name` here.ps1' -verb RunAs}"
powershell.exe -command "&{ Start-Process powershell -ArgumentList '-noprofile -file:"C:\long name here.ps1' -verb RunAs}"
Also, I am completely lost as to how to send arguments to the actual script.
If I'm reading your question correctly - powershell wont find the file as it stops reading the path name when it encounters a blank space?
The example given here specifies that; powershell commands to be run from command prompt as an administrator should have the following syntax:
powershell.exe -noprofile -command "&{ start-process powershell -ArgumentList '-noprofile -file MyScript.ps1' -verb RunAs}"
Couple of ways to achieve what you're looking for. But the easiest method would be to escape the quotes using a ` character. So something similar to;
powershell.exe -noprofile -command "&{ start-process powershell -ArgumentList '-noprofile -file `"C:\long file name.ps1`"' -verb RunAs}"
Also might be worth checking out other answers here
Use a Freeware Third Party Utility
If a freeware third-party executable is permissible, you can use a short tool I wrote called elevate32.exe (32-bit) and elevate64.exe (64-bit) to launch powershell.exe as administrator with the -File parameter and the script arguments you want to use:
elevate64 -- powershell.exe -File "<path>\<long script name>.ps1" -Arg "<long script argument>"
You can get the tool from www.westmesatech.com (copyrighted freeware, free to use anywhere, no installation needed).
Use a WSH Script
If you can't use an external executable, you can also do this (although it does not handle quoting in as robust a manner as the elevate tool's -- parameter) using a Windows Script Host (WSH) script, elevate.js:
var args = WScript.Arguments;
if ( args.Length >= 1 ) {
var exec = args.Item(0);
var cmdLine = "";
for (var i = 1; i < WScript.Arguments.Length; i++ ) {
cmdLine += cmdLine == "" ? '"' + args.Item(i) + '"' : ' "' + args.Item(i) + '"';
}
var shellApp = new ActiveXObject("Shell.Application");
shellApp.ShellExecute(exec, cmdLine, "", "runas");
}
You can call as follows:
wscript.exe "d:\path\elevate.js" powershell.exe -File "C:\long path\script name.ps1" "long script argument"
Self-Elevate your PowerShell Script
Another option is to write a self-elevating PowerShell script. You can check for elevation in the script; if not elevated, it can launch itself elevated and run any command you need. Example:
$isElevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ( -not $isElevated ) {
Start-Process powershell.exe "-File",('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs
exit
}
& "d:\long path name\script name.ps1" "Long Argument 1" "Long Argument 2"
When you use PowerShell.exe -Command you don't need to use quotes. For example, you can run the following:
PowerShell.exe -Command Get-Service 'wuauserv'
Everything after -Command is interpreted as the command. Note also that double quotes in CMD need escaping with a backslash. Therefore:
powershell.exe -Command Start-Process PowerShell -ArgumentList '-NoProfile -File \"C:\long name here.ps1\"' -Verb RunAs
If your file has arguments:
powershell.exe -Command Start-Process PowerShell -ArgumentList '-NoProfile -File \"C:\long name here.ps1\" \"Arg1\" \"Arg2\"' -Verb RunAs

Calling powershell cmdlets from Windows batch file

Ok something so simple is just not working for me. I got a cmdlet that accepts a single parameter. I am trying to call a cmdlet within a Windows batch file. The batch file contains:
cd %SystemRoot%\system32\WindowsPowerShell\v1.0
powershell Set-ExecutionPolicy Unrestricted
powershell 'C:\convert-utf8-to-utf16.ps1 C:\test.txt'
powershell Set-ExecutionPolicy Restricted
pause
My ps1 file again not doing anything special:
function convert-utf8-to-utf16 {
$tempfile = "C:\temp.txt"
set-ExecutionPolicy Unrestricted
get-content -Path $args[0] -encoding utf8 | out-file $tempfile -encoding Unicode
set-ExecutionPolicy Restricted
}
When i execute the bat file it just runs to completion (no error messages) and it does not appear to create the temp.txt file.
I can run the powershell command file at the PS command prompt but not in cmd!
Anyone got any ideas what could be wrong?
Starting with Powershell version 2, you can run a Powershell script like so...
powershell -ExecutionPolicy RemoteSigned -File "C:\Path\Script.ps1" "Parameter with spaces" Parameter2
Now if I could only figure out a way to handle dragging and dropping files to a Powershell script.
I explain both why you would want to call a PowerShell script from a batch file and how to do it in my blog post here.
This is basically what you are looking for:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& 'C:\convert-utf8-to-utf16.ps1' 'C:\test.txt'"
And if you need to run your PowerShell script as an admin, use this:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& {Start-Process PowerShell -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""C:\convert-utf8-to-utf16.ps1"" ""C:\test.txt""' -Verb RunAs}"
Rather than hard-coding the entire path to the PowerShell script though, I recommend placing the batch file and PowerShell script file in the same directory, as my blog post describes.
The problem is in the ps1 file - you declare a function but you don't call it.
I would modify it like this:
param($path)
function convert-utf8-to-utf16 {
$tempfile = "C:\temp.txt"
set-ExecutionPolicy Unrestricted
get-content -Path $args[0] -encoding utf8 | out-file $tempfile -encoding Unicode
set-ExecutionPolicy Restricted
}
convert-utf8-to-utf16 $path
it will work. However, it is not needed, you can simply ommit the function declaration and move the body into the script itself:
param($path)
$tempfile = "C:\temp.txt"
set-ExecutionPolicy Unrestricted
get-content -Path $path -encoding utf8 | out-file $tempfile -encoding Unicode
set-ExecutionPolicy Restricted
# Test-Args.ps1
param($first, $second)
write-host $first
write-host $second
Call from Command Prompt:
PowerShell.exe -NoProfile -Command "& {./Test-Args.ps1 'C:\Folder A\One' 'C:\Folder B\Two'}"
What's confusing is that if the script is in a folder path containing spaces, PowerShell doesn't recognize the script name in quotes:
PowerShell.exe -NoProfile -Command "& {'C:\Folder X\Test-Args.ps1' 'C:\Folder
A\One' 'C:\Folder B\Two'}"
But you can get around that using something like:
PowerShell.exe -NoProfile -Command "& {set-location 'C:\Folder X';./Test-Args.ps1 'C:\Folder
A\One' 'C:\Folder B\Two'}"
Don't use spaces in your .PS1 file name, or you're outta luck.
I got this working...The ps1 file does not need to be wrapped into a function. Just this declaration is ok.
$tempfile = "C:\temp.txt"
get-content -Path $args[0] -encoding utf8 | out-file $tempfile -encoding unicode
and the bat file calls it like:
cd %SystemRoot%\system32\WindowsPowerShell\v1.0
powershell Set-ExecutionPolicy Unrestricted
powershell "& 'C:\convert-utf8-to-utf16.ps1 C:\test.txt' 'C:\test.txt'"
powershell Set-ExecutionPolicy Restricted
pause
Try this syntax instead:
cd %SystemRoot%\system32\WindowsPowerShell\v1.0
powershell {Set-ExecutionPolicy Unrestricted}
powershell "& C:\convert-utf8-to-utf16.ps1 C:\test.txt"
powershell {Set-ExecutionPolicy Restricted}
pause