Skip to content

Conversation

@daxian-dbw
Copy link
Member

@daxian-dbw daxian-dbw commented Mar 8, 2017

Add support to ShellExecute in powershell core when it's running on Windows full SKUs.
Updated Get-Help -Online, Invoke-Item and Start-Process to support start a process using ShellExecute on powershell core on windows full SKUs.

TODO: In .NET Core, managed threads are all eagerly initialized with MTA mode, so to call ShellExecuteEx from a STA thread, we need to create a native thread using CreateThread function and initialize COM with STA on that thread. In #3281, we are calling ShellExecuteEx directly on MTA thread, and it works for things like opening a folder in File Explorer, opening a file with the application that is associated with its extension in shell, opening URL in web browser and etc, but it's not guaranteed to work in all ShellExecution scenarios. #2969 will be used to track the "invoke-on-STA-thread" work.

try
{
// Try Process.Start first. This works for executables even on headless SKUs.
invokeProcess.StartInfo.FileName = path;
Copy link
Contributor

Choose a reason for hiding this comment

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

Have you tested this on a headless SKU?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes I did. It's able to start executable files, like .exe file, on NanoServer.

Copy link
Contributor

Choose a reason for hiding this comment

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

Awesome. Thanks!

$_.Exception.Message | Should match '-Verb'
}
## -Verb is supported in PowerShell core on Windows full desktop.
It "Should give an error when -Verb parameter is used" -Skip:$isFullWin {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this test case be skipped on IoT and Nano Server?

Copy link
Member Author

@daxian-dbw daxian-dbw Mar 14, 2017

Choose a reason for hiding this comment

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

No, -Verb is not supported on non-windows platforms and windows headless SKUs. So, on NanoServer and IoT, using -Verb should result in a terminating error.

}

## -WindowStyle is supported in PowerShell core on Windows full desktop.
It "Should give an error when -WindowStyle parameter is used" -Skip:$isFullWin {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Same reason as above.

$process | Stop-Process
}

It "Should open the application that associates with extension '.txt'" {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will not run on IoT and Nano.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. I will fix it.

/// There are instances where ShellExecuteEx does not use one of these types of Shell extension and those instances would not require
/// COM to be initialized at all. Nonetheless, it is good practice to always initalize COM before using this function."
///
/// TODO: In .NET Core, managed threads are all eagerly initialized with MTA mode, so to call 'ShellExecuteEx' from a STA thread, we
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you have an issue number for this TODO?

Copy link
Member Author

Choose a reason for hiding this comment

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

#2969 will be used to track the "invoke-on-STA-thread" work.

Yes, it's recorded in the description of this PR. This Start method will be touched when fixing that issue and this TODO can be removed then.

Copy link
Member Author

Choose a reason for hiding this comment

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

I will add the issue number in the comment here as well.

if (shellExecuteInfo.lpDirectory != (IntPtr)0) Marshal.FreeHGlobal(shellExecuteInfo.lpDirectory);
}

Process processToReturn = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please write a comment on what is happening right here? Please correct me if I am wrong. In the finally block you are freeing memory for lpfile, lpVerb, lpParameters, and lpDirectory. Then you use the pointer to the process to fetch the process using its id. My question is: Do we need to free anymore memory from shellExecuteInfo once the process is returned?

Copy link
Member Author

Choose a reason for hiding this comment

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

No more resource needs to be freed. This code mainly comes from .NET code here

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok. Thanks.

// If it's headless SKUs, rethrow.
if (Platform.IsNanoServer || Platform.IsIoT) { throw; }
// If it's full Windows, then try ShellExecute.
ShellExecuteHelper.Start(invokeProcess.StartInfo);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a possibility that this call will throw? If it does, how are you handling it?

Copy link
Member Author

@daxian-dbw daxian-dbw Mar 14, 2017

Choose a reason for hiding this comment

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

If it throws, then the exception just propagates and powershell will handle it. It's like what would happen when invokeProcess.Start() throws.

@Francisco-Gamino
Copy link
Contributor

Hi @daxian-dbw, I left some minor comments/questions. Overall it looks very good. Thanks for enabling this!

@daxian-dbw
Copy link
Member Author

@Francisco-Gamino I have addressed your comments. Could you please take another look?

@Francisco-Gamino
Copy link
Contributor

@daxian-dbw: LGTM, thanks for getting this done!
ship-it-squirrel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants