[MFC] 레지스트리 값으로 시리얼 번호 자동으로 찾기
- 최초 작성일: 2022년 2월 21일 (월)
목차
[TOC]
목적
컴퓨터에 USB를 통해 하드웨어 연결시 ‘COMXX’ 식의 시리얼 번호를 확인할 수 있는데,
프로그램 실행시 이 포트 번호를 자동으로 찾아 설정해주는 기능을 구현하고자 한다.
구현
시리얼 포트를 스캔하기 위해서는 레지스트리의
HKEY_LOCALMACHINE\HARDWARE\DEVICEMAP\SERIALCOMM 항목을 찾아보면 된다.
int findComPortList(int *list)
{
HKEY hSerialCom;
TCHAR buffer[_MAX_PATH];
char data[_MAX_PATH];
DWORD len, type, dataSize;
long i;
char idata[3];
int port_list_count = 0;
if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_ALL_ACCESS, &hSerialCom) == ERROR_SUCCESS)
{
for (i = 0, len = dataSize = _MAX_PATH;
::RegEnumValue(hSerialCom, i, buffer, &len, NULL, &type, (BYTE *)data, &dataSize) == ERROR_SUCCESS;
i++, len = dataSize = _MAX_PATH)
{
RegQueryValueEx(hSerialCom, buffer, &len, NULL, (BYTE *)data, &dataSize);
int tmp = _tcslen(buffer);
if (tmp > 17)
{
buffer[17] = '\0';
tmp++;
}
if (_tcscmp(buffer, _T("\\Device\\USBSER000")) == 0)
{
//int l_size = dataSize - 4;
//int i;
//for (i = 0; i < l_size; i++)
//{
// idata[i] = data[i + 3];
//}
//idata[i] = '\0';
int cnt = 0;
for (i = 0; i < dataSize; i++)
{
if (data[i] >= 0x30 && data[i] <= 0x39)
{
idata[cnt] = data[i];
cnt++;
}
}
if(cnt == 2)
idata[cnt] = '\0';
else if (cnt == 1)
{
idata[cnt] = '\0';
idata[cnt+1] = '\0';
}
list[port_list_count] = atoi(idata);
port_list_count++;
}
}::RegCloseKey(hSerialCom);
}
return port_list_count;
}
char * byIndexComPort(int xPort)
{
static char PortName[30] = { 0, };
TCHAR PortName2[30];
// sprintf_s(PortName, 30, "\\\\.\\COM%d", xPort);
wsprintf(PortName2, TEXT("\\\\.\\COM%d"), xPort);
// MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PortName, strlen(PortName), PortName2, 60);
return PortName;
}
BOOL open_comport()
{
int portList[10];
int candidateSize = 0;
candidateSize = findComPortList(portList);
if (candidateSize == 0)
{
m_portfound = FALSE;
m_Comportnum = 10;
}
else if (candidateSize == 1)
{
m_portfound = TRUE;
m_Comportnum = portList[0];
}
else
{
m_portfound = TRUE;
m_Comportnum = 10;
}
//serial.iBaudRate = 1; //9600
//serial.iDataBit = 3; //8
//serial.iStopBit = 1;//ONE5STOPBITS
//serial.iParity = 0; //NOPARITY
if (m_pCom1)
{
m_Connected = FALSE;
delete m_pCom1;
m_pCom1 = NULL;
}
TCHAR PortName2[30];
wsprintf(PortName2, _T("\\\\.\\COM%d"), m_Comportnum);
m_pCom1 = new CSerialPort(PortName2);
if (m_pCom1 == NULL)
return FALSE;
else
{
m_pCom1->SetBaudRate(CBR_9600);//테스트용
m_pCom1->SetBufferSizes(4096, 4096);
m_pCom1->SetParityDataStop(NOPARITY, EIGHTDATABITS, ONE5STOPBITS);
m_pCom1->SetFlowControl(PCF_XONXOFF);
m_pCom1->SetBufferSizes(SP_INBUFSIZE, SP_OUTBUFSIZE);
m_pCom1->SetReadTimeouts(MAXDWORD, 0, 0);
m_pCom1->SetWriteTimeouts(0, SP_WRITETIMEOUT);
m_pCom1->StartCommThread(Com1Reader, 0);
m_Connected = TRUE;
m_realtimestart = FALSE;
return m_pCom1->IsValid();
}
}
void close_comport()
{
Sleep(100);
if (m_pCom1)
{
if (m_pCom1->IsValid())
{
m_pCom1->PurgeComm(PURGE_RXCLEAR);
m_pCom1->StopCommThread();
}
delete m_pCom1;
m_pCom1 = NULL;
m_Connected = FALSE;
}
}