gpt4 book ai didi

windows - SetupAPI(setupdi 函数)不链接

转载 作者:可可西里 更新时间:2023-11-01 11:49:28 39 4
gpt4 key购买 nike

我想要一个函数来枚举 Windows 上的串行 (COM) 端口。为此,我主要从 http://www.codeguru.com/cpp/w-p/system/hardwareinformation/article.php/c5721/Determining-What-Serial-Ports-Are-Available-on-a-Windows-Machine.htm 复制了代码。

在头文件中:

#include "SerialPort.h"
#include <list>
#include <objbase.h>
#include <initguid.h>
#include <Setupapi.h>
typedef std::list<SerialPort> PortList;
class SerialConnection
{
private:
static PortList availible_ports;
public:
static void enumerateSerialPorts(bool);
static const PortList& getPortList(){ return availible_ports; }
}

实现:

void SerialConnection::enumerateSerialPorts(bool check)
{
availible_ports.clear();
CString strErr;
// Create a device information set that will be the container for
// the device interfaces.
GUID *guidDev = (GUID*)&GUID_CLASS_COMPORT;

HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA *pDetData = NULL;

try {
hDevInfo = SetupDiGetClassDevs(guidDev,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
);

if (hDevInfo == INVALID_HANDLE_VALUE)
{
strErr.Format(_T("SetupDiGetClassDevs failed. (err=%lx)"),
GetLastError());
throw strErr;
}

// Enumerate the serial ports
BOOL bOk = TRUE;
SP_DEVICE_INTERFACE_DATA ifcData;
DWORD dwDetDataSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
pDetData = (SP_DEVICE_INTERFACE_DETAIL_DATA*) new char[dwDetDataSize];
// This is required, according to the documentation. Yes,
// it's weird.
ifcData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
pDetData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
for (DWORD ii = 0; bOk; ii++) {
bOk = SetupDiEnumDeviceInterfaces(hDevInfo,
NULL, guidDev, ii, &ifcData);
if (bOk) {
// Got a device. Get the details.
SP_DEVINFO_DATA devdata = { sizeof(SP_DEVINFO_DATA) };
bOk = SetupDiGetDeviceInterfaceDetail(hDevInfo,
&ifcData, pDetData, dwDetDataSize, NULL, &devdata);
if (bOk) {
CString strDevPath(pDetData->DevicePath);
// Got a path to the device. Try to get some more info.
TCHAR fname[256];
TCHAR desc[256];
BOOL bSuccess = SetupDiGetDeviceRegistryProperty(
hDevInfo, &devdata, SPDRP_FRIENDLYNAME, NULL,
(PBYTE)fname, sizeof(fname), NULL);
bSuccess = bSuccess && SetupDiGetDeviceRegistryProperty(
hDevInfo, &devdata, SPDRP_DEVICEDESC, NULL,
(PBYTE)desc, sizeof(desc), NULL);
BOOL bUsbDevice = FALSE;
TCHAR locinfo[256];
if (SetupDiGetDeviceRegistryProperty(
hDevInfo, &devdata, SPDRP_LOCATION_INFORMATION, NULL,
(PBYTE)locinfo, sizeof(locinfo), NULL))
{
// Just check the first three characters to determine
// if the port is connected to the USB bus. This isn't
// an infallible method; it would be better to use the
// BUS GUID. Currently, Windows doesn't let you query
// that though (SPDRP_BUSTYPEGUID seems to exist in
// documentation only).
// bUsbDevice = (strncmp(locinfo, "USB", 3) == 0);
}
if (bSuccess) {
// Add an entry to the array
SerialPort sp;
sp.full_path = strDevPath;
sp.port_name = fname;
sp.full_name = desc;

availible_ports.push_back(sp);
}

}
else {
strErr.Format(_T("SetupDiGetDeviceInterfaceDetail failed. (err=%lx)"),
GetLastError());
throw strErr;
}
}
else {
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_ITEMS) {
strErr.Format(_T("SetupDiEnumDeviceInterfaces failed. (err=%lx)"), err);
throw strErr;
}
}
}
}
catch (CString strCatchErr) {
strErr = strCatchErr;
}

if (pDetData != NULL)
delete[](char*)pDetData;
if (hDevInfo != INVALID_HANDLE_VALUE)
SetupDiDestroyDeviceInfoList(hDevInfo);

if (!strErr.IsEmpty())
throw strErr;

if (check)
{
for (auto it = availible_ports.begin(); it != availible_ports.end(); it++)
{
HANDLE hCom = CreateFile(it->full_path,
GENERIC_READ | GENERIC_WRITE,
0, /* comm devices must be opened w/exclusive-access */
NULL, /* no security attrs */
OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
0, /* not overlapped I/O */
NULL /* hTemplate must be NULL for comm devices */
);
if (hCom == INVALID_HANDLE_VALUE) {
// It can't be opened; remove it.
auto erase_it = it;
it++;
availible_ports.erase(erase_it);

}
else {
// It can be opened! Close it and add it to the list
::CloseHandle(hCom);
}
}
}

此代码编译失败,但如果我尝试像这样使用它

#include "SerialConnection.h"
int main()
{
SerialConnection::enumerateSerialPorts(false);
auto cl = SerialConnection::getPortList();
return 0;
}

错误 LNK2019:未解析的外部符号 __imp__SetupDiDestroyDeviceInfoList@4 在函数 __catch$?enumerateSerialPorts@SerialConnection@@SAX_N@Z$0 中引用

错误 LNK2019:未解析的外部符号 __imp__SetupDiEnumDeviceInterfaces@20 在函数“public: static void __cdecl SerialConnection::enumerateSerialPorts(bool)” (?enumerateSerialPorts@SerialConnection@@SAX_N@Z) 中引用

错误 LNK2019:未解析的外部符号 __imp__SetupDiGetDeviceInterfaceDetailW@24 在函数“public: static void __cdecl SerialConnection::enumerateSerialPorts(bool)” (?enumerateSerialPorts@SerialConnection@@SAX_N@Z) 中引用

错误 LNK2019:未解析的外部符号 __imp__SetupDiGetClassDevsW@16 在函数“public: static void __cdecl SerialConnection::enumerateSerialPorts(bool)” (?enumerateSerialPorts@SerialConnection@@SAX_N@Z) 中引用

错误 LNK2019:未解析的外部符号 __imp__SetupDiGetDeviceRegistryPropertyW@28 在函数“public: static void __cdecl SerialConnection::enumerateSerialPorts(bool)” (?enumerateSerialPorts@SerialConnection@@SAX_N@Z) 中引用

我错过了什么?我使用 MVS 2013

最佳答案

您必须将您的项目与 Setupapi.lib 链接起来。您可以通过两种方式做到这一点:

  1. 使用#pragma 注释
#pragma comment (lib, "Setupapi.lib")
  1. 转到“属性”>“配置属性”>“链接器”>“输入”>“附加依赖项”并添加 Setupapi.lib 库。

另见: https://social.msdn.microsoft.com/Forums/vstudio/en-US/e14ce1a2-08b9-4291-b035-f72171bcbdbc/error-lnk2019-unresolved-external-symbol?forum=vclanguage

关于windows - SetupAPI(setupdi 函数)不链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33640791/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com