PowerShell's Clear-History doesn't clear history - powershell

Recently I had to run a command that unfortunately required me to type a password right on the command line.
Afterwards, I cleared my screen with "Clear", but also wanted to clear the command history so the offending command wouldn't show up in the session history. Unfortunately, the Clear-History cmdlet doesn't seem to actually do what its documentation claims - running Clear-History doesn't seem to have any impact on the session history whatsoever.
I can still see previous commands in the pop-up history menu, and scroll through old commands by pressing the up key. Here's a screengrab demonstrating the problem:
I've verified with Get-Command that Clear-History is indeed executing the expected built-in PowerShell cmdlet.
I've tried a few variations, such as "Clear-History -count 10 -newest", all failing to show any effect. When I specify an exact history ID, such as "Clear-History -id 3", I receive an error like this:
Clear-History : Cannot locate history for Id 3.
Even if I can see command #3 on the screen.

On Windows 10, the history and sensitive data show up again in future sessions, even after Alt+F7 and clear-history. It turns out the history is stored in a text file found at:
(Get-PSReadlineOption).HistorySavePath
Delete the offending line from that file and end the current session (or clear it via CB's answer).
You can upvote this request for an easier way to temporarily disable the history.

tl;dr
There are two histories to clear:
PowerShell's own (Clear-History)
Additionally, in consoles (terminals), that of the PSReadLine module that is used for command-line editing by default in PowerShell v5+ ([Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory())
In versions 1.2+ of PSReadLine (verify with Get-Module PSReadLine) pressing Alt+F7 performs both calls for you, and therefore fully clears the in-session history.
However, it does not clear the saved history that has accumulated up to this point, so even the cleared session's history will resurface in future sessions.
To also clear the saved history, you have to manually delete the file in which the saved session is stored ((Get-PSReadlineOption).HistorySavePath), as discussed below, and as wrapped by the Clear-SavedHistory function in the bottom section.
To complement CB.'s helpful answer and JVimes's helpful answer:
PowerShell's own history mechanism (Get-History, Clear-History) is host-independent, which is why - somewhat unexpectedly - you also need to clear the hosts's command history separately.
As for the console host's own history feature:
doskey-style history feature, before module PSReadline shipped with PowerShell (see below):
There is no saved history - a history is kept only for the duration of the current session.
Alt+F7 must be used to clear the console's history, with no (obvious) programmatic way to do it (in a cmd.exe console window you could use doskey /reinstall, but that doesn't work in PS).
CB.'s answer shows you how to simulate this keyboard combination; remember: this must be used in addition to Clear-History.
The PSReadline module comes with PowerShell v5 and v5.1 on Windows 10 and will also ship with Windows Server 2016, and also ships with the cross-platform Powershell (Core) v7+ edition; it replaces the doskey-style line-editing and command-history features with more sophisticated functionality; it is also possible to retrofit older Windows editions / PS versions (>= v3) versions with it, using the PowerShell Gallery (PSv3 and PSv4 must first install PowerShellGet).
Command history is now saved across sessions, in file
(Get-PSReadlineOption).HistorySavePath.
[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory() can be used to clear the current session's history (note that v1.2+ also supports Alt+F7 for interactive clearing of the current history).
CAVEAT: With PSReadline's default history-saving style, SaveIncrementally, any sensitive commands have already been saved by the time to you call [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory(), and will reappear in the next session.
The only way to handle this is to remove the saved-history file, as demonstrated in JVimes's answer which, however, invariably wipes out the entire history.
IF you set up your profile to call Set-PSReadlineOption -HistorySaveStyle SaveAtExit every time a session starts - the setting apparenly does NOT "stick" by itself - you should be able to get away with only calling [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory() (in addition to Clear-History) without also having to delete the saved-history file, in which case you won't lose your saved history from previous sessions. HOWEVER, AS OF v2.1.0 (the latest as of this writing), SaveAtExit is BROKEN ALTOGETHER - no history is saved at all; see https://github.com/lzybkr/PSReadLine/issues/262
The following advanced function bundles all commands necessary to clear the command history (both for PowerShell itself and the console), both for doskey-style and PSReadline-module PowerShell console windows:
Note:
Because it's (currently) the only safe option, PSReadline's saved-history file is deleted as well, which means the entire history, including from previous sessions, is cleared.
Therefore, a confirmation prompt is shown by default.
<#
# .SYNOPSIS
# Clears the command history, including the saved-to-file history, if applicable.
#>
function Clear-SavedHistory {
[CmdletBinding(ConfirmImpact='High', SupportsShouldProcess)]
param(
)
# Debugging: For testing you can simulate not having PSReadline loaded with
# Remove-Module PSReadline -Force
$havePSReadline = ($null -ne (Get-Module -EA SilentlyContinue PSReadline))
Write-Verbose "PSReadline present: $havePSReadline"
$target = if ($havePSReadline) { "entire command history, including from previous sessions" } else { "command history" }
if (-not $pscmdlet.ShouldProcess($target))
{
return
}
if ($havePSReadline) {
Clear-Host
# Remove PSReadline's saved-history file.
if (Test-Path (Get-PSReadlineOption).HistorySavePath) {
# Abort, if the file for some reason cannot be removed.
Remove-Item -EA Stop (Get-PSReadlineOption).HistorySavePath
# To be safe, we recreate the file (empty).
$null = New-Item -Type File -Path (Get-PSReadlineOption).HistorySavePath
}
# Clear PowerShell's own history
Clear-History
# Clear PSReadline's *session* history.
# General caveat (doesn't apply here, because we're removing the saved-history file):
# * By default (-HistorySaveStyle SaveIncrementally), if you use
# [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory(), any sensitive
# commands *have already been saved to the history*, so they'll *reappear in the next session*.
# * Placing `Set-PSReadlineOption -HistorySaveStyle SaveAtExit` in your profile
# SHOULD help that, but as of PSReadline v1.2, this option is BROKEN (saves nothing).
[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
} else { # Without PSReadline, we only have a *session* history.
Clear-Host
# Clear the doskey library's buffer, used pre-PSReadline.
# !! Unfortunately, this requires sending key combination Alt+F7.
# Thanks, https://stackoverflow.com/a/13257933/45375
$null = [system.reflection.assembly]::loadwithpartialname("System.Windows.Forms")
[System.Windows.Forms.SendKeys]::Sendwait('%{F7 2}')
# Clear PowerShell's own history
Clear-History
}
}

To clear the on screen display history (F7) you have to press Alt + F7.
This history is managed by the console buffer, not by PowerShell that has its history clearable by the Clear-History cmdlet.
To script it, try:
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.SendKeys]::Sendwait('%{F7 2}')

At the moment my only solution will be to delete the psreadline.txt text from the folder periodically by running an automated Job.
The file path to the command is #
PS C:\Users\{{user}}\appdata\roaming\microsoft\windows\powershell\psreadline>
and the filename is history.txt

By the best answer from #mklement0 I ended up with the next function, that is placed in my $PROFILE
I don't really care about any other sessions, I just want that stupid history to be cleared and that's it.
Cmdlet name Clear-History confuses as much as it can.
# it's a default alias for Get-History cmdlet
Remove-Alias history
# Usage: history - just print the history, same as call Get-History
# Usage: history -c - really clears the history
function history {
param (
# Clears history
[Parameter()]
[Alias("c")]
[Switch]
$Clear
)
if ($Clear){
Clear-History
[Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
return
}
Get-History
}

There is another way to remove the selected history entry in Prediction.I found this elegant way in PSReadLine issue
Set-PSReadLineKeyHandler -Key Shift+Delete `
-BriefDescription RemoveFromHistory `
-LongDescription "Removes the content of the current line from history" `
-ScriptBlock {
param($key, $arg)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
$toRemove = [Regex]::Escape(($line -replace "\n", "```n"))
$history = Get-Content (Get-PSReadLineOption).HistorySavePath -Raw
$history = $history -replace "(?m)^$toRemove\r\n", ""
Set-Content (Get-PSReadLineOption).HistorySavePath $history
}

Related

Format PS1 to be Double-Clicked [duplicate]

I have my_project.ps1 file from which I am activating virtual environment & starting my project.
currently I need to open my powershell then after I need to go to directory where I have saved my .ps1 file & have to open it from powershell only.
Is there any way so that I can double click on .ps1 file & it will open automatically in power shell ?
By design, double-clicking (opening) *.ps1 files from the Windows [GUI] shell (in this case: Desktop, File Explorer, and the taskbar, via pinned items) does not execute them - instead they're opened for editing in Notepad or in the PowerShell ISE, depending on the Windows / PowerShell version.
However, since at least Windows 7, the shortcut menu for *.ps1 files contains a Run with PowerShell command, which does invoke the script at hand; this may be enough for your purposes, but this invocation method has limitations - see the bottom section for details.
If you do want to redefine double-clicking / opening so that it executes *.ps1 scripts, you have two options:
Note:
For a given script (as opposed to all .ps1 files), you may alternatively create a shortcut file or batch file that launches it, but that isn't a general solution, as you'd have to create a companion file for each and every .ps1 file you want to run by double-clicking. It does, however, give you full control over the invocation. You can create shortcut files interactively, via File Explorer, as described in this answer, or programmatically, as shown in this answer. Similarly, you may create a companion batch file (.cmd or .bat) that invokes your script, because batch file are executed when double-clicked; e.g., if you place a batch file with the same base name as your .ps1 script in the same directory (e.g., foo.cmd next to foo.ps1), you can call it from your batch file as follows; -NoExit keeps the session open:
#powershell.exe -NoExit -File "%~dpn0.ps1" %*
The methods below also enable direct execution of a .ps1 script from a cmd.exe console window, synchronously, inside the same window. In other words: You can execute, say, script foo.ps1 directly as such, instead of having to use the PowerShell CLI, say, powershell.exe -File foo.ps1
[Not recommended] GUI method:
Use File Explorer to make PowerShell execute .ps1 files by default:
Right-click on a .ps1 file and select Properties.
Click on Change... next to the Opens with: label.
Click on More apps on the bottom of the list and scroll down to Look for another app on this PC
Browse to or paste file path C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe and submit.
This method gives you no control over the specifics of the PowerShell invocation and has major limitations; in effect you'll end up with the following behavior:
Major limitations:
Script paths with embedded spaces and ' chars. cannot be invoked this way, because, even though such paths are passed with double quotes, the latter are in effect stripped by PowerShell, because the path is passed to the implied -Command parameter, which first strips (unescaped) double quotes from the command line before interpreting the result as PowerShell code - in which case paths with spaces are seen as multiple arguments / paths that contain (an odd number of) ' cause a syntax error.
Note that if you were to select pwsh.exe instead, the CLI of the cross-platform, install-on-demand PowerShell (Core) 7+ edition, that problem would not arise, because it defaults to the -File parameter - in which case a double-quoted script-file path is properly recognized.
For the difference between PowerShell CLI calls using -Command vs. those using -File, see this answer.
Passing arguments is not supported, which matters if you want to invoke .ps1 files directly from cmd.exe and need to pass arguments.
The redefinition is only in effect for the current user - which is probably a good thing, as other users may not expect this change, which can result in unwanted execution of scripts.
Whatever execution policy is in effect will be honored; e.g., if Restricted is in effect, invocation will fail altogether.
As with the default Run in PowerShell command, the window in which the script runs will automatically close when the script ends - thus, unless the script explicitly prompts the user before exiting, you may not be able to examine its output.
To exercise more control over how PowerShell invokes the script including support for paths with spaces and for passing arguments, use the programmatic method shown in the next section.
Programmatic method:
Important:
The GUI method overrides a programmatic solution, so it must be removed - the code below does this automatically.
Unfortunately, there's another, accidental override that can happen if you have Visual Studio Code installed: Whenever you use File Explorer's shortcut menu to open a file in Visual Studio Code, it unexpectedly becomes the default action. The code below detects this condition and fixes the problem, but it will resurface the next time a .ps1 file is opened this way.
Modify the registry to redefine the Open shortcut-menu command for *.ps1 files at HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\Open\Command, as shown below.
You can run the code as-is to create a user-level file-type definition that:
uses the executable that runs the current PowerShell session, i.e. powershell.exe in Windows PowerShell, and pwsh.exe in PowerShell (Core) 7+.
respects the effective execution policy - add an -ExecutionPolicy argument to override.
loads the profiles first - add -NoProfile to suppress loading; this is primarily of interest if you're planning to directly invoke .ps1 files from cmd.exe, not (just) from File Explorer, in combination with not using -NoExit.
runs in the script in its own directory
keeps the session open after the script exits - remove -NoExit to exit the session when the script ends; this is primarily of interest if you're planning to directly invoke .ps1 files from cmd.exe, not (just) from File Explorer.
If you requirements differ - if you need different CLI parameters and /or you want to use pwsh.exe, i.e. PowerShell (Core) 7+ instead - tweak the code first, by modifying the $cmd = ... line below; see the comments above it.
# Specify if the change should apply to the CURRENT USER only, or to ALL users.
# NOTE: If you set this to $true - which is NOT ADVISABLE -
# you'll need to run this code ELEVATED (as administrator)
$forAllUsers = $false
# Determine the chosen scope's target registry key path.
$targetKey = "$(('HKCU', 'HKLM')[$forAllUsers]):\Software\Classes\Microsoft.PowerShellScript.1\shell\Open\Command"
# In the user-specific hive (HKCU: == HKEY_CURRENT_USER), the target key
# doesn't exist by default (whereas it does in the local-machine hive (HLKM: == HKEY_LOCAL_MACHINE)),
# so we need to make sure that it exists.
if (-not $forAllUsers -and -not (Test-Path -LiteralPath $targetKey)) {
$null = New-Item -Path $targetKey -Force -ErrorAction Stop
}
# Specify the command to use when opening / double-clicking *.ps1 scripts:
# As written here:
# * The script runs in the directory in which it resides.
# * The profiles are loaded (add -NoProfile to change).
# * The current execution policy is respected (add -ExecutionPolicy <policy> to override, if possible)
# * The window stays open after the script exits (remove -NoExit to change)
# For help with all parameters, see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
$cmd = "`"$((Get-Process -Id $PID).Path)`" -nologo -noexit -file `"%1`" %*"
# Write the command to the registry.
Set-ItemProperty -ErrorAction Stop -LiteralPath $targetKey -Name '(default)' -Value $cmd
Write-Verbose -Verbose "$(('User-level', 'Machine-level')[$forAllUsers]) file-type definition for *.ps1 files successfully updated."
# Additionally, make sure that NO OVERRIDES preempt the new definition.
# See if a user override established interactively via File Explorer happens to be defined,
# and remove it, if so.
if ($fileExplorerOverrideKey = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\UserChoice') {
Write-Verbose -Verbose 'Removing File Explorer override...'
# Get the parent key path and the key name
$parentKeyPath = $fileExplorerOverrideKey.PSParentPath -replace '^.+?::\w+\\' # Remove the 'Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\' prefix
$keyName = $fileExplorerOverrideKey.PSChildName
$key = $null
try {
# Open the *parent* key for writing.
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubkey($parentKeyPath, $true)
# Delete the subkey.
# !! Due to the specific permissions assigned by File Explorer to the key
# !! (an additional DENY access-control entry for the current user, for the key itself only, for the 'Set Value' permission),
# !! using the .DeleteSubKey*Tree*() method fails (Remove-Item implicitly uses this method and therefore fails too)
# !! However, since there should be no nested subkeys, using .DeleteSubkey() should work fine.
$key.DeleteSubKey($keyName)
}
catch {
throw
}
finally {
if ($key) { $key.Close()}
}
}
# See if *Visual Studio Code* was most recently used to open a *.ps1 file:
# If so, it inexplicably OVERRIDES a file-type definition.
# (This doesn't seem to happen with other executables.)
# !! We fix the problem, but it will RESURFACE the next time File Explorer's shortcut menu
# !! is used to open a *.ps1 file in Visual Studio Code.
if ($itm = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\OpenWithList') {
if (($names = $itm.GetValueNames().Where({ $itm.GetValue($_) -ceq 'Code.exe' })) -and ($mruList = $itm.GetValue('MRUList')) -and $mruList[0] -in $names) {
Write-Warning "Visual Studio Code was most recently used to open a .ps1 file, which unexpectedly overrides the file-type definition.`nCorrecting the problem for now, but it will resurface the next time you use File Explorer's shortcut menu to open a .ps1 file in Visual Studio Code."
# Note: Normally there aren't, but there *can* be *multiple* Code.exe entries, namely after manual removal of the MRUList:
# The next time you choose to open in VSCode via File Explorer's shortcut menu, an *additional* Code.exe entry is added.
do { # Trim the start of the MRUList until its first entry no longer references Code.exe
$mruList = $mruList.Substring(1)
} while ($mruList[0] -in $names)
# Update the MRUList value in the registry.
$itm | Set-ItemProperty -Name 'MRUList' -Value $mruList
}
}
Explanation of the predefined Run in PowerShell shortcut-menu command:
It is defined in registry key HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\0\Command (as of Windows 10) as follows:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
This command is flawed in that it breaks with script-file paths that happen to contain ' characters.
Unless execution policy AllSigned is in effect - in which case only signed scripts can be executed but are executed without prompting - the command attempts to set the execution policy for the invoked process to Bypass, which means that any script can be executed, but only after the user responds to a confirmation prompt beforehand (irrespective of whether the script is signed or not, and whether it was downloaded from the web or not).
At least in earlier Windows 7 releases / PowerShell versions, the command was misdefined[1] in a way that effectively ignored the attempt to set the process' execution policy, which meant that whatever execution policy was persistently configured applied - and no confirmation prompt was shown.
Unless the targeted script explicitly pauses to wait for user input before exiting, the window in which the script will close automatically when the script finishes, so you may not get to see its output.
The targeted script executes in the directory in which it is located as the working directory (current location)
[1] The earlier, broken command definition was "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" "-Command" "if((Get-ExecutionPolicy ) -ne AllSigned) { Set-ExecutionPolicy -Scope Process Bypass }", which meant what anything after -file "%1" was passed as arguments to file "%1" instead of the intended execution of the commands following -Command; additionally - a moot point - the AllSigned operand would have need to be quoted.
To execute a PS1 file by double-click (to run)
Make a shortcut for the file and set the target to this:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Temp\MyPowershellScript.ps1"
Replace the second directory (the one in quotes) with the location of your script.
To read a PS1 file by double-click (to edit)
Same as above, but target ISE instead, as that will force it into edit mode.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe "C:\Temp\MyPowershellScript.ps1"
Server 2012 and newer by default do not associate the .PS1 file extension with the PowerShell executable; rather, they default to open .PS1 files with notepad by default for security reasons.
If you have access, you need to change the file association through the 'default programs' in your control panel for the .PS1 files to execute by double clicking.
Also be aware that you may have to change your execution policy to get particular scripts to run.
Also, as it sounds like this script might be a core automation, you can execute scripts from in another one with either of these, without the need to change the active working directory:
Invoke-Item ""
& ''
I have fixed the registry values so that the .ps1 scripts are executed with double click or with "Run with PowerShell" from any position without problem, even with paths with multiple consecutive spaces and with apostrophes:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.ps1]
#="Microsoft.PowerShellScript.1"
[HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Directory\Shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Drive\shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\DefaultIcon]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\",0"
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""
[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\0\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""
[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\Edit\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe\" -File \"%1\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell]
"ExecutionPolicy"="RemoteSigned"

Powershell script executes correctly when I choose "run with powershell", but not when I "open with" powershell or double-click it [duplicate]

I have my_project.ps1 file from which I am activating virtual environment & starting my project.
currently I need to open my powershell then after I need to go to directory where I have saved my .ps1 file & have to open it from powershell only.
Is there any way so that I can double click on .ps1 file & it will open automatically in power shell ?
By design, double-clicking (opening) *.ps1 files from the Windows [GUI] shell (in this case: Desktop, File Explorer, and the taskbar, via pinned items) does not execute them - instead they're opened for editing in Notepad or in the PowerShell ISE, depending on the Windows / PowerShell version.
However, since at least Windows 7, the shortcut menu for *.ps1 files contains a Run with PowerShell command, which does invoke the script at hand; this may be enough for your purposes, but this invocation method has limitations - see the bottom section for details.
If you do want to redefine double-clicking / opening so that it executes *.ps1 scripts, you have two options:
Note:
For a given script (as opposed to all .ps1 files), you may alternatively create a shortcut file or batch file that launches it, but that isn't a general solution, as you'd have to create a companion file for each and every .ps1 file you want to run by double-clicking. It does, however, give you full control over the invocation. You can create shortcut files interactively, via File Explorer, as described in this answer, or programmatically, as shown in this answer. Similarly, you may create a companion batch file (.cmd or .bat) that invokes your script, because batch file are executed when double-clicked; e.g., if you place a batch file with the same base name as your .ps1 script in the same directory (e.g., foo.cmd next to foo.ps1), you can call it from your batch file as follows; -NoExit keeps the session open:
#powershell.exe -NoExit -File "%~dpn0.ps1" %*
The methods below also enable direct execution of a .ps1 script from a cmd.exe console window, synchronously, inside the same window. In other words: You can execute, say, script foo.ps1 directly as such, instead of having to use the PowerShell CLI, say, powershell.exe -File foo.ps1
[Not recommended] GUI method:
Use File Explorer to make PowerShell execute .ps1 files by default:
Right-click on a .ps1 file and select Properties.
Click on Change... next to the Opens with: label.
Click on More apps on the bottom of the list and scroll down to Look for another app on this PC
Browse to or paste file path C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe and submit.
This method gives you no control over the specifics of the PowerShell invocation and has major limitations; in effect you'll end up with the following behavior:
Major limitations:
Script paths with embedded spaces and ' chars. cannot be invoked this way, because, even though such paths are passed with double quotes, the latter are in effect stripped by PowerShell, because the path is passed to the implied -Command parameter, which first strips (unescaped) double quotes from the command line before interpreting the result as PowerShell code - in which case paths with spaces are seen as multiple arguments / paths that contain (an odd number of) ' cause a syntax error.
Note that if you were to select pwsh.exe instead, the CLI of the cross-platform, install-on-demand PowerShell (Core) 7+ edition, that problem would not arise, because it defaults to the -File parameter - in which case a double-quoted script-file path is properly recognized.
For the difference between PowerShell CLI calls using -Command vs. those using -File, see this answer.
Passing arguments is not supported, which matters if you want to invoke .ps1 files directly from cmd.exe and need to pass arguments.
The redefinition is only in effect for the current user - which is probably a good thing, as other users may not expect this change, which can result in unwanted execution of scripts.
Whatever execution policy is in effect will be honored; e.g., if Restricted is in effect, invocation will fail altogether.
As with the default Run in PowerShell command, the window in which the script runs will automatically close when the script ends - thus, unless the script explicitly prompts the user before exiting, you may not be able to examine its output.
To exercise more control over how PowerShell invokes the script including support for paths with spaces and for passing arguments, use the programmatic method shown in the next section.
Programmatic method:
Important:
The GUI method overrides a programmatic solution, so it must be removed - the code below does this automatically.
Unfortunately, there's another, accidental override that can happen if you have Visual Studio Code installed: Whenever you use File Explorer's shortcut menu to open a file in Visual Studio Code, it unexpectedly becomes the default action. The code below detects this condition and fixes the problem, but it will resurface the next time a .ps1 file is opened this way.
Modify the registry to redefine the Open shortcut-menu command for *.ps1 files at HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\Open\Command, as shown below.
You can run the code as-is to create a user-level file-type definition that:
uses the executable that runs the current PowerShell session, i.e. powershell.exe in Windows PowerShell, and pwsh.exe in PowerShell (Core) 7+.
respects the effective execution policy - add an -ExecutionPolicy argument to override.
loads the profiles first - add -NoProfile to suppress loading; this is primarily of interest if you're planning to directly invoke .ps1 files from cmd.exe, not (just) from File Explorer, in combination with not using -NoExit.
runs in the script in its own directory
keeps the session open after the script exits - remove -NoExit to exit the session when the script ends; this is primarily of interest if you're planning to directly invoke .ps1 files from cmd.exe, not (just) from File Explorer.
If you requirements differ - if you need different CLI parameters and /or you want to use pwsh.exe, i.e. PowerShell (Core) 7+ instead - tweak the code first, by modifying the $cmd = ... line below; see the comments above it.
# Specify if the change should apply to the CURRENT USER only, or to ALL users.
# NOTE: If you set this to $true - which is NOT ADVISABLE -
# you'll need to run this code ELEVATED (as administrator)
$forAllUsers = $false
# Determine the chosen scope's target registry key path.
$targetKey = "$(('HKCU', 'HKLM')[$forAllUsers]):\Software\Classes\Microsoft.PowerShellScript.1\shell\Open\Command"
# In the user-specific hive (HKCU: == HKEY_CURRENT_USER), the target key
# doesn't exist by default (whereas it does in the local-machine hive (HLKM: == HKEY_LOCAL_MACHINE)),
# so we need to make sure that it exists.
if (-not $forAllUsers -and -not (Test-Path -LiteralPath $targetKey)) {
$null = New-Item -Path $targetKey -Force -ErrorAction Stop
}
# Specify the command to use when opening / double-clicking *.ps1 scripts:
# As written here:
# * The script runs in the directory in which it resides.
# * The profiles are loaded (add -NoProfile to change).
# * The current execution policy is respected (add -ExecutionPolicy <policy> to override, if possible)
# * The window stays open after the script exits (remove -NoExit to change)
# For help with all parameters, see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
$cmd = "`"$((Get-Process -Id $PID).Path)`" -nologo -noexit -file `"%1`" %*"
# Write the command to the registry.
Set-ItemProperty -ErrorAction Stop -LiteralPath $targetKey -Name '(default)' -Value $cmd
Write-Verbose -Verbose "$(('User-level', 'Machine-level')[$forAllUsers]) file-type definition for *.ps1 files successfully updated."
# Additionally, make sure that NO OVERRIDES preempt the new definition.
# See if a user override established interactively via File Explorer happens to be defined,
# and remove it, if so.
if ($fileExplorerOverrideKey = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\UserChoice') {
Write-Verbose -Verbose 'Removing File Explorer override...'
# Get the parent key path and the key name
$parentKeyPath = $fileExplorerOverrideKey.PSParentPath -replace '^.+?::\w+\\' # Remove the 'Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\' prefix
$keyName = $fileExplorerOverrideKey.PSChildName
$key = $null
try {
# Open the *parent* key for writing.
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubkey($parentKeyPath, $true)
# Delete the subkey.
# !! Due to the specific permissions assigned by File Explorer to the key
# !! (an additional DENY access-control entry for the current user, for the key itself only, for the 'Set Value' permission),
# !! using the .DeleteSubKey*Tree*() method fails (Remove-Item implicitly uses this method and therefore fails too)
# !! However, since there should be no nested subkeys, using .DeleteSubkey() should work fine.
$key.DeleteSubKey($keyName)
}
catch {
throw
}
finally {
if ($key) { $key.Close()}
}
}
# See if *Visual Studio Code* was most recently used to open a *.ps1 file:
# If so, it inexplicably OVERRIDES a file-type definition.
# (This doesn't seem to happen with other executables.)
# !! We fix the problem, but it will RESURFACE the next time File Explorer's shortcut menu
# !! is used to open a *.ps1 file in Visual Studio Code.
if ($itm = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\OpenWithList') {
if (($names = $itm.GetValueNames().Where({ $itm.GetValue($_) -ceq 'Code.exe' })) -and ($mruList = $itm.GetValue('MRUList')) -and $mruList[0] -in $names) {
Write-Warning "Visual Studio Code was most recently used to open a .ps1 file, which unexpectedly overrides the file-type definition.`nCorrecting the problem for now, but it will resurface the next time you use File Explorer's shortcut menu to open a .ps1 file in Visual Studio Code."
# Note: Normally there aren't, but there *can* be *multiple* Code.exe entries, namely after manual removal of the MRUList:
# The next time you choose to open in VSCode via File Explorer's shortcut menu, an *additional* Code.exe entry is added.
do { # Trim the start of the MRUList until its first entry no longer references Code.exe
$mruList = $mruList.Substring(1)
} while ($mruList[0] -in $names)
# Update the MRUList value in the registry.
$itm | Set-ItemProperty -Name 'MRUList' -Value $mruList
}
}
Explanation of the predefined Run in PowerShell shortcut-menu command:
It is defined in registry key HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\0\Command (as of Windows 10) as follows:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
This command is flawed in that it breaks with script-file paths that happen to contain ' characters.
Unless execution policy AllSigned is in effect - in which case only signed scripts can be executed but are executed without prompting - the command attempts to set the execution policy for the invoked process to Bypass, which means that any script can be executed, but only after the user responds to a confirmation prompt beforehand (irrespective of whether the script is signed or not, and whether it was downloaded from the web or not).
At least in earlier Windows 7 releases / PowerShell versions, the command was misdefined[1] in a way that effectively ignored the attempt to set the process' execution policy, which meant that whatever execution policy was persistently configured applied - and no confirmation prompt was shown.
Unless the targeted script explicitly pauses to wait for user input before exiting, the window in which the script will close automatically when the script finishes, so you may not get to see its output.
The targeted script executes in the directory in which it is located as the working directory (current location)
[1] The earlier, broken command definition was "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" "-Command" "if((Get-ExecutionPolicy ) -ne AllSigned) { Set-ExecutionPolicy -Scope Process Bypass }", which meant what anything after -file "%1" was passed as arguments to file "%1" instead of the intended execution of the commands following -Command; additionally - a moot point - the AllSigned operand would have need to be quoted.
To execute a PS1 file by double-click (to run)
Make a shortcut for the file and set the target to this:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Temp\MyPowershellScript.ps1"
Replace the second directory (the one in quotes) with the location of your script.
To read a PS1 file by double-click (to edit)
Same as above, but target ISE instead, as that will force it into edit mode.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe "C:\Temp\MyPowershellScript.ps1"
Server 2012 and newer by default do not associate the .PS1 file extension with the PowerShell executable; rather, they default to open .PS1 files with notepad by default for security reasons.
If you have access, you need to change the file association through the 'default programs' in your control panel for the .PS1 files to execute by double clicking.
Also be aware that you may have to change your execution policy to get particular scripts to run.
Also, as it sounds like this script might be a core automation, you can execute scripts from in another one with either of these, without the need to change the active working directory:
Invoke-Item ""
& ''
I have fixed the registry values so that the .ps1 scripts are executed with double click or with "Run with PowerShell" from any position without problem, even with paths with multiple consecutive spaces and with apostrophes:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.ps1]
#="Microsoft.PowerShellScript.1"
[HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Directory\Shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Drive\shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\DefaultIcon]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\",0"
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""
[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\0\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""
[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\Edit\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe\" -File \"%1\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell]
"ExecutionPolicy"="RemoteSigned"

Any way to double-click on .PS1 file & open them in PowerShell?

I have my_project.ps1 file from which I am activating virtual environment & starting my project.
currently I need to open my powershell then after I need to go to directory where I have saved my .ps1 file & have to open it from powershell only.
Is there any way so that I can double click on .ps1 file & it will open automatically in power shell ?
By design, double-clicking (opening) *.ps1 files from the Windows [GUI] shell (in this case: Desktop, File Explorer, and the taskbar, via pinned items) does not execute them - instead they're opened for editing in Notepad or in the PowerShell ISE, depending on the Windows / PowerShell version.
However, since at least Windows 7, the shortcut menu for *.ps1 files contains a Run with PowerShell command, which does invoke the script at hand; this may be enough for your purposes, but this invocation method has limitations - see the bottom section for details.
If you do want to redefine double-clicking / opening so that it executes *.ps1 scripts, you have two options:
Note:
For a given script (as opposed to all .ps1 files), you may alternatively create a shortcut file or batch file that launches it, but that isn't a general solution, as you'd have to create a companion file for each and every .ps1 file you want to run by double-clicking. It does, however, give you full control over the invocation. You can create shortcut files interactively, via File Explorer, as described in this answer, or programmatically, as shown in this answer. Similarly, you may create a companion batch file (.cmd or .bat) that invokes your script, because batch file are executed when double-clicked; e.g., if you place a batch file with the same base name as your .ps1 script in the same directory (e.g., foo.cmd next to foo.ps1), you can call it from your batch file as follows; -NoExit keeps the session open:
#powershell.exe -NoExit -File "%~dpn0.ps1" %*
The methods below also enable direct execution of a .ps1 script from a cmd.exe console window, synchronously, inside the same window. In other words: You can execute, say, script foo.ps1 directly as such, instead of having to use the PowerShell CLI, say, powershell.exe -File foo.ps1
[Not recommended] GUI method:
Use File Explorer to make PowerShell execute .ps1 files by default:
Right-click on a .ps1 file and select Properties.
Click on Change... next to the Opens with: label.
Click on More apps on the bottom of the list and scroll down to Look for another app on this PC
Browse to or paste file path C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe and submit.
This method gives you no control over the specifics of the PowerShell invocation and has major limitations; in effect you'll end up with the following behavior:
Major limitations:
Script paths with embedded spaces and ' chars. cannot be invoked this way, because, even though such paths are passed with double quotes, the latter are in effect stripped by PowerShell, because the path is passed to the implied -Command parameter, which first strips (unescaped) double quotes from the command line before interpreting the result as PowerShell code - in which case paths with spaces are seen as multiple arguments / paths that contain (an odd number of) ' cause a syntax error.
Note that if you were to select pwsh.exe instead, the CLI of the cross-platform, install-on-demand PowerShell (Core) 7+ edition, that problem would not arise, because it defaults to the -File parameter - in which case a double-quoted script-file path is properly recognized.
For the difference between PowerShell CLI calls using -Command vs. those using -File, see this answer.
Passing arguments is not supported, which matters if you want to invoke .ps1 files directly from cmd.exe and need to pass arguments.
The redefinition is only in effect for the current user - which is probably a good thing, as other users may not expect this change, which can result in unwanted execution of scripts.
Whatever execution policy is in effect will be honored; e.g., if Restricted is in effect, invocation will fail altogether.
As with the default Run in PowerShell command, the window in which the script runs will automatically close when the script ends - thus, unless the script explicitly prompts the user before exiting, you may not be able to examine its output.
To exercise more control over how PowerShell invokes the script including support for paths with spaces and for passing arguments, use the programmatic method shown in the next section.
Programmatic method:
Important:
The GUI method overrides a programmatic solution, so it must be removed - the code below does this automatically.
Unfortunately, there's another, accidental override that can happen if you have Visual Studio Code installed: Whenever you use File Explorer's shortcut menu to open a file in Visual Studio Code, it unexpectedly becomes the default action. The code below detects this condition and fixes the problem, but it will resurface the next time a .ps1 file is opened this way.
Modify the registry to redefine the Open shortcut-menu command for *.ps1 files at HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\Open\Command, as shown below.
You can run the code as-is to create a user-level file-type definition that:
uses the executable that runs the current PowerShell session, i.e. powershell.exe in Windows PowerShell, and pwsh.exe in PowerShell (Core) 7+.
respects the effective execution policy - add an -ExecutionPolicy argument to override.
loads the profiles first - add -NoProfile to suppress loading; this is primarily of interest if you're planning to directly invoke .ps1 files from cmd.exe, not (just) from File Explorer, in combination with not using -NoExit.
runs in the script in its own directory
keeps the session open after the script exits - remove -NoExit to exit the session when the script ends; this is primarily of interest if you're planning to directly invoke .ps1 files from cmd.exe, not (just) from File Explorer.
If you requirements differ - if you need different CLI parameters and /or you want to use pwsh.exe, i.e. PowerShell (Core) 7+ instead - tweak the code first, by modifying the $cmd = ... line below; see the comments above it.
# Specify if the change should apply to the CURRENT USER only, or to ALL users.
# NOTE: If you set this to $true - which is NOT ADVISABLE -
# you'll need to run this code ELEVATED (as administrator)
$forAllUsers = $false
# Determine the chosen scope's target registry key path.
$targetKey = "$(('HKCU', 'HKLM')[$forAllUsers]):\Software\Classes\Microsoft.PowerShellScript.1\shell\Open\Command"
# In the user-specific hive (HKCU: == HKEY_CURRENT_USER), the target key
# doesn't exist by default (whereas it does in the local-machine hive (HLKM: == HKEY_LOCAL_MACHINE)),
# so we need to make sure that it exists.
if (-not $forAllUsers -and -not (Test-Path -LiteralPath $targetKey)) {
$null = New-Item -Path $targetKey -Force -ErrorAction Stop
}
# Specify the command to use when opening / double-clicking *.ps1 scripts:
# As written here:
# * The script runs in the directory in which it resides.
# * The profiles are loaded (add -NoProfile to change).
# * The current execution policy is respected (add -ExecutionPolicy <policy> to override, if possible)
# * The window stays open after the script exits (remove -NoExit to change)
# For help with all parameters, see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
$cmd = "`"$((Get-Process -Id $PID).Path)`" -nologo -noexit -file `"%1`" %*"
# Write the command to the registry.
Set-ItemProperty -ErrorAction Stop -LiteralPath $targetKey -Name '(default)' -Value $cmd
Write-Verbose -Verbose "$(('User-level', 'Machine-level')[$forAllUsers]) file-type definition for *.ps1 files successfully updated."
# Additionally, make sure that NO OVERRIDES preempt the new definition.
# See if a user override established interactively via File Explorer happens to be defined,
# and remove it, if so.
if ($fileExplorerOverrideKey = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\UserChoice') {
Write-Verbose -Verbose 'Removing File Explorer override...'
# Get the parent key path and the key name
$parentKeyPath = $fileExplorerOverrideKey.PSParentPath -replace '^.+?::\w+\\' # Remove the 'Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\' prefix
$keyName = $fileExplorerOverrideKey.PSChildName
$key = $null
try {
# Open the *parent* key for writing.
$key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubkey($parentKeyPath, $true)
# Delete the subkey.
# !! Due to the specific permissions assigned by File Explorer to the key
# !! (an additional DENY access-control entry for the current user, for the key itself only, for the 'Set Value' permission),
# !! using the .DeleteSubKey*Tree*() method fails (Remove-Item implicitly uses this method and therefore fails too)
# !! However, since there should be no nested subkeys, using .DeleteSubkey() should work fine.
$key.DeleteSubKey($keyName)
}
catch {
throw
}
finally {
if ($key) { $key.Close()}
}
}
# See if *Visual Studio Code* was most recently used to open a *.ps1 file:
# If so, it inexplicably OVERRIDES a file-type definition.
# (This doesn't seem to happen with other executables.)
# !! We fix the problem, but it will RESURFACE the next time File Explorer's shortcut menu
# !! is used to open a *.ps1 file in Visual Studio Code.
if ($itm = Get-Item -ErrorAction Ignore -LiteralPath 'registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\OpenWithList') {
if (($names = $itm.GetValueNames().Where({ $itm.GetValue($_) -ceq 'Code.exe' })) -and ($mruList = $itm.GetValue('MRUList')) -and $mruList[0] -in $names) {
Write-Warning "Visual Studio Code was most recently used to open a .ps1 file, which unexpectedly overrides the file-type definition.`nCorrecting the problem for now, but it will resurface the next time you use File Explorer's shortcut menu to open a .ps1 file in Visual Studio Code."
# Note: Normally there aren't, but there *can* be *multiple* Code.exe entries, namely after manual removal of the MRUList:
# The next time you choose to open in VSCode via File Explorer's shortcut menu, an *additional* Code.exe entry is added.
do { # Trim the start of the MRUList until its first entry no longer references Code.exe
$mruList = $mruList.Substring(1)
} while ($mruList[0] -in $names)
# Update the MRUList value in the registry.
$itm | Set-ItemProperty -Name 'MRUList' -Value $mruList
}
}
Explanation of the predefined Run in PowerShell shortcut-menu command:
It is defined in registry key HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\shell\0\Command (as of Windows 10) as follows:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
This command is flawed in that it breaks with script-file paths that happen to contain ' characters.
Unless execution policy AllSigned is in effect - in which case only signed scripts can be executed but are executed without prompting - the command attempts to set the execution policy for the invoked process to Bypass, which means that any script can be executed, but only after the user responds to a confirmation prompt beforehand (irrespective of whether the script is signed or not, and whether it was downloaded from the web or not).
At least in earlier Windows 7 releases / PowerShell versions, the command was misdefined[1] in a way that effectively ignored the attempt to set the process' execution policy, which meant that whatever execution policy was persistently configured applied - and no confirmation prompt was shown.
Unless the targeted script explicitly pauses to wait for user input before exiting, the window in which the script will close automatically when the script finishes, so you may not get to see its output.
The targeted script executes in the directory in which it is located as the working directory (current location)
[1] The earlier, broken command definition was "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" "-Command" "if((Get-ExecutionPolicy ) -ne AllSigned) { Set-ExecutionPolicy -Scope Process Bypass }", which meant what anything after -file "%1" was passed as arguments to file "%1" instead of the intended execution of the commands following -Command; additionally - a moot point - the AllSigned operand would have need to be quoted.
To execute a PS1 file by double-click (to run)
Make a shortcut for the file and set the target to this:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Temp\MyPowershellScript.ps1"
Replace the second directory (the one in quotes) with the location of your script.
To read a PS1 file by double-click (to edit)
Same as above, but target ISE instead, as that will force it into edit mode.
C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe "C:\Temp\MyPowershellScript.ps1"
Server 2012 and newer by default do not associate the .PS1 file extension with the PowerShell executable; rather, they default to open .PS1 files with notepad by default for security reasons.
If you have access, you need to change the file association through the 'default programs' in your control panel for the .PS1 files to execute by double clicking.
Also be aware that you may have to change your execution policy to get particular scripts to run.
Also, as it sounds like this script might be a core automation, you can execute scripts from in another one with either of these, without the need to change the active working directory:
Invoke-Item ""
& ''
I have fixed the registry values so that the .ps1 scripts are executed with double click or with "Run with PowerShell" from any position without problem, even with paths with multiple consecutive spaces and with apostrophes:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\.ps1]
#="Microsoft.PowerShellScript.1"
[HKEY_CLASSES_ROOT\Directory\Background\shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Directory\Shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Drive\shell\Powershell\command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -Command \"Set-Location -LiteralPath \\\"%V\\\"\""
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\DefaultIcon]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\",0"
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""
[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\0\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -File \"%1\""
[HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\Edit\Command]
#="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell_ise.exe\" -File \"%1\""
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell]
"ExecutionPolicy"="RemoteSigned"

Get-Content with wait parameter doesn't update in Powershell

I'm trying to monitor a file using Get-Content $path -wait in Windows Powershell V3.0. Sometimes when I execute this command line in Powershell it will function as expected. But sometimes it will only execute (or at least it seems like) get-content but without the -wait parameter. Even though the file get's updated it won't be shown in Powershell. If I cancel the command and rerun it it will show the updated file content.
What do I need to do?
EDIT: It seems to update blocks after a while. But it's not real-time really.
Not allowed to comment (don't have a 50 reputation), so have to give an Answer....
Less for Windows (http://gnuwin32.sourceforge.net/packages/less.htm) with the +F or Shift-F option (http://www.commandlinefu.com/commands/view/1024/make-less-behave-like-tail-f.) showed updated file content where PowerShell "get-content $path -wait" did not.

Powershell_ise doesn't refresh modification done outside

How to refresh Powershell_ise for contents modified outside the IDE.
Most of the time i would have opened both Powershell_ise and notepad++
If i does changes in Powershell_ise , notepad++ asks for reload but if i modify in notepad++ there is no way to refresh in Powershell_ise.
Whether any way to refresh the content or am i overlooking any feature which provides this?
This post is old, but I figured I'd post this as google brought me here with the same issue.
I eventually just wrote this little function which doesn't do exactly what the OP wanted, but maybe other googlers will find it useful:
function Build {
#Reload file
$CurrentFile = $psise.CurrentFile
$FilePath = $CurrentFile.FullPath
$PsISE.CurrentPowerShellTab.Files.remove($CurrentFile)
$PsISE.CurrentPowerShellTab.Files.add($FilePath)
iex $PsISE.CurrentPowerShellTab.Files.Editor.Text
}
$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Clear()
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Reload file and run",{Build},'f4')
Its not perfect, but its good enough for me for now. All is does is create a key binding that closes,reopens, and then executes the current file. Its a bit jarring though because when you run it you'll lose your current cursor position when the file is closed and reopened. I'm sure you could store the column and line position of the cursor and restore it when reloading, but I'm too lazy to bother with that for the time being.
Edit: I accidentally posted an older non-working version of my code. Updated with working version.
Here is a different spin on red888's script:
function Reload {
$CurrentFile = $psise.CurrentFile
$FilePath = $CurrentFile.FullPath
$lineNum = $psise.CurrentFile.Editor.CaretLine
$colNum = $psise.CurrentFile.Editor.CaretColumn
$PsISE.CurrentPowerShellTab.Files.remove($CurrentFile) > $null
$newFile = $PsISE.CurrentPowerShellTab.Files.add($FilePath)
$newfile.Editor.SetCaretPosition($lineNum,$colNum)
}
$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Clear()
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Reload File",{Reload},'f4') > $null
It restores the position of the caret after reload. I removed the line
iex $PsISE.CurrentPowerShellTab.Files.Editor.Text
As I didn't need it and its also not the same as running the script (and so results in strange behavior of statements like $script:MyInvocation.MyCommand.Path).
Incidentally, if you put this code in your ISE profile it will automatically run when you first load the ISE. The ISE profile is just a powershell script whose location is given by the $profile variable.
Here are some commands that create the profile if it doesn't exist, and then opens it. Run it from inside the ISE:
if (!(Test-Path (Split-Path $profile))) { mkdir (Split-Path $profile) } ;
if (!(Test-Path $profile)) { New-Item $profile -ItemType file } ;
notepad $profile
PowerShell ISE does not support refreshing the changed files automatically. It is not there even in ISE v3.
There is connect suggestion on this topic: https://connect.microsoft.com/PowerShell/feedback/details/711915/open-ise-files-should-update-when-edited-externally
However, this can be done using PowerShell ISE Object model and PowerShell eventing. Explore $psise.CurrentFile and $psise.CurrentPowerShellTab.Files collection. This must give you enough information to write your own simple addon.