Retrieving Information from Task Manager using Powershell - powershell

Am currently working with a business automation software, the idea is Robots simulate user actions. Is there a way to access the task manager through powershell as the robots are meant to manipulate the task manager e.g Pass in a value to start a new task, end a process and view the performance of the cpu etc . I know this can be achieved using powershell scripts or better still vb script. Please how do I achieve this?
For the records, I am using a windows 7 machine with powershell version 3.0.

List running processes and terminate calculator.
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
msgbox objItem.ProcessID & " " & objItem.CommandLine
If objItem.name = "Calculator.exe" then objItem.terminate
Next
Monitor for notepad exiting and restart it.
Also available is Win32_ProcessStartTrace and Win32_ProcessStartStopTrace
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessStopTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
msgbox objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
Msgbox "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
The WMIC command line program uses same classes as vbscript (and powershell), so you can use it for help.
wmic /?
wmic path win32_process /?
or using the only available in wmic aliases of process alias for win32_process
wmic process /?
wmic process call /?
wmic process get /?
and for other uses of wmic
wmic /node /?
wmic /format /?

Try get-process for a list of running processes.
With i.e. get-process myprocess |stop-process you can stop myprocess.
For new processes you can & them ( & C:\Windows\System32\taskmgr.exe) or use the start-process (check Get-help Start-Process for help ) cmdlet.
You can also use Invoke-WmiMethodfor this :
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList taskmgr.exe'

Related

Run Powershell Encoded Command, single .vbs file, no third-party tools [duplicate]

