From 942c68e796c2ff8c40ed31faffe9527e15c8339c Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 23 Apr 2018 14:27:47 -0700 Subject: [PATCH] Add '-WorkingDirectory' parameter to pwsh (#6612) Add `-WorkingDirectory` parameter to `pwsh` to allow starting in right working directory. --- .../host/msh/CommandLineParameterParser.cs | 21 +++++++++- .../host/msh/ConsoleHost.cs | 25 ++++++++++++ .../CommandLineParameterParserStrings.resx | 5 ++- .../resources/ManagedEntranceStrings.resx | 7 ++++ test/powershell/Host/ConsoleHost.Tests.ps1 | 38 +++++++++++++++++++ 5 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs index 0854b7a2c..db86a208f 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs @@ -187,7 +187,8 @@ namespace Microsoft.PowerShell "executionpolicy", "command", "settingsfile", - "help" + "help", + "workingdirectory" }; internal CommandLineParameterParser(PSHostUserInterface hostUI, string bannerText, string helpText) @@ -387,6 +388,11 @@ namespace Microsoft.PowerShell get { return _noInteractive; } } + internal string WorkingDirectory + { + get { return _workingDirectory; } + } + private void ShowHelp() { Dbg.Assert(_helpText != null, "_helpText should not be null"); @@ -767,6 +773,18 @@ namespace Microsoft.PowerShell _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. @@ -1223,6 +1241,7 @@ namespace Microsoft.PowerShell private Collection _collectedArgs = new Collection(); private string _file; private string _executionPolicy; + private string _workingDirectory; } } // namespace diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs index a5a0bb0ce..f40c74a15 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs +++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs @@ -1752,6 +1752,31 @@ namespace Microsoft.PowerShell 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) { diff --git a/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx b/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx index d600de01d..8c6eda44c 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx +++ b/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx @@ -187,7 +187,7 @@ Cannot process the command because -Configuration requires an argument that is a remote endpoint configuration name. Specify this argument and try again. - Cannot process the command because -SettingsFile requires a file path. Supply a path for the SettingsFile parameter and then try the command again. + Cannot process the command because -SettingsFile requires an argument that is a file path. Processing -SettingsFile '{0}' failed: {1}. Specify a valid path for the -SettingsFile parameter. @@ -201,4 +201,7 @@ Parameter -WindowStyle is not implemented on this platform. + + Cannot process the command because -WorkingDirectory requires an argument that is a directory path. + diff --git a/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx b/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx index 6f33bbf89..72ae00245 100644 --- a/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx +++ b/src/Microsoft.PowerShell.ConsoleHost/resources/ManagedEntranceStrings.resx @@ -132,6 +132,7 @@ Type 'help' to get help. [-ExecutionPolicy <ExecutionPolicy>] [-InputFormat {Text | XML}] [-Interactive] [-NoExit] [-NoLogo] [-NonInteractive] [-NoProfile] [-OutputFormat {Text | XML}] [-Version] [-WindowStyle <style>] + [-WorkingDirectory <directoryPath>] pwsh[.exe] -h | -Help | -? | /? @@ -249,6 +250,12 @@ All parameters are case-insensitive. -WindowStyle | -w Sets the window style to Normal, Minimized, Maximized or Hidden. + +-WorkingDirectory | -wd + Sets the working directory at the start of PowerShell given a valid PowerShell directory path. + Executing `Set-Location -LiteralPath <path>` at startup. + + Example: pwsh -WorkingDirectory ~ diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1 index caa075e82..1a633559b 100644 --- a/test/powershell/Host/ConsoleHost.Tests.ps1 +++ b/test/powershell/Host/ConsoleHost.Tests.ps1 @@ -561,6 +561,44 @@ foo } } } + + Context "-WorkingDirectory parameter" { + BeforeAll { + $folderName = (New-Guid).ToString() + " test"; + New-Item -Path ~/$folderName -ItemType Directory + $ExitCodeBadCommandLineParameter = 64 + } + + AfterAll { + Remove-Item ~/$folderName -Force -ErrorAction SilentlyContinue + } + + It "Can set working directory to ''" -TestCases @( + @{ 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 '' 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 {