11

ウィンドウをRegisterDeviceNotificationに登録し、 DEV_BROADCAST_DEVICEINTERFACEメッセージを正常に受信できます。ただし、dbcc_name返される構造体のフィールドは常に空です。私が持っている構造体は次のように定義されています。

[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;
}

そしてMarshal.PtrToStructureWM_DEVICECHANGEメッセージの LParam で使用しています。

これは機能するはずですか?

またはさらに良い...接続時にデバイスの名前を取得する別の方法はありますか?

編集 (2010 年 2 月 5 日 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 から「わかりやすい」名前を取得する方法が必要です。次のようになります。

\?\USB#VID_05AC&PID_1294​​&MI_00#0#{6bdd1fc6-810f-11d0-bec7-08002be2092f}

そして、私は本当に「Apple iPhone」と言いたいだけです(この場合のデバイスはこれです)。

4

3 に答える 3

10

さて、上記のように、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;
}
于 2010-02-08T17:20:18.540 に答える
0

これを少し変更する必要がある可能性があります

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

を 255 に設定し、dbcc_size以下に示すように StringBuilder を作成します。

DEV_BROADCAST_DEVICEINTERFACE dbd = 新しい DEV_BROADCAST_DEVICEINTERFACE;
dbd.dbcc_size = 255;
dbd.dbcc_name = 新しい StringBuilder(dbd.dbcc_size);

次に、その構造体を渡すと、値が設定されdbcc_nameます。

編集:スニッカーのコメントの後...私はこれを別の方法で考えました...

public struct DEV_BROADCAST_DEVICEINTERFACE
{
    public int dbcc_size;
    public int dbcc_devicetype;
    public int dbcc_reserved;
    パブリック Guid dbcc_classguid;
[System.Runtime.InteropServices.MarshalAsAttribute (System.Runtime.InteropServices.UnmanagedType.ByValArray、SizeConst = 255、ArraySubType = System.Runtime.InteropServices.UnmanagedType.LPArray)]
    公開文字列 dbcc_name;
}

を 255 に設定し、dbcc_sizeそこから取得します...

編集#2:これは興味深いです...今はよくわかりません。CodeprojectRegisterDeviceNotificationで使用するこの記事を見つけました。構造体がにマーシャリングされ、APIを呼び出すために使用されるという点で、RegisterDeviceNotificationの別の方法を使用しています...IntPtr

于 2010-02-05T16:49:55.993 に答える