2010-02-05 14 views
11

से दोस्ताना डिवाइस का नाम कैसे प्राप्त करें मैंने RegisterDeviceNotification के साथ एक विंडो पंजीकृत की है और DEV_BROADCAST_DEVICEINTERFACE संदेशों को सफलतापूर्वक प्राप्त कर सकता है। हालांकि, लौटाई गई संरचना में dbcc_name फ़ील्ड हमेशा खाली होता है। struct मैं इस तरह के रूप में परिभाषित किया जाता है:DEV_BROADCAST_DEVICEINTERFACE और डिवाइस इंस्टेंस आईडी

[StructLayout(LayoutKind.Sequential)] 
public struct DEV_BROADCAST_DEVICEINTERFACE 
{ 
    public int dbcc_size; 
    public int dbcc_devicetype; 
    public int dbcc_reserved; 
    public Guid dbcc_classguid; 
    [MarshalAs(UnmanagedType.LPStr)] 
    public string dbcc_name; 
} 

और मैं WM_DEVICECHANGE संदेश की lParam पर Marshal.PtrToStructure उपयोग कर रहा हूँ।

क्या यह काम कर रहा है?

या इससे भी बेहतर ... कनेक्शन पर डिवाइस का नाम पाने का कोई वैकल्पिक तरीका है?

संपादित करें (2010/02/05 20: 56GMT):

मुझे पता चला कैसे dbcc_name क्षेत्र ऐसा करके पॉप्युलेट करने के लिए प्राप्त करने के लिए:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
public struct DEV_BROADCAST_DEVICEINTERFACE 
{ 
    public int dbcc_size; 
    public int dbcc_devicetype; 
    public int dbcc_reserved; 
    public Guid dbcc_classguid; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=255)] 
    public string dbcc_name; 
} 

लेकिन मैं अभी भी कोई तरीका होना चाहिए int dbcc_name क्या है उससे "मित्रवत" नाम प्राप्त करने के लिए। ऐसा लग रहा है निम्नलिखित:

\ \ यूएसबी # VID_05AC & PID_1294 ​​& MI_00 # 0 # {6bdd1fc6-810f-11d0-bec7-08002be2092f}

और मैं वास्तव में सिर्फ यह कहना चाहता हूँ? "ऐप्पल आईफोन" (जो इस मामले में डिवाइस है)।

 
DEV_BROADCAST_DEVICEINTERFACE dbd = new DEV_BROADCAST_DEVICEINTERFACE; 
dbd.dbcc_size = 255; 
dbd.dbcc_name = new StringBuilder(dbd.dbcc_size); 

फिर में उस संरचना गुजरती हैं, के मूल्य:

उत्तर

9

ठीक है, जैसा ऊपर बताया गया है, मुझे पता चला कि dbcc_name सही तरीके से पॉप्युलेट करने के लिए कैसे मिलता है। मैंने पाया है कि यह सबसे आसान तरीका है डिवाइस का नाम मिल गया था:

private static string GetDeviceName(DEV_BROADCAST_DEVICEINTERFACE dvi) 
{ 
    string[] Parts = dvi.dbcc_name.Split('#'); 
    if (Parts.Length >= 3) 
    { 
     string DevType = Parts[0].Substring(Parts[0].IndexOf(@"?\") + 2); 
     string DeviceInstanceId = Parts[1]; 
     string DeviceUniqueID = Parts[2]; 
     string RegPath = @"SYSTEM\CurrentControlSet\Enum\" + DevType + "\\" + DeviceInstanceId + "\\" + DeviceUniqueID; 
     RegistryKey key = Registry.LocalMachine.OpenSubKey(RegPath); 
     if (key != null) 
     { 
      object result = key.GetValue("FriendlyName"); 
      if (result != null) 
       return result.ToString(); 
      result = key.GetValue("DeviceDesc"); 
      if (result != null) 
       return result.ToString(); 
     } 
    } 
    return String.Empty; 
} 
+0

धन्यवाद !! मैं वही काम करने की कोशिश कर रहा हूं। –

0

यह संभव है आप इस थोड़ा

 
[StructLayout(LayoutKind.Sequential)] 
public struct DEV_BROADCAST_DEVICEINTERFACE 
{ 
    public int dbcc_size; 
    public int dbcc_devicetype; 
    public int dbcc_reserved; 
    public Guid dbcc_classguid; 
    [MarshalAs(UnmanagedType.LPStr)] 
    public StringBuilder dbcc_name; 
} 

dbcc_size 255 करने के लिए सेट बदलने के लिए, और StringBuilder निर्माण करने के लिए के रूप में नीचे दिखाया गया है की जरूरत है dbcc_name जनसंख्या होना चाहिए।

संपादित करें:के बाद हिनहिनाहट की टिप्पणी ... मैं इस एक और तरीका है के बारे में सोचा ...

 
public struct DEV_BROADCAST_DEVICEINTERFACE 
{ 
    public int dbcc_size; 
    public int dbcc_devicetype; 
    public int dbcc_reserved; 
    public Guid dbcc_classguid; 
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 255, ArraySubType = System.Runtime.InteropServices.UnmanagedType.LPArray)] 
    public string dbcc_name; 
} 

