diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs
index fd6823d6b2a..0bfb719e7be 100644
--- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs
+++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs
@@ -169,6 +169,30 @@ public override void WriteWarningLine(string message)
internal class CommandLineParameterParser
{
+ internal static string[] validParameters = {
+ "psconsoleFile",
+ "version",
+ "nologo",
+ "noexit",
+#if !CORECLR
+ "sta",
+ "mta",
+#endif
+ "noprofile",
+ "noninteractive",
+ "inputformat",
+ "outputformat",
+#if !UNIX
+ "windowstyle",
+#endif
+ "encodedcommand",
+ "configurationname",
+ "file",
+ "executionpolicy",
+ "command",
+ "help"
+ };
+
internal CommandLineParameterParser(PSHostUserInterface hostUI, string bannerText, string helpText)
{
if (hostUI == null) { throw new PSArgumentNullException("hostUI"); }
@@ -593,7 +617,7 @@ private void ParseHelper(string[] args)
break;
}
}
-#if !CORECLR // windowstyle parameter not supported on NanoServer because ProcessWindowStyle does Not exist on CoreCLR
+#if !UNIX
else if (MatchSwitch(switchKey, "windowstyle", "w"))
{
++i;
@@ -657,7 +681,7 @@ private void ParseHelper(string[] args)
WriteCommandLineError(
"The -module option can only be specified with the -iss option.",
showHelp: true,
- showBanner: true);
+ showBanner: false);
break;
}
@@ -880,7 +904,7 @@ bool TryGetBoolValue(string arg, out bool boolValue)
WriteCommandLineError(
CommandLineParameterParserStrings.MissingFileArgument,
showHelp: true,
- showBanner: true);
+ showBanner: false);
return false;
}
@@ -924,15 +948,36 @@ bool TryGetBoolValue(string arg, out bool boolValue)
{
WriteCommandLineError(
string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.InvalidFileArgument, args[i], exceptionMessage),
- showBanner: true);
+ showBanner: false);
return false;
}
if (!System.IO.File.Exists(_file))
{
+ if (args[i].StartsWith("-") && args[i].Length > 1)
+ {
+ string param = args[i].Substring(1, args[i].Length - 1).ToLower();
+ StringBuilder possibleParameters = new StringBuilder();
+ foreach (string validParameter in validParameters)
+ {
+ if (validParameter.Contains(param))
+ {
+ possibleParameters.Append("\n -");
+ possibleParameters.Append(validParameter);
+ }
+ }
+ if (possibleParameters.Length > 0)
+ {
+ WriteCommandLineError(
+ string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.InvalidArgument, args[i]),
+ showBanner: false);
+ WriteCommandLineError(possibleParameters.ToString(), showBanner: false);
+ return false;
+ }
+ }
WriteCommandLineError(
string.Format(CultureInfo.CurrentCulture, CommandLineParameterParserStrings.ArgumentFileDoesNotExist, args[i]),
- showBanner: true);
+ showBanner: false);
return false;
}
diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs
index 2513fe9e963..0f0c7f5cc4d 100644
--- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs
+++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleControl.cs
@@ -445,8 +445,7 @@ internal enum KeyboardFlag : uint
internal const int SW_FORCEMINIMIZE = 11;
internal const int SW_MAX = 11;
-
-#if !CORECLR // ProcessWindowStyle does Not exist on CoreCLR
+#if !UNIX
///
/// Code to control the display properties of the a window...
///
diff --git a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs
index c2eb41a1f85..a2bb66e1ce8 100644
--- a/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs
+++ b/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs
@@ -53,10 +53,10 @@ internal sealed partial class ConsoleHost
{
#region static methods
- internal const uint ExitCodeSuccess = 0x00000000;
- internal const uint ExitCodeCtrlBreak = 0xFFFE0000;
- internal const uint ExitCodeInitFailure = 0xFFFF0000;
- internal const uint ExitCodeBadCommandLineParameter = 0xFFFD0000;
+ internal const int ExitCodeSuccess = 0;
+ internal const int ExitCodeCtrlBreak = 128+21; // SIGBREAK
+ internal const int ExitCodeInitFailure = 70; // Internal Software Error
+ internal const int ExitCodeBadCommandLineParameter = 64; // Command Line Usage Error
// NTRAID#Windows Out Of Band Releases-915506-2005/09/09
// Removed HandleUnexpectedExceptions infrastructure
@@ -212,10 +212,7 @@ internal static int Start(
{
s_theConsoleHost.ui.WriteErrorLine(ConsoleHostStrings.ConflictingServerModeParameters);
}
- unchecked
- {
- return (int)ExitCodeBadCommandLineParameter;
- }
+ return ExitCodeBadCommandLineParameter;
}
// First check for and handle PowerShell running in a server mode.
diff --git a/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx b/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx
index 9209d37a603..92ef090cd2a 100644
--- a/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx
+++ b/src/Microsoft.PowerShell.ConsoleHost/resources/CommandLineParameterParserStrings.resx
@@ -252,7 +252,7 @@ EXAMPLES
Processing -File '{0}' failed because the file does not have a '.ps1' extension. Specify a valid Windows PowerShell script file name, and then try again.
- The argument '{0}' to the -File parameter does not exist. Provide the path to an existing '.ps1' file as an argument to the -File parameter.
+ The argument '{0}' is not recognized as the name of a script file. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
Cannot process the command because the value specified with -EncodedArguments is not properly encoded. The value must be Base64 encoded.
@@ -269,4 +269,7 @@ EXAMPLES
Cannot process the command because -Configuration requires an argument that is a remote endpoint configuration name. Specify this argument and try again.
+
+ Invalid argument '{0}', did you mean:
+
diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1
index 4bb8b8b0581..16c8032381c 100644
--- a/test/powershell/Host/ConsoleHost.Tests.ps1
+++ b/test/powershell/Host/ConsoleHost.Tests.ps1
@@ -52,6 +52,7 @@ Describe "ConsoleHost unit tests" -tags "Feature" {
BeforeAll {
$powershell = Join-Path -Path $PsHome -ChildPath "powershell"
+ $ExitCodeBadCommandLineParameter = 64
function NewProcessStartInfo([string]$CommandLine, [switch]$RedirectStdIn)
{
@@ -492,6 +493,95 @@ foo
powershell -v | Should Match $psversiontable.GitCommitId
}
}
+
+ Context "Ambiguous arguments" {
+ It "Ambiguous argument '' should return possible matches" -TestCases @(
+ @{testArg="-no";expectedMatches=@("-nologo","-noexit","-noprofile","-noninteractive")},
+ @{testArg="-format";expectedMatches=@("-inputformat","-outputformat")}
+ ) {
+ param($testArg, $expectedMatches)
+ $output = & $powershell $testArg -File foo 2>&1
+ $LASTEXITCODE | Should Be $ExitCodeBadCommandLineParameter
+ $outString = [String]::Join(",", $output)
+ foreach ($expectedMatch in $expectedMatches)
+ {
+ $outString | Should Match $expectedMatch
+ }
+ }
+ }
+}
+
+Describe "WindowStyle argument" -Tag Feature {
+ BeforeAll {
+ $defaultParamValues = $PSDefaultParameterValues.Clone()
+ $PSDefaultParameterValues["it:skip"] = !$IsWindows
+
+ if ($IsWindows)
+ {
+ $ExitCodeBadCommandLineParameter = 64
+ Add-Type -Name User32 -Namespace Test -MemberDefinition @"
+public static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)
+{
+ WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
+ placement.length = Marshal.SizeOf(placement);
+ GetWindowPlacement(hwnd, ref placement);
+ return placement;
+}
+
+[DllImport("user32.dll", SetLastError = true)]
+[return: MarshalAs(UnmanagedType.Bool)]
+public static extern bool GetWindowPlacement(
+ IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
+
+[Serializable]
+[StructLayout(LayoutKind.Sequential)]
+public struct WINDOWPLACEMENT
+{
+ public int length;
+ public int flags;
+ public ShowWindowCommands showCmd;
+ public System.Drawing.Point ptMinPosition;
+ public System.Drawing.Point ptMaxPosition;
+ public System.Drawing.Rectangle rcNormalPosition;
+}
+
+public enum ShowWindowCommands : int
+{
+ Hidden = 0,
+ Normal = 1,
+ Minimized = 2,
+ Maximized = 3,
+}
+"@
+ }
+ }
+
+ AfterAll {
+ $global:PSDefaultParameterValues = $defaultParamValues
+ }
+
+ It "-WindowStyle should work on Windows" -TestCases @(
+ @{WindowStyle="Normal"},
+ @{WindowStyle="Minimized"},
+ @{WindowStyle="Maximized"} # hidden doesn't work in CI/Server Core
+ ) {
+ param ($WindowStyle)
+ $ps = Start-Process powershell -ArgumentList "-WindowStyle $WindowStyle -noexit -interactive" -PassThru
+ $startTime = Get-Date
+ $showCmd = "Unknown"
+ while (((Get-Date) - $startTime).TotalSeconds -lt 10 -and $showCmd -ne $WindowStyle)
+ {
+ Start-Sleep -Milliseconds 100
+ $showCmd = ([Test.User32]::GetPlacement($ps.MainWindowHandle)).showCmd
+ }
+ $showCmd | Should BeExactly $WindowStyle
+ $ps | Stop-Process -Force
+ }
+
+ It "Invalid -WindowStyle returns error" {
+ powershell -WindowStyle invalid
+ $LASTEXITCODE | Should Be $ExitCodeBadCommandLineParameter
+ }
}
Describe "Console host api tests" -Tag CI {