Find what windows version is on a specified drive - c#

I want to find what OS version (e.g.: Window 7 Pro) is on drive D: without digging through D:\Windows\System32\license.rtf
Is there a class within System.Management namespace that will let me find OS Versions on a specified local drive letter?

//This will help you detect the version of the OS for NT based system, if ntoskrnl.exe doesnt exist its ME/95/98
var DriveLetter = "D"; //D drive.
var pathTontoskrnl = string.Format("{0}:\\{1}", DriveLetter, "\\Windows\System32\ntoskrnl.exe");
if (!File.Exists(pathTontoskrnl))
{
Console.WriteLine("Windows ME/95/98");
}
var versionInfo = FileVersionInfo.GetVersionInfo(pathTontoskrnl);
string version = versionInfo.ProductVersion;
if ( version.StartsWith("5.1") )
{
Console.WriteLine("XP");
}
//4.x: NT 4.x
//5.0: Win2k
//5.1: WinXP
//5.2: Win2003 or XP-x64
//6.0: WinVista
//6.1: Win7
//6.2; Win8
//6.3: Win8.1
//6.4: Win10 ??? (not sure)

Related

How can I find the Windows product name in Windows 11?

Windows 11, released yesterday, reports itself as Windows 10.0 just about everywhere - RtlGetVersion says 10.0, and if you ask VerifyVersionInfo if you are 11.0 or greater, it says no.
There seems to be no new GUID to shove into app.manifest to say "hey I support Windows 11" like there was for Windows 7, 8, 8.1, and 10.
Currently I rely on HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName to tell me what the current version of Windows is, but on my machine that I've upgraded, it still says "Windows 10 Enterprise", not "Windows 11 Enterprise".
There appears to only be a single place in the registry that contains the text "Windows 11" and that is the BCD section (boot configuration), which can also be renamed so I don't want to touch that.
So far I have only identified a handful of methods to tell if I am running on Windows 11:
Invoke WMI to query Win32_OperatingSystem and check the Name property, which simply says "Windows 11". This is incomplete (it does not include the SKU such as "Enterprise"), and WMI is relatively slow and slightly brittle, so it's not an acceptable solution for my use-case.
Check the build number to see if it is above 21996 (beta builds) or 22000 (first public release). As above, this won't include the SKU, and would require some manual jiggery-pokery in order to build the full string.
Run sysinfo and parse the output. This is quite slow, and possibly brittle (I haven't checked but the output might be localised into different languages).
winver knows, but it's a GUI application so I can't exactly query it programmatically.
Does anyone have any other ideas on how to get the string "Windows 11 Enterprise" (or "Windows 11 Pro", etc. as the case may be) out of my operating system in a performant and complete manner? Where do WMI, sysinfo, and winver get it from?
I need to do this from a .NET library, but P/Invokes / native function calls are acceptable solutions.
Leaving this here so that I can find it later:
It seems that Windows itself (e.g. winver) gets this information from Windows branding - specifically from the resource table in %WinDir%\Branding\Basebrd\en-US\basebrd.dll.mui.
To access this one could use the private APIs in %WinDir%\System32\winbrand.dll. Specifically, the function BrandingFormatString which accepts a wide string (LPW[C]STR) and returns a wide string.
e.g. BrandingFormatString("%WINDOWS_LONG%") returns "Windows 11 Pro" on my home PC.
I do not know the lifecycle semantics of the resulting string, i.e. if/when/how it should be freed.
The following code serves as a functional proof-of-concept (C# 9.0):
using System;
using System.Runtime.InteropServices;
[DllImport("winbrand.dll", CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
static extern string BrandingFormatString(string format);
Console.WriteLine(BrandingFormatString("Hello World from %WINDOWS_LONG%!"));
tldr - Using the EditionID and the CurrentBuild from the CurrentVersion in the registry seems to be a reliable way to determine Win10 vs Win11 and the "edition" of the software. EditionID is "Professional" on Windows 10 Pro and Windows 11 Pro, and CurrentBuild >= ~22000 tells you if it is 10 or 11.
The collection of registry values in the HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion reveals what feels like a lack of planning on Microsoft's part. There's ReleaseId, which is a number that changed with each Windows 10 release (e.g., 1903, 1909, 2004,...) until its last change for Windows 10 20H2, where it changed to 2009. At the same time, DisplayVersion was added, and was set to 20H2.
Then Windows 10 21H1 released, and ReleaseId inexplicably stayed at 2009.
The fact that both current Windows 10 and Windows 11 releases can have the same DisplayVersion (e.g., 21H2 when Windows 10 21H2 releases soon) and ProductName (e.g., Windows 10 Pro) is really head-scratching. (Thanks #yaakov for catching my mistake saying it was 21H1.)
The following code has been tested on Windows XP, 7, 10, 11. It works on 32 bit and 64 bit operating systems. It works inside 32 bit and 64 bit applications.
The following strings will be generated:
"Microsoft Windows XP, Build 2600, 32 bit"
"Windows 7 Ultimate, Build 7601, 64 bit"
"Windows 10 Enterprise LTSC 2019, Version 1809, Build 17763, 64 bit"
"Windows 10 Pro, Version 1909, Build 18362, 64 bit"
"Windows 11 Professional, Version 21H2, Build 22000, 64 bit"
Put the code into a static constructor so it executes only once and writes the version into a static variable.
static String ms_OperatingSystem;
static Constructor()
{
try
{
String s_KernelPath = Path.Combine(Environment.SystemDirectory,"Kernel32.dll");
FileVersionInfo k_Kernel = FileVersionInfo.GetVersionInfo(s_KernelPath);
// on 32 bit Windows this will read the 32 bit hive instead
using (RegistryKey i_HKLM = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
using (RegistryKey i_RegVer = i_HKLM.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion", false))
{
// Kernel32.dll on Windows 11 has Product Version 10.0.22000.120
if (k_Kernel.ProductMajorPart == 10 && k_Kernel.ProductBuildPart >= 22000)
{
ms_OperatingSystem = "Windows 11";
Object o_Edition = i_RegVer.GetValue("EditionID"); // "Professional"
if (o_Edition is String)
ms_OperatingSystem += " " + o_Edition;
}
else
{
// "Microsoft Windows XP"
// "Windows 7 Ultimate"
// "Windows 10 Pro" (same string on Windows 11. Microsoft SUCKS!)
ms_OperatingSystem = (String)i_RegVer.GetValue("ProductName");
}
// See: https://en.wikipedia.org/wiki/Windows_10_version_history
// Windows 10 older releases --> "2009" (invalid if DisplayVersion exists)
Object o_ReleaseID = i_RegVer.GetValue("ReleaseId");
// Windows 10 latest release --> "21H1"
// Windows 11 first release --> "21H2"
Object o_DispVer = i_RegVer.GetValue("DisplayVersion");
// Use ReleaseID ONLY if DisplayVersion does not exist in registry!
if (o_DispVer is String) ms_OperatingSystem += ", Version " + o_DispVer;
else if (o_ReleaseID is String) ms_OperatingSystem += ", Version " + o_ReleaseID;
ms_OperatingSystem += ", Build " + k_Kernel.ProductBuildPart;
if (Environment.Is64BitOperatingSystem) ms_OperatingSystem += ", 64 bit";
else ms_OperatingSystem += ", 32 bit";
}
}
}
catch (Exception Ex)
{
ms_OperatingSystem = Ex.Message;
}
}
I created a remote support tool for desktop admins (see http://www.appslife-rdt.appspot.com) In VB.Dot.Net i used a call to the WMI space Win32_OperatingSystem and got the "Name" value back. This then needs to be split to get the first object which is what you require. i.e.
Dim query2 As New SelectQuery("SELECT * FROM Win32_OperatingSystem")
Dim searcher2 As New ManagementObjectSearcher(objManagementScope2, query2, QueryOptions)
For Each mo As ManagementObject In searcher2.[Get]()
OSname = mo("Name")
Next
Dim array1 As Array = Nothing
array1 = Split(OSname, "|")
OSname = array1(0).ToString
OSname then gives you the "Windows 11 Pro" or "Windows XP Professional" that you require.
I also get the OSVersion with the latest patch update info from registry as follows if needed...
THIS IS FOR CLIENT VERSIONS 10/11 :-
.SetPropertyValue("sSubKeyName", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Update\TargetingInfo\Installed\Client.OS.rs2.amd64")
.SetPropertyValue("sValueName", "Version")
THIS IS FOR SERVER VERSIONS 2019 :-
.SetPropertyValue("sSubKeyName", "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Update\TargetingInfo\Installed\Server.OS.amd64")
.SetPropertyValue("sValueName", "Version")
Hope this is of help.

C# Get OS Name Windows 8.1

I like to check if the running window is windows 8 or windows 8.1.
With the Windows Major Check
6.2 -> Win 8
6.3 -> Win 8.1
That doesn't work, because with the release of Windows 8.1, the behavior of the GetVersion API has changed in the value it will return for the operating system version.
How can I still get the Version correctly?
You could find that info in the registry of Windows. For example, if you have installed Windows 8.1 Pro Edition and execute this lines:
using Microsoft.Win32;
//...
var windowsName= Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "ProductName","");
var version= Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "CurrentVersion", "");
var build= Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\", "CurrentBuild", "");
You will get Windows 8.1 Pro, 6.3 and 9600 respectively.
Also you could use the WMI to get the Windows name, check the answer in this post:
public static string GetOSFriendlyName()
{
string result = string.Empty;
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem");
foreach (ManagementObject os in searcher.Get())
{
result = os["Caption"].ToString();
break;
}
return result;
}
try this
it concats the major version no followed by the minor version
there are many methods to play with according here Environment Class (System)
string ver = Environment.OSVersion.Version.Major + "." + Environment.OSVersion.Version.Minor;
and the output would be:
6.2

How to detect Windows Phone 8.1 OS version programmatically?

The question in title is not the real problem. I went through many sites and blogs and go to know that Environment.OSVersion gives you the current OS version of the phone using our app. But the problem is, There is no OSVersion under the class Environment. Please refer the screenshot for better understanding.
My question why I am not able to see the OSVersion property under Environment class? Am I missing something?
Universal/WinRT apps only work in wp 8.1, so the OS version can only be 8.1. When they make wp8.2 or wp9, they'll probably add a way to check what OS version is installed...
If you're looking for the firmware version, you can get it with:
Windows.Security.ExchangeActiveSyncProvisioning.EasClientDeviceInformation deviceInfo = new Windows.Security.ExchangeActiveSyncProvisioning.EasClientDeviceInformation();
var firmwareVersion = deviceInfo.SystemFirmwareVersion;
Copied from duped question:
Windows Phone 8.1 Silverlight apps can use the .NET version APIs. There is no supported mechanism to get a version number in Universal 8.1 apps, but you can try using reflection to get the Windows 10 AnalyticsInfo class, which will at least tell you the version number if you are running on Windows 10.
Note: Checking the OS version is almost always the wrong thing to do, unless you're simply displaying it to the user (eg, in an "About" box) or sending it to your back-end analytics server for number crunching. It should not be used to make any run-time decisions, because in general it's a poor proxy for whatever-you're-actually-trying-to-do.
Here is a sample:
var analyticsInfoType = Type.GetType(
"Windows.System.Profile.AnalyticsInfo, Windows, ContentType=WindowsRuntime");
var versionInfoType = Type.GetType(
"Windows.System.Profile.AnalyticsVersionInfo, Windows, ContentType=WindowsRuntime");
if (analyticsInfoType == null || versionInfoType == null)
{
Debug.WriteLine("Apparently you are not on Windows 10");
return;
}
var versionInfoProperty = analyticsInfoType.GetRuntimeProperty("VersionInfo");
object versionInfo = versionInfoProperty.GetValue(null);
var versionProperty = versionInfoType.GetRuntimeProperty("DeviceFamilyVersion");
object familyVersion = versionProperty.GetValue(versionInfo);
long versionBytes;
if (!long.TryParse(familyVersion.ToString(), out versionBytes))
{
Debug.WriteLine("Can't parse version number");
return;
}
Version uapVersion = new Version((ushort)(versionBytes >> 48),
(ushort)(versionBytes >> 32),
(ushort)(versionBytes >> 16),
(ushort)(versionBytes));
Debug.WriteLine("UAP Version is " + uapVersion);
Obviously you can update this to return the version etc. rather than print it to the debug console.
You cannot get the OS Version in Windows 8.1 .Check the following link for the same - https://social.msdn.microsoft.com/Forums/windowsapps/en-US/2b455331-3bad-4d26-b615-a59d0e05d0dd/how-to-get-os-version-on-window-phone?forum=wpdevelop
I found a tricky way to detect if a device is running a Windows Phone 8.1 or Windows Phone 10. I compared 3 different devices, a Nokia Lumia 925 ( wp 8.1 ) a Nokia Lumia 735 ( wp 10 ) and a Nokia Lumia 930 ( wp 10 ). I noticed that on wp8.1 there is no device info id ( it causes a not implemented exception ) but it exists on windows phone 10 on both tested devices. Morover the system firmware version format seems different between wp 8.1 and wp 10 ( the first is xxxx.xxxxx.xxxx.xxxx while the second is xxxxx.xxxxx.xxxxx.xxxxx ). Below my function:
/// <summary>
/// Indicates if this device is running a version of Windows Phone 8.1. It use a dirty trick for detecting the OS major version
/// based on the system firmware version format (8.1 is xxxx.xxxxx.xxxx.xxxx while 10 is xxxxx.xxxxx.xxxxx.xxxxx )
/// moreover, the "deviceInfo.id" is not implemented on Windows Phone 8.1, but it is on Windows Phone 10
/// </summary>
/// <returns></returns>
public static bool liIsWindowsPhone81(bool basedOnDeviceInfoId)
{
EasClientDeviceInformation deviceInfo = new Windows.Security.ExchangeActiveSyncProvisioning.EasClientDeviceInformation();
bool isWin81 = false;
if (basedOnDeviceInfoId)
{
try
{
var deviceInfoId = deviceInfo.Id;
}
catch
{
isWin81 = true;
}
}
else
{
string firmwareVersion = deviceInfo.SystemFirmwareVersion.Trim();
string[] parts = firmwareVersion.Split('.');
if (parts[0].Length == 4 && parts[1].Length == 5 && parts[2].Length == 4 && parts[3].Length == 4)
{
isWin81 = true;
}
}
return isWin81;
}
I haven't had the opportunity to test this on further devices, but so far seems to work. I use it to distinguish the code for the app rating function between Windows Phone 8.1 and Windows Phone 10, that in my specific case are not UWP
Hope this helps
If your app is Silverlight based, you can use System.Environment.OSVersion.Version across Windows Phone 8.0 and 8.1 as well as Windows Mobile 10.
Here is an example of a method we utilize when determining whether to display our own opt-in dialog for geo-tracking or let the Windows Mobile 10 present its own opt-in dialog.
public static bool IsWindowsPhone8x()
{
try
{
Version version = System.Environment.OSVersion.Version;
return version.Major > 8 ? false : true;
}
catch (Exception)
{
return false;
}
}
Simply use this line to get the Application Name and Id, publisher name etc...
string name = Windows.ApplicationModel.Package.Current.DisplayName;

Mono on debian error CS0234

I have a debian server and i saved its mac address on a txt file in the /usr folder.
Every time i start the machine the script i'm trying to do should check the current mac address and compare it to the one saved on the txt file. If they don't match than the machine should shutdown.
The code works on Windows , but i have to make it work on debian. So i installed mono (apt-get install mono-complete) ,created the .cs file containing the code and transferred it on debian machine.
When i run the mcs shutdown.cs (shutdown is the name of the file i created) command i get this error :
CS0234: The type or namespace name 'NetworkInformation' does not exist i the namespace 'System.Net'. Are you missing an assembly reference?**
How can this be solved?
using System.Net.NetworkInformation;
static void Main(string[] args)
{
string newmc = Convert.ToString(GetMacAddress()); //current mac address
string mc = File.ReadAllText(#"/usr/mc.txt"); //mac address saved on a txt file previously
if (newmc != mc) //shutdown if the mac addresses dont match
{
System.Diagnostics.Process.Start("shutdown.exe", "-s -t 0");
}
}
static string GetMacAddress()
{
string macAddresses = "";
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.NetworkInterfaceType != NetworkInterfaceType.Ethernet) continue;
if (nic.OperationalStatus == OperationalStatus.Up)
{
macAddresses += nic.GetPhysicalAddress().ToString();
break;
}
}
return macAddresses;
}
System.Net.NetworkInformation.NetworkInterface class is in System.dll according to this: http://msdn.microsoft.com/en-us/library/system.net.networkinformation.networkinterface . Did you try adding a reference to System.dll when compiling? I believe it's the "-r" argument to mcs.
BTW, what version of Mono are you using. Debian is famous for shipping very old versions of Mono in the "stable" flavour. Mono 2.10.x or higher is recommended, nowadays, as stable.
System.Net.NetworkInformation.NetworkInterface was introduced .NET 2.0. You need to target .NET 2.0 profile or newer if you want to use it.
If you are compiling using command line compiler use gmcs or dmcs to compile your project.
If you are using MonoDevelop you need to set in project setting appropriate framework version.
This is how you might do this in Ruby.
begin
theMac = File.read("/usr/path/to/text/file.txt")
rescue Exception => e
puts e.message
puts e.backtrace.inspect
end
response = `ifconfig eth0`
mac = response.match(/HWaddr (.*?):(.*?):(.*?):(.*?):(.*?):(.*?) /)
if theMac == mac[0] then `sudo shutdown -h now`; end
f = File.open("/usr/path/to/text/file.txt", "w")
f.write(mac[0])
f.close()

how to detect only windows 2003 computers from domain

Consider domain of all windows based computers. from these computers i want to detect only windows server 2003 computers.
I have all machine names of all machines in domain. then how to determine OS version from machine name. I have used Environment.OSVersion to get os version of local computer. How can i obtain OS version of remote computer if i know remote computer name ?
You can use WMI (Windows Management Instrumentation) to access the remote computer's
Win32_OperatingSystem class instance.
using (var mc = new ManagementClass(#"\\" + computerName + #"\root\cimv2:Win32_OperatingSystem"))
{
foreach (var obj in mc.GetInstances())
{
if (((bool)obj.Properties["Primary"].Value))
{
int productType = (int)obj.Properties["ProductType"].Value;
string version = obj.Properties["Version"].Value.ToString();
bool isServer = (productType == 2 || productType == 3); // "Domain Controller" or "Server
if (version == "5.2.3790" && isServer)
{
// "Caption" should contain something like "Microsoft(R) Windows(R) Server 2003..."
// Please resist parsing that, however.
Console.WriteLine(obj.Properties["Caption"].Value);
}
}
}
}
For details on the properties and what values are available, see the MSDN pages for the Win32_OperatingSystem class.

Categories

Resources