8000 using helper to shellexecute to make it thread safe · PowerShell/PowerShell@d523ca0 · GitHub
[go: up one dir, main page]

Skip to content

Commit d523ca0

Browse files
committed
using helper to shellexecute to make it thread safe
1 parent f21a6ed commit d523ca0

File tree

1 file changed

+42
-26
lines changed
  • src/System.Management.Automation/engine

1 file changed

+42
-26
lines changed

src/System.Management.Automation/engine/Utils.cs

Lines changed: 42 additions & 26 deletions
8000
Original file line numberDiff line numberDiff line change
@@ -1501,8 +1501,14 @@ public static void SetTestHook(string property, bool value)
15011501
/// </summary>
15021502
internal class ShellExecuteHelper
15031503
{
1504-
private static bool _succeeded;
1505-
private static int _errorCode;
1504+
private NativeMethods.ShellExecuteInfo _executeInfo;
1505+
private int _errorCode;
1506+
private bool _succeeded;
1507+
1508+
/// <summary>
1509+
/// Constructor for ShellExecuteHelper
1510+
/// </summary>
1511+
private ShellExecuteHelper(NativeMethods.ShellExecuteInfo executeInfo) { _executeInfo = executeInfo; }
15061512

15071513 8000
/// <summary>
15081514
/// Start a process using ShellExecuteEx with default settings about WindowStyle and Verb.
@@ -1549,28 +1555,16 @@ internal static Process Start(ProcessStartInfo startInfo, ProcessWindowStyle win
15491555
shellExecuteInfo.lpDirectory = Marshal.StringToHGlobalUni(startInfo.WorkingDirectory);
15501556

15511557
shellExecuteInfo.fMask |= NativeMethods.SEE_MASK_FLAG_DDEWAIT;
1552-
if (Thread.CurrentThread.GetApartmentState() == System.Threading.ApartmentState.STA)
1558+
ShellExecuteHelper helper = new ShellExecuteHelper(shellExecuteInfo);
1559+
if (!helper.ExecuteOnSTAThread())
15531560
{
1554-
InvokeShellExecuteEx(shellExecuteInfo);
1555-
}
1556-
else
1557-
{
1558-
ParameterizedThreadStart threadStart = new ParameterizedThreadStart(InvokeShellExecuteEx);
1559-
Thread thread = new Thread(threadStart);
1560-
thread.SetApartmentState(System.Threading.ApartmentState.STA);
1561-
thread.Start(shellExecuteInfo);
1562-
thread.Join();
1563-
}
1564-
1565-
if (!_succeeded)
1566-
{
1567-
if(_errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || _errorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH)
1561+
if(helper.ErrorCode == NativeMethods.ERROR_BAD_EXE_FORMAT || helper.ErrorCode == NativeMethods.ERROR_EXE_MACHINE_TYPE_MISMATCH)
15681562
{
1569-
throw new Win32Exception(_errorCode, "InvalidApplication");
1563+
throw new Win32Exception(helper.ErrorCode, "InvalidApplication");
15701564
}
15711565
else
15721566
{
1573-
throw new Win32Exception(_errorCode);
1567+
throw new Win32Exception(helper.ErrorCode);
15741568
}
15751569
}
15761570
}
@@ -1597,16 +1591,13 @@ internal static Process Start(ProcessStartInfo startInfo, ProcessWindowStyle win
15971591
return processToReturn;
15981592
}
15991593

1600-
private static void InvokeShellExecuteEx(object param)
1601-
{
1602-
NativeMethods.ShellExecuteInfo shellExecuteInfo = (NativeMethods.ShellExecuteInfo)param;
1603-
_succeeded = true;
1604-
if (!NativeMethods.ShellExecuteEx(shellExecuteInfo))
1594+
private void ShellExecuteFunction() {
1595+
if (!NativeMethods.ShellExecuteEx(_executeInfo))
16051596
{
16061597
_errorCode = Marshal.GetLastWin32Error();
16071598
if (_errorCode == 0)
16081599
{
1609-
switch ((long)shellExecuteInfo.hInstApp)
1600+
switch ((long)_executeInfo.hInstApp)
16101601
{
16111602
case NativeMethods.SE_ERR_FNF: _errorCode = NativeMethods.ERROR_FILE_NOT_FOUND; break;
16121603
case NativeMethods.SE_ERR_PNF: _errorCode = NativeMethods.ERROR_PATH_NOT_FOUND; break;
@@ -1618,13 +1609,38 @@ private static void InvokeShellExecuteEx(object param)
16181609
case NativeMethods.SE_ERR_SHARE: _errorCode = NativeMethods.ERROR_SHARING_VIOLATION; break;
16191610
case NativeMethods.SE_ERR_NOASSOC: _errorCode = NativeMethods.ERROR_NO_ASSOCIATION; break;
16201611
case NativeMethods.SE_ERR_DLLNOTFOUND: _errorCode = NativeMethods.ERROR_DLL_NOT_FOUND; break;
1621-
default: _errorCode = (int)shellExecuteInfo.hInstApp; break;
1612+
default: _errorCode = (int)_executeInfo.hInstApp; break;
16221613
}
16231614
}
16241615
_succeeded = false;
16251616
}
16261617
}
16271618

1619+
private bool ExecuteOnSTAThread()
1620+
{
1621+
if (Thread.CurrentThread.GetApartmentState() != System.Threading.ApartmentState.STA)
1622+
{
1623+
ThreadStart threadStart = new ThreadStart(this.ShellExecuteFunction);
1624+
Thread thread = new Thread(threadStart);
1625+
thread.SetApartmentState(System.Threading.ApartmentState.STA);
1626+
thread.Start();
1627+
thread.Join();
1628+
}
1629+
else
1630+
{
1631+
ShellExecuteFunction();
1632+
}
1633+
return _succeeded;
1634+
}
1635+
1636+
private int ErrorCode
1637+
{
1638+
get
1639+
{
1640+
return _errorCode;
1641+
}
1642+
}
1643+
16281644
private static int GetProcessIdFromHandle(SafeProcessHandle processHandle)
16291645
{
16301646
NativeMethods.NtProcessBasicInfo info = new NativeMethods.NtProcessBasicInfo();

0 commit comments

Comments
 (0)
0