Powershell_ise doesn't refresh modification done outside - powershell

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.

Related

Change the default "Edit" action for .ps1 from ISE to VS Code

Like the person in this question, it is frustrating that such obvious things have no clear answers (I've looked at 20 pages and found nothing yet).
The default right-click "Edit" action in Windows for .ps1 files is to open with PowerShell_ISE. ISE is an ancient and bloated relic of a bygone age, and incredibly slow to open, so when you accidently do right-click > Edit, it is tortuous watching ISE slowly open.
How can we programmatically alter the default "Edit" action for .ps1 / .psm1 etc such that they will point to VS Code instead of ISE?
Alternatively, if we can't alter it, can we completely remove it (so that "Edit with VS Code" is the only option left)?
This is actually pretty easy to do in PowerShell, or by tweaking the registry by hand.
Here's a script that will change things over.
Because you're going to be changing HKEY_CLASSES_ROOT, you're going to need to be running as administrator:
# This a "provider qualified" path to the edit command
$editRegistryPath = 'Microsoft.PowerShell.Core\Registry::HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\Edit\Command'
# This is how we will get the default value
$defaultEdit = Get-ItemProperty $editRegistryPath -Name '(default)'
# If we couldn't get it, something's wrong, so return
if (-not $defaultEdit) {
return
}
# Get the path to code.cmd (this must be in $env:PATH)
$codePath = Get-Command code -CommandType Application | Select-Object -First 1 | Select-Object -ExpandProperty Source
# Change the property. Make sure we quote our command name and our arguments.
Set-ItemProperty -Path $editRegistryPath -Name '(default)' -Value "`"$($codePath)`" `"%1`""
You simply need to change the exe path to vs code in the following registry key
Computer\HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\Edit\Command
Double click the default property and replace the ISE path with the path to your vscode.exe

Can I remove the location from my terminal in VSC? [duplicate]

So I've just downloaded Visual Studio Code to use as my default IDE for learning Python. I'm running on a 64-bit machine so I made the default terminal windows powershell.
The place where I'll be saving most of my files is about 8 folders deep which all show up in the terminal before any commands can be written. Is there any way to hide or shorten the file path in the terminal?
As #Biclops suggested, there is good info here: configure PowerShell to only show the current folder in the prompt
However, I needed more basic info to get this to work. This is a very good resource to get started: Windows PowerShell Profiles. So I first followed the steps suggested there:
[always using vscode's integrated terminal using PowerShell]
test-path $profile (is there a profile set up?)
new-item -path $profile -itemtype file -force (assuming the answer to the above is false)
notepad $profile (opens notepad)
paste in (from the SuperUser answer above)
function prompt {
$p = Split-Path -leaf -path (Get-Location)
"$p> "
}
save (you shouldn't have to chose a location, it is already done for you)
reload vscode - you will probably get an error message about running scripts (or just do next step before reload)
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser (at your integrated terminal PS prompt, also from the SuperUser answer)
reload vscode
You should be good to go!
Great Question and Great Answers.
But this information is dated, and Windows is currently updating from Windows 10 to Windows 11. In addition, the base Windows PowerShell has been incorporated into the new Windows Terminal Preview app. which is being used here.
The solution provided above by Mark and Tarruda23 (above) almost works. But Windows throws an error - described below.
The steps:
First, it was necessary to determine whether a profile existed. Using the Windows Explorer, the following path was checked. If a profile already exists, this path shows where an existing profile should be found. On this PC, no profile ( .ps1 ) file existed and this folder was empty. Don't close the Explorer.
C:\Users\prior\OneDrive\Documents\WindowsPowerShell
Since no file exists, a new file needed to be created. This new file must be saved with a specific name - shown below.
Navigate to the empty folder and open PowerShell. The .ps1 profile must be created and saved in this folder. Use the Powershell's build-in text editor to create the new file. Type:
ISE
Then type or paste the following into the empty text file:
function prompt {
$p = Split-Path -leaf -path (Get-Location)
"$p> "
}
Save this file with the following name:
Microsoft.PowerShell_profile.ps1
Use the PowerShell to open Notepad and check that .ps1 file. This demonstrates the Windows system has found the new .ps1. Next close the Notepad.
Notepad $profile
Now the PowerShell is probably displaying an error message in red text. This error message reads in part:
\Microsoft.PowerShell _profile.ps1 cannot be loaded because running scripts is disabled on this system.
Run the PowerShell as the Administrator. Type the following.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
Windows will prompt with a question:
Do you want to change the execution policy?
Type y for yes. This will change and remove the Windows default settings that prevents running script files. Once done, this will remove that error message.
All should be good now. PowerShell will now start and run with shorter and abbreviated PS> prompt that shows either the User name, or the name of the folder where the PowerShell is running.

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
}

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's Clear-History doesn't clear history

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
}