dbcc_size 255 करने के लिए सेट करें, और उसे वहाँ से ले ...

# 2 संपादित करें: यह दिलचस्प है ... अब इतना यकीन नहीं कर रहा हूँ, मैं इस लेख Codeproject पर RegisterDeviceNotification का उपयोग करता है पाया जाता है और यह एक diff का उपयोग करता है RegisterDeviceNotification का इन्टेंट तरीका है कि संरचना को IntPtr में घुमाया गया है और इसका उपयोग एपीआई को कॉल करने के लिए किया जाता है ...

+0

आप स्ट्रिंगबिल्डर्स वाले मार्शल फ़ील्ड नहीं कर सकते हैं। यह काम नहीं करता है। – snicker

+0

@ स्निकर: बस एहसास हुआ ... इस उत्तर को थोड़ा और संपादित करेगा .. – t0mm13b

+0

टॉम। आपका संपादन अभी भी काम नहीं करता है। आप केवल एलपीएसआरटी, एलपीडब्ल्यूएसआरटी, एलपीटीएसआरटी, बीएसआरटी, या बायवेलैट्स को मार्शल स्ट्रिंग्स कर सकते हैं। – snicker

2

यह जानकारी SetupAPI के माध्यम से और अधिक औपचारिक रूप प्राप्त किया जा सकता।dbcc_name से SetupDiOpenDeviceInterface पास करें और SetupDiGetDeviceRegistryProperty के साथ दोस्ताना नाम SPDRP_FRIENDLYNAME में गुजरें।

