diff --git a/src/System.Management.Automation/engine/InitialSessionState.cs b/src/System.Management.Automation/engine/InitialSessionState.cs
index c30e199b2b1b..0c6e373c5fef 100644
--- a/src/System.Management.Automation/engine/InitialSessionState.cs
+++ b/src/System.Management.Automation/engine/InitialSessionState.cs
@@ -1678,6 +1678,7 @@ public InitialSessionState Clone()
ss.ThreadOptions = this.ThreadOptions;
ss.ThrowOnRunspaceOpenError = this.ThrowOnRunspaceOpenError;
ss.ApartmentState = this.ApartmentState;
+ ss.WorkingDirectory = this.WorkingDirectory;
foreach (ModuleSpecification modSpec in this.ModuleSpecificationsToImport)
{
@@ -1831,6 +1832,12 @@ public Microsoft.PowerShell.ExecutionPolicy ExecutionPolicy
///
public bool ThrowOnRunspaceOpenError { get; set; } = false;
+ ///
+ /// If not null, the working directory of the runspace is set to this path. If null,
+ /// the process working directory is used as a default.
+ ///
+ public string WorkingDirectory { get; set; } = null;
+
///
/// This property will be set only if we are refreshing the Type/Format settings by calling UpdateTypes/UpdateFormats directly.
/// In this case, we should wait until all type/format entries get processed. After that, if there were errors
@@ -2128,6 +2135,7 @@ public virtual HashSet StartupScripts
private readonly object _syncObject = new object();
+ /// User configured a custom WorkingDirectory, which does not exist in the configured providers.
internal void Bind(ExecutionContext context, bool updateOnly, PSModuleInfo module, bool noClobber, bool local, bool setLocation)
{
Host = context.EngineHostInterface;
@@ -2231,7 +2239,7 @@ internal void Bind(ExecutionContext context, bool updateOnly, PSModuleInfo modul
}
}
- SetSessionStateDrive(context, setLocation: setLocation);
+ SetSessionStateDrive(context, setLocation, WorkingDirectory);
}
private void Bind_SetVariables(SessionStateInternal ss)
@@ -3331,6 +3339,7 @@ private RunspaceOpenModuleLoadException ValidateAndReturnRunspaceOpenModuleLoadE
/// This allows for runspace reuse with minimal chance for contamination.
///
///
+ /// User configured a custom WorkingDirectory, which does not exist in the configured providers.
internal void ResetRunspaceState(ExecutionContext context)
{
lock (_syncObject)
@@ -3370,7 +3379,7 @@ internal void ResetRunspaceState(ExecutionContext context)
InitialSessionState.CreateQuestionVariable(context);
// Reset the path for this runspace.
- SetSessionStateDrive(context, true);
+ SetSessionStateDrive(context, true, WorkingDirectory);
// Reset the event, transaction and debug managers.
context.ResetManagers();
@@ -3381,7 +3390,7 @@ internal void ResetRunspaceState(ExecutionContext context)
}
}
- private static bool TryInitSessionStateCurrentDrive(ExecutionContext context)
+ private static bool TryInitSessionStateCurrentDrive(ExecutionContext context, string location)
{
try
{
@@ -3408,13 +3417,14 @@ private static bool TryInitSessionStateCurrentDrive(ExecutionContext context)
}
else
{
- ItemNotFoundException itemNotFound = new(Environment.CurrentDirectory, "PathNotFound", SessionStateStrings.PathNotFound);
+ ItemNotFoundException itemNotFound = new(location ?? Environment.CurrentDirectory, "PathNotFound", SessionStateStrings.PathNotFound);
context.ReportEngineStartupError(itemNotFound);
return false;
}
}
- internal static void SetSessionStateDrive(ExecutionContext context, bool setLocation)
+ /// User configured a custom WorkingDirectory, which does not exist in the configured providers.
+ internal static void SetSessionStateDrive(ExecutionContext context, bool setLocation, string location)
{
if (context.EngineSessionState.ProviderCount == 0)
{
@@ -3424,7 +3434,7 @@ internal static void SetSessionStateDrive(ExecutionContext context, bool setLoca
// NTRAID#Windows Out Of Band Releases-908481-2005/07/01-JeffJon
// Make sure we have a CurrentDrive set so that we can deal with
// UNC paths
- if (context.EngineSessionState.CurrentDrive == null && !TryInitSessionStateCurrentDrive(context))
+ if (context.EngineSessionState.CurrentDrive == null && !TryInitSessionStateCurrentDrive(context, location))
{
return;
}
@@ -3436,7 +3446,16 @@ internal static void SetSessionStateDrive(ExecutionContext context, bool setLoca
var providerContext = new CmdletProviderContext(context) { SuppressWildcardExpansion = true };
- // Set the starting location to the current process working directory
+ // User set a custom initial working directory.
+ if (location != null)
+ {
+ // If the location is invalid or does not exist, let the exception bubble up; since the user explicitly
+ // configured the working directory, he probably wants to get notified on failure.
+ context.EngineSessionState.SetLocation(location, providerContext);
+ return;
+ }
+
+ // As a fallback, set the starting location to the current process working directory.
// Ignore any errors as the file system provider may not be loaded or
// a drive with the same name as the real file system drive may not have
// been mounted.