How is it possible to run a PowerShell script without displaying a window or any other sign to the user?
In other words, the script should run quietly in the background without any sign to the user.
Extra credit for an answer that does not use third party components :)
You can either run it like this (but this shows a window for a while):
PowerShell.exe -WindowStyle hidden { your script.. }
Or you use a helper file I created to avoid the window called PsRun.exe that does exactly that. You can download the source and exe file from Run scheduled tasks with WinForm GUI in PowerShell. I use it for scheduled tasks.
Edited: as Marco noted this -WindowStyle parameter is available only for V2 and above.
I was having this same issue. I found out if you go to the Task in Task Scheduler that is running the powershell.exe script, you can click "Run whether user is logged on or not" and that will never show the powershell window when the task runs.
You can use the PowerShell Community Extensions and do this:
start-process PowerShell.exe -arg $pwd\foo.ps1 -WindowStyle Hidden
You can also do this with VBScript: http://blog.sapien.com/index.php/2006/12/26/more-fun-with-scheduled-powershell/
Schedule Hidden PowerShell Tasks (Internet Archive)
More fun with scheduled PowerShell (Internet Archive)
(Via this forum thread.)
The answer with -WindowStyle Hidden is great but the windows will still flash.
I've never seen a window flash when calling it via cmd /c start /min "".
Your machine or setup may differ but it works well for me.
1. Call a file
cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Users\username\Desktop\test.ps1"
2. Call a file with arguments
cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -Command ". 'C:\Users\username\Desktop\test me.ps1' -Arg1 'Hello' -Arg2 'World'"ps1'; -Arg1 'Hello' -Arg2 ' World'"
Powershell content for 2. Call a file with arguments is:
Param
(
[Parameter(Mandatory = $true, HelpMessage = 'The 1st test string parameter.')]
[String]$Arg1,
[Parameter(Mandatory = $true, HelpMessage = 'The 2nd test string parameter.')]
[String]$Arg2
)
Write-Host $Arg1
Write-Host $Arg2
3. Call a file with a function and arguments
cmd /c start /min "" powershell -WindowStyle Hidden -ExecutionPolicy Bypass -Command ". 'C:\Users\username\Desktop\test me.ps1'; Get-Test -stringTest 'Hello World'"
Powershell content for 3. Call a file with a function and arguments is:
function Get-Test() {
[cmdletbinding()]
Param
(
[Parameter(Mandatory = $true, HelpMessage = 'The test string.')]
[String]$stringTest
)
Write-Host $stringTest
return
}
In case you need to run this in Task Scheduler then call %comspec% as the Program/Script and then code for calling the file above as the argument.
Note: All examples work when the PS1 file has spaces in its path.
Here's an approach that that doesn't require command line args or a separate launcher. It's not completely invisible because a window does show momentarily at startup. But it then quickly vanishes. Where that's OK, this is, I think, the easiest approach if you want to launch your script by double-clicking in explorer, or via a Start menu shortcut (including, of course the Startup submenu). And I like that it's part of the code of the script itself, not something external.
Put this at the front of your script:
$t = '[DllImport("user32.dll")] public static extern bool ShowWindow(int handle, int state);'
add-type -name win -member $t -namespace native
[native.win]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)
Here's a one-liner:
mshta vbscript:Execute("CreateObject(""Wscript.Shell"").Run ""powershell -NoLogo -Command """"& 'C:\Example Path That Has Spaces\My Script.ps1'"""""", 0 : window.close")
Although it's possible for this to flash a window very briefly, that should be a rare occurrence.
ps1 hidden from the Task Scheduler and shortcut too
mshta vbscript:Execute("CreateObject(""WScript.Shell"").Run ""powershell -ExecutionPolicy Bypass & 'C:\PATH\NAME.ps1'"", 0:close")
I think that the best way to hide the console screen of the PowerShell when your are running a background scripts is this code ("Bluecakes" answer).
I add this code in the beginning of all my PowerShell scripts that I need to run in background.
# .Net methods for hiding/showing the console in the background
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function Hide-Console
{
$consolePtr = [Console.Window]::GetConsoleWindow()
#0 hide
[Console.Window]::ShowWindow($consolePtr, 0)
}
Hide-Console
If this answer was help you, please vote to "Bluecakes" in his answer in this post.
I was having this problem when running from c#, on Windows 7, the "Interactive Services Detection" service was popping up when running a hidden powershell window as the SYSTEM account.
Using the "CreateNoWindow" parameter prevented the ISD service popping up it's warning.
process.StartInfo = new ProcessStartInfo("powershell.exe",
String.Format(#" -NoProfile -ExecutionPolicy unrestricted -encodedCommand ""{0}""",encodedCommand))
{
WorkingDirectory = executablePath,
UseShellExecute = false,
CreateNoWindow = true
};
Here's a fun demo of controlling the various states of the console, including minimize and hidden.
Add-Type -Name ConsoleUtils -Namespace WPIA -MemberDefinition #'
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'#
$ConsoleMode = #{
HIDDEN = 0;
NORMAL = 1;
MINIMIZED = 2;
MAXIMIZED = 3;
SHOW = 5
RESTORE = 9
}
$hWnd = [WPIA.ConsoleUtils]::GetConsoleWindow()
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MAXIMIZED)
"maximized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.NORMAL)
"normal $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.MINIMIZED)
"minimized $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.RESTORE)
"restore $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.HIDDEN)
"hidden $a"
Start-Sleep 2
$a = [WPIA.ConsoleUtils]::ShowWindow($hWnd, $ConsoleMode.SHOW)
"show $a"
When you scheduled task, just select "Run whether user is logged on or not" under the "General" tab.
Alternate way is to let the task run as another user.
Create a shortcut that calls the PowerShell script and set the Run option to Minimized. This will prevent a window from flashing although you will still get a momentary blip of the script running on the Task Bar.
For easy command line usage, there is a simple wrapper app:
https://github.com/stax76/run-hidden
Example command line:
run-hidden powershell -command calc.exe
I got really tired of going through answers only to find it did not work as expected.
Solution
Make a vbs script to run a hidden batch file which launches the powershell script. Seems silly to make 3 files for this task but atleast the total size is less than 2KB and it runs perfect from tasker or manually (you dont see anything).
scriptName.vbs
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "C:\Users\leathan\Documents\scriptName.bat" & Chr(34), 0
Set WinScriptHost = Nothing
scriptName.bat
powershell.exe -ExecutionPolicy Bypass C:\Users\leathan\Documents\scriptName.ps1
scriptName.ps1
Your magical code here.
I have created a small tool passing the call to any console tool you want to start windowless through to the original file:
https://github.com/Vittel/RunHiddenConsole
After compiling just rename the executable to "<targetExecutableName>w.exe" (append a "w"), and put it next to the original executable.
You can then call e.G. powershellw.exe with the usual parameters and it wont pop up a window.
If someone has an idea how to check whether the created process is waiting for input, ill be happy to include your solution :)
Wait until Powershell is executed and get the result in vbs
This is an improved version of the Omegastripes code Hide command prompt window when using Exec()
Splits the confused responses from cmd.exe into an array instead of putting everything into a hard-to-parse string.
In addition, if an error occurs during the execution of cmd.exe, a message about its occurrence will become known in vbs.
Option Explicit
Sub RunCScriptHidden()
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty strSignature, Me
objShell.Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True
End Sub
Sub WshShellExecCmd()
For Each objWnd In CreateObject("Shell.Application").Windows
If IsObject(objWnd.getProperty(WScript.Arguments.Named("signature"))) Then Exit For
Next
Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))
objWnd.Quit
'objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll() 'simple solution
Set exec = CreateObject("WScript.Shell").Exec(objParent.strCmd)
While exec.Status = WshRunning
WScript.Sleep 20
Wend
Dim err
If exec.ExitCode = WshFailed Then
err = exec.StdErr.ReadAll
Else
output = Split(exec.StdOut.ReadAll,Chr(10))
End If
If err="" Then
objParent.strRes = output(UBound(output)-1) 'array of results, you can: output(0) Join(output) - Usually needed is the last
Else
objParent.wowError = err
End If
WScript.Quit
End Sub
Const WshRunning = 0,WshFailed = 1:Dim i,name,objShell
Dim strCmd, strRes, objWnd, objParent, strSignature, wowError, output, exec
Set objShell = WScript.CreateObject("WScript.Shell"):wowError=False
strCmd = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass Write-Host Hello-World."
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
RunCScriptHidden
If wowError=False Then
objShell.popup(strRes)
Else
objShell.popup("Error=" & wowError)
End If
powershell.exe -windowstyle hidden -noexit -ExecutionPolicy Bypass -File <path_to_file>
then set the run: Minimized
should work as expected without added code for hidden window flash
just slightly more delayed execution.
Here is a working solution in windows 10 that does not include any third-party components. It works by wrapping the PowerShell script into VBScript.
Step 1: we need to change some windows features to allow VBScript to run PowerShell and to open .ps1 files with PowerShell by default.
-go to run and type "regedit". Click on ok and then allow it to run.
-paste this path "HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell" and press enter.
-now open the entry on the right and change the value to 0.
-open PowerShell as an administrator and type "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned", press enter and confirm the change with "y" and then enter.
Step 2: Now we can start wrapping our script.
-save your Powershell script as a .ps1 file.
-create a new text document and paste this script.
Dim objShell,objFSO,objFile
Set objShell=CreateObject("WScript.Shell")
Set objFSO=CreateObject("Scripting.FileSystemObject")
'enter the path for your PowerShell Script
strPath="c:\your script path\script.ps1"
'verify file exists
If objFSO.FileExists(strPath) Then
'return short path name
set objFile=objFSO.GetFile(strPath)
strCMD="powershell -nologo -command " & Chr(34) & "&{" &_
objFile.ShortPath & "}" & Chr(34)
'Uncomment next line for debugging
'WScript.Echo strCMD
'use 0 to hide window
objShell.Run strCMD,0
Else
'Display error message
WScript.Echo "Failed to find " & strPath
WScript.Quit
End If
-now change the file path to the location of your .ps1 script and save the text document.
-Now right-click on the file and go to rename. Then change the filename extension to .vbs and press enter and then click ok.
DONE! If you now open the .vbs you should see no console window while your script is running in the background.
c="powershell.exe -ExecutionPolicy Bypass (New-Object -ComObject Wscript.Shell).popup('Hello World.',0,'ОК',64)"
s=Left(CreateObject("Scriptlet.TypeLib").Guid,38)
GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty s,Me
WScript.CreateObject("WScript.Shell").Run c,0,false
Out of all the solutions I've tried, this is by far the best and easiest to set up. Download hiddenw.exe from here - https://github.com/SeidChr/RunHiddenConsole/releases
Let's say you want to run Powershell v5 consoleless. Simply rename hiddenw.exe to powershellw.exe. If you want to do this for cmd, then rename to cmdw.exe. If you want to do it for Powershell v7 (pwsh), then rename to pwshw.exe. You can create multiple copies of hiddenw.exe and just rename to the actual process with the letter w at the end. Then, simply add the process to your system environmental PATH, so you can call it from anywhere. Or just copy to C:\Windows. Then, just call it, like this:
powershellw .\example.ps1
I found compiling to exe was the easiest way to achieve this. Theres a number of ways to compile a script, but you can try ISE Steroids
Open "Windows PowerShell ISE", install and run ISESteroids:
Install-Module -Name "ISESteroids" -Scope CurrentUser -Repository PSGallery -Force
Start-Steroids
Then go to Tools->Turn code into EXE, select 'Hide Console Window', and then create the application.
You can run this directly from task scheduler without the need for wrappers or 3rd party apps.
What I do is transform the .ps1 file into an invisible .exe file using an awesome app called Ps1 To Exe which you can download here : https://www.majorgeeks.com/files/details/ps1_to_exe.html
Maybe this helps (although I hope after 12 years you have found a suitable solution... 🙂)
In other words, the script should run quietly in the background without any sign to the user.
Extra credit for an answer that does not use third party components :)
I found a way to do this by compiling a PowerShell script to a Windows executable. Third party modules are required to build the executable but not to run it. My end goal was to compile a one line PowerShell script that ejects a DVD on my system:
(New-Object -com "WMPlayer.OCX.7").cdromcollection.item(0).eject()
My target system is running Windows 7. The specific WMF update needed varies based on Windows version:
Download and install the WMF 5.1 package
The required PowerShell modules should be applicable to any Windows version. Here are the exact commands I used to install the necessary modules and compile the exe. You'll need to tweak the drive, directory and filename details for your system:
mkdir i:\tmp\wmf
cd i:\tmp\wmf
pkunzip ..\Win7AndW2K8R2-KB3191566-x64.zip
c:\windows\system32\windowspowershell\v1.0\powershell.exe
Set-ExecutionPolicy RemoteSigned
.\Install-WMF5.1.ps1
<click> "Restart Now"
c:\Windows\System32\WindowsPowerShell\v1.0\powershell -version 3.0
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name ps2exe -RequiredVersion 1.0.5
ps2exe i:\utils\scripts\ejectDVD.ps1 -noConsole

