1 // ***********************************************************************
2 // Copyright (c) 2008-2016 Charlie Poole
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
25 #define NUNIT_FRAMEWORK
30 using Microsoft.Win32;
32 using System.Runtime.InteropServices;
34 namespace NUnit.Framework.Internal
37 /// OSPlatform represents a particular operating system platform
39 public class OSPlatform
41 readonly PlatformID _platform;
42 readonly Version _version;
43 readonly ProductType _product;
45 #region Static Members
46 private static readonly Lazy<OSPlatform> currentPlatform = new Lazy<OSPlatform> (() =>
48 OSPlatform currentPlatform;
50 OperatingSystem os = Environment.OSVersion;
52 #if SILVERLIGHT || NETCF
53 // TODO: Runtime silverlight detection?
54 currentPlatform = new OSPlatform(os.Platform, os.Version);
56 if (os.Platform == PlatformID.Win32NT && os.Version.Major >= 5)
58 OSVERSIONINFOEX osvi = new OSVERSIONINFOEX();
59 osvi.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
60 GetVersionEx(ref osvi);
61 if (os.Version.Major == 6 && os.Version.Minor >= 2)
62 os = new OperatingSystem(os.Platform, GetWindows81PlusVersion(os.Version));
63 currentPlatform = new OSPlatform(os.Platform, os.Version, (ProductType)osvi.ProductType);
65 else if (CheckIfIsMacOSX(os.Platform))
67 // Mono returns PlatformID.Unix for OSX (see http://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform)
68 // The above check uses uname to confirm it is MacOSX and we change the PlatformId here.
69 currentPlatform = new OSPlatform(PlatformID.MacOSX, os.Version);
72 currentPlatform = new OSPlatform(os.Platform, os.Version);
74 return currentPlatform;
79 /// Platform ID for Unix as defined by Microsoft .NET 2.0 and greater
81 public static readonly PlatformID UnixPlatformID_Microsoft = (PlatformID)4;
84 /// Platform ID for Unix as defined by Mono
86 public static readonly PlatformID UnixPlatformID_Mono = (PlatformID)128;
89 /// Platform ID for XBox as defined by .NET and Mono, but not CF
91 public static readonly PlatformID XBoxPlatformID = (PlatformID)5;
94 /// Platform ID for MacOSX as defined by .NET and Mono, but not CF
96 public static readonly PlatformID MacOSXPlatformID = (PlatformID)6;
99 /// Get the OSPlatform under which we are currently running
101 public static OSPlatform CurrentPlatform
105 return currentPlatform.Value;
109 #if !SILVERLIGHT && !NETCF
111 /// Gets the actual OS Version, not the incorrect value that might be
112 /// returned for Win 8.1 and Win 10
115 /// If an application is not manifested as Windows 8.1 or Windows 10,
116 /// the version returned from Environment.OSVersion will not be 6.3 and 10.0
117 /// respectively, but will be 6.2 and 6.3. The correct value can be found in
120 /// <param name="version">The original version</param>
121 /// <returns>The correct OS version</returns>
122 private static Version GetWindows81PlusVersion(Version version)
126 using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
130 var buildStr = key.GetValue("CurrentBuildNumber") as string;
132 int.TryParse(buildStr, out build);
134 // These two keys are in Windows 10 only and are DWORDS
135 var major = key.GetValue("CurrentMajorVersionNumber") as int?;
136 var minor = key.GetValue("CurrentMinorVersionNumber") as int?;
137 if (major.HasValue && minor.HasValue)
139 return new Version(major.Value, minor.Value, build);
142 // If we get here, we are not Windows 10, so we are Windows 8
143 // or 8.1. 8.1 might report itself as 6.2, but will have 6.3
144 // in the registry. We can't do this earlier because for backwards
145 // compatibility, Windows 10 also has 6.3 for this key.
146 var currentVersion = key.GetValue("CurrentVersion") as string;
147 if(currentVersion == "6.3")
149 return new Version(6, 3, build);
162 #region Members used for Win32NT platform only
164 /// Product Type Enumeration used for Windows
166 public enum ProductType
169 /// Product type is unknown or unspecified
174 /// Product type is Workstation
179 /// Product type is Domain Controller
184 /// Product type is Server
189 [StructLayout(LayoutKind.Sequential)]
190 struct OSVERSIONINFOEX
192 public uint dwOSVersionInfoSize;
193 public readonly uint dwMajorVersion;
194 public readonly uint dwMinorVersion;
195 public readonly uint dwBuildNumber;
196 public readonly uint dwPlatformId;
197 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
198 public readonly string szCSDVersion;
199 public readonly Int16 wServicePackMajor;
200 public readonly Int16 wServicePackMinor;
201 public readonly Int16 wSuiteMask;
202 public readonly Byte ProductType;
203 public readonly Byte Reserved;
206 [DllImport("Kernel32.dll")]
207 private static extern bool GetVersionEx(ref OSVERSIONINFOEX osvi);
211 /// Construct from a platform ID and version
213 public OSPlatform(PlatformID platform, Version version)
215 _platform = platform;
220 /// Construct from a platform ID, version and product type
222 public OSPlatform(PlatformID platform, Version version, ProductType product)
223 : this( platform, version )
229 /// Get the platform ID of this instance
231 public PlatformID Platform
233 get { return _platform; }
237 /// Get the Version of this instance
239 public Version Version
241 get { return _version; }
245 /// Get the Product Type of this instance
247 public ProductType Product
249 get { return _product; }
253 /// Return true if this is a windows platform
255 public bool IsWindows
259 return _platform == PlatformID.Win32NT
260 || _platform == PlatformID.Win32Windows
261 || _platform == PlatformID.Win32S
262 || _platform == PlatformID.WinCE;
267 /// Return true if this is a Unix or Linux platform
273 return _platform == UnixPlatformID_Microsoft
274 || _platform == UnixPlatformID_Mono;
279 /// Return true if the platform is Win32S
283 get { return _platform == PlatformID.Win32S; }
287 /// Return true if the platform is Win32Windows
289 public bool IsWin32Windows
291 get { return _platform == PlatformID.Win32Windows; }
295 /// Return true if the platform is Win32NT
297 public bool IsWin32NT
299 get { return _platform == PlatformID.Win32NT; }
303 /// Return true if the platform is Windows CE
307 get { return _platform == PlatformID.WinCE; }
311 /// Return true if the platform is Xbox
315 get { return _platform == XBoxPlatformID; }
319 /// Return true if the platform is MacOSX
323 get { return _platform == MacOSXPlatformID; }
326 #if !NETCF && !SILVERLIGHT
328 static extern int uname(IntPtr buf);
330 static bool CheckIfIsMacOSX(PlatformID platform)
332 if (platform == PlatformID.MacOSX)
335 if (platform != PlatformID.Unix)
338 IntPtr buf = Marshal.AllocHGlobal(8192);
339 bool isMacOSX = false;
342 string os = Marshal.PtrToStringAnsi(buf);
343 isMacOSX = os.Equals("Darwin");
345 Marshal.FreeHGlobal(buf);
351 /// Return true if the platform is Windows 95
355 get { return _platform == PlatformID.Win32Windows && _version.Major == 4 && _version.Minor == 0; }
359 /// Return true if the platform is Windows 98
363 get { return _platform == PlatformID.Win32Windows && _version.Major == 4 && _version.Minor == 10; }
367 /// Return true if the platform is Windows ME
371 get { return _platform == PlatformID.Win32Windows && _version.Major == 4 && _version.Minor == 90; }
375 /// Return true if the platform is NT 3
379 get { return _platform == PlatformID.Win32NT && _version.Major == 3; }
383 /// Return true if the platform is NT 4
387 get { return _platform == PlatformID.Win32NT && _version.Major == 4; }
391 /// Return true if the platform is NT 5
395 get { return _platform == PlatformID.Win32NT && _version.Major == 5; }
399 /// Return true if the platform is Windows 2000
403 get { return IsNT5 && _version.Minor == 0; }
407 /// Return true if the platform is Windows XP
411 get { return IsNT5 && (_version.Minor == 1 || _version.Minor == 2 && Product == ProductType.WorkStation); }
415 /// Return true if the platform is Windows 2003 Server
417 public bool IsWin2003Server
419 get { return IsNT5 && _version.Minor == 2 && Product == ProductType.Server; }
423 /// Return true if the platform is NT 6
427 get { return _platform == PlatformID.Win32NT && _version.Major == 6; }
431 /// Return true if the platform is NT 6.0
435 get { return IsNT6 && _version.Minor == 0; }
439 /// Return true if the platform is NT 6.1
443 get { return IsNT6 && _version.Minor == 1; }
447 /// Return true if the platform is NT 6.2
451 get { return IsNT6 && _version.Minor == 2; }
455 /// Return true if the platform is NT 6.3
459 get { return IsNT6 && _version.Minor == 3; }
463 /// Return true if the platform is Vista
467 get { return IsNT60 && Product == ProductType.WorkStation; }
471 /// Return true if the platform is Windows 2008 Server (original or R2)
473 public bool IsWin2008Server
475 get { return IsWin2008ServerR1 || IsWin2008ServerR2; }
479 /// Return true if the platform is Windows 2008 Server (original)
481 public bool IsWin2008ServerR1
483 get { return IsNT60 && Product == ProductType.Server; }
487 /// Return true if the platform is Windows 2008 Server R2
489 public bool IsWin2008ServerR2
491 get { return IsNT61 && Product == ProductType.Server; }
495 /// Return true if the platform is Windows 2012 Server (original or R2)
497 public bool IsWin2012Server
499 get { return IsWin2012ServerR1 || IsWin2012ServerR2; }
503 /// Return true if the platform is Windows 2012 Server (original)
505 public bool IsWin2012ServerR1
507 get { return IsNT62 && Product == ProductType.Server; }
511 /// Return true if the platform is Windows 2012 Server R2
513 public bool IsWin2012ServerR2
515 get { return IsNT63 && Product == ProductType.Server; }
519 /// Return true if the platform is Windows 7
521 public bool IsWindows7
523 get { return IsNT61 && Product == ProductType.WorkStation; }
527 /// Return true if the platform is Windows 8
529 public bool IsWindows8
531 get { return IsNT62 && Product == ProductType.WorkStation; }
535 /// Return true if the platform is Windows 8.1
537 public bool IsWindows81
539 get { return IsNT63 && Product == ProductType.WorkStation; }
543 /// Return true if the platform is Windows 10
545 public bool IsWindows10
547 get { return _platform == PlatformID.Win32NT && _version.Major == 10 && Product == ProductType.WorkStation; }
551 /// Return true if the platform is Windows Server. This is named Windows
552 /// Server 10 to distinguish it from previous versions of Windows Server.
554 public bool IsWindowsServer10
556 get { return _platform == PlatformID.Win32NT && _version.Major == 10 && Product == ProductType.Server; }