Пошаговое руководство. Получение имени и идентификатора устройства
Обновлен: Ноябрь 2007
Чтобы получить имя устройства, используйте свойство Dns.GetHostName. Типичным именем по умолчанию является "PocketPC".
Пример
В этом примере отображается идентификатор и имя устройства в окнах сообщения при загрузке формы.
Чтобы получить идентификатор устройства или серийное имя, следует использовать вызов платформы для доступа к машинной функции KernelIoControl.
Imports System
Imports System.Drawing
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Text
Imports Microsoft.VisualBasic
Public Class DeviceID
Inherits System.Windows.Forms.Form
Declare Function KernelIoControl Lib "CoreDll.dll" _
(ByVal dwIoControlCode As Int32, _
ByVal lpInBuf As IntPtr, _
ByVal nInBufSize As Int32, _
ByVal lpOutBuf() As Byte, _
ByVal nOutBufSize As Int32, _
ByRef lpBytesReturned As Int32) As Boolean
Public Sub New()
Me.Text = "DeviceID"
' Display OK close button.
Me.MinimizeBox = False
End Sub
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
MyBase.Dispose(disposing)
End Sub
Shared Sub Main()
Application.Run(New DeviceID)
End Sub
Private Shared METHOD_BUFFERED As Int32 = 0
Private Shared FILE_ANY_ACCESS As Int32 = 0
Private Shared FILE_DEVICE_HAL As Int32 = &H101
Private Const ERROR_NOT_SUPPORTED As Int32 = &H32
Private Const ERROR_INSUFFICIENT_BUFFER As Int32 = &H7A
Private Shared IOCTL_HAL_GET_DEVICEID As Int32 = _
(&H10000 * FILE_DEVICE_HAL) Or (&H4000 * FILE_ANY_ACCESS) _
Or (&H4 * 21) Or METHOD_BUFFERED
Private Shared Function GetDeviceID() As String
' Initialize the output buffer to the size of a
' Win32 DEVICE_ID structure
Dim outbuff(19) As Byte
Dim dwOutBytes As Int32
Dim done As Boolean = False
Dim nBuffSize As Int32 = 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 Not done
If KernelIoControl(IOCTL_HAL_GET_DEVICEID, IntPtr.Zero, _
0, outbuff, nBuffSize, dwOutBytes) Then
done = True
Else
Dim errnum As Integer = Marshal.GetLastWin32Error()
Select Case errnum
Case ERROR_NOT_SUPPORTED
Throw New NotSupportedException( _
"IOCTL_HAL_GET_DEVICEID is not supported on this device", _
New Win32Exception(errnum))
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)
Case Else
Throw New Win32Exception(errnum, "Unexpected error")
End Select
End If
End While
' Copy the elements of the DEVICE_ID structure.
Dim dwPresetIDOffset As Int32 = BitConverter.ToInt32(outbuff, &H4)
Dim dwPresetIDSize As Int32 = BitConverter.ToInt32(outbuff, &H8)
Dim dwPlatformIDOffset As Int32 = BitConverter.ToInt32(outbuff, &HC)
Dim dwPlatformIDSize As Int32 = BitConverter.ToInt32(outbuff, &H10)
Dim sb As New StringBuilder
Dim i As Integer
For i = dwPresetIDOffset To (dwPresetIDOffset + dwPresetIDSize) - 1
sb.Append(String.Format("{0:X2}", outbuff(i)))
Next i
sb.Append("-")
For i = dwPlatformIDOffset To (dwPlatformIDOffset + dwPlatformIDSize) - 1
sb.Append(String.Format("{0:X2}", outbuff(i)))
Next i
Return sb.ToString()
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
' Show the device ID.
Dim deviceID As String = GetDeviceID()
MessageBox.Show("Device ID: " + deviceID)
' Show the device name.
Dim deviceName As String = System.Net.Dns.GetHostName()
MessageBox.Show("Device Name: " & deviceName)
Catch ex As Exception
MessageBox.Show(ex.Message.ToString())
End Try
End Sub
End Class
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
//
InitializeComponent();
//
// 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());
}
#endregion
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;
}
else
{
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);
break;
default:
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]));
}
sb.Append("-");
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)
{
try
{
// 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)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
}
Компиляция кода
Для этого примера требуются ссылки на следующие пространства имен:
Отказоустойчивость
В следующей таблице перечисляются параметры машинных функций KernelIoControl. Все по 32 бита.
Параметр |
Тип Win32 |
Управляемый тип |
Типичное значение |
---|---|---|---|
dwIoControlCode |
DWORD |
IOCTL_HAL_GET_DEVICEID |
|
lpInBuf |
LPVOID |
IntPtr.Zero( не требуется никаких входных данных). |
|
nInBufSize |
DWORD |
0 ( не требуется никаких входных данных). |
|
lpOutBuf |
LPVOID* |
Двадцатибайтный элемент массива Byte (20 байтов — это размер структуры DEVICE_ID). |
|
nOutBufSize |
DWORD |
20 |
|
lpBytesReturned |
LPWORD |
refInt32 |
0 |
Параметр lpOutBuf имеет следующую структуру:
Structure DEVICE_ID
Private dwSize As Integer
Private dwPresetIDOffset As Integer
Private dwPresetIDBytes As Integer
Private dwPlatformIDOffset As Integer
Private dwPlatformIDBytes As Integer
End Structure
struct DEVICE_ID
{
int dwSize;
int dwPresetIDOffset;
int dwPresetIDBytes;
int dwPlatformIDOffset;
int dwPlatformIDBytes;
}
Обработка ошибок и возвращение значений.
Функция KernelIoControl возвращает true, если идентификатор устройства был скопирован во внешний буфер; в противном случае она возвращает false. Если KernelIoControl вызывает ошибку, вызов управляемого метода GetLastWin32Errorполучает Win32-код ошибки. Код ошибки должен быть следующего вида:
ERROR_NOT_SUPPORTED — Указывает, что устройство не выполнило код элемента управления IOCTL_HAL_GET_DEVICEID.
ERROR_INSUFFICIENT_BUFFER — Указывает, что внешний буфер был недостаточно велик, чтобы вместить идентификатор устройства. Требуемое количество байтов, указанное dwSize в структуре DEVICE_ID, возвращают первые четыре байта выходного буфера Если возникает эта ошибка, перераспределите выходной буфер, увеличив его до размера dwSize, и снова вызовите KernelIoControl.
См. также
Задачи
Практическое руководство. Возвращение значения памяти устройства