c# How to use the new Version Helper API - c#

Since OSVersion is now not reliable since Windows 10 has been released (this function reports Windows 8 for Windows 10), I'm attempting to use the new Version Helper API functions in my C# application. Here they are.
I apologize if this is simply a issue with my DLL import, but here is my attempt to pull in these new methods to detect the OS correctly.
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows7OrGreater();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows8OrGreater();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows8Point1OrGreater();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindows10OrGreater();
Whenever I'm calling these methods, I'm getting:
Exception is: EntryPointNotFoundException - Unable to find an entry point named 'IsWindows7OrGreater' in DLL 'kernel32.dll'.
Am I doing something wrong? Anyone have any ideas? Thanks for any help!
EDIT: Please see the accepted answer and take a look at this code project for a good start on porting these methods over to C#.

Your code must have a Manifest that contains
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of all Windows versions that this application is designed to work with. Windows will automatically select the most compatible environment.-->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
</application>
</compatibility>
This tells the OS your code supports the newer OS
Use the following class
using System;
using System.Runtime.InteropServices;
namespace VersionHelper
{
public static class VersionHelper
{
const byte VER_EQUAL = 1;
const byte VER_GREATER = 2;
const byte VER_GREATER_EQUAL = 3;
const byte VER_LESS = 4;
const byte VER_LESS_EQUAL = 5;
const byte VER_AND = 6;
const byte VER_OR = 7;
const byte VER_CONDITION_MASK = 7;
const byte VER_NUM_BITS_PER_CONDITION_MASK = 3;
//
// RtlVerifyVersionInfo() type mask bits
//
const uint VER_MINORVERSION = 0x0000001;
const uint VER_MAJORVERSION = 0x0000002;
const uint VER_BUILDNUMBER = 0x0000004;
const uint VER_PLATFORMID = 0x0000008;
const uint VER_SERVICEPACKMINOR = 0x0000010;
const uint VER_SERVICEPACKMAJOR = 0x0000020;
const uint VER_SUITENAME = 0x0000040;
const uint VER_PRODUCT_TYPE = 0x0000080;
// wProductType
// Any additional information about the system.This member can be one of the following values.
const byte VER_NT_DOMAIN_CONTROLLER = 0x0000002;
const byte VER_NT_SERVER = 0x0000003;
const byte VER_NT_WORKSTATION = 0x0000001;
//
// _WIN32_WINNT version constants
//
const ushort _WIN32_WINNT_NT4 = 0x0400;
const ushort _WIN32_WINNT_WIN2K = 0x0500;
const ushort _WIN32_WINNT_WINXP = 0x0501;
const ushort _WIN32_WINNT_WS03 = 0x0502;
const ushort _WIN32_WINNT_WIN6 = 0x0600;
const ushort _WIN32_WINNT_VISTA = 0x0600;
const ushort _WIN32_WINNT_WS08 = 0x0600;
const ushort _WIN32_WINNT_LONGHORN = 0x0600;
const ushort _WIN32_WINNT_WIN7 = 0x0601;
const ushort _WIN32_WINNT_WIN8 = 0x0602;
const ushort _WIN32_WINNT_WINBLUE = 0x0603;
const ushort _WIN32_WINNT_WINTHRESHOLD = 0x0A00; /* ABRACADABRA_THRESHOLD*/
const ushort _WIN32_WINNT_WIN10 = 0x0A00; /* ABRACADABRA_THRESHOLD*/
const bool FALSE = false;
static byte LOBYTE(ushort w)
{
return ((byte)(w & 0xff));
}
static byte HIBYTE(ushort w)
{
return ((byte)(w >> 8 & 0xff));
}
[DllImport("kernel32.dll")]
static extern ulong VerSetConditionMask(ulong ConditionMask, uint TypeMask, byte Condition );
[DllImport("kernel32.dll")]
static extern bool VerifyVersionInfoW(ref OSVERSIONINFOEXW lpVersionInformation, uint dwTypeMask, ulong dwlConditionMask);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct OSVERSIONINFOEXW
{
public int dwOSVersionInfoSize;
public int dwMajorVersion;
public int dwMinorVersion;
public int dwBuildNumber;
public int dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szCSDVersion;
public UInt16 wServicePackMajor;
public UInt16 wServicePackMinor;
public UInt16 wSuiteMask;
public byte wProductType;
public byte wReserved;
}
public static bool
IsWindowsVersionOrGreater(ushort wMajorVersion, ushort wMinorVersion, ushort wServicePackMajor)
{
var osvi = new OSVERSIONINFOEXW
{
dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEXW))
};
var dwlConditionMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(ref osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}
public static bool
IsWindowsXPOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
}
public static bool
IsWindowsXPSP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
}
public static bool
IsWindowsXPSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
}
public static bool
IsWindowsXPSP3OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
}
public static bool
IsWindowsVistaOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
}
public static bool
IsWindowsVistaSP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
}
public static bool
IsWindowsVistaSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}
public static bool
IsWindows7OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
}
public static bool
IsWindows7SP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
}
public static bool
IsWindows8OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
}
public static bool
IsWindows8Point1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
}
public static bool
IsWindowsThresholdOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINTHRESHOLD), LOBYTE(_WIN32_WINNT_WINTHRESHOLD), 0);
}
public static bool
IsWindows10OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINTHRESHOLD), LOBYTE(_WIN32_WINNT_WINTHRESHOLD), 0);
}
public static bool
IsWindowsServer()
{
var osvi = new OSVERSIONINFOEXW
{
dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEXW)),
wProductType = VER_NT_WORKSTATION
};
var dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
return !VerifyVersionInfoW( ref osvi, VER_PRODUCT_TYPE, dwlConditionMask);
}
}
}