Batch: How to focus on cmd after task is initialized

Say my program is as follows
#ECHO Off
start "" "Notepad.exe"
pause
After it opens notepad the windows focus is on notepad so whatever I type is on there, but I want the focus to go back to cmd; is this possible? How?
The specific program i'm trying to run it on, is below:
#ECHO OFF
title SortV8
SETLOCAL ENABLEDELAYEDEXPANSION
cd "C:\img\Unsorted"
:SORT
FOR /R %%f IN (*.jpg *.png *.gif *.jpeg) DO (
echo Current file is: %%f
start "" "D:\Downloads\ImageGlass_Kobe_8.6.7.13_x64\ImageGlass.exe" %%f
powershell.exe -NoProfile -Command "(New-Object -ComObject WScript.Shell).AppActivate((Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId)"
CHOICE /N /C 1234 /M "PICK A NUMBER (1 (Photo), 2 (Video), or 3(Delete), 4 (Terminate Program)"%1
IF ERRORLEVEL 4 goto END
IF ERRORLEVEL 3 echo "To the trash it goes!" && move %%f "C:\img\Delete"
IF ERRORLEVEL 2 echo "Video" && move %%f "C:\img\Videos"
IF ERRORLEVEL 1 echo "Photo" && move %%f "C:\img\Photos"
taskkill /IM ImageGlass.exe
cls
GOTO SORT
)
:END
taskkill /IM ImageGlass.exe
cls
echo "Goodbye!"
pause
:eol
You can use PowerShell via its CLI to reactivate your console window, but note that the execution overhead is not insignificant.
Note: This solution is not fully robust, but may work well enough in practice:
#ECHO Off
:: Asynchronously launch Notepad, which steals the focus
:: (Notepad becomes the active window).
start "" "Notepad.exe"
:: Reactivate this console window with the help of PowerShell.
powershell.exe -NoProfile -Command "(New-Object -ComObject WScript.Shell).SendKeys('%%{tab}')"
pause
The above simulates user input, namely an Alt-Tab keypress, in order to reactivate the current console window.
This relies on:
Notepad's window already having been activated (which is likely, given the execution overhead of calling powershell.exe)
the user not manually activating other windows while the batch file runs.
The following variant is more robust, but has a prerequisite that is unlikely to be met:
Rather than sending keystrokes, it properly tries to reactivate the current console window via its process ID.
However, this programmatic window activation only succeeds if the effective SPI_GETFOREGROUNDLOCKTIMEOUT value as reported by the SystemParametersInfo WinAPI function WinAPI function in the current OS uses session is 0, which is not the case by default.
While it is possible in principle to set this value to 0 on demand with PowerShell code, executing such code from cmd.exe (a batch file) inexplicably fails with an Access denied error (whereas direct execution of the same code works fine from PowerShell) - I haven't found a way around this (if someone has an explanation or solution, please tell us).
Certain third-party software - notably AutoHotkey - itself sets the value to 0 once it has run in a session, so if you happen to have a run-on-login AutoHotkey script (it doesn't matter what it does), the code below will work. That said, if you have AutoHotkey already installed, you could try to solve the problem at hand with a specific AutoHotkey script.
#ECHO Off
:: Asynchronously launch Notepad, which steals the focus
:: (Notepad becomes the active window).
start "" "Notepad.exe"
:: !! SEE LIMITATION DISCUSSED ABOVE
:: Reactivate this console window with the help of PowerShell.
powershell.exe -NoProfile -Command "$null = (New-Object -ComObject WScript.Shell).AppActivate((Get-CimInstance Win32_Process -Filter \"ProcessId = $PID\").ParentProcessId)"
pause

how to run several cmd command prompts from powershell

So I am trying to write a script that allows me to open several cmd command prompt and write in them the same command but with different variables.
The solution that I came with was to write a PowerShell script that calls inside a loop a cmd file and pass a variable each time to the cmd file but I'm stuck, the PowerShell script execute only one cmd.
Can someone help to figure this out ?
Thanks :)
You can use the following :
cmd.exe /c [command]
for example
$x = 1..100
foreach ($n in $x){cmd.exe /c ping 192.168.1.$n}
mohamed saeed's answer shows you to execute cmd.exe commands synchronously, in sequence in the current console window.
If, by contrast, you want to open multiple interactive cmd.exe sessions, asynchronously, each in its separate, new window, use cmd.exe's /k option and invoke cmd.exe via Start-Process:
# Open three new interactive cmd.exe sessions in new windows
# and execute a sample command in each.
'date /t', 'ver', "echo $PSHOME" | ForEach-Object {
# Parameters -FilePath and -ArgumentList implied.
Start-Process cmd.exe /k, $_
}
Note:
Unless your cmd.exe console windows have the Let the system position the window checkbox in the Properties dialog checked by default, all new windows will fully overlap, so that you'll immediately only see the last one opened.
The last new window opened will have the keyboard focus.
The commands passed to /k are instantly executed, but an interactive session is then entered.
If you would like to keep in purely batch, you can use the start command. The /k switch keeps the command line open. You would use /c if you want to carry out the command and terminate :
start "" %comspec% /k ping 192.168.1.1
From powershell, you can use the Start-Process command with an ArgumentList:
Start-Process cmd.exe -ArgumentList "/k ping 192.168.1.1"

