Powershell Start-Process VS Invoke-Item - powershell

What's the difference between Start-Process and Invoke-Item? I noticed that you can't Invoke-Item chrome. I assume that Invoke-Item is specifically for files with a given file path. But are there any advantages to using Invoke-Item instead of Start-Process (besides that typing ii is faster than typing start)?

The Invoke-Item cmdlet performs the default action on the specified item. For example, it runs an executable file or opens a document file in the application associated with the document file type. The default action depends on the type of item and is determined by the PowerShell provider that provides access to the data.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-item?view=powershell-6
The Start-Process cmdlet starts one or more processes on the local computer. To specify the program that runs in the process, enter an executable file or script file, or a file that can be opened by using a program on the computer. If you specify a non-executable file, Start-Process starts the program that is associated with the file, similar to the Invoke-Item cmdlet.
You can use the parameters of Start-Process to specify options, such as loading a user profile, starting the process in a new window, or using alternate credentials.
https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Management/Start-Process?view=powershell-6

Related

Powershell Script only opens as a .txt file when run

Hi I have a script on a memory stick that I want to be able to run in cmd line before a computer has windows fully installed. (the stage just after you've connected to a network).
Cmd used to run the script.
Start > Run D:\pscript\Intune.ps1
This only opens a .txt file, while researching I've found that the reason this happens is due to security, is there anyway to override this bar changing the default file type out.
Unlike batch files (.cmd, .bat) associated with cmd.exe (the legacy Command Prompt), PowerShell's .ps1 script files are by default not directly executable from outside PowerShell.
Instead, they are treated as documents that are by default associated with either Notepad or the (obsolescent) Windows PowerShell ISE, depending on the , and invoking them therefore opens them for editing, which applies to the following contexts:
Invoking a .ps1 file from cmd.exe
Invoking a .ps1 file from Start Menu's Run dialog, as in your case (which you can invoke with WinKey+R, for instance)
Opening (double-clicking) a .ps1 file from File Explorer or Desktop.
To execute a .ps1 script from outside PowerShell, you must therefore invoke it via PowerShell's CLI, powershell.exe for Windows PowerShell, pwsh for PowerShell (Core) 7+.
In the simplest case, using Windows PowerShell and the -File parameter, as also shown by Mathias R. Jessen in a comment; see the comments below and the linked docs for additional parameters:
# Note:
# * The effective execution policy applies; use -ExecutionPolicy Bypass to bypass.
# * Profiles are loaded; use -NoProfile to suppress.
# * The console window auto-closes when the script terminates; use -NoExit
# to keep the session open.
powershell.exe -File D:\pscript\Intune.ps1
For a comprehensive overview of PowerShell's CLI, see this post.
It is possible - though not advisable - to configure your system to execute .ps1 files by default - see this answer.

Powershell $PSScriptRoot empty when using Invoke-Command

When running a .ps1 on a remote computer using Invoke-Command, $PSScriptRoot is empty on the remote computer.
Is this normal? How can one find the .ps1 path when using Invoke-Command?
Further, other methods, such as through $MyInvocation are also empty.
Is this normal? How can one find the .ps1 path when using Invoke-Command?
There is no script file involved on the remote computer when you call
Invoke-Command -ComputerName $someComputer -FilePath c:\path\to\some\script.ps1
What PowerShell does in this case is to send the contents (parsed source code)[1] of the caller-local script file to the remote machine and executes it there.
Therefore, $PSScriptRoot (the directory in which a script file resides) doesn't apply and returns the empty string.
The same applies to other script-file-related automatic variables, such as $PSCommandPath and $MyInvocation.MyCommand.Name (see about_Automatic_Variables).
To put it differently: When the script file's code executes remotely, it doesn't know anything about the file it came from on the caller's side.
Thus, the only information available you there is $PWD, i.e., the current (working) location (directory).
[1] From the docs: "When you use this [the -FilePath] parameter, PowerShell converts the contents of the specified script file to a script block, transmits the script block to the remote computer, and runs it on the remote computer."

Powershell equivalent of Batch command "START" to open window with Mapped Drive

This is the batch commands I use to open a window with Mapped Drive:
net use X: "\\SERVERNAME\FOLDER" /user:"USER" "PASSWORD"
START X:\
What is the Powershell version of this?
Both of your commands work as-is in PowerShell:
net refers to the net.exe external program (a standard Windows utility), which PowerShell can equally call.
On Windows 8 / Windows Server 2012 or higher, you can use the New-SmbMapping cmdlet as an alternative to net use.
Note that while PowerShell cmdlets are generally more secure by not allowing passwords to be specified as plain text and requiring a credential object instead (see Get-Credential), this appears not to be the case with New-SmbMapping.
While start is an internal cmd.exe command, PowerShell has an alias named start for its own Start-Process cmdlet; if you pass a drive specification, the two commands work the same.
Alternatively, you could have used the Invoke-Item cmdlet (Invoke-Item X:\),
which more narrowly supports opening only documents and folders, by relative or absolute paths (no $env:PATH search for executables is performed).
in the case of a drive-spec-only path such as X:, Invoke-Item opens File Explorer in whatever directory is current on that drive (by contrast, Start-Process and cmd.exe's start open the target drive's root directory).

Run command on powershell launch using pwd variable

When you're in file explorer you can click on File > Open Windows Powershell(or its icon in the Quick Access Toolbar) to start an instance of Powershell in the directory that your file explorer is in. I would like to then automatically run a simple command in this directory and close the Powershell window after it is done.
I have tried adding my command to my Powershell Profile but it executes before the path variable has been set and it runs with $pwd being equal to C:\Users\MyUsername (my home directory) or C:\WINDOWS\system32 (seems to be a race condition of some sort, no idea why it does one or the other). To the best of my understanding this is because the file explorer "open in powershell button" opens powershell and THEN cd's to the directory I was in in file explorer. So when the profile.ps1 is ran it is using the only directories it knows if since the cd call hasn't been made yet. This is similar to running the command start powershell.exe in cmd vs start powershell.exe -command "cd 'C:\wherever'". The former correctly runs my profile command while the latter uses the current directory of cmd and not the C:\wherever.
So, obviously the $pwd variable is being assigned at different times in the case of opening it from cmd and opening it from file explorer. Is there some way to delay the execution of a command in the profile until after the shell has fully loaded? Simply sleeping the script doesn't help.
Alternatively, if anyone knows how to edit the registry so that I can change the behavior of clicking File > Open Windows Powershell (since it must have access to some variable storing the current directory and I assume it calls the Powershell executable with this variable as an argument being cd'd to), that would work too.
Then again I could be incredibly naive about how File > Open Windows Powershell and the Powershell instantiation process works.
Any help is greatly appreciated, thank you!
I figured it out in the most hacky, gross way ever, but without easy access to Windows internals this is the only working method I could find. I set up my powershell profile to make my window title my prompt like so:
function Prompt
{
$host.ui.RawUI.WindowTitle = $(get-location)
“PS> “
}
Then I set up a task in the Task Scheduler that was triggered by powershell reaching its prompt (there are 3 possible hooks, when the console is starting up, when it starts an IPC listening thread, and when the console is ready for input). I used the Event Viewer to do this (I was going to post screenshots but I don't have 10 reputation yet).
Then, I set the action on this task to run the script shown below, which reads from the window title of my first instance of powershell
Start-Sleep -s 1
$A = Get-Process -Name powershell | Where-Object -FilterScript {$_.Id -ne $PID}
$B = $A.MainWindowTitle
& C:\Program` Files\MyProgram\MyProgram.exe "$B"
stop-process -Id $A.Id
stop-process -Id $PID
This whole menagerie of events properly runs my program with the current file explorer directory as an argument (and then closes powershell) when I click the little powershell icon on the quick access toolbar in file explorer.
Found a much cleaner and faster way to do this. All I had to do was set up my profile to look like this, no tasks or second instance of powershell required
function Prompt
{
& C:\Program` Files\MyProgram\MyProgram.exe "$pwd"
stop-process -Id $PID
}

How to automatically save PowerShell session

How can i redirect everything what happens within a PowerShell windows (inputs and outputs) automatically to a file? I don't mean single commands instead i would like to have something like a logger which captures everything and logs into a local file so that i have a history of things done within the powershell window.
You're looking for PowerShell's Start-Transcript cmdlet, which:
creates a record of all or part of a Windows PowerShell session to a text file. The transcript includes all command that the user types and all output that appears on the console.
Running transcripts must be stopped explicitly, with the Stop-Transcript cmdlet.