Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit e31787c

Browse files
committed
Replace with IsUwp / IsNetNative detection from corefx PlatformDetection
1 parent 3fa520a commit e31787c

File tree

1 file changed

+75
-48
lines changed

1 file changed

+75
-48
lines changed

src/ServiceStack.Text/Env.cs

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ static Env()
1515
throw new ArgumentException("PclExport.Instance needs to be initialized");
1616

1717
var platformName = PclExport.Instance.PlatformName;
18+
19+
#if NETSTANDARD2_0
1820
IsUWP = IsRunningAsUwp();
21+
#endif
22+
1923
if (!IsUWP)
2024
{
2125
IsMono = AssemblyUtils.FindType("Mono.Runtime") != null;
@@ -55,8 +59,7 @@ static Env()
5559
IsIOS = runtimeDir.StartsWith("/private/var") ||
5660
runtimeDir.Contains("/CoreSimulator/Devices/");
5761
}
58-
IsNetNative = fxDesc.Contains(".NET Native");
59-
IsNetCore = fxDesc.Contains(".NET Core");
62+
IsNetCore = fxDesc.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase);
6063
}
6164
catch (Exception) {} //throws PlatformNotSupportedException in AWS lambda
6265
IsUnix = IsOSX || IsLinux;
@@ -68,14 +71,16 @@ static Env()
6871
IsLinux = IsUnix;
6972
if (Environment.GetEnvironmentVariable("OS")?.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0)
7073
IsWindows = true;
74+
SupportsDynamic = true;
7175
#elif NETCORE2_1
7276
IsNetCore = true;
77+
SupportsDynamic = true;
7378
#endif
7479

75-
SupportsExpressions = !IsIOS;
76-
SupportsEmit = !IsIOS && !IsUWP;
80+
SupportsExpressions = true;
81+
SupportsEmit = !(IsUWP || IsIOS);
7782

78-
if (IsNetNative || IsIOS)
83+
if (!SupportsEmit)
7984
{
8085
ReflectionOptimizer.Instance = ExpressionReflectionOptimizer.Provider;
8186
}
@@ -110,7 +115,7 @@ static Env()
110115

111116
public static bool IsNetNative { get; set; }
112117

113-
public static bool IsUWP { get; set; }
118+
public static bool IsUWP { get; private set; }
114119

115120
public static bool IsNetStandard { get; set; }
116121

@@ -122,6 +127,8 @@ static Env()
122127

123128
public static bool SupportsEmit { get; private set; }
124129

130+
public static bool SupportsDynamic { get; private set; }
131+
125132
public static bool StrictMode { get; set; }
126133

127134
public static string ServerUserAgent { get; set; }
@@ -177,26 +184,18 @@ public static string ReferenceAssembyPath
177184
set => referenceAssembyPath = value;
178185
}
179186

