SerialPort.GetPortNames Error and Bluetooth 의 해결책

[목차(도우미)]
VB.NET또는 .NET 프레임워크를 사용하는 System.IO.Ports.SerialPort.GetPortNames 에서는 내장 Bluetooth 기기의 시리얼포트가 문자깨짐이 일어난다. 이러한 현상의 원인은 .NET Framework의 버그라고 보고되었고 내장 블루투스 기기가 마이크로소프트 제품일 경우에 레지스트리(regedit.exe)에 널문자(NULL)가 들어 있지 않은 경우에 생겨나는 문제라고 한다.

특이한 점은 이러한 문제점이 오래전 2006년경부터 보고되어 왔고 해결책이 공개되어 있지만 공개된 문헌을 그대로 따라 해도 해결되지 않는다는 점이다.
참조: http://connect.microsoft.com/VisualStudio/feedback/details/236183/system-io-ports-serialport-getportnames-error-with-bluetooth

파란니는 아니지만

살아있는 암모나이트류로서

수족관(바다물)에서 헤엄친다.

앵무조개 문헌: http://en.wikipedia.org/wiki/Nautilus

내장 블루투스와 시리얼포트의 인식 문제

How to find available COM ports in VB.NET framework ? All right, just be patient a little more. I found the solution available for VB.NET. As expected, .net framework cannot be solved without native Windows API codes. Anyway, keep going in Korean instead.

문제점

Windows 7, 내장 블루투스 기기일 경우 시리얼포트가 COM3c, COM4o, COM52 등으로 표시되고 끝자리에 임의의 문자, 숫자가 붙어 버린다.

해결 방법

.NET Framework 자체의 버그가 해결되지 않기 때문에 Windows native API 함수를 불러 써야 한다.
COM3c처럼 뒤에 붙는 문자열이 숫자가 아닌 경우라면 3c부분을 숫자로 변환하여 다시 재결합시키면 되지만 간혹 숫자가 붙는 경우가 있다고 보고되어 있다.

한편 VB.NET 으로 바뀌면서 "As Any" 선언이 불가능하기 때문에 native Windows API 함수의 호출 방법이 바뀌어야 한다.

Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Integer, ByVal dwIndex As Integer, ByVal lpValueName As String, ByRef lpcbValueName As Integer, ByVal lpReserved As Integer, ByRef lpType As Integer, ByRef lpData As Byte, ByRef lpcbData As Integer) As Integer

위와 같이 선언하면 잘 안되고 다음과 같이 선언하고 StringBuilder 를 값에 의한 참조(ByVal)로 넘겨 주어야 한다.

Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Integer, ByVal dwIndex As Integer, ByVal lpValueName As StringBuilder, ByRef lpcbValueName As Integer, ByVal lpReserved As Integer, ByRef lpType As Integer, ByVal lpData As StringBuilder, ByRef lpcbData As Integer) As Integer

나머지 다른 소스 코드의 예는 http://connect.microsoft.com/ 를 참조하면 알수 있고, 흔한 처리 부분이므로 간단히 작성할 수 있다.
by 금메달.아빠 on 2012. 2. 23. 07:16