Unfortunately, it's a little more complicated than that. The "functions" are actually macros defined in VersionHelpers.h.
If you think of it, that's the only way to do it - they can't add functions to older Windows versions retroactively.
You have to port the macros over to C#.

VersionHelpers functions are not exported in any dll, but rather defined in VersionHelpers.h file,
in order to utilize the functionality in your C# code you can copy the functionality from the header file,
Import those 2 functions:
[DllImport("kernel32.dll")]
static extern ulong VerSetConditionMask(ulong dwlConditionMask, uint dwTypeBitMask, byte dwConditionMask);
[DllImport("kernel32.dll")]
static extern bool VerifyVersionInfo([In] ref OsVersionInfoEx lpVersionInfo, uint dwTypeMask, ulong dwlConditionMask);
Define the following structure:
[StructLayout(LayoutKind.Sequential)]
struct OsVersionInfoEx
{
public uint OSVersionInfoSize;
public uint MajorVersion;
public uint MinorVersion;
public uint BuildNumber;
public uint PlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string CSDVersion;
public ushort ServicePackMajor;
public ushort ServicePackMinor;
public ushort SuiteMask;
public byte ProductType;
public byte Reserved;
}
Then use the following function:
static bool IsWindowsVersionOrGreater(uint majorVersion, uint minorVersion, ushort servicePackMajor)
{
OsVersionInfoEx osvi = new OsVersionInfoEx();
osvi.OSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
osvi.MajorVersion = majorVersion;
osvi.MinorVersion = minorVersion;
osvi.ServicePackMajor = servicePackMajor;
// These constants initialized with corresponding definitions in
// winnt.h (part of Windows SDK)
const uint VER_MINORVERSION = 0x0000001;
const uint VER_MAJORVERSION = 0x0000002;
const uint VER_SERVICEPACKMAJOR = 0x0000020;
const byte VER_GREATER_EQUAL = 3;
ulong versionOrGreaterMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
uint versionOrGreaterTypeMask = VER_MAJORVERSION |VER_MINORVERSION | VER_SERVICEPACKMAJOR;
return VerifyVersionInfo(ref osvi, versionOrGreaterTypeMask, versionOrGreaterMask);
}

There's no need to work with interop/unmanaged code or add a target manifest.
Get Windows OS version with WMI

