How to: Get the Device ID and Name
Important This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here. ArchiveDisclaimer

How to: Get the Device ID and Name

To get the name of the device, use the Dns.GetHostName property. A typical default name is "PocketPC".

This example displays the ID and name of the device in messages boxes when the form loads.

To get the device ID, or serial number, you must use platform invoke to access the native Windows CE KernelIoControl function.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;

namespace DeviceID
    /// <summary> 
    /// Summary description for DeviceID. 
    /// </summary> 
    public class DeviceID : System.Windows.Forms.Form

    public DeviceID()
            // Required for Windows Form Designer support 

            // TODO: Add any constructor code after InitializeComponent call 

        /// <summary> 
        /// Clean up any resources being used. 
        /// </summary> 
        protected override void Dispose( bool disposing )
            base.Dispose( disposing );

        #region Windows Form Designer generated code
        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor. 
        /// </summary> 
        private void InitializeComponent()
            // DeviceID 
            this.Text = "DeviceID";
            this.Load += new System.EventHandler(this.DeviceID_Load);

        static void Main() 
            Application.Run(new DeviceID());

        private static Int32 METHOD_BUFFERED = 0;
        private static Int32 FILE_ANY_ACCESS = 0;
        private static Int32 FILE_DEVICE_HAL = 0x00000101;

        private const Int32 ERROR_NOT_SUPPORTED = 0x32;
        private const Int32 ERROR_INSUFFICIENT_BUFFER = 0x7A;

        private static Int32 IOCTL_HAL_GET_DEVICEID = 
            ((FILE_DEVICE_HAL) << 16) | ((FILE_ANY_ACCESS) << 14) 
            | ((21) << 2) | (METHOD_BUFFERED);

        [DllImport("coredll.dll", SetLastError=true)]
        private static extern bool KernelIoControl(Int32 dwIoControlCode, 
            IntPtr lpInBuf, Int32 nInBufSize, byte[] lpOutBuf, 
            Int32 nOutBufSize, ref Int32 lpBytesReturned);

        private static string GetDeviceID()
            // Initialize the output buffer to the size of a  
            // Win32 DEVICE_ID structure. 
            byte[] outbuff = new byte[20];
            Int32  dwOutBytes;
            bool done = false;

            Int32 nBuffSize = outbuff.Length;

            // Set DEVICEID.dwSize to size of buffer.  Some platforms look at 
            // this field rather than the nOutBufSize param of KernelIoControl 
            // when determining if the buffer is large enough.
            BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0);  
            dwOutBytes = 0;

            // Loop until the device ID is retrieved or an error occurs. 
            while (! done)
                if (KernelIoControl(IOCTL_HAL_GET_DEVICEID, IntPtr.Zero, 
                    0, outbuff, nBuffSize, ref dwOutBytes))
                    done = true;
                    int error = Marshal.GetLastWin32Error();
                    switch (error)
                    case ERROR_NOT_SUPPORTED:
                        throw new NotSupportedException(
                            "IOCTL_HAL_GET_DEVICEID is not supported on this device",
                            new Win32Exception(error));

                    case ERROR_INSUFFICIENT_BUFFER:

                        // The buffer is not big enough for the data.  The 
                        // required size is in the first 4 bytes of the output 
                        // buffer (DEVICE_ID.dwSize).
                        nBuffSize = BitConverter.ToInt32(outbuff, 0);
                        outbuff = new byte[nBuffSize];

                        // Set DEVICEID.dwSize to size of buffer.  Some 
                        // platforms look at this field rather than the 
                        // nOutBufSize param of KernelIoControl when 
                        // determining if the buffer is large enough.
                        BitConverter.GetBytes(nBuffSize).CopyTo(outbuff, 0);

                        throw new Win32Exception(error, "Unexpected error");

            // Copy the elements of the DEVICE_ID structure.
            Int32 dwPresetIDOffset = BitConverter.ToInt32(outbuff, 0x4);
            Int32 dwPresetIDSize = BitConverter.ToInt32(outbuff, 0x8);
            Int32 dwPlatformIDOffset = BitConverter.ToInt32(outbuff, 0xc);
            Int32 dwPlatformIDSize = BitConverter.ToInt32(outbuff, 0x10);
            StringBuilder sb = new StringBuilder();

            for (int i = dwPresetIDOffset; 
                i < dwPresetIDOffset + dwPresetIDSize; i++)
                sb.Append(String.Format("{0:X2}", outbuff[i]));


            for (int i = dwPlatformIDOffset; 
                i < dwPlatformIDOffset + dwPlatformIDSize; i ++ )  
                sb.Append( String.Format("{0:X2}", outbuff[i]));
            return sb.ToString();

        private void DeviceID_Load(object sender, System.EventArgs e)
                // Show the device ID. 
                string strDeviceID = GetDeviceID();
                MessageBox.Show("Device ID: " + strDeviceID);

                // Show the device name. 
                string deviceName = System.Net.Dns.GetHostName();
                MessageBox.Show("Device Name: " + deviceName);

            catch (Exception ex)

The following table lists the native KernelIoControl function parameters. All are 32 bits.


Win32 type

Managed type

Typical value








IntPtr.Zero (no input data required)




0 (no input data required)




A 20-element Byte array (20 bytes is the size of the DEVICE_ID structure)







ref Int32


The lpOutBuf parameter has the following structure:

struct DEVICE_ID
    int dwSize;
    int dwPresetIDOffset;
    int dwPresetIDBytes;
    int dwPlatformIDOffset;
    int dwPlatformIDBytes;

Return Values and Error Handling

The KernelIoControl function returns true if the device ID was copied to the output buffer; otherwise, it returns false. If KernelIoControl fails, call the managed GetLastWin32Error method to get the Win32 error code. The error code is likely to be either of the following:

  • ERROR_NOT_SUPPORTED - Indicates that the device does not implement the IOCTL_HAL_GET_DEVICEID control code.

  • ERROR_INSUFFICIENT_BUFFER - Indicates that the output buffer was not large enough to hold the device ID. The required number of bytes, specified by dwSize in the DEVICE_ID structure, is returned in the first four bytes of the output buffer. If this error occurs, reallocate the output buffer to the size specified by dwSize and call KernelIoControl again.

© 2016 Microsoft