Trying to run a headless executable command through Powershell that works on cmd line

I am trying to run an executable through powershell to run headless, to install a program onto a VM/LocalHost machine. I can get the wizard to open, but for whatever reason I cannot get it to run headless. Here is the cmd line that I run that works:
start /WAIT setup.exe /clone_wait /S /v" /qn"
This is my attempts in powershell
Start-Process .\setup.exe /S -Wait -PassThru
Start-Process .\setup.exe /S /v /qn -Wait -PassThru
Start-Process setup.exe -ArgumentList '/clone_wait /S /v /qn' -Wait
In the cmd line instance the application installs without issue - in the powershell instance the wizard opens and is on the first "Next" prompt. Any help would be appreciated!
I also attempted to add the additional parameters "/v" and "/qn" which return an error : Start-Process : A positional parameter cannot be found that accepts argument '/v'
The bottom attempt runs but it's not waiting for the installation to complete
You may be overthinking it. Remember that PowerShell is a shell. One of the purposes of a shell is to run commands that you type.
Thus: You don't need Start-Process. Just type the command to run and press Enter.
PS C:\> .\setup.exe /clone_wait /S /v /qn
Now if the executable (or script) you want to run contains spaces in the path or name, then use the call/invocation operator (&) and specify the quotes; for example:
PS C:\> & "\package files\setup.exe" /clone_wait /S /v /qn
(This behavior is the same no matter whether you are at the PowerShell prompt or if you put the command in a script.)
This worked for me. You need to quote the whole argumentlist, plus embed double quotes to pass what you want to /v.
start-process -wait SetupStata16.exe -ArgumentList '/s /v"/qb ADDLOCAL=core,StataMP64"'
Running the command normally and then using wait-process after might be a simpler alternative, if you're sure there's only one process with that name:
notepad
wait-process notepad
To follow-up to all that you have been given thus far. Running executables via PowerShell is a well-documented use case.
PowerShell: Running Executables
Solve Problems with External Command Lines in PowerShell
Top 5 tips for running external commands in Powershell
Using Windows PowerShell to run old command-line tools (and their
weirdest parameters)
So, from the first link provides more validation of what you've been given.
5. The Call Operator &
Why: Used to treat a string as a SINGLE command. Useful for dealing with spaces.
In PowerShell V2.0, if you are running 7z.exe (7-Zip.exe) or another command that starts with a number, you have to use the command invocation operator &.
The PowerShell V3.0 parser do it now smarter, in this case you don’t need the & anymore.
Details: Runs a command, script, or script block. The call operator, also known as the "invocation operator," lets you run commands that are stored in variables and represented by strings. Because the call operator does not parse the command, it cannot interpret command parameters
Example:
& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
Things can get tricky when an external command has a lot of parameters or there are spaces in the arguments or paths!
With spaces you have to nest Quotation marks and the result it is not always clear!
In this case it is better to separate everything like so:
$CMD = 'SuperApp.exe'
$arg1 = 'filename1'
$arg2 = '-someswitch'
$arg3 = 'C:\documents and settings\user\desktop\some other file.txt'
$arg4 = '-yetanotherswitch'
& $CMD $arg1 $arg2 $arg3 $arg4
# or same like that:
$AllArgs = #('filename1', '-someswitch', 'C:\documents and settings\user\desktop\some other file.txt', '-yetanotherswitch')
& 'SuperApp.exe' $AllArgs
6. cmd /c - Using the old cmd shell
** This method should no longer be used with V3
Why: Bypasses PowerShell and runs the command from a cmd shell. Often times used with a DIR which runs faster in the cmd shell than in PowerShell (NOTE: This was an issue with PowerShell v2 and its use of .Net 2.0, this is not an issue with V3).
Details: Opens a CMD prompt from within powershell and then executes the command and returns the text of that command. The /c tells CMD that it should terminate after the command has completed. There is little to no reason to use this with V3.
Example:
#runs DIR from a cmd shell, DIR in PowerShell is an alias to GCI. This will return the directory listing as a string but returns much faster than a GCI
cmd /c dir c:\windows
7. Start-Process (start/saps)
Why: Starts a process and returns the .Net process object Jump if -PassThru is provided. It also allows you to control the environment in which the process is started (user profile, output redirection etc). You can also use the Verb parameter (right click on a file, that list of actions) so that you can, for example, play a wav file.
Details: Executes a program returning the process object of the application. Allows you to control the action on a file (verb mentioned above) and control the environment in which the app is run. You also have the ability to wait on the process to end. You can also subscribe to the processes Exited event.
Example:
#starts a process, waits for it to finish and then checks the exit code.
$p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode
#to find available Verbs use the following code.
$startExe = new-object System.Diagnostics.ProcessStartInfo -args PowerShell.exe
$startExe.verbs