Like already mentioned here and on GetVersionEx and Environment.OSVersion docs, GetVersionEx behavior/availability changed with Windows 8.1. (And for .NET < 5.0, Environment.OSVersion reflects this)
The same applies to the VerifyVersionInfo function. If you use .NET 5 or Core, you can just use Environment.OSVersion again and by the way, my colleague working on our Core project, excluded the code that was querying WMI using ManagementObjectSearcher with directives as it did not compile for Core )
An alternate way would be to use the PInvoke from other answers with the Windows SDK counterparts (from ntdll.dll) of these functions
RtlGetVersion ( can use either the OSVERSIONINFOW a OSVERSIONINFOEXW structure, which are aliases for non-SDK counterparts. Just be sure to set the dwOSVersionInfoSize before calling it so it knows which one you are referencing. )
RtlVerifyVersionInfo
They use the same structs as the functions from kernel23.dll, and can be used the same way (also using the VerSetConditionMask function as substitute for the documented VER_SET_CONDITION macro but only Unicode versions are available, so be sure to annotate the structs with StructLayoutAttribute with Charset set to CharSet.Unicode as C# defaults to ANSI)
So code already posted should give reliable results if the following imports are used instead:
(In case you can't or don't want to use WMI or the registry)
[DllImport("kernel32.dll")]
private static extern ulong VerSetConditionMask(ulong dwlConditionMask, uint dwTypeBitMask, byte dwConditionMask);
[DllImport("ntdll.dll")]
private static extern uint RtlGetVersion(ref OSVERSIONINFOW lpVersionInformation);
[DllImport("ntdll.dll")]
private static extern uint RtlGetVersion(ref OSVERSIONINFOEXW lpVersionInformation);
[DllImport("ntdll.dll")]
private static extern bool RtlVerifyVersionInfo([In] ref OSVERSIONINFOEXW lpVersionInformation, uint dwTypeMask, ulong dwlConditionMask);

Related

How can I detect which version of Windows is running?

I have an application which runs as a Word add-in. (VSTO).
It runs on many PCs all over the world. In certain cases I need to trouble shoot problems (obviously remotely) and have a reporting mechanism which tells me which Windows OS is running - I use Environment.OSVersion in .NET. At least it did until Windows 10.
There is an article on MSDN (Targeting your application for Windows) about creating an application manifest which will enable the correct version to be returned.
But my application is a DLL, not an EXE and so won't really accommodate the XML code referred to in that article.
Is there no way to just ask Windows, "What version are you? Really, I won't cry if you admit to the real version".
Or an entry in the registry or something?
If WMI is not an option for you, You could use the SDK counterparts of the GetVersionEx functions, RtlGetVersion. They don't lie.
If you use .NET 5.0 or Core, Environment.OSVersion reports the actual version of Windows.
I posted more detail about this as addition to the answers on this other thread:
https://stackoverflow.com/a/64804643/2240196
EDIT: Added example code as requested. (You probably don't need all of it)
using System;
using System.Runtime.InteropServices;
namespace VersionHelper
{
public static class VersionHelper
{
// The C(++) macro VER_SET_CONDITION mentioned in the documentation for RtlVerifyVersionInfo seems to be equivalent to the VerSetConditionMask function in kernel32.dll
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-versetconditionmask
[DllImport("kernel32.dll")]
private static extern ulong VerSetConditionMask(ulong dwlConditionMask, uint dwTypeBitMask, byte dwConditionMask);
// https://learn.microsoft.com/en-us/windows/win32/devnotes/rtlgetversion
[DllImport("ntdll.dll")]
private static extern int RtlGetVersion(ref OSVERSIONINFOW lpVersionInformation);
[DllImport("ntdll.dll")]
private static extern int RtlGetVersion(ref OSVERSIONINFOEXW lpVersionInformation);
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlverifyversioninfo
[DllImport("ntdll.dll")]
private static extern bool RtlVerifyVersionInfo([In] ref OSVERSIONINFOEXW lpVersionInformation, uint dwTypeMask, ulong dwlConditionMask);
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexw
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct OSVERSIONINFOEXW
{
internal uint dwOSVersionInfoSize;
internal uint dwMajorVersion;
internal uint dwMinorVersion;
internal uint dwBuildNumber;
internal uint dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
internal string szCSDVersion;
internal ushort wServicePackMajor;
internal ushort wServicePackMinor;
internal ushort wSuiteMask;
internal byte wProductType;
internal byte wReserved;
}
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfow
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct OSVERSIONINFOW
{
internal uint dwOSVersionInfoSize;
internal uint dwMajorVersion;
internal uint dwMinorVersion;
internal uint dwBuildNumber;
internal uint dwPlatformId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
internal string szCSDVersion;
}
/*
* RTL_OSVERSIONINFOEX(A/W) and OSVERSIONINFOEX(A/W) are aliases for the same structures
* RTL_OSVERSIONINFO(A/W) and OSVERSIONINFO(A/W) are aliases for the same structures
* */
// These constants initialized with corresponding definitions in
// winnt.h (part of Windows SDK)
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-ver_set_condition
private const byte VER_EQUAL = 1;
private const byte VER_GREATER = 2;
private const byte VER_GREATER_EQUAL = 3;
private const byte VER_LESS = 4;
private const byte VER_LESS_EQUAL = 5;
private const byte VER_AND = 6;
private const byte VER_OR = 7;
private const byte VER_CONDITION_MASK = 7;
private const byte VER_NUM_BITS_PER_CONDITION_MASK = 3;
private const uint STATUS_SUCCESS = 0x00000000;
//
// RtlVerifyVersionInfo() type mask bits
//
private const uint VER_MINORVERSION = 0x0000001;
private const uint VER_MAJORVERSION = 0x0000002;
private const uint VER_BUILDNUMBER = 0x0000004;
private const uint VER_PLATFORMID = 0x0000008;
private const uint VER_SERVICEPACKMINOR = 0x0000010;
private const uint VER_SERVICEPACKMAJOR = 0x0000020;
private const uint VER_SUITENAME = 0x0000040;
private const uint VER_PRODUCT_TYPE = 0x0000080;
// wProductType
// Any additional information about the system.This member can be one of the following values.
private const byte VER_NT_DOMAIN_CONTROLLER = 0x0000002;
private const byte VER_NT_SERVER = 0x0000003;
private const byte VER_NT_WORKSTATION = 0x0000001;
// You can customize this to check for the condition(s) you need using any field from the OSVERSIONINFOW struct with the corresponding VER_ and VER_<operator> constants
public static bool IsWindowsVersionOrGreater(uint majorVersion, uint minorVersion, ushort servicePackMajor = 0, uint buildNumber = 0)
{
var osVerInfo = new OSVERSIONINFOEXW
{
dwOSVersionInfoSize = (uint) Marshal.SizeOf(typeof(OSVERSIONINFOEXW)),
dwMajorVersion = majorVersion,
dwMinorVersion = minorVersion,
wServicePackMajor = servicePackMajor,
dwBuildNumber = buildNumber
};
ulong versionOrGreaterMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
uint versionOrGreaterTypeMask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
if (buildNumber > 0)
{
versionOrGreaterMask = VerSetConditionMask(versionOrGreaterMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
versionOrGreaterTypeMask |= VER_BUILDNUMBER;
}
return RtlVerifyVersionInfo(ref osVerInfo, versionOrGreaterTypeMask, versionOrGreaterMask);
}
public static bool IsWindowsServer()
{
var osVerInfo = new OSVERSIONINFOEXW
{
dwOSVersionInfoSize = (uint) Marshal.SizeOf(typeof(OSVERSIONINFOEXW)),
wProductType = VER_NT_WORKSTATION
};
ulong dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
return !RtlVerifyVersionInfo(ref osVerInfo, VER_PRODUCT_TYPE, dwlConditionMask);
}
public static int GetWindowsBuildNumber()
{
var osVerInfo = new OSVERSIONINFOW
{
dwOSVersionInfoSize = (uint) Marshal.SizeOf(typeof(OSVERSIONINFOW))
};
if (STATUS_SUCCESS == RtlGetVersion(ref osVerInfo)) // documented to always return STATUS_SUCCESS
return (int)osVerInfo.dwBuildNumber;
throw new Win32Exception("Failed to determine Windows build number.");
}
// Other functions replicating SDK Version Helper functions
// https://learn.microsoft.com/en-us/windows/win32/sysinfo/version-helper-apis
//
// _WIN32_WINNT version constants
//
const ushort _WIN32_WINNT_NT4 = 0x0400;
const ushort _WIN32_WINNT_WIN2K = 0x0500;
const ushort _WIN32_WINNT_WINXP = 0x0501;
const ushort _WIN32_WINNT_WS03 = 0x0502;
const ushort _WIN32_WINNT_WIN6 = 0x0600;
const ushort _WIN32_WINNT_VISTA = 0x0600;
const ushort _WIN32_WINNT_WS08 = 0x0600;
const ushort _WIN32_WINNT_LONGHORN = 0x0600;
const ushort _WIN32_WINNT_WIN7 = 0x0601;
const ushort _WIN32_WINNT_WIN8 = 0x0602;
const ushort _WIN32_WINNT_WINBLUE = 0x0603;
const ushort _WIN32_WINNT_WINTHRESHOLD = 0x0A00;
const ushort _WIN32_WINNT_WIN10 = 0x0A00;
const bool FALSE = false;
static byte LOBYTE(ushort w)
{
return ((byte)(w & 0xff));
}
static byte HIBYTE(ushort w)
{
return ((byte)(w >> 8 & 0xff));
}
public static bool
IsWindowsXPSP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
}
public static bool
IsWindowsXPSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
}
public static bool
IsWindowsXPSP3OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
}
public static bool
IsWindowsVistaOrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
}
public static bool
IsWindowsVistaSP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
}
public static bool
IsWindowsVistaSP2OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}
public static bool
IsWindows7OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
}
public static bool
IsWindows7SP1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
}
public static bool
IsWindows8OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
}
public static bool
IsWindows8Point1OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
}
public static bool
IsWindows10OrGreater()
{
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0);
}
}
}
private String GetOSVersion()
{
var wmiEnum = new ManagementObjectSearcher("root\\CIMV2", "SELECT Version FROM Win32_OperatingSystem").Get().GetEnumerator();
wmiEnum.MoveNext();
return wmiEnum.Current.Properties["Version"].Value as String;
}
Returns 6.1.7601 on my W7 system and 10.0.14393 on my Server 2016 system.
No need to add a target manifest.
WMI is the best way to do this kind of stuff You can use this to retrieve OS informations :
ManagementObjectSearcher objMOS =
new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_OperatingSystem");
OS.Name = ((string)objMOS["Caption"]).Trim();
OS.Version = (string)objMOS["Version"];
OS.MaxProcessCount = (uint)objMOS["MaxNumberOfProcesses"];
OS.MaxProcessRAM = (ulong)objMOS["MaxProcessMemorySize"];
OS.Architecture = (string)objMOS["OSArchitecture"];
OS.SerialNumber = (string)objMOS["SerialNumber"];
OS.Build = ((string)objMOS["BuildNumber"]).ToUint();
This can fetch the OS details for you.
You can try GetVersionEx Win32 API.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx
Note that Windows 10 in fact is version 6.4. Ver 6.0 is Vista, 6.1 - 7, 6.2 - 8.

