WindowsでCOMポートのフレンドリ名を取得するにはどうすればよいですか?
-
08-07-2019 - |
質問
GSMモデムをUSB経由で接続しています。モデムは2つのシリアルポートを作成します。 1つ目はモデムに自動的に接続され、2つ目はデバイスマネージャーに「HUAWEI Mobile Connect-3G PC UIインターフェイス(COM6)」として表示されます
2番目のポートは、信号品質などの重要な情報をモデムから取得するために使用されます。テキストメッセージを送受信します。その他の多くの機能。
2番目のポートが提供する機能の一部をまとめるアプリケーションを作成しています。必要なのは、どのCOMポートが予備のポートであるかを特定する確実な方法です。ポートを繰り返し、「ATE0」への応答を確認します。十分ではありません。通常、モデムのポートは小さい番号のポートであり、ダイヤルアップ接続がアクティブでない場合、「ATE0」に応答します。 2番目のポートと同じ。
デバイスマネージャーに表示されているように、ポートを繰り返し処理してポートのフレンドリ名を確認することを考えていました。そうすれば、アプリケーションのポートを「HUAWEI Mobile Connect-3G PC UIインターフェイス(COM6)」というラベルの付いたポートにリンクできます。デバイスマネージャーで。プログラムでその名前を取得できる情報はまだ見つかりません。
解決
ずっと前に、私はクライアントがこれだけを行うためのユーティリティを作成しましたが、モデムではなくGPS用です。
見たところ、役に立つと思われる部分は次のとおりです。
GUID guid = GUID_DEVCLASS_PORTS;
SP_DEVICE_INTERFACE_DATA interfaceData;
ZeroMemory(&interfaceData, sizeof(interfaceData));
interfaceData.cbSize = sizeof(interfaceData);
SP_DEVINFO_DATA devInfoData;
ZeroMemory(&devInfoData, sizeof(devInfoData));
devInfoData.cbSize = sizeof(devInfoData);
if(SetupDiEnumDeviceInfo(
hDeviceInfo, // Our device tree
nDevice, // The member to look for
&devInfoData
))
{
DWORD regDataType;
BYTE hardwareId[300];
if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, hardwareId, sizeof(hardwareId), NULL))
{
...
(nDeviceをインクリメントしながらループでこのビットを呼び出します)
そして
BYTE friendlyName[300];
if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, friendlyName, sizeof(friendlyName), NULL))
{
strFriendlyNames += (LPCTSTR)friendlyName;
strFriendlyNames += '\n';
}
デバイスの名前を見つけます。
うまくいけば、正しい方向に進むことができます。
他のヒント
シリアルポートデバイスが目的のデバイスであると判断した後(フレンドリ名を確認したり、親デバイスを確認したりするなど)、ポート名を取得する適切な方法は次のようになります。
-
SetupDiOpenDevRegKey(hDevInfo、devInfoData、DICS_FLAG_GLOBAL、0、DIREG_DEV、KEY_READ)
を呼び出して、いわゆるデバイスキーへのHKEY
を取得 -
REG_SZ
の値" PortName"についてこのレジストリキーを照会します -
HKEY
を閉じることを忘れないでください:)
ただし、これにはC#での相互運用が必要になる可能性があり、面白くもないため、文字列解析ソリューションを続けても私はあなたを責めません。
ウィルディーンが投稿した情報が最も役に立ちました。これは最終的に私のために働いたコードです。 PInvokeクラスのすべては、 http://www.pinvoke.net から逐語的に取られました。 (uintの代わりにenumを使用する場合のように)データ型をここまたはそこに変更して動作させる必要がありましたが、簡単に理解できるはずです。
internal static string GetComPortByDescription(string Description)
{
string Result = string.Empty;
Guid guid = PInvoke.GUID_DEVCLASS_PORTS;
uint nDevice = 0;
uint nBytes = 300;
byte[] retval = new byte[nBytes];
uint RequiredSize = 0;
uint PropertyRegDataType = 0;
PInvoke.SP_DEVINFO_DATA devInfoData = new PInvoke.SP_DEVINFO_DATA();
devInfoData.cbSize = Marshal.SizeOf(typeof(PInvoke.SP_DEVINFO_DATA));
IntPtr hDeviceInfo = PInvoke.SetupDiGetClassDevs(
ref guid,
null,
IntPtr.Zero,
PInvoke.DIGCF.DIGCF_PRESENT);
while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData))
{
if (PInvoke.SetupDiGetDeviceRegistryProperty(
hDeviceInfo,
ref devInfoData,
PInvoke.SPDRP.SPDRP_FRIENDLYNAME,
out PropertyRegDataType,
retval,
nBytes,
out RequiredSize))
{
if (System.Text.Encoding.Unicode.GetString(retval).Substring(0, Description.Length).ToLower() ==
Description.ToLower())
{
string tmpstring = System.Text.Encoding.Unicode.GetString(retval);
Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM"));
} // if retval == description
} // if (PInvoke.SetupDiGetDeviceRegistryProperty( ... SPDRP_FRIENDLYNAME ...
} // while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData))
PInvoke.SetupDiDestroyDeviceInfoList(hDeviceInfo);
return Result;
}
行 Result = tmpstring.Substring(tmpstring.IndexOf(" COM")、tmpstring.IndexOf( ')')-tmpstring.IndexOf(" COM"));
少し不器用ですが、それをきれいにする方法についての提案をいただければ幸いです。
この件についてご協力いただきありがとうございます。あなたがいなければ、私はまだGoogleを検索しています。
@Will Deanの回答に基づいたC ++バージョン。
#include <windows.h>
#include <initguid.h>
#include <devguid.h>
#include <setupapi.h>
void enumerateSerialPortsFriendlyNames()
{
SP_DEVINFO_DATA devInfoData = {};
devInfoData.cbSize = sizeof(devInfoData);
// get the tree containing the info for the ports
HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,
0,
nullptr,
DIGCF_PRESENT
);
if (hDeviceInfo == INVALID_HANDLE_VALUE)
{
return;
}
// iterate over all the devices in the tree
int nDevice = 0;
while (SetupDiEnumDeviceInfo(hDeviceInfo, // Our device tree
nDevice++, // The member to look for
&devInfoData))
{
DWORD regDataType;
DWORD reqSize = 0;
// find the size required to hold the device info
SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize);
BYTE* hardwareId = new BYTE[(reqSize > 1) ? reqSize : 1];
// now store it in a buffer
if (SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, hardwareId, sizeof(hardwareId) * reqSize, nullptr))
{
// find the size required to hold the friendly name
reqSize = 0;
SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize);
BYTE* friendlyName = new BYTE[(reqSize > 1) ? reqSize : 1];
// now store it in a buffer
if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, friendlyName, sizeof(friendlyName) * reqSize, nullptr))
{
// device does not have this property set
memset(friendlyName, 0, reqSize > 1 ? reqSize : 1);
}
// use friendlyName here
delete[] friendlyName;
}
delete[] hardwareId;
}
}
それが機能して良かった。
試すことができます:
Regex.Match(tmpstring、@&quot; COM \ s \ d +&quot;)。ToString()
文字列のマッチング用。
。 finally {}句。
LiGenChenによって投稿されたメソッドを使用しました。メソッドComPortSetupAPISetupDiClassGuidsは、最適な時間とフレンドリ名を提供しました。