Link a file extension to an app

I was wondering if it would be possible to create PowerShell script that would link a certain file extension to an application.
For example:
The .ntb extension has to be opened using the following application by default:
C:\Program Files\SMART Technologies\Education Software\Notebook.exe
Why would I need a script for this you ask?
It could indeed be done by using Run With and then ticking the Default box. However I need to perform this on about 150+ computers. So I'd think to run the script when booting once.
I am a newbie when it comes to PowerShell, so if anyone could give a "small" start, I would be grateful.
For a scripted solution I'd use the cmd built-ins assoc and ftype:
$prg = 'C:\Program Files\SMART Technologies\Education Software\Notebook.exe'
$ext = '.ntb'
& cmd /c "ftype SMART.Notebook=`"$prg`" %1"
& cmd /c "assoc $ext=SMART.Notebook"
The above can be run on remote hosts via the Invoke-Command cmdlet:
Invoke-Command -Computer HostA,HostB,... -ScriptBlock {
$prg = 'C:\Program Files\SMART Technologies\Education Software\Notebook.exe'
$ext = '.ntb'
& cmd /c "ftype SMART.Notebook=`"$prg`" %1"
& cmd /c "assoc $ext=SMART.Notebook"
}
Otherwise you'll have to edit the registry, in which case the deployment via group policy would be preferable, as others have already pointed out.