Marshalling Struct with Array of Struct Member

I'm trying to marshal the MIB_TCPTABLE_OWNER_MODULE struct from a P/Invoked' call into GetExtendedTcpTable, defined in iphlpapi.dll.
My P/Invoke signature is defined as this:
[DllImport("iphlpapi.dll", SetLastError = true)]
private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwSize, bool sort, int ipVersion, int tableClass, int reserved);
According to the documentation on MSDN (and looking through the header files), this should set the pTcpTable parameter to the address of a MIB_TCPTABLE_OWNER_MODULE structure, who has a member which is an array of MIB_TCPROW_OWNER_MODULE structures. From tcpmib.h:
typedef struct _MIB_TCPTABLE_OWNER_MODULE
{
DWORD dwNumEntries;
MIB_TCPROW_OWNER_MODULE table[ANY_SIZE];
} MIB_TCPTABLE_OWNER_MODULE, *PMIB_TCPTABLE_OWNER_MODULE;
ANY_SIZE is defined to be 1.
Here is my problem; I've defined the MIB_TCPTABLE_OWNER_MODULE and MIB_TCPROW_OWNER_MODULE structs in C# like so:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_MODULE
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_MODULE table;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_MODULE
{
public uint dwState;
public uint dwLocalAddr;
public uint dwLocalPort;
public uint dwRemoteAddr;
public uint dwRemotePort;
public uint dwOwningPid;
public ulong liCreateTimestamp;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TCPIP_OWNING_MODULE_SIZE)]
public ulong[] OwningModuleInfo;
}
Since I won't know the size of the returned MIB_TCPTABLE_OWNER_MODULE's table member at declaration, my plan was to increment the IntPtr and use Marshal.PtrToStructure to extract each array member from the table member.
The call to Marshal.PtrToStructure returns (no memory violation exceptions), but I wind up with garbage values in the struct members. Here is my complete code:
[DllImport("iphlpapi.dll", SetLastError = true)]
private static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref int dwSize, bool sort, int ipVersion, int tableClass, int reserved);
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_MODULE
{
public uint dwState;
public uint dwLocalAddr;
public uint dwLocalPort;
public uint dwRemoteAddr;
public uint dwRemotePort;
public uint dwOwningPid;
public ulong liCreateTimestamp;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = TCPIP_OWNING_MODULE_SIZE)]
public ulong[] OwningModuleInfo;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_MODULE
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_MODULE table;
}
private const int TCPIP_OWNING_MODULE_SIZE = 16;
private const int AF_INET = 2;
private const int TCP_TABLE_OWNER_MODULE_ALL = 8;
public static void GetConnectionDetails()
{
var bufferSize = 0;
var ret = GetExtendedTcpTable(IntPtr.Zero, ref bufferSize, true, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
var tableBuffer = Marshal.AllocHGlobal(bufferSize);
try
{
ret = GetExtendedTcpTable(tableBuffer, ref bufferSize, true, AF_INET, TCP_TABLE_OWNER_MODULE_ALL, 0);
if (ret != 0)
throw new Exception("Oh noes!");
var convertedTable = (MIB_TCPTABLE_OWNER_MODULE)Marshal.PtrToStructure(tableBuffer, typeof (MIB_TCPTABLE_OWNER_MODULE));
var finalTable = new MIB_TCPROW_OWNER_MODULE[convertedTable.dwNumEntries];
var rowPtr = (IntPtr) ((long) tableBuffer + Marshal.SizeOf(convertedTable.dwNumEntries));
for (int i = 0; i < convertedTable.dwNumEntries; i++)
{
var row = (MIB_TCPROW_OWNER_MODULE)Marshal.PtrToStructure(rowPtr, typeof (MIB_TCPROW_OWNER_MODULE));
finalTable[i] = row;
rowPtr = (IntPtr) ((long) rowPtr + Marshal.SizeOf(row)); // Move to the next entry
}
foreach (var entry in finalTable)
{
// do something with each entry
Console.WriteLine(entry.dwState);
Console.WriteLine(entry.dwRemoteAddr);
}
}
finally
{
Marshal.FreeHGlobal(tableBuffer);
}
}
Comparing memory between this and an unmanaged version (that works properly), I do see some differences in the memory of the marshaled struct that I can't account for; there are a few bytes different.
Any assistance is most appreciated!
Consider this struct:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_MODULE
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_MODULE table;
}
You are assuming that the offset of table is equal to the size of dwNumEntries. But you are forgetting about alignment. Since the largest type in MIB_TCPROW_OWNER_MODULE is 8 bytes wide, that type has alignment of 8. Which means that in order for it to be aligned it must be placed at an offset that is a multiple of 8. And hence there is padding between dwNumEntries and table. You need to allow for that padding.
So, at this point:
var rowPtr = (IntPtr) ((long) tableBuffer +
Marshal.SizeOf(convertedTable.dwNumEntries));
you add 4 to the address held in tableBuffer. You actually need to add 8. You should use Marshal.OffsetOf to calculate the offset:
var rowPtr = (IntPtr)((long)tableBuffer +
(long)Marshal.OffsetOf(typeof(MIB_TCPTABLE_OWNER_MODULE), "table"));

