From ce2e5d6492873901689b8e60d6d212093164ca57 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 6 Jul 2016 14:59:44 -0700 Subject: [PATCH 1/7] Set UseShellExecute to false in Get-Help --- src/System.Management.Automation/help/HelpCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index ed8593d904..c9bc50ffd5 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -699,7 +699,7 @@ namespace Microsoft.PowerShell.Commands { this.WriteVerbose(string.Format(CultureInfo.InvariantCulture, HelpDisplayStrings.OnlineHelpUri, uriToLaunch.OriginalString)); System.Diagnostics.Process browserProcess = new System.Diagnostics.Process(); - browserProcess.StartInfo.UseShellExecute = true; + browserProcess.StartInfo.UseShellExecute = false; if (Platform.IsWindows) { browserProcess.StartInfo.FileName = uriToLaunch.OriginalString; From afc1d8a4592241eac0d5194cae89c7ffb31df722 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 6 Jul 2016 15:00:01 -0700 Subject: [PATCH 2/7] Use start in Get-Help -Online to open URL on Windows --- .../help/HelpCommands.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index c9bc50ffd5..52a74fed07 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -699,17 +699,25 @@ namespace Microsoft.PowerShell.Commands { this.WriteVerbose(string.Format(CultureInfo.InvariantCulture, HelpDisplayStrings.OnlineHelpUri, uriToLaunch.OriginalString)); System.Diagnostics.Process browserProcess = new System.Diagnostics.Process(); + browserProcess.StartInfo.UseShellExecute = false; + if (Platform.IsWindows) { - browserProcess.StartInfo.FileName = uriToLaunch.OriginalString; - } else if (Platform.IsOSX) { + browserProcess.StartInfo.FileName = "cmd.exe"; + browserProcess.StartInfo.Arguments = string.Format(@"/c ""start /b """" {0}""", uriToLaunch.OriginalString); + } + else if (Platform.IsOSX) + { browserProcess.StartInfo.FileName = "open"; browserProcess.StartInfo.Arguments = uriToLaunch.OriginalString; - } else if (Platform.IsLinux) { + } + else if (Platform.IsLinux) + { browserProcess.StartInfo.FileName = "xdg-open"; browserProcess.StartInfo.Arguments = uriToLaunch.OriginalString; } + browserProcess.Start(); } catch (InvalidOperationException ioe) From ef2ba40ca7f60782de12b50394c0833bdb8789d3 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 6 Jul 2016 15:00:23 -0700 Subject: [PATCH 3/7] Use start in Invoke-Item to open items on Windows Since `UseShellExecute` cannot be used. --- .../namespaces/FileSystemProvider.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 2c83a4ea18..7ee00beb27 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1333,14 +1333,18 @@ namespace Microsoft.PowerShell.Commands { System.Diagnostics.Process invokeProcess = new System.Diagnostics.Process(); + invokeProcess.StartInfo.UseShellExecute = false; + if (Platform.IsWindows) { - System.Diagnostics.Process.Start(path); - } + invokeProcess.StartInfo.FileName = "cmd.exe"; + // start is very picky: the "optional" TITLE as the first argument should always be included, otherwise it can silently fail + invokeProcess.StartInfo.Arguments = string.Format(@"/c ""start /b """" ""{0}""""", path); + } else if (Platform.IsOSX) { invokeProcess.StartInfo.FileName = "open"; invokeProcess.StartInfo.Arguments = path; - } + } else if (Platform.IsLinux) { invokeProcess.StartInfo.FileName = "xdg-open"; invokeProcess.StartInfo.Arguments = path; From 09f20879b8738e69cfa52d4e3131980358c3466b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 6 Jul 2016 15:00:53 -0700 Subject: [PATCH 4/7] Guard use of UseShellExecute in PackageManagement To re-enable elevation, the process will need to fork. For now, don't fail fatally. --- .../Implementation/ProviderServicesImpl.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PackageManagement/Implementation/ProviderServicesImpl.cs b/src/Microsoft.PackageManagement/Implementation/ProviderServicesImpl.cs index 6034776e8c..dc8a2e4c32 100644 --- a/src/Microsoft.PackageManagement/Implementation/ProviderServicesImpl.cs +++ b/src/Microsoft.PackageManagement/Implementation/ProviderServicesImpl.cs @@ -190,9 +190,14 @@ namespace Microsoft.PackageManagement.Internal.Implementation { public int StartProcess(string filename, string arguments, bool requiresElevation, out string standardOutput, IRequest requestObject) { Process p = new Process(); - if (requiresElevation) { +#if !CORECLR + if (requiresElevation) + { p.StartInfo.UseShellExecute = true; - } else { + } + else +#endif + { p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; } From 9a7199b05b1055aaff93d1b96ac8a61a5f6f7860 Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Wed, 6 Jul 2016 15:53:36 -0700 Subject: [PATCH 5/7] Enable Invoke-Item test for Windows --- .../Invoke-Item.Tests.ps1 | 40 +++---------------- 1 file changed, 5 insertions(+), 35 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 index efc9b7917c..f17a716959 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 @@ -2,14 +2,6 @@ using namespace System.Diagnostics Describe "Invoke-Item" { - $tmpDirectory = $TestDrive - $testfile = "testfile.txt" - $testfolder = "newDirectory" - $testlink = "testlink" - $FullyQualifiedFile = Join-Path -Path $tmpDirectory -ChildPath $testfile - $FullyQualifiedFolder = Join-Path -Path $tmpDirectory -ChildPath $testfolder - $FullyQualifiedLink = Join-Path -Path $tmpDirectory -ChildPath $testlink - function NewProcessStartInfo([string]$CommandLine, [switch]$RedirectStdIn) { return [ProcessStartInfo]@{ @@ -39,38 +31,16 @@ Describe "Invoke-Item" { } } - function Clean-State - { - if (Test-Path $FullyQualifiedLink) - { - Remove-Item $FullyQualifiedLink -Force - } - - if (Test-Path $FullyQualifiedFile) - { - Remove-Item $FullyQualifiedFile -Force - } - - if (Test-Path $FullyQualifiedFolder) - { - Remove-Item $FullyQualifiedFolder -Force - } - } - BeforeAll { $powershell = Join-Path -Path $PsHome -ChildPath "powershell" + Setup -File testfile.txt -Content "Hello World" + $testfile = Join-Path $TestDrive testfile.txt } -#Both tests are pending due to a bug in Invoke-Item on Windows. Fixed for Linux - - It "Should call the function without error" -Pending:$IsWindows { - { New-Item -Name $testfile -Path $tmpDirectory -ItemType file } | Should Not Throw - } - - It "Should invoke a text file without error" -Pending:$IsWindows { - $debugfn = NewProcessStartInfo "-noprofile ""``Invoke-Item $FullyQualifiedFile`n" -RedirectStdIn + It "Should invoke a text file without error" { + $debugfn = NewProcessStartInfo "-noprofile ""``Invoke-Item $testfile`n" -RedirectStdIn $process = RunPowerShell $debugfn EnsureChildHasExited $process $process.ExitCode | Should Be 0 - } + } } From 6200f084cd949358f11c25c8c0e6ed550e02343d Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 8 Jul 2016 09:20:58 -0700 Subject: [PATCH 6/7] Invoke-Item and Get-Help -Online are unsupported on Nano These currently fail at runtime on Nano, and will continue to do so. But this implements these much needed cmdlets for Open PowerShell. If there is a way to determine that PowerShell is being run on the Nano OS at runtime, then we could instead throw a platform unsupported exception, but this cannot be based on the target compilation framework, as .NET Core is shared for both Nano and Windows. --- .../help/HelpCommands.cs | 14 +++++++++++++- .../namespaces/FileSystemProvider.cs | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index 52a74fed07..b6f69d498a 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -704,8 +704,20 @@ namespace Microsoft.PowerShell.Commands if (Platform.IsWindows) { + // this is a re-implementation of the unavailable (on .NET Core) UseShellExecute, + // where we manually execute a cmd.exe shell, and use its start command to + // launch the default application for the given path browserProcess.StartInfo.FileName = "cmd.exe"; - browserProcess.StartInfo.Arguments = string.Format(@"/c ""start /b """" {0}""", uriToLaunch.OriginalString); + + // start is very picky: the "optional" TITLE as the first argument should always + // be included, otherwise it can silently fail + browserProcess.StartInfo.Arguments = string.Format(CultureInfo.InvariantCulture, + @"/c ""start /b """" {0}""", uriToLaunch.OriginalString); + + // please note that there is currently no way to differentiate between running + // on Nano as an OS and having targeted the .NET Core framework, thus this code + // will continue to fail on Nano (as there is no browser), but at least is + // implemented for .NET Core PowerShell on Windows } else if (Platform.IsOSX) { diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 7ee00beb27..2504bb3491 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1337,9 +1337,20 @@ namespace Microsoft.PowerShell.Commands if (Platform.IsWindows) { + // this is a re-implementation of the unavailable (on .NET Core) UseShellExecute, + // where we manually execute a cmd.exe shell, and use its start command to + // launch the default application for the given path invokeProcess.StartInfo.FileName = "cmd.exe"; - // start is very picky: the "optional" TITLE as the first argument should always be included, otherwise it can silently fail - invokeProcess.StartInfo.Arguments = string.Format(@"/c ""start /b """" ""{0}""""", path); + + // start is very picky: the "optional" TITLE as the first argument should always + // be included, otherwise it can silently fail + invokeProcess.StartInfo.Arguments = string.Format(CultureInfo.InvariantCulture, + @"/c ""start /b """" ""{0}""""", path); + + // please note that there is currently no way to differentiate between running + // on Nano as an OS and having targeted the .NET Core framework, thus this code + // will continue to fail on Nano (as there is no browser), but at least is + // implemented for .NET Core PowerShell on Windows } else if (Platform.IsOSX) { invokeProcess.StartInfo.FileName = "open"; From 50e6627a8eac099de9db4740cf665310b0c2b25b Mon Sep 17 00:00:00 2001 From: Andrew Schwartzmeyer Date: Fri, 8 Jul 2016 12:25:40 -0700 Subject: [PATCH 7/7] Throw PlatformNotSupported on Windows .NET Core build --- .../help/HelpCommands.cs | 39 +++++-------------- .../namespaces/FileSystemProvider.cs | 37 +++++------------- .../Invoke-Item.Tests.ps1 | 6 ++- 3 files changed, 23 insertions(+), 59 deletions(-) diff --git a/src/System.Management.Automation/help/HelpCommands.cs b/src/System.Management.Automation/help/HelpCommands.cs index b6f69d498a..fe2be6fe3c 100644 --- a/src/System.Management.Automation/help/HelpCommands.cs +++ b/src/System.Management.Automation/help/HelpCommands.cs @@ -700,37 +700,16 @@ namespace Microsoft.PowerShell.Commands this.WriteVerbose(string.Format(CultureInfo.InvariantCulture, HelpDisplayStrings.OnlineHelpUri, uriToLaunch.OriginalString)); System.Diagnostics.Process browserProcess = new System.Diagnostics.Process(); - browserProcess.StartInfo.UseShellExecute = false; - - if (Platform.IsWindows) - { - // this is a re-implementation of the unavailable (on .NET Core) UseShellExecute, - // where we manually execute a cmd.exe shell, and use its start command to - // launch the default application for the given path - browserProcess.StartInfo.FileName = "cmd.exe"; - - // start is very picky: the "optional" TITLE as the first argument should always - // be included, otherwise it can silently fail - browserProcess.StartInfo.Arguments = string.Format(CultureInfo.InvariantCulture, - @"/c ""start /b """" {0}""", uriToLaunch.OriginalString); - - // please note that there is currently no way to differentiate between running - // on Nano as an OS and having targeted the .NET Core framework, thus this code - // will continue to fail on Nano (as there is no browser), but at least is - // implemented for .NET Core PowerShell on Windows - } - else if (Platform.IsOSX) - { - browserProcess.StartInfo.FileName = "open"; - browserProcess.StartInfo.Arguments = uriToLaunch.OriginalString; - } - else if (Platform.IsLinux) - { - browserProcess.StartInfo.FileName = "xdg-open"; - browserProcess.StartInfo.Arguments = uriToLaunch.OriginalString; - } - +#if LINUX + browserProcess.StartInfo.FileName = Platform.IsLinux ? "xdg-open" : /* OS X */ "open"; + browserProcess.StartInfo.Arguments = uriToLaunch.OriginalString; browserProcess.Start(); +#elif CORECLR + throw new PlatformNotSupportedException(); +#else + browserProcess.StartInfo.FileName = uriToLaunch.OriginalString; + browserProcess.Start(); +#endif } catch (InvalidOperationException ioe) { diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 2504bb3491..39c60e005b 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1333,35 +1333,16 @@ namespace Microsoft.PowerShell.Commands { System.Diagnostics.Process invokeProcess = new System.Diagnostics.Process(); - invokeProcess.StartInfo.UseShellExecute = false; - - if (Platform.IsWindows) - { - // this is a re-implementation of the unavailable (on .NET Core) UseShellExecute, - // where we manually execute a cmd.exe shell, and use its start command to - // launch the default application for the given path - invokeProcess.StartInfo.FileName = "cmd.exe"; - - // start is very picky: the "optional" TITLE as the first argument should always - // be included, otherwise it can silently fail - invokeProcess.StartInfo.Arguments = string.Format(CultureInfo.InvariantCulture, - @"/c ""start /b """" ""{0}""""", path); - - // please note that there is currently no way to differentiate between running - // on Nano as an OS and having targeted the .NET Core framework, thus this code - // will continue to fail on Nano (as there is no browser), but at least is - // implemented for .NET Core PowerShell on Windows - } - else if (Platform.IsOSX) { - invokeProcess.StartInfo.FileName = "open"; - invokeProcess.StartInfo.Arguments = path; - } - else if (Platform.IsLinux) { - invokeProcess.StartInfo.FileName = "xdg-open"; - invokeProcess.StartInfo.Arguments = path; - } - +#if LINUX + invokeProcess.StartInfo.FileName = Platform.IsLinux ? "xdg-open" : /* OS X */ "open"; + invokeProcess.StartInfo.Arguments = path; invokeProcess.Start(); +#elif CORECLR + throw new PlatformNotSupportedException(); +#else + invokeProcess.StartInfo.FileName = path; + invokeProcess.Start(); +#endif } } // InvokeDefaultAction diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 index f17a716959..bc16864990 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Invoke-Item.Tests.ps1 @@ -37,10 +37,14 @@ Describe "Invoke-Item" { $testfile = Join-Path $TestDrive testfile.txt } - It "Should invoke a text file without error" { + It "Should invoke a text file without error" -Skip:($IsWindows -and $IsCore) { $debugfn = NewProcessStartInfo "-noprofile ""``Invoke-Item $testfile`n" -RedirectStdIn $process = RunPowerShell $debugfn EnsureChildHasExited $process $process.ExitCode | Should Be 0 } + + It "Should throw not supported on Windows with .NET Core" -Skip:($IsLinux -or $IsOSX -or !$IsCore) { + { Invoke-Item $testfile }| Should Throw "Operation is not supported on this platform." + } }