8000 Default to MTA on Windows platforms where STA is not supported (#15106) · rkeithhill/PowerShell@6f173f4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6f173f4

Browse files
SteveL-MSFTrkeithhill
authored andcommitted
Default to MTA on Windows platforms where STA is not supported (PowerShell#15106)
1 parent b51b8de commit 6f173f4

File tree

Collapse file tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

src/Microsoft.PowerShell.ConsoleHost/host/msh/CommandLineParameterParser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ internal bool StaMode
477477
}
478478
else
479479
{
480-
return true;
480+
return Platform.IsStaSupported;
481481
}
482482
}
483483
}
@@ -929,7 +929,7 @@ private void ParseHelper(string[] args)
929929
}
930930
else if (MatchSwitch(switchKey, "sta", "sta"))
931931
{
932-
if (!Platform.IsWindowsDesktop)
932+
if (!Platform.IsWindowsDesktop || !Platform.IsStaSupported)
933933
{
934934
SetCommandLineError(
935935
CommandLineParameterParserStrings.STANotImplemented);

src/System.Management.Automation/CoreCLR/CorePsPlatform.cs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ namespace System.Management.Automation
1616
/// </summary>
1717
public static class Platform
1818
{
19-
private static string _tempDirectory = null;
20-
2119
/// <summary>
2220
/// True if the current platform is Linux.
2321
/// </summary>
@@ -140,6 +138,21 @@ public static bool IsWindowsDesktop
140138
}
141139
}
142140

141+
/// <summary>
142+
/// Gets a value indicating whether the underlying system supports single-threaded apartment.
143+
/// </summary>
144+
public static bool IsStaSupported
145+
{
146+
get
147+
{
148+
#if UNIX
149+
return false;
150+
#else
151+
return _isStaSupported.Value;
152+
#endif
153+
}
154+
}
155+
143156
#if UNIX
144157
// Gets the location for cache and config folders.
145158
internal static readonly string CacheDirectory = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE);
@@ -148,6 +161,22 @@ public static bool IsWindowsDesktop
148161
// Gets the location for cache and config folders.
149162
internal static readonly string CacheDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\PowerShell";
150163
internal static readonly string ConfigDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\PowerShell";
164+
private static readonly Lazy<bool> _isStaSupported = new Lazy<bool>(() =>
165+
{
166+
// See objbase.h
167+
const int COINIT_APARTMENTTHREADED = 0x2;
168+
const int E_NOTIMPL = unchecked((int)0X80004001);
169+
int result = Windows.NativeMethods.CoInitializeEx(IntPtr.Zero, COINIT_APARTMENTTHREADED);
170+
171+
// If 0 is returned the thread has been initialized for the first time
172+
// as an STA and thus supported and needs to be uninitialized.
173+
if (result > 0)
174+
{
175+
Windows.NativeMethods.CoUninitialize();
176+
}
177+
178+
return result != E_NOTIMPL;
179+
});
151180

152181
private static bool? _isNanoServer = null;
153182
private static bool? _isIoT = null;
@@ -170,6 +199,8 @@ public static bool IsWindowsDesktop
170199
"WSMan.format.ps1xml"
171200
};
172201

202+
private static string _tempDirectory = null;
203+
173204
/// <summary>
174205
/// Some common environment variables used in PS have different
175206
/// names in different OS platforms.
@@ -557,6 +588,21 @@ internal static int NonWindowsGetProcessParentPid(int pid)
557588
return IsMacOS ? Unix.NativeMethods.GetPPid(pid) : Unix.GetProcFSParentPid(pid);
558589
}
559590

591+
internal static class Windows
592+
{
593+
/// <summary>The native methods class.</summary>
594+
internal static class NativeMethods
595+
{
596+
private const string ole32Lib = "api-ms-win-core-com-l1-1-0.dll";
597+
598+
[DllImport(ole32Lib)]
599+
internal static extern int CoInitializeEx(IntPtr reserve, int coinit);
600+
601+
[DllImport(ole32Lib)]
602+
internal static extern void CoUninitialize();
603+
}
604+
}
605+
560606
// Please note that `Win32Exception(Marshal.GetLastWin32Error())`
561607
// works *correctly* on Linux in that it creates an exception with
562608
// the string perror would give you for the last set value of errno.

src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ protected override void StartPipelineExecution()
192192
}
193193

194194
#if !UNIX
195-
if (apartmentState != ApartmentState.Unknown && !Platform.IsNanoServer && !Platform.IsIoT)
195+
if (apartmentState != ApartmentState.Unknown && Platform.IsStaSupported)
196196
{
197197
invokeThread.SetApartmentState(apartmentState);
198198
}
@@ -1165,7 +1165,7 @@ internal PipelineThread(ApartmentState apartmentState)
11651165
_closed = false;
11661166

11671167
#if !UNIX
1168-
if (apartmentState != ApartmentState.Unknown && !Platform.IsNanoServer && !Platform.IsIoT)
1168+
if (apartmentState != ApartmentState.Unknown && Platform.IsStaSupported)
11691169
{
11701170
_worker.SetApartmentState(apartmentState);
11711171
}

test/xUnit/csharp/test_CommandLineParser.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,15 @@ public static void TestDefaults()
4848
Assert.False(cpp.SkipProfiles);
4949
Assert.False(cpp.SocketServerMode);
5050
Assert.False(cpp.SSHServerMode);
51-
Assert.True(cpp.StaMode);
51+
if (Platform.IsWindows)
52+
{
53+
Assert.True(cpp.StaMode);
54+
}
55+
else
56+
{
57+
Assert.False(cpp.StaMode);
58+
}
59+
5260
Assert.False(cpp.ThrowOnReadAndPrompt);
5361
Assert.False(cpp.WasInitialCommandEncoded);
5462
Assert.Null(cpp.WorkingDirectory);
@@ -1226,7 +1234,15 @@ public static void TestParameter_LastParameterIsFileName_Exist(params string[] c
12261234
Assert.False(cpp.NoExit);
12271235
Assert.False(cpp.ShowShortHelp);
12281236
Assert.False(cpp.ShowBanner);
1229-
Assert.True(cpp.StaMode);
1237+
if (Platform.IsWindows)
1238+
{
1239+
Assert.True(cpp.StaMode);
1240+
}
1241+
else
1242+
{
1243+
Assert.False(cpp.StaMode);
1244+
}
1245+
12301246
Assert.Equal(CommandLineParameterParser.NormalizeFilePath(commandLine[commandLine.Length - 1]), cpp.File);
12311247
Assert.Null(cpp.ErrorMessage);
12321248
}

0 commit comments

Comments
 (0)
0