SendInput fails on 64bit [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
SendInput and 64bits
I'm using SendInput from .NET code (PInvoke). code used to work fine on 32bit OS, but now on WIN7 SendInput returns 0, and last error is set to 57 (ERROR_INVALID_PARAMETER).I cannot compile my code as x86 as I am loaded into a 64bit host. Also, I tried various solutions regarding structure sizes and field offsets, none worked.
These are my PInvoke imports and types:
[StructLayout(LayoutKind.Sequential)]
struct KEYBOARD_INPUT
{
public uint type;
public ushort vk;
public ushort scanCode;
public uint flags;
public uint time;
public uint extrainfo;
public uint padding1;
public uint padding2;
}
[DllImport("User32.dll", SetLastError=true)]
private static extern uint SendInput(
uint numberOfInputs,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] KEYBOARD_INPUT[] input,
int structSize);
and code usage is:
uint result = SendInput(
(uint)inputs.Count,
inputs.ToArray(),
Marshal.SizeOf(inputs[0]));
where inputs array contains 1 KEYBOARD_INPUT struct.
this yields in result = 0, and when I check last error I get that last error is set to 57 (ERROR_INVALID_PARAMETER, The parameter is incorrect).
Is there a way to make this work under 64bit host in WIN7 64bit OS? this works in XP...
thanks
Try using the following definitions (courtesy of pinvoke.net):
const int INPUT_MOUSE = 0;
const int INPUT_KEYBOARD = 1;
const int INPUT_HARDWARE = 2;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_UNICODE = 0x0004;
const uint KEYEVENTF_SCANCODE = 0x0008;
struct INPUT
{
public int type;
public InputUnion u;
}
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
/*Virtual Key code. Must be from 1-254. If the dwFlags member specifies KEYEVENTF_UNICODE, wVk must be 0.*/
public ushort wVk;
/*A hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies a Unicode character which is to be sent to the foreground application.*/
public ushort wScan;
/*Specifies various aspects of a keystroke. See the KEYEVENTF_ constants for more information.*/
public uint dwFlags;
/*The time stamp for the event, in milliseconds. If this parameter is zero, the system will provide its own time stamp.*/
public uint time;
/*An additional value associated with the keystroke. Use the GetMessageExtraInfo function to obtain this information.*/
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
[DllImport("user32.dll")]
static extern IntPtr GetMessageExtraInfo();
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
Then, in your client code, use:
INPUT[] inputs = new INPUT[]
{
new INPUT
{
type = INPUT_KEYBOARD,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = key,
wScan = 0,
dwFlags = 0,
dwExtraInfo = GetMessageExtraInfo(),
}
}
}
};
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));

