views:

846

answers:

2

The normal way to get the windows serial number is WMI.

 ManagementObjectSearcher mos = new ManagementObjectSearcher("Select * From Win32_OperatingSystem");
 // ...
 // Select number from managementobject mo["SerialNumber"]

I don't want to use WMI because the compact framework dosn't support it. The assembly must work on the desktop and the compact framework side so i can't add the reference.

How can i get the same result using a pinvoke call?

+1  A: 

You'll need to invoke KernelIOControl for WindowsCE.

Here's the c++ code, don't have the time to convert it to c#

#include <WINIOCTL.H> 
extern "C" __declspec(dllimport) 
BOOL KernelIoControl( DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned ); 
#define IOCTL_HAL_GET_DEVICEID CTL_CODE(FILE_DEVICE_HAL, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) 

CString GetSerialNumberFromKernelIoControl() { 
    DWORD dwOutBytes; 
    const int nBuffSize = 4096; 
    byte arrOutBuff[nBuffSize]; 
    BOOL bRes = ::KernelIoControl(IOCTL_HAL_GET_DEVICEID, 0, 0, arrOutBuff, nBuffSize, &dwOutBytes); 
    if (bRes) { CString strDeviceInfo; for (unsigned int i = 0; i<dwOutBytes; i++) { 
     CString strNextChar; strNextChar.Format(TEXT("%02X"), arrOutBuff[i]); strDeviceInfo += strNextChar; 
    } 
    CString strDeviceId = strDeviceInfo.Mid(40,2) + strDeviceInfo.Mid(45,9) + strDeviceInfo.Mid(70,6); 
    return strDeviceId; 
    } else { 
     return _T(""); 
    } 
}

Edit: (pinvoke kernelIOControl c#)

[DllImport("coredll.dll")]
    public static extern bool KernelIoControl(long dwIoControlCode, IntPtr lpInBuff, long dwInBuffSize, IntPtr lpOutBuff, long dwOutBuffSize, IntPtr lpBytesReturned);
Stormenet
A: 

First off, you're not going to have a single call that works on the desktop and the device. Just won't happen. What you can do is determine the runtime environment with a call something like this:

if(Environment.OSVersion.Platform == PlatformID.WinCE) { ... }

This will give you separation for desktop and device.

Then you have to add the complexity for devices, and for that you need to know about your target hardware. For Windows Mobile 5.0 and later you want to call GetDeviceUniqueID, as the KernelIoControl call is very likely going to be protected.FOr Pocket PC 2003 and earlier, the KernelIoControl P/Invoke is reasonable, though many devices are known to present the same result, so it's not guaranteed unique.

For generic Windows CE devices it's far more varied. There's nothing that guarantees that a platform implements IOCTL_HAL_GET_DEVICEID, so you're going to want to protect for the failure and find some other mechanism (often OEMs implement their own ID API). For CE 6.0, KernelIoControl is very restricted for apps, and it's unlikely that you can call it without a kernel or driver wrapper API from the OEM.

ctacke