यहां कुछ डेल्फी कोड है जो यह करेगा। (क्षमा करें, आपको स्वतंत्र रूप से सी # में अनुवाद करना होगा)।

function ConvertDbccNameToFriendlyName(aDeviceInterfaceDbccName : string) : string; 
var 
    deviceInfoHandle : HDEVINFO; 
    deviceInfoData : SP_DEVINFO_DATA; 
    deviceInterfaceData : SP_DEVICE_INTERFACE_DATA; 
    deviceInstanceId : string; 
    memberIndex : Cardinal; 
begin 
    result := ''; 

    // Create a new empty "device info set" 
    deviceInfoHandle := SetupDiCreateDeviceInfoList(nil, 0); 
    if deviceInfoHandle <> INVALID_HANDLE_VALUE then 
    begin 
    try 
     // Add "aDeviceInterfaceDbccName" to the device info set 
     FillChar(deviceInterfaceData, SizeOf(deviceInterfaceData), 0); 
     deviceInterfaceData.cbSize := SizeOf(deviceInterfaceData); 
     if SetupDiOpenDeviceInterface(deviceInfoHandle, PChar(aDeviceInterfaceDbccName),  0, @deviceInterfaceData) then 
     begin 
     try 
      // iterate over the device info set 
      // (though I only expect it to contain one item) 
      memberIndex := 0; 
      while true do 
      begin 
      // get device info that corresponds to the next memberIndex 
      FillChar(deviceInfoData, SizeOf(deviceInfoData), 0); 
      deviceInfoData.cbSize := SizeOf(deviceInfoData); 
      if not SetupDiEnumDeviceInfo(deviceInfoHandle, memberIndex, deviceInfoData) then 
      begin 
       // The enumerator is exhausted when SetupDiEnumDeviceInfo returns false 
       break; 
      end 
      else 
      begin 
       Inc(memberIndex); 
      end; 

      // Get the friendly name for that device info 
      if TryGetDeviceFriendlyName(deviceInfoHandle, deviceInfoData, {out} friendlyName) then 
      begin 
       result := friendlyName; 
       break; 
      end; 
      end; 
     finally 
      SetupDiDeleteDeviceInterfaceData(deviceInfoHandle, deviceInterfaceData); 
     end; 
     end; 
    finally 
     SetupDiDestroyDeviceInfoList(deviceInfoHandle); 
    end; 
    end; 
end; 

function TryGetDeviceFriendlyName(
    var aDeviceInfoHandle : HDEVINFO; 
    var aDeviceInfoData : SP_DEVINFO_DATA; 
    out aFriendlyName : string) : boolean; 
var 
    valueBuffer : array of byte; 
    regProperty : Cardinal; 
    propertyRegDataType : DWord; 
    friendlyNameByteSize : Cardinal; 
    success : boolean; 
begin 
    aFriendlyName := ''; 
    result := false; 

    // Get the size of the friendly device name 
    regProperty := SPDRP_FRIENDLYNAME; 
    friendlyNameByteSize := 0; 
    SetupDiGetDeviceRegistryProperty(
    aDeviceInfoHandle,  // handle to device information set 
    aDeviceInfoData,  // pointer to SP_DEVINFO_DATA structure 
    regProperty,   // property to be retrieved 
    propertyRegDataType, // pointer to variable that receives the data type of the property 
    nil,     // pointer to PropertyBuffer that receives the property 
    0,      // size, in bytes, of the PropertyBuffer buffer. 
    friendlyNameByteSize); // pointer to variable that receives the required size of PropertyBuffer 

    // Prepare a buffer for the friendly device name (plus space for a null terminator) 
    SetLength(valueBuffer, friendlyNameByteSize + sizeof(char)); 

    success := SetupDiGetDeviceRegistryProperty(
    aDeviceInfoHandle, 
    aDeviceInfoData, 
    regProperty, 
    propertyRegDataType, 
    @valueBuffer[0], 
    friendlyNameByteSize, 
    friendlyNameByteSize); 

    if success then 
    begin 
    // Ensure that only 'friendlyNameByteSize' bytes are used. 
    // Ensure that the string is null-terminated. 
    PChar(@valueBuffer[friendlyNameByteSize])^ := char(0); 

    // Get the returned value as a string 
    aFriendlyName := StrPas(PChar(@valueBuffer[0])); 
    end; 

    result := success; 
end; 

अंत में ... यदि आप एक तरह से विशिष्ट रूप से एक यूएसबी डिवाइस की पहचान करने (आप के लिए क्या नहीं कहा, लेकिन आमतौर पर यह भी जरूरी है) की जरूरत है, SetupDiGetDeviceInstanceId पर गौर।

+0

उत्तर देने के लिए थोड़ा देर हो चुकी है। एक जवाब पहले से ही सात वोटों के साथ स्वीकार कर लिया गया है। –

+4

बेहतर उत्तर के लिए यह बहुत देर हो चुकी नहीं है =) (मैं किसी भी दिन मैन्युअल स्ट्रिंग पार्सिंग पर औपचारिक एपीआई पसंद करता हूं) –

+0

@NathanSchubkegel अगर आप इसे सी # में अनुवाद करने के लिए किसी को ढूंढ सकते हैं, तो मैं स्वीकृत उत्तर बदल दूंगा। यह बिल्कुल बेहतर समाधान होगा, मैंने जो कोड ऊपर पोस्ट किया है वह सुगंधित है और रजिस्ट्री (या बिल्कुल मौजूद रजिस्ट्री) में एक ही स्थान पर हमेशा कुछ निर्भर करता है, एक winapi समाधान सबसे अच्छा है – snicker

संबंधित मुद्दे