Execute powershell string via CMD - windows

I try to execute the following command in console:
powershell.exe -NoLogo -Command `"Get-ChildItem "Cert:\CurrentUser\My" | WHERE{$_.Extensions['Certificate Template Name'] -match 'CA'}`"
But I get this error:
I need to execute this command in CMD, not ps1 script.

There was in issue with your double quotes.
I've changed it slightly:
powershell.exe -NoLogo -Command "Get-ChildItem Cert:\CurrentUser\My | where {$_.Extensions['Certificate Template Name'] -match 'CA'}"

Related

Running SendKeys commands from a .lnk (shortcut) with powershell doesn't work

I'm playing around with SendKeys and powershell. I tried to close the active window with SendKeys (ALT + F4) after running a shortcut. I got this working with adding the following command to the Target field of a Windows shortcut(.lnk):
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "C:\Users\user\Documents\TEST\test.ps1"
Code in test.ps1:
(New-Object -ComObject Wscript.Shell).SendKeys("%{F4}")
When I run the shortcut the active windows closes. Now I wanted to make this work without .ps1 script. I tried to run the powershell command from the Target field of the shortcut and that didn't work.
The commands I added to the shortcut Target field that didn't work:
$ C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe $wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys("%{F4}")
$ C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys("%{F4}")"
$ C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe (New-Object -ComObject Wscript.Shell).SendKeys("%{F4}")
$ C:\Windows\System32\cmd.exe /c powershell.exe -noprofile -executionpolicy bypass $wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys("%{F4}")
$ C:\Windows\System32\cmd.exe /c powershell.exe -noprofile -executionpolicy bypass "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys("%{F4}")"
$ C:\Windows\System32\cmd.exe /c powershell.exe -noprofile -executionpolicy bypass (New-Object -ComObject Wscript.Shell).SendKeys("%{F4}")
What I'm doing wrong in the commands above? I need to use a different syntax when I run powershell commands from Shortcuts?
What I'm doing wrong in the commands above?
You're calling powershell.exe, the Windows PowerShell CLI, from outside PowerShell, such as in the no-shell context in which shortcut-file command lines are executed.
For troubleshooting such command lines, use -noexit as the first powershell.exe parameter in order to keep the resulting PowerShell session open, which allows you to see any error message.
The implied CLI parameter of powershell.exe is -Command (-c), which treats all subsequent arguments as tokens of a piece of PowerShell code to execute.
However, any unquoted " characters are stripped beforehand, during PowerShell's command-line processing.
In order to pass " characters through as part of a PowerShell command being passed to the PowerShell CLI via (possibly implied) -Command (-c), you need to escape them as \" (sic)
Additionally, for full robustness, it is best to pass the entire PowerShell command inside a single (unescaped) "..." string.
Therefore:
powershell.exe -noprofile -executionpolicy bypass "(New-Object -ComObject Wscript.Shell).SendKeys(\"%{F4}\")"
However, given that, in the context of your PowerShell command, a single-quoted string ('...') to represent the key combination %{F4} argument will do (and is arguably preferable, given that you only need "..." quoting in PowerShell for string interpolation), you can simplify to:
powershell.exe -noprofile -executionpolicy bypass "(New-Object -ComObject Wscript.Shell).SendKeys('%{F4}')"
The issue here is that the commands you are attempting to execute aren't being passed to the powershell exe correctly.
The below works for me in the terminal and also in the shortcut field:
powershell.exe -command "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('%{F4}')"
If the command you are attempting to execute does not need to interpolate any variables in its strings etc. (yours does not) then you can test your statements by executing them in a powershell session (Note that i have switched to single quotes ' for $wshell.SendKeys('%{F4}')"). Your examples would yield some errors and so you know it wont work in the shortcut.
and to give an example for the rest of your attempts (full path removed for brevity)
powershell.exe -command "(New-Object -ComObject Wscript.Shell).SendKeys('%{F4}')"
powershell.exe -noprofile -executionpolicy bypass -command "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('%{F4}')"

Split string in Windows batch file over multiple lines

I want to invoke an elevated Powershell to execute a script and pass a bunch of parameters. I would like to have every parameter in the .bat file on its own line. Usually I can use the carat ^ to span commands over several lines in .bat files, just like using a grave accent ` in Powershell scripts. But both don't work in this situation:
As a one-liner it works:
Powershell.exe -Command "& {Start-Process Powershell.exe -Verb RunAs -ArgumentList '-ExecutionPolicy Bypass -File %~dp0HelloWorld.ps1 -parameter1 Long -parameter2 list -parameter3 of -parameter4 parameters' }"
Trying to split it up into multiple lines using a caret ^ doesn't work:
Powershell.exe -Command "& {Start-Process Powershell.exe -Verb RunAs -ArgumentList '-ExecutionPolicy Bypass -File %~dp0HelloWorld.ps1 ^
-parameter1 Long ^
-parameter2 list ^
-parameter3 of ^
-parameter4 parameters ^
'}"
Here is an example HelloWorld.ps1 to test with, (has to be in the same directory as the batch file):
param (
$parameter1="",
$parameter2="",
$parameter3="",
$parameter4=""
)
write-host "$parameter1 $parameter2 $parameter3 $parameter4"
Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
The simplest way to handle the issue in your example case above, is to use doublequotes, " instead of single, '. However to prevent cmd.exe from failing to parse the command, you'll need to escape those nested doublequotes, using backslashes, i.e. \".
Example:
#Powershell.exe -Command "& {Start-Process Powershell.exe -Verb RunAs -ArgumentList \" ^
-ExecutionPolicy RemoteSigned ^
-File `\"%~dp0HelloWorld.ps1`\" ^
-parameter1 Long ^
-parameter2 list ^
-parameter3 of ^
-parameter4 parameters ^
\"}"
I have specifically changed the ExecutionPolicy from Bypass, (which I wouldn't ever recommend using, even moreso when running elevated), to RemoteSigned, please do not change it back. Also for added safety, I have quoted your .ps1 file path, which could contain spaces. The backslashes escape the doublequotes for the cmd.exe parser, (as already mentioned), and then backticks escape the remaining nested doublequotes for the powershell.exe parser.

How to start PowerShell script from BAT file with proper Working Directory?

I'm trying to create bat script that can start PowerShell script named the same as bat file in proper working directotry.
This is what I got:
#ECHO OFF
PowerShell.exe -NoProfile -Command "& {Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""%~dpn0.ps1""' -WorkingDirectory '%~dp0' -Verb RunAs}"
PAUSE
Passing working directory this way does not work.
How to make script that will pass proper working directroy and also command line arguments?
The -WorkingDirectory parameter doesn't work when using -Verb RunAs. Instead, you have to set the working directory by calling cd within a -Command string.
This is what I use: (cmd/batch-file command)
powershell -command " Start-Process PowerShell -Verb RunAs \""-Command `\""cd '%cd%'; & 'PathToPS1File';`\""\"" "
If you want to make a "Run script as admin" right-click command in Windows Explorer, create a new registry key at HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Run with PowerShell (Admin)\Command, and set its value to the command above -- except replacing %cd% with %W, and PathToPS1File with %1 (if you want it to execute the right-clicked file).
Result: (Windows Explorer context-menu shell command)
powershell -command " Start-Process PowerShell -Verb RunAs \""-Command `\""cd '%W'; & '%1';`\""\"" "
EDIT: There's an alternative way to have the script be run as admin from Explorer, by using the "runas" sub-key: https://winaero.com/blog/run-as-administrator-context-menu-for-power-shell-ps1-files
If you want to run your script as admin from an existing powershell, remove the outer powershell call, replace %W with $pwd, replace %1 with the ps1 file-path, and replace each \"" with just ".
Note: The \""'s are just escaped quotes, for when calling from the Windows shell/command-line (it's quote-handling is terrible). In this particular case, just \" should also work, but I use the more robust \"" for easier extension.
See here for more info: https://stackoverflow.com/a/31413730/2441655
Result: (PowerShell command)
Start-Process PowerShell -Verb RunAs "-Command `"cd '$pwd'; & 'PathToPS1File';`""
Important note: The commands above are assuming that your computer has already been configured to allow script execution. If that's not the case, you may need to add -ExecutionPolicy Bypass to your powershell flags. (you may also want -NoProfile to avoid running profile scripts)
A workaround is to let the PowerShell script change the directory to it's own origin with:
Set-Location (Split-Path $MyInvocation.MyCommand.Path)
as the first command.
As per mklement0s hint: In PSv3+ use the simpler:
Set-Location -LiteralPath $PSScriptRoot
Or use this directory to open adjacent files.
$MyDir = Split-Path $MyInvocation.MyCommand.Path
$Content = Get-Content (Join-Path $MyDir OtherFile.txt)

PowerShell in command prompt issue, 'Format-Table' is not recognized as an internal or external command, operable program or batch file

I am executing powershell script in cmd.
First i write command
C:\Windows\system32>start powershell.exe Set-ExecutionPolicy RemoteSigned
it works successfully
than for running script i write command
C:\Windows\system32>start powershell.exe C:\\Get-NetworkStatistics.ps1
It also works successfully
the problem is when i try to run the function
C:\Windows\system32>start powershell.exe Get-NetworkStatistics -computername Gbsi1 | Format-Table -autosize
it gives error that "'Format-Table' is not recognized as an internal or external command,
operable program or batch file."
here is the screenshot for it.
It runs successfully in powershell but no in cmd. Is there any issue with pipe | which i put before Format-Table
As your it is, the pipe is interpreted by CMD not powershell.
Thus, CMD will try to execute a command named Format-Table, which does not exist (outside powershell).
You can escape it using ^:
start powershell.exe Get-NetworkStatistics -computername Gbsi1 ^| Format-Table -autosize
Or by quoting the complete command line
start powershell.exe "Get-NetworkStatistics -computername Gbsi1 | Format-Table -autosize"
Note that your invocation is errnous anyhow, you need to provide the -Command option to powershell, like so:
start powershell.exe -Command "Get-NetworkStatistics -computername Gbsi1 | Format-Table -autosize"
Finally, do you really want to use start? It will open a new window, that will close immediately after the command is through. You could also use:
powershell.exe -Command "Get-NetworkStatistics -computername Gbsi1 | Format-Table -autosize"

How to run a PowerShell script from a batch file

I am trying to run this script in PowerShell. I have saved the below script as ps.ps1 on my desktop.
$query = "SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"
Register-WMIEvent -Query $query -Action { invoke-item "C:\Program Files\abc.exe"}
I have made a batch script to run this PowerShell script
#echo off
Powershell.exe set-executionpolicy remotesigned -File C:\Users\SE\Desktop\ps.ps1
pause
But I am getting this error:
You need the -ExecutionPolicy parameter:
Powershell.exe -executionpolicy remotesigned -File C:\Users\SE\Desktop\ps.ps1
Otherwise PowerShell considers the arguments a line to execute and while Set-ExecutionPolicy is a cmdlet, it has no -File parameter.
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:\Users\SE\Desktop\ps.ps1'"
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:\Users\SE\Desktop\ps.ps1""' -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.
If you want to run from the current directory without a fully qualified path, you can use:
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& './ps.ps1'"
If you run a batch file calling PowerShell as a administrator, you better run it like this, saving you all the trouble:
powershell.exe -ExecutionPolicy Bypass -Command "Path\xxx.ps1"
It is better to use Bypass...
Small sample test.cmd
<# :
#echo off
powershell /nologo /noprofile /command ^
"&{[ScriptBlock]::Create((cat """%~f0""") -join [Char[]]10).Invoke(#(&{$args}%*))}"
exit /b
#>
Write-Host Hello, $args[0] -fo Green
#You programm...
Posted it also here:
How to run powershell command in batch file
Following this thread:
https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/converting-powershell-to-batch
you can convert any PowerShell script into a batch file easily using this PowerShell function:
function Convert-PowerShellToBatch
{
param
(
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[string]
[Alias("FullName")]
$Path
)
process
{
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
$newPath = [Io.Path]::ChangeExtension($Path, ".bat")
"#echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
}
}
To convert all PowerShell scripts inside a directory, simply run the following command:
Get-ChildItem -Path <DIR-PATH> -Filter *.ps1 |
Convert-PowerShellToBatch
Where is the path to the desired folder. For instance:
Get-ChildItem -Path "C:\path\to\powershell\scripts" -Filter *.ps1 |
Convert-PowerShellToBatch
To convert a single PowerShell script, simply run this:
Get-ChildItem -Path <FILE-PATH> |
Convert-PowerShellToBatch
Where is the path to the desired file.
The converted files are located in the source directory. i.e., <FILE-PATH> or <DIR-PATH>.
Putting it all together:
create a .ps1 file (PowerShell script) with the following code in it:
function Convert-PowerShellToBatch
{
param
(
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[string]
[Alias("FullName")]
$Path
)
process
{
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes((Get-Content -Path $Path -Raw -Encoding UTF8)))
$newPath = [Io.Path]::ChangeExtension($Path, ".bat")
"#echo off`npowershell.exe -NoExit -encodedCommand $encoded" | Set-Content -Path $newPath -Encoding Ascii
}
}
# change <DIR> to the path of the folder in which the desired powershell scripts are.
# the converted files will be created in the destination path location (in <DIR>).
Get-ChildItem -Path <DIR> -Filter *.ps1 |
Convert-PowerShellToBatch
And don't forget, if you wanna convert only one file instead of many, you can replace the following
Get-ChildItem -Path <DIR> -Filter *.ps1 |
Convert-PowerShellToBatch
with this:
Get-ChildItem -Path <FILE-PATH> |
Convert-PowerShellToBatch
as I explained before.
If you want to run a few scripts, you can use Set-executionpolicy -ExecutionPolicy Unrestricted and then reset with Set-executionpolicy -ExecutionPolicy Default.
Note that execution policy is only checked when you start its execution (or so it seems) and so you can run jobs in the background and reset the execution policy immediately.
# Check current setting
Get-ExecutionPolicy
# Disable policy
Set-ExecutionPolicy -ExecutionPolicy Unrestricted
# Choose [Y]es
Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 example.com | tee ping__example.com.txt }
Start-Job { cd c:\working\directory\with\script\ ; ./ping_batch.ps1 google.com | tee ping__google.com.txt }
# Can be run immediately
Set-ExecutionPolicy -ExecutionPolicy Default
# [Y]es
Another easy way to execute a ps script from batch is to simply incorporate it between the ECHO and the Redirection characters,(> and >>),
example:
#echo off
set WD=%~dp0
ECHO New-Item -Path . -Name "Test.txt" -ItemType "file" -Value "This is a text string." -Force > "%WD%PSHELLFILE.ps1"
ECHO add-content -path "./Test.txt" -value "`r`nThe End" >> "%WD%PSHELLFILE.ps1"
powershell.exe -ExecutionPolicy Bypass -File "%WD%PSHELLFILE.ps1"
del "%WD%PSHELLFILE.ps1"
Last line deletes the created temp file.
If your PowerShell login script is running after 5 minutes (as mine was) on a 2012 server, there is a GPO setting on a server - 'Configure Login script Delay' the default setting 'not configured' this will leave a 5-minute delay before running the login script.

Resources