delete executing file on windows ce

i want to make a uninstaller on windows ce.
The Problem is I want to delete the uninstaller itself after executed everything else.
Is this possible somehow? Or is there someway to make a unistaller in another way?
You can just have the app move itself to the recycle bin. It's a pain because you have to P/Invoke to do this with an unintuative structure. This swatch should help with that.
private bool Recycle(string path)
{
try
{
ShowProgress(string.Format("Moving {0} to Recycle bin.", path));
SHFILEOPSTRUCT sfo = new SHFILEOPSTRUCT();
sfo.hwnd = IntPtr.Zero;
sfo.wFunc = FO_DELETE;
sfo.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
sfo.pFrom = path +'\0' + '\0';
sfo.pTo = null;
sfo.fAnyOperationsAborted = false;
sfo.hNameMappings = IntPtr.Zero;
sfo.lpszProgressTitle = string.Empty;
int ret = SHFileOperation(ref sfo);
return (ret == 0);
}
catch (Exception ex)
{
ShowProgress(string.Format("Failed to move {0} to Recycle bin.", path));
ShowProgress(ex.ToString());
}
return false;
}
// SHFileOperation wFunc and wFunc values
public const uint FO_MOVE = 0x0001;
public const uint FO_COPY = 0x0002;
public const uint FO_DELETE = 0x0003;
public const uint FO_RENAME = 0x0004;
public const ushort FOF_MULTIDESTFILES = 0x0001;
public const ushort FOF_CONFIRMMOUSE = 0x0002;
public const ushort FOF_SILENT = 0x0004; // don't create progress/report
public const ushort FOF_RENAMEONCOLLISION = 0x0008;
public const ushort FOF_NOCONFIRMATION = 0x0010; // Don't prompt the user.
public const ushort FOF_WANTMAPPINGHANDLE = 0x0020;// Fill in SHFILEOPSTRUCT.hNameMappings
// Must be freed using SHFreeNameMappings
public const ushort FOF_ALLOWUNDO = 0x0040;
public const ushort FOF_FILESONLY = 0x0080; // on *.*, do only files
public const ushort FOF_SIMPLEPROGRESS = 0x0100; // means don't show names of files
public const ushort FOF_NOCONFIRMMKDIR = 0x0200; // don't confirm making any needed dirs
public const ushort FOF_NOERRORUI = 0x0400; // don't put up error UI
public const ushort FOF_NOCOPYSECURITYATTRIBS = 0x0800; // dont copy NT file Security Attributes
public const ushort FOF_NORECURSION = 0x1000; // don't recurse ushorto directories.
//[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
//If you use the above you may encounter an invalid memory access exception (when using ANSI
//or see nothing (when using unicode) when you use FOF_SIMPLEPROGRESS flag.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;
public uint wFunc;
[MarshalAs(UnmanagedType.LPWStr)]
public string pFrom;
[MarshalAs(UnmanagedType.LPWStr)]
public string pTo;
public ushort fFlags;
[MarshalAs(UnmanagedType.Bool)]
public bool fAnyOperationsAborted;
public IntPtr hNameMappings;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpszProgressTitle;
}
[DllImport("ceshell.dll")]
public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);
killer.cmd:
:a
del uninstaller.exe
if exist uninstaller.exe goto a
del killer.cmd
Start it before exitting your uninstaller, so uninstaller.exe will be removed as soon as it's possible, and then killer.cmd is also removed.
// Though, not sure if there are .cmds in CE.

Detecting Audio Input & output devices connected to system

I want to findout how many audio input and output devices connected to my system in C#.net
Please suggest any.
Thanks.
You need to access the necessary Windows API functions.
This class should get you started - Win32.GetSoundDevices returns a list of device names. Look up WAVEOUTCAPS in the Windows SDK for details of the other information you can get.
public class Win32 {
[DllImport("winmm.dll", SetLastError=true)]
static extern uint waveOutGetNumDevs();
[DllImport("winmm.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern uint waveOutGetDevCaps(uint hwo,ref WAVEOUTCAPS pwoc,uint cbwoc);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct WAVEOUTCAPS {
public ushort wMid;
public ushort wPid;
public uint vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string szPname;
public uint dwFormats;
public ushort wChannels;
public ushort wReserved1;
public uint dwSupport;
}
public static string [] GetSoundDevices() {
uint devices = waveOutGetNumDevs();
string [] result = new string[devices];
WAVEOUTCAPS caps = new WAVEOUTCAPS();
for(uint i = 0; i < devices; i++) {
waveOutGetDevCaps(i, ref caps, (uint)Marshal.SizeOf(caps));
result[i] = caps.szPname;
}
return result;
}
}

Categories

Resources