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 @@ -187,7 +187,8 @@ internal class CommandLineParameterParser
"executionpolicy",
"command",
"settingsfile",
"help"
"help",
"workingdirectory"
};

internal CommandLineParameterParser(PSHostUserInterface hostUI, string bannerText, string helpText)
Expand Down Expand Up @@ -387,6 +388,11 @@ internal bool NonInteractive
get { return _noInteractive; }
}

internal string WorkingDirectory
{
get { return _workingDirectory; }
}

private void ShowHelp()
{
Dbg.Assert(_helpText != null, "_helpText should not be null");
Expand Down Expand Up @@ -767,6 +773,18 @@ private void ParseHelper(string[] args)
_staMode = false;
}
#endif
else if (MatchSwitch(switchKey, "workingdirectory", "wo") || MatchSwitch(switchKey, "wd", "wd"))
{
++i;
if (i >= args.Length)
{
WriteCommandLineError(
CommandLineParameterParserStrings.MissingWorkingDirectoryArgument);
break;
}

_workingDirectory = args[i];
}
else
{
// The first parameter we fail to recognize marks the beginning of the file string.
Expand Down Expand Up @@ -1223,6 +1241,7 @@ private bool CollectArgs(string[] args, ref int i)
private Collection<CommandParameter> _collectedArgs = new Collection<CommandParameter>();
private string _file;
private string _executionPolicy;
private string _workingDirectory;
}
} // namespace

25 changes: 25 additions & 0 deletions src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1752,6 +1752,31 @@ private void DoRunspaceInitialization(bool skipProfiles, string initialCommand,
TelemetryAPI.ReportStartupTelemetry(this);
#endif

// If working directory was specified, set it
if (s_cpp != null && s_cpp.WorkingDirectory != null)
{
Pipeline tempPipeline = exec.CreatePipeline();
var command = new Command("Set-Location");
command.Parameters.Add("LiteralPath", s_cpp.WorkingDirectory);
tempPipeline.Commands.Add(command);

Exception exception;
if (IsRunningAsync)
{
exec.ExecuteCommandAsyncHelper(tempPipeline, out exception, Executor.ExecutionOptions.AddOutputter);
}
else
{
exec.ExecuteCommandHelper(tempPipeline, out exception, Executor.ExecutionOptions.AddOutputter);
}

if (exception != null)
{
_lastRunspaceInitializationException = exception;
ReportException(exception, exec);
}
}

// If a file was specified as the argument to run, then run it...
if (s_cpp != null && s_cpp.File != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
<value>Cannot process the command because -Configuration requires an argument that is a remote endpoint configuration name. Specify this argument and try again.</value>
</data>
<data name="MissingSettingsFileArgument" xml:space="preserve">
<value>Cannot process the command because -SettingsFile requires a file path. Supply a path for the SettingsFile parameter and then try the command again.</value>
<value>Cannot process the command because -SettingsFile requires an argument that is a file path.</value>
</data>
<data name="InvalidSettingsFileArgument" xml:space="preserve">
<value>Processing -SettingsFile '{0}' failed: {1}. Specify a valid path for the -SettingsFile parameter.</value>
Expand All @@ -201,4 +201,7 @@
<data name="WindowStyleArgumentNotImplemented" xml:space="preserve">
<value>Parameter -WindowStyle is not implemented on this platform.</value>
</data>
<data name="MissingWorkingDirectoryArgument" xml:space="preserve">
<value>Cannot process the command because -WorkingDirectory requires an argument that is a directory path.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ Type 'help' to get help.</value>
[-ExecutionPolicy &lt;ExecutionPolicy&gt;] [-InputFormat {Text | XML}]
[-Interactive] [-NoExit] [-NoLogo] [-NonInteractive] [-NoProfile]
[-OutputFormat {Text | XML}] [-Version] [-WindowStyle &lt;style&gt;]
[-WorkingDirectory &lt;directoryPath&gt;]

pwsh[.exe] -h | -Help | -? | /?

Expand Down Expand Up @@ -249,6 +250,12 @@ All parameters are case-insensitive.</value>

-WindowStyle | -w
Sets the window style to Normal, Minimized, Maximized or Hidden.

-WorkingDirectory | -wd

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like -wo should also be mentioned in the help text.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pwsh parameters work the same as PowerShell parameters in that if there is sufficient difference in the name, it will figure it out. So -wi will work for -windowstyle and -wo will work for -workingdirectory, although -w is reserved for -windowstyle. So for that reason, I don't think it needs to be added explicitly to the help.

Sets the working directory at the start of PowerShell given a valid PowerShell directory path.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should mention that this "valid PowerShell directory path" is used as a LiteralPath.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this true for all providers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be true for all well written providers

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sense add this to the help or online help?

Executing `Set-Location -LiteralPath &lt;path&gt;` at startup.

Example: pwsh -WorkingDirectory ~
</value>
</data>
</root>
38 changes: 38 additions & 0 deletions test/powershell/Host/ConsoleHost.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,44 @@ foo
}
}
}

Context "-WorkingDirectory parameter" {
BeforeAll {
$folderName = (New-Guid).ToString() + " test";
New-Item -Path ~/$folderName -ItemType Directory
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use $pwd instead of ~ alias? Below too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For installer use, I think we want to test ~ for the user home directory

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder - is this a suitable place for ~ tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent is to validate a path understood by the FileSystemProvider which abstracts ~ for Windows and Unix

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why we place FileSystemProvider tests in ConsoleHost.Tests.ps1.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation for this parameter is that any file system provider path is accepted, and ~ is handled by the provider which is why I added that test case.

$ExitCodeBadCommandLineParameter = 64
}

AfterAll {
Remove-Item ~/$folderName -Force -ErrorAction SilentlyContinue
}

It "Can set working directory to '<value>'" -TestCases @(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to have a case where $value has a space in directory name.
Also a case for Windows-style path separators in directory path.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add those cases

@{ value = "~" ; expectedPath = $((Get-Item ~).FullName) },
@{ value = "~/$folderName"; expectedPath = $((Get-Item ~/$folderName).FullName) },
@{ value = "~\$folderName"; expectedPath = $((Get-Item ~\$folderName).FullName) }
) {
param($value, $expectedPath)
$output = & $powershell -WorkingDirectory "$value" -Command "`$pwd.Path"
$output | Should -BeExactly $expectedPath
}

It "Can use '<parameter>' to set working directory" -TestCases @(
@{ parameter = '-workingdirectory' },
@{ parameter = '-wd' },
@{ parameter = '-wo' }
) {
param($parameter)
$output = & $powershell $parameter ~ -Command "`$pwd.Path"
$output | Should -BeExactly $((Get-Item ~).FullName)
}

It "Error case if -WorkingDirectory isn't given argument as last on command line" {
$output = & $powershell -WorkingDirectory
$LASTEXITCODE | Should -Be $ExitCodeBadCommandLineParameter
$output | Should -Not -BeNullOrEmpty
}
}
}

Describe "WindowStyle argument" -Tag Feature {
Expand Down