"File not found" Can not use Invoke-SCScriptCommand with anything but cmd.exe + args - powershell

I have made a plugin for Microsoft System Center Virtual Machine Manager that executes a powershell script on a host machine through a powershell script called by the c# code of the plugin. (Shellception :P)
Since I allways got an error I decided to test it manually in SCVMM by right clicking on the host and entering powershell.exe or powershellfor executable and export-v -name [name] -path [path] -force - copystate -wait.
Now it tells me that there is no such file.
Strangely it works with cmd(.exe) and echo test.
Shouldn't powershell be installed on Windows Server 2012?
Also, if I remotecontroll the host, it works just fine in the console.
What am I missing?

I figured out that you need to provide the full path when using powershell.exe as executable. The issue is that not all hosts have the system variable PATH that includes the path to the powershell.exe executable.
You can run powershell.exe by providing the full path:
%WINDIR%\System32\WindowsPowerShell\v1.0\PowerShell.exe
Or you can run cmd.exe as executable and then to run powershell.exe from this cmd:
executable: cmd.exe
parameters: /c powershell.exe echo 1; return 0;

Related

Powershell not finding PNPUTIL when script launched from shortcut

I have a Powershell script to install TCP/IP printers on Windows 10 that uses PNPUTIL to load drivers. When the script is run from a Powershell window, everything works great.
When I launch the script from a shortcut using the format
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -file MyScript.PS1
I get an error 'The term 'pnputil.exe' is not recognized as the name of a cmdlet, function, script file, or operable program' when PNPUTIL is called. The rest of the script runs fine.
Relevant code:
Write-Host `n 'Installing printer driver..'
pnputil.exe /add-driver "\\myServer\HP UPD PCL 5\hpcu180t.inf"
Any ideas as to why this won't work when launched from a shortcut?
EDIT:I tried using
& pnputil.exe /add-driver "\\myServer\HP UPD PCL 5\hpcu180t.inf"
as referenced in
Running CMD command in PowerShell
but I still get the error. I also tried
start-process pnputil.exe /add-driver "\\myServer\HP UPD PCL 5\hpcu180t.inf"
but got a similar error that pnputil.exe could not be found.
Both of these options work from a Powershell prompt, but again, fail when launched from a shortcut.
Thank you in advance.
You're invoking a 32-bit instance of PowerShell on a 64-bit system, and that instance doesn't see pnputil.exe (by filename only).
Instead of:
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -file MyScript.PS1
use:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -file MyScript.PS1
Folder C:\Windows\SysWOW64 is where the 32-bit executables live.
Paradoxically, for historical reasons, it is C:\Windows\System32 that houses the 64-bit executables.
If, for some reason, you do need to run a 32-bit instance of PowerShell, you can invoke pnputil.exe by its full path:
It only exists as a 64-bit executable in the 64-bit system folder, which 32-bit processes can access as C:\Windows\SysNative:
C:\Windows\SysNative\pnputil.exe

how to exec ps1 file from cmd?

I have a ps1 file, Test.ps1, which I need to exec from cmd. For test purposes this file only has 1 line:
write "ps1 test successful"
I was trying to exec this ps1 file from cmd. I googled and it seemed that including the following line might help:
Set-ExecutionPolicy RemoteSigned
write "ps1 test successful"
However I still can't exec this test. I've tried:
powershell Test
powershell Test.ps1
Test
Test.ps1
The cmd path context is set to the dir in which the ps1 script resides. Any idea what I might be doing wrong here?
Does this work?
Powershell -ExecutionPolicy Bypass -File .\Test.ps1
I've done this before with a .bat file, and this was the syntax used. In this instance, you're running from within the same directory as the powershell script (otherwise adjust the filename argument as necessary). And you may need to be running the CMD prompt as admin, if you aren't already.
Use
powershell.exe -ExecutionPolicy Bypass -File "C:\dir name\test.ps1"
Of course, replace C:\dir name\test.ps1 with the path and filename of the script you want to run, enclosed in " (double quotes).
Alternatively, start PowerShell in its own window, then run the script.
On macOS:
Use Homebrew to install Powershell:
brew install --cask powershell
Switch to Powershell:
pwsh
Execute the script:
./Test.ps1
My PowerShell script (Test.ps1):
echo "trying to test something"
I can execute it in cmd with this command:
.\Test.ps1
My output:
trying to test something

Windows shortcut to a PowerShell script with relative path

When creating a Windows shortcut to launch a PowerShell script the following works fine when double clicked as a regular user and with right click Run as administrator:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy "Bypass" -Command "&{& 'C:\Script.ps1'}"
However, when the path is relative and not known upfront the following works fine when double clicked as a regular user but not with right click Run as administrator:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy "Bypass" -Command "&{& '.\Script.ps1'}"
My question, how can I have it work in both cases when the path is relative? I tried using PSScriptRoot but that didn't work either.
Thank you for your help.
When launching as admin from Explorer, you must provide an absolute path to the script.
Explorer.exe ignores the starting directory from the shortcut when launching a process as admin. Instead, Admin-level processes always launch with the current directory in [Environment]::GetFolderPath('System') (usually C:\Windows\System32)
The easy way to run in a different directory is to change directory at the beginning of your script. The following line will cd to the directory the script is in.
Set-Location $PsScriptRoot
If the script needs to start in a different path, then you may have to write a function to discover where that path is on the local machine (such as enumerating USB drives)
You can use your current solution for non-admin promoted shortcuts then auto promote the script internally:
# ========================================= Admin Rights =======================================================
# Usage: asAdmin $PSCommandPath
function asAdmin
{
[string]$cmdPath = $args[0]
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Start-Process powershell.exe "-NoProfile -ExecutionPolicy Bypass -File `"$cmdPath`"" -Verb RunAs; exit }
}

