USB 및 하드웨어 인식

Program/C# 2008. 4. 1. 18:35

환경 : VS2008, WPF, C#

컴퓨터가 하드웨어를 인식했을때 이에 대한 이벤트를 처리하는 부분입니다.
C# 에서 API를 사용해서 구현하는 방법에 대해 알아보겠습니다.

알아야 할 것은 두가지 입니다.
하드웨어가 인식되었을대 어떠한 메세지가 오느냐?
이 메세지에 포함된 값을 어떻게 확인하느냐?

답을 먼저 말한다면
하드웨어를 인식했을 경우 WM_DEVICECHANGE 라는 메세지가 날라옵니다.
USB 의 인식 및 제거를 확인하기 위해서 아래와 같은 상수 값들이 필요합니다.

            UInt32 WM_DEVICECHANGE    = 0x0219;
            UInt32 DBT_DEVTUP_VOLUME = 0x02;
            UInt32 DBT_DEVICEARRIVAL = 0x8000;
            UInt32 DBT_DEVICEREMOVECOMPLETE = 0x8004;

UInt32는 닷넷에서 메세지 상수값에 대응하는 타입입니다.
각 값들에 대해서는 MSDN 및 구글을 검색하시면 쉽게 아실 수 있습니다.
만약 USB 가 아닌 다른 장치를 인식해야 한다면.. 그에 해당하는 상수값들을 사용하면 될 것입니다.

첫번째, 우선 메세지 프로시져를 만들어야 합니다.

protected override void WndProc(ref Message m)

닷넷에서는 WndProc 를 오버라이드 함으로서 메세지를 가로챌 수 있습니다.


두번째, 장치가 인식되었는지를 확인해야 합니다.

if (m.Msg == WM_DEVICECHANGE)

장치의 변화는 확인하였군요...


셋째, 어떠한 장치인지를 확인해야 합니다.
   int devType = Marshal.ReadInt32(m.LParam, 4);
   (devType == DBT_DEVTUP_VOLUME)

Marshal(마샬) 클래스는 언메니지드 코드에 접근할 수 있고,
기타 포인터및 C 스타일의 자료형들을 사용할 수 있도록 지원하는 클래스다라고..
알고 있습니다. 정확히 알아보진 않았고 대략 그런 용도로 사용하고 있느니까요..
이에 대해선 좀더 자세히 알아 보시길 바랍니다.
어쨌건 마샬 클래스를 통해서 LParam 값을 읽어 장치의 타입을 검색하는 군요..

넷째, 그렇다면 장치의 인식인지, 제거 인지를 판단해야 합니다.
if (m.WParam.ToInt32() == DBT_DEVICEARRIVAL)
if (m.WParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE)

추가로, 볼륨 장치 일경우 드라이브의 형태로 잡힐텐데요. 드라이브명까지 알아본다면

DEV_BROADCAST_VOLUME 라는 구조체를 정의합니다.
LParam 에서 볼륨 정보를 가지고 있는 놈이지요.

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        public struct DEV_BROADCAST_VOLUME
        {
            public int dbcv_size;
            public int dbcv_devicetype;
            public int dbcv_reserved;
            public int dbcv_unitmask;
        }

TJ.TJUtil.DEV_BROADCAST_VOLUME vol;
vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));

vol.dbcv_unimask 값으로 드라이브 명을 얻을 수가 있는데요...
값을 바로 주진 않는군요... 아래 함수를 정의 해 봅니다.
public static char DriveMaskToLetter(int mask)
        {
            char letter;
            string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            int cnt = 0;
            int pom = mask / 2;
            while (pom != 0)
            {
                pom = pom / 2;
                cnt++;
            }

            if (cnt < drives.Length)
                letter = drives[cnt];
            else
                letter = '?';

            return letter;
        }

vol.dbcv_unimask 값을 파라미터로 받아서 드라이브 명의 문자를 리턴 합니다.


'Program > C#' 카테고리의 다른 글

네트워크 드라이브  (0) 2008.04.02
XML Serialize  (0) 2008.04.01
Shallow Vs Deep Copy 깊은 복사  (0) 2008.03.07
: