Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1978,6 +1978,22 @@ internal override IList<PSModuleInfo> ImportModulesUsingWinCompat(IEnumerable<st
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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4792,7 +4792,7 @@ internal static Collection<string> GetResolvedPathCollection(string filePath, Ex
return filePaths;
}

internal PSSession GetWindowsPowerShellCompatRemotingSession()
internal static PSSession GetWindowsPowerShellCompatRemotingSession()
{
PSSession result = null;
var commandInfo = new CmdletInfo("Get-PSSession", typeof(GetPSSessionCommand));
Expand All @@ -4807,7 +4807,7 @@ internal PSSession GetWindowsPowerShellCompatRemotingSession()
return result;
}

internal PSSession CreateWindowsPowerShellCompatResources()
internal static PSSession CreateWindowsPowerShellCompatResources()
{
PSSession compatSession = null;
lock (s_WindowsPowerShellCompatSyncObject)
Expand All @@ -4832,13 +4832,18 @@ internal PSSession CreateWindowsPowerShellCompatResources()
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);
Expand All @@ -4848,6 +4853,21 @@ internal void CleanupWindowsPowerShellCompatResources()
}
}

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(
Expand Down Expand Up @@ -4944,7 +4964,7 @@ internal void RemoveModule(PSModuleInfo module, string moduleNameInRemoveModuleC

if (module.IsWindowsPowerShellCompatModule && (System.Threading.Interlocked.Decrement(ref s_WindowsPowerShellCompatUsageCounter) == 0))
{
CleanupWindowsPowerShellCompatResources();
CleanupWindowsPowerShellCompatResources(this.SessionState);
}

// First remove cmdlets from the session state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down