187+
#if NETSTANDARD2_0
180188
private static bool IsRunningAsUwp()
181189
{
182-
//TODO: find a more reliable way to detect UWP https://github.com/dotnet/corefx/issues/31599
183-
#if NETSTANDARD2_0
184190
try
185191
{
186-
if (IsWindows7OrLower)
187-
return false;
188-
189-
var isWin = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows);
190-
var fxDesc = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
191-
var isNetNative = fxDesc.Contains(".NET Native");
192-
var onlyInDebugType = Type.GetType("System.Runtime.InteropServices.WindowsRuntime.IActivationFactory,System.Runtime.InteropServices.WindowsRuntime");
193-
return isWin && (isNetNative || onlyInDebugType != null);
192+
IsNetNative = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription.StartsWith(".NET Native", StringComparison.OrdinalIgnoreCase);
193+
return IsInAppContainer || IsNetNative;
194194
}
195-
catch (Exception) {} //throws PlatformNotSupportedException in AWS lambda
196-
#endif
195+
catch (Exception) {}
197196
return false;
198197
}
199-
198+
200199
private static bool IsWindows7OrLower
201200
{
202201
get
@@ -207,42 +206,70 @@ private static bool IsWindows7OrLower
207206
return version <= 6.1;
208207
}
209208
}
210-
211-
/* Only way to determine if .NET Standard 2.0 .dll is running in UWP is now a build error from VS.NET 15.8 Preview
212-
213-
//https://blogs.msdn.microsoft.com/appconsult/2016/11/03/desktop-bridge-identify-the-applications-context/
214-
//https://github.com/qmatteoq/DesktopBridgeHelpers/blob/master/DesktopBridge.Helpers/Helpers.cs
215-
const long APPMODEL_ERROR_NO_PACKAGE = 15700L;
216-
217-
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
218-
static extern int GetCurrentPackageFullName(ref int packageFullNameLength, System.Text.StringBuilder packageFullName);
219-
220-
private static bool IsRunningAsUwp()
209+
210+
// From: https://github.com/dotnet/corefx/blob/master/src/CoreFx.Private.TestUtilities/src/System/PlatformDetection.Windows.cs
211+
private static int s_isInAppContainer = -1;
212+
private static bool IsInAppContainer
221213
{
222-
try
214+
// This actually checks whether code is running in a modern app.
215+
// Currently this is the only situation where we run in app container.
216+
// If we want to distinguish the two cases in future,
217+
// EnvironmentHelpers.IsAppContainerProcess in desktop code shows how to check for the AC token.
218+
get
223219
{
224-
if (IsWindows7OrLower)
225-
return false;
220+
if (s_isInAppContainer != -1)
221+
return s_isInAppContainer == 1;
226222

227-
int length = 0;
228-
var sb = new System.Text.StringBuilder(0);
229-
int result = GetCurrentPackageFullName(ref length, sb);
223+
if (!IsWindows || IsWindows7OrLower)
224+
{
225+
s_isInAppContainer = 0;
226+
return false;
227+
}
230228

231-
sb = new System.Text.StringBuilder(length);
232-
result = GetCurrentPackageFullName(ref length, sb);
229+
byte[] buffer = TypeConstants.EmptyByteArray;
230+
uint bufferSize = 0;
231+
try
232+
{
233+
int result = GetCurrentApplicationUserModelId(ref bufferSize, buffer);
234+
switch (result)
235+
{
236+
case 15703: // APPMODEL_ERROR_NO_APPLICATION
237+
s_isInAppContainer = 0;
238+
break;
239+
case 0: // ERROR_SUCCESS
240+
case 122: // ERROR_INSUFFICIENT_BUFFER
241+
// Success is actually insufficent buffer as we're really only looking for
242+
// not NO_APPLICATION and we're not actually giving a buffer here. The
243+
// API will always return NO_APPLICATION if we're not running under a
244+
// WinRT process, no matter what size the buffer is.
245+
s_isInAppContainer = 1;
246+
break;
247+
default:
248+
throw new InvalidOperationException($"Failed to get AppId, result was {result}.");
249+
}
250+
}
251+
catch (Exception e)
252+
{
253+
// We could catch this here, being friendly with older portable surface area should we
254+
// desire to use this method elsewhere.
255+
if (e.GetType().FullName.Equals("System.EntryPointNotFoundException", StringComparison.Ordinal))
256+
{
257+
// API doesn't exist, likely pre Win8
258+
s_isInAppContainer = 0;
259+
}
260+
else
261+
{
262+
throw;
263+
}
264+
}
233265

234-
return result != APPMODEL_ERROR_NO_PACKAGE;
235-
}
236-
catch (TypeLoadException e) //of course the recommended code to detect UWP fails in .NET Native UWP
237-
{
238-
return IsWindows && IsNetNative;
239-
}
240-
catch (Exception e)
241-
{
242-
return false;
266+
return s_isInAppContainer == 1;
243267
}
244268
}
245-
*/
269+
270+
[System.Runtime.InteropServices.DllImport("kernel32.dll", ExactSpelling = true)]
271+
private static extern int GetCurrentApplicationUserModelId(ref uint applicationUserModelIdLength, byte[] applicationUserModelId);
272+
#endif
246273

247274
}
248275
}

0 commit comments

Comments
 (0)