mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Sync current directory in WinCompat remote session (#11809)
This commit is contained in:
@@ -1978,6 +1978,22 @@ namespace Microsoft.PowerShell.Commands
|
||||
string message = StringUtil.Format(Modules.WinCompatModuleWarning, moduleProxy.Name, WindowsPowerShellCompatRemotingSession.Name);
|
||||
WriteWarning(message);
|
||||
}
|
||||
|
||||
// register LocationChanged handler so that $PWD in Windows PS process mirrors local $PWD changes
|
||||
if (moduleProxyList.Count > 0)
|
||||
{
|
||||
// make sure that we add registration only once to a multicast delegate
|
||||
SyncCurrentLocationDelegate ??= SyncCurrentLocationHandler;
|
||||
var alreadyregistered = this.SessionState.InvokeCommand.LocationChangedAction?.GetInvocationList().Contains(SyncCurrentLocationDelegate);
|
||||
|
||||
if (!alreadyregistered ?? true)
|
||||
{
|
||||
this.SessionState.InvokeCommand.LocationChangedAction += SyncCurrentLocationDelegate;
|
||||
|
||||
// first sync has to be triggered manually
|
||||
SyncCurrentLocationHandler(sender: this, args: new LocationChangedEventArgs(sessionState: null, oldPath: null, newPath: this.SessionState.Path.CurrentLocation));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return moduleProxyList;
|
||||
}
|
||||
|
||||
@@ -4792,7 +4792,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
internal PSSession GetWindowsPowerShellCompatRemotingSession()
|
||||
internal static PSSession GetWindowsPowerShellCompatRemotingSession()
|
||||
{
|
||||
PSSession result = null;
|
||||
var commandInfo = new CmdletInfo("Get-PSSession", typeof(GetPSSessionCommand));
|
||||
@@ -4807,7 +4807,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
return result;
|
||||
}
|
||||
|
||||
internal PSSession CreateWindowsPowerShellCompatResources()
|
||||
internal static PSSession CreateWindowsPowerShellCompatResources()
|
||||
{
|
||||
PSSession compatSession = null;
|
||||
lock (s_WindowsPowerShellCompatSyncObject)
|
||||
@@ -4832,13 +4832,18 @@ namespace Microsoft.PowerShell.Commands
|
||||
return compatSession;
|
||||
}
|
||||
|
||||
internal void CleanupWindowsPowerShellCompatResources()
|
||||
internal static void CleanupWindowsPowerShellCompatResources(SessionState sessionState)
|
||||
{
|
||||
lock (s_WindowsPowerShellCompatSyncObject)
|
||||
{
|
||||
var compatSession = GetWindowsPowerShellCompatRemotingSession();
|
||||
if (compatSession != null)
|
||||
{
|
||||
if (sessionState?.InvokeCommand.LocationChangedAction != null)
|
||||
{
|
||||
sessionState.InvokeCommand.LocationChangedAction -= SyncCurrentLocationDelegate;
|
||||
}
|
||||
|
||||
var commandInfo = new CmdletInfo("Remove-PSSession", typeof(RemovePSSessionCommand));
|
||||
using var ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace);
|
||||
ps.AddCommand(commandInfo);
|
||||
@@ -4848,6 +4853,21 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SyncCurrentLocationHandler(object sender, LocationChangedEventArgs args)
|
||||
{
|
||||
PSSession compatSession = GetWindowsPowerShellCompatRemotingSession();
|
||||
if (compatSession?.Runspace.RunspaceStateInfo.State == RunspaceState.Opened)
|
||||
{
|
||||
using var ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace);
|
||||
ps.AddCommand(new CmdletInfo("Invoke-Command", typeof(InvokeCommandCommand)));
|
||||
ps.AddParameter("Session", compatSession);
|
||||
ps.AddParameter("ScriptBlock", ScriptBlock.Create(string.Format("Set-Location -Path '{0}'", args.NewPath.Path)));
|
||||
ps.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
internal static System.EventHandler<LocationChangedEventArgs> SyncCurrentLocationDelegate;
|
||||
|
||||
internal virtual IList<PSModuleInfo> ImportModulesUsingWinCompat(IEnumerable<string> moduleNames, IEnumerable<ModuleSpecification> moduleFullyQualifiedNames, ImportModuleOptions importModuleOptions) { throw new System.NotImplementedException(); }
|
||||
|
||||
private void RemoveTypesAndFormatting(
|
||||
@@ -4944,7 +4964,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
|
||||
if (module.IsWindowsPowerShellCompatModule && (System.Threading.Interlocked.Decrement(ref s_WindowsPowerShellCompatUsageCounter) == 0))
|
||||
{
|
||||
CleanupWindowsPowerShellCompatResources();
|
||||
CleanupWindowsPowerShellCompatResources(this.SessionState);
|
||||
}
|
||||
|
||||
// First remove cmdlets from the session state
|
||||
|
||||
+28
@@ -327,6 +327,34 @@ Describe "Import-Module from CompatiblePSEditions-checked paths" -Tag "CI" {
|
||||
[System.Management.Automation.Internal.InternalTestHooks]::SetTestHook("TestWindowsPowerShellVersionString", $null)
|
||||
}
|
||||
}
|
||||
|
||||
It "Current location in Windows PS mirrors local current location" -TestCases $failCases -Skip:(-not $IsWindows) {
|
||||
param($Editions, $ModuleName, $Result)
|
||||
$pwdBackup = $PWD
|
||||
$location = Join-Path $TestDrive "Custom dir" (New-Guid).ToString()
|
||||
$null = New-Item -Path $location -ItemType Directory
|
||||
Push-Location -Path $location
|
||||
try
|
||||
{
|
||||
# right after module import remote $PWD should be synchronized
|
||||
Import-Module $ModuleName -UseWindowsPowerShell
|
||||
$s = Get-PSSession -Name WinPSCompatSession
|
||||
(Invoke-Command -Session $s {Get-Location}).Path | Should -BeExactly $PWD.Path
|
||||
|
||||
# after local $PWD changes remote $PWD should be synchronized
|
||||
Set-Location -Path ..
|
||||
(Invoke-Command -Session $s {Get-Location}).Path | Should -BeExactly $PWD.Path
|
||||
|
||||
# after WinCompat cleanup local $PWD changes should not cause errors
|
||||
Remove-module $ModuleName -Force
|
||||
|
||||
Pop-Location
|
||||
}
|
||||
finally
|
||||
{
|
||||
Set-Location $pwdBackup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context "Imports from absolute path" {
|
||||
|
||||
Reference in New Issue
Block a user