Running CMD command in PowerShell

I am having a bunch of issues with getting a PowerShell command to run. All it is doing is running a command that would be run in a CMD prompt window.
Here is the command:
"C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe" PCNAME
I have tried the following with no success (I have tried many iterations of this to try and get one that works. Syntax is probably all screwed up):
$TEXT = $textbox.Text #$textbox is where the user enters the PC name.
$CMDCOMMAND = "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe"
Start-Process '"$CMDCOMMAND" $TEXT'
#iex -Command ('"C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe"' $TEXT)
The command will just open SCCM remote connection window to the computer the user specifies in the text box.
Try this:
& "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\i386\CmRcViewer.exe" PCNAME
To PowerShell a string "..." is just a string and PowerShell evaluates it by echoing it to the screen. To get PowerShell to execute the command whose name is in a string, you use the call operator &.
To run or convert batch files externally from PowerShell (particularly if you wish to sign all your scheduled task scripts with a certificate) I simply create a PowerShell script, e.g. deletefolders.ps1.
Input the following into the script:
cmd.exe /c "rd /s /q C:\#TEMP\test1"
cmd.exe /c "rd /s /q C:\#TEMP\test2"
cmd.exe /c "rd /s /q C:\#TEMP\test3"
*Each command needs to be put on a new line calling cmd.exe again.
This script can now be signed and run from PowerShell outputting the commands to command prompt / cmd directly.
It is a much safer way than running batch files!
One solution would be to pipe your command from PowerShell to CMD. Running the following command will pipe the notepad.exe command over to CMD, which will then open the Notepad application.
PS C:\> "notepad.exe" | cmd
Once the command has run in CMD, you will be returned to a PowerShell prompt, and can continue running your PowerShell script.
Edits
CMD's Startup Message is Shown
As mklement0 points out, this method shows CMD's startup message. If you were to copy the output using the method above into another terminal, the startup message will be copied along with it.
For those who may need this info:
I figured out that you can pretty much run a command that's in your PATH from a PS script, and it should work.
Sometimes you may have to pre-launch this command with cmd.exe /c
Examples
Calling git from a PS script
I had to repackage a git client wrapped in Chocolatey (for those who may not know, it's a package manager for Windows) which massively uses PS scripts.
I found out that, once git is in the PATH, commands like
$ca_bundle = git config --get http.sslCAInfo
will store the location of git crt file in $ca_bundle variable.
Looking for an App
Another example that is a combination of the present SO post and this SO post is the use of where command
$java_exe = cmd.exe /c where java
will store the location of java.exe file in $java_exe variable.
You must use the Invoke-Command cmdlet to launch this external program. Normally it works without an effort.
If you need more than one command you should use the Invoke-Expression cmdlet with the -scriptblock option.

TeamCity Powershell Runner - Unable to run Source Code

Im trying to run some PS scripts using the Powershell Runner in TC and defining my own script as "Source Code" instead of a script file.
My script is as simple as:
"Hello World!"
Im running on Windows Server 2008 R2 and ive tried with to:
Run it as x86 + x64
Using "Execute .ps1 with '-File' argument" + "Put script into powershell stdin with "-Command -" arguments.
Ive set the security policy to Unrestricted in an attempt to get it to work, but no luck.
If I instead use a Command Line runner and for example writes:
powershell -Command Get-ExecutionPolicy
It works fine.
The errors im getting (depending on which of the 2 execution modes im using) are:
Starting: C:\...\cmd.exe /c C:\...\powershell.exe -NonInteractive -Command
- "<C:\...\powershell3889347351955805274.ps1" && exit /b %ERRORLEVEL%
in directory: C:\...\e18dda4054c166c7
'-' was specified with the -Command parameter; no other arguments to -Command are permitted.
OR
Starting: C:\...\cmd.exe /c C:\...\powershell.exe -NonInteractive -File
"C:\...\powershell8264270201473986040.ps1" && exit /b %ERRORLEVEL%
in directory: C:\...\e18dda4054c166c7
The term 'f' is not recognized as the name of a cmdlet, function, script file,
It looks to me like TC puts something in the actual script itself, but im not sure. Im stuck and I cant figure out what point im missing here :S.
Can anyone help?
I wasn't able to reproduce this, but I noticed something pretty weird with the command that TeamCity was trying to run:
-NonInteractive -Command - "<C:\...\powershell3889347351955805274.ps1"
I did not see it adding the quotes for me, so I thought maybe TeamCity is trying to quote a path with space(s) in it ( would have helped if you hadn't redacted your path)
So I switched my agent to a path with a space in it and I got the same command, and yes, the same error. So TeamCity is quoting the path wrongly. It is including the < in the quotes while it should have been <"c:\path with\space"
I will see if I can file a bug for this ( if there isn't one)
Try moving your agent to a non-space path as a workaround.