Created
May 6, 2014 05:05
-
-
Save gpduck/659dee8053cff25e095e to your computer and use it in GitHub Desktop.
A crude attempt at providing file change notifications for ISE.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") > $Null | |
$Watchers = @{} | |
$TabCollectionChangedEvent = { | |
$EventArgs.NewItems | %{ | |
Register-ObjectEvent -InputObject $_.Files -EventName CollectionChanged -Action $FileCollectionChangedEvent | |
} | |
} | |
$FileCollectionChangedEvent = { | |
Write-Debug "FileCollectionChanged" | |
if($EventArgs.Action -eq "Add") { | |
$NewFile = $EventArgs.NewItems[0] | |
$ParentFolder = Split-Path -Path $NewFile.FullPath -Parent | |
if(!$Watchers.ContainsKey($ParentFolder)) { | |
Write-Debug "Adding Watcher" | |
$Watcher = New-Object System.IO.FileSystemWatcher($ParentFolder) | |
$Watcher.NotifyFilter = [System.IO.NotifyFilters]::Size -bor [System.IO.NotifyFilters]::LastWrite | |
$Watcher.EnableRaisingEvents = $true | |
$Watchers[$ParentFolder] = [PSCustomObject]@{ | |
Watcher = $Watcher; | |
WatchedFiles = (New-Object Collections.ArrayList) | |
EventSubscriber = $null; | |
} | |
Write-Debug $Watchers[$ParentFolder].WatchedFiles.GetType() | |
$Watchers[$ParentFolder].WatchedFiles.Add($NewFile.FullPath) | |
$Watchers[$ParentFolder].EventSubscriber = Register-ObjectEvent -InputObject $Watcher -EventName Changed -Action $FileChangedEvent | |
} else { | |
$Watchers[$ParentFolder].WatchedFiles.Add($NewFile.FullPath) | |
} | |
} elseif($EventArgs.Action -eq "Remove") { | |
$OldFile = $EventArgs.OldItems[0] | |
Write-Debug "Removing file $($OldFile.FullPath)" | |
$ParentFolder = Split-Path -Path $OldFile.FullPath -Parent | |
if($Watchers.ContainsKey($ParentFolder)) { | |
$Watchers[$ParentFolder].WatchedFiles.Remove($OldFile.FullPath) | |
if($Watchers[$ParentFolder].WatchedFiles.Count -eq 0) { | |
Unregister-Event -SourceIdentifier $Watchers[$ParentFolder].EventSubscriber.Name | |
$Watchers[$ParentFolder].Watcher.EnableRaisingEvents = $false | |
$Watchers[$ParentFolder].Watcher.Dispose() | |
if((Get-Job -Name $Watchers[$ParentFolder].EventSubscriber.Name).State -ne "Failed") { | |
Remove-Job -Name $Watchers[$ParentFolder].EventSubscriber.Name | |
} | |
$Watchers.Remove($ParentFolder) | |
} | |
} | |
} | |
} | |
$FileChangedEvent = { | |
Write-Debug "FileChanged $($EventArgs.Action)" | |
$ChangedFile = $EventArgs.FullPath | |
$ParentFolder = Split-Path -Path $ChangedFile -Parent | |
Write-Debug $psISE.CurrentPowershellTab.Files.SelectedFile.FullPath | |
Write-Debug $ChangedFile | |
# Don't provide notifications for the current file. This is the only way I could prevent self notifiying when ISE saved a file. | |
if($Watchers[$ParentFolder].WatchedFiles -contains $ChangedFile -and $psISE.CurrentPowershellTab.Files.SelectedFile.FullPath -ne $ChangedFile) { | |
$psISE.PowerShellTabs | %{ | |
$Tab = $_ | |
$FilesToReload = $Tab.Files | ?{$_.FullPath -eq $ChangedFile} | |
$FilesToReload | %{ | |
$ShouldChange = [Microsoft.VisualBasic.Interaction]::MsgBox("File $($_.Fullpath) has changed outside the editor. Would you like to reload?","YesNo,Question","File Changed") | |
if($ShouldChange -eq "Yes") { | |
#I don't like the Text= method becuase it marks the file as changed | |
$_.Editor.Text = [System.IO.File]::ReadAllText($_.FullPath) | |
#I don't like the remove/add method because it re-orders the tabs and flashes | |
#$Tab.Files.Remove($_) | |
#$Tab.Files.Add($_.FullPath) | |
} | |
} | |
} | |
} | |
} | |
Register-ObjectEvent -InputObject $psISE.PowerShellTabs -EventName CollectionChanged -Action $TabCollectionChangedEvent > $null | |
$psise.PowerShellTabs | %{ | |
Register-ObjectEvent -InputObject $_.Files -EventName CollectionChanged -Action $FileCollectionChangedEvent > $null | |
} |
Thanks for working this up Chris.
Yeah, I was working with the FileSystemWatcher in .NET in PowerShell and getting double events and there are many who get the same issues in C#. It'd be nice to have a solid watcher to use from PS. We could build tools like grunt and gulp in the JavaScript world.
I think it's something for Microsoft to solve in ISE. Then again, the ISE editor is the Visual Studio editor. Too bad this isn't baked in.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm getting double events so you get 2 popups, and then it "manually" updates the contents of the editor from disk, so ISE marks it as modified :(
And it only works for files other than the current one to prevent the ISE saving from triggering the change event.