GetLastError 增强封装(显示更具体信息)

本文介绍了一种改进后的GetLastError宏定义方法,通过该方法能够详细地展示错误发生的具体位置,包括文件名、行号、函数名以及错误信息等,并支持自定义附加信息。

单纯使用GetLastError()只显示错误编号~很多时候都不知道具体意思,写了一个增强效果的封装

#define filename(x) strrchr(x,'\\')?strrchr(x,'\\')+1:x
#define GetLastErrorEx(lpszFunction){LPVOID lpMsgBuf;DWORD dw = GetLastError();FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dw,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&lpMsgBuf,0, NULL);\
if (lpszFunction)\
printf("%s(Line:%d)->Funtion:%s\ndiyInfo:%s\nError(%d)->Info:%s\n",\
filename(__FILE__), __LINE__, __FUNCTION__, lpszFunction, dw, lpMsgBuf);\
else \
printf("%s(Line:%d)->Funtion:%s\nError(%d)->Info:%s\n",\
filename(__FILE__), __LINE__, __FUNCTION__, dw, lpMsgBuf);\
LocalFree(lpMsgBuf);\
}

//调用例子
GetLastErrorEx("自定义附加信息");
GetLastErrorEx(0);

使用这个宏方法可以更具体显示出 
错误发生在哪一个文件、
第几行代码、
调用的函数是哪一个、
错误编码,以及错误的解释信息。

还可以另外附加 一个自己想附加的信息

 




<think> 我们遇到连接失败的问题,需要增加调试信息。首先,我们需要在TViscellMedicalDevice.Connect函数中添加详细的错误信息返回机制。 修改方案: 1. 修改Connect函数,使其能返回具体的错误信息(例如HIDAPI的错误码)。 2. 在MainForm中捕获这些错误信息显示在日志中。 由于原TViscellMedicalDevice.Connect函数返回Boolean,我们可以改为返回错误字符串(或者保持返回Boolean,但通过额外参数返回错误信息)。 这里我选择扩展Connect函数,让它返回一个字符串(成功返回空字符串,失败返回错误描述)。同时为了兼容性,我们也可以保留原来的函数,但为了调试,我们修改它。 步骤: 1. 修改Viscell.MedicalDevice.pas中的Connect函数。 2. 在MainForm中调用时获取错误信息并记录。 首先修改Viscell.MedicalDevice单元: 原函数声明: function Connect(VendorID, ProductID: Word): Boolean; 修改为: function Connect(VendorID, ProductID: Word; out ErrorMsg: string): Boolean; 然后实现中,当连接失败时,设置ErrorMsg为具体的错误信息。 由于我们使用的是HidApi,可以从HidApi函数中获取错误信息(在Windows下,可以通过GetLastError或者HidApi提供的hid_error函数)。 注意:我们之前使用的是THidDevice类,它可能封装了错误信息。如果THidDevice.Open返回nil,我们可以通过THidDevice.LastError来获取错误信息(如果THidDevice有提供的话)。如果没有,我们可以使用Windows API的GetLastError。 假设我们的THidDevice类没有提供错误信息,我们可以使用Windows API。 修改后的Connect函数: ```delphi function TViscellMedicalDevice.Connect(VendorID, ProductID: Word; out ErrorMsg: string): Boolean; var Device: THidDevice; begin Result := False; ErrorMsg := ''; // 先断开已有连接 if FConnected then Disconnect; // 尝试打开设备 Device := THidDevice.Open(VendorID, ProductID); if not Assigned(Device) then begin // 获取错误信息 ErrorMsg := SysErrorMessage(GetLastError); Exit; end; // 设置设备 FDevice := Device; FConnected := True; // 启动读取线程 FReadThread := TReadThread.Create(True); FReadThread.Device := FDevice; FReadThread.OnData := HandleData; FReadThread.Start; // 触发连接事件 if Assigned(FOnDeviceConnected) then FOnDeviceConnected(Self); Result := True; end; ``` 在MainForm中,我们需要修改btnConnectClick事件处理程序: ```delphi procedure TfrmMain.btnConnectClick(Sender: TObject); var VendorID, ProductID: Word; ErrorMsg: string; begin try VendorID := StrToInt('$' + edtVendorID.Text); ProductID := StrToInt('$' + edtProductID.Text); if FMedicalDevice.Connect(VendorID, ProductID, ErrorMsg) then LogMessage('正在尝试连接设备...') else LogMessage('连接失败: ' + ErrorMsg); // 显示具体的错误信息 except on E: Exception do LogMessage('错误: ' + E.Message); end; end; ``` 但是,请注意:原来在连接成功时,我们只是记录“正在尝试连接设备...”,实际上在Connect函数内部,如果连接成功,会触发OnDeviceConnected事件,然后在事件中记录“设备已成功连接”。所以这里记录“正在尝试连接设备”可能不太合适,我们可以改为在连接成功时不在这个按钮事件中记录,而是等待事件触发。所以可以去掉这里的成功日志。 修改为: ```delphi procedure TfrmMain.btnConnectClick(Sender: TObject); var VendorID, ProductID: Word; ErrorMsg: string; begin try VendorID := StrToInt('$' + edtVendorID.Text); ProductID := StrToInt('$' + edtProductID.Text); if FMedicalDevice.Connect(VendorID, ProductID, ErrorMsg) then LogMessage('连接请求已发送,等待设备响应...') else LogMessage('连接失败: ' + ErrorMsg); // 显示具体的错误信息 except on E: Exception do LogMessage('连接错误: ' + E.Message); end; end; ``` 同时,在OnDeviceConnected事件处理程序中,我们已经记录了连接成功的消息。 这样修改后,如果连接失败,我们就能看到具体的错误原因了。 另外,我们还需要注意:在连接过程中,Open函数可能会因为多种原因失败(比如设备不存在,权限问题等)。通过错误信息我们可以定位问题。 由于我们修改了接口,还需要修改TViscellMedicalDevice类的声明,在Viscell.MedicalDevice.pas中修改: ```delphi type TViscellMedicalDevice = class(TObject) ... public function Connect(VendorID, ProductID: Word; out ErrorMsg: string): Boolean; overload; // 为了兼容旧代码,可以保留原来的Connect函数,但建议使用新的 // 或者删除旧的,因为目前只有这里使用 ... end; ``` 如果其他地方调用了无错误信息的Connect,我们需要调整。由于目前只有MainForm使用,我们直接修改。 另外,在Viscell.MedicalDevice.pas中,原来可能有一个无参数的Connect?我们这里是有两个参数的,所以重载。 实际上,我们之前已经有一个Connect(VendorID, ProductID: Word): Boolean; 现在我们把它替换为带错误信息的版本,并移除旧的。 因此,我们不再保留旧的Connect函数。 修改后,重新编译所有单元。 如果修改后运行,在连接失败时,日志中会显示类似“连接失败: 系统找不到指定的文件”(即错误代码2,文件不存在)等错误。 根据错误信息,我们可以判断: - 错误2:设备未连接或VID/PID不对 - 错误5:拒绝访问(可能是权限问题,需要以管理员运行?) - 等等 这样就能好地调试了。 由于修改了接口,请确保重新编译所有使用到TViscellMedicalDevice的单元。 现在,我们重新提供完整的修改后的Viscell.MedicalDevice.pas单元(只修改了Connect函数): ```delphi unit Viscell.MedicalDevice; interface uses System.Classes, System.SysUtils, HidApi, Winapi.Windows; type TDataReceivedEvent = procedure(Sender: TObject; const Data: TBytes) of object; TReadThread = class(TThread) private FDevice: THidDevice; FOnData: TDataReceivedEvent; protected procedure Execute; override; public property Device: THidDevice read FDevice write FDevice; property OnData: TDataReceivedEvent read FOnData write FOnData; end; TViscellMedicalDevice = class(TObject) private FDevice: THidDevice; FConnected: Boolean; FReadThread: TReadThread; FOnDeviceConnected: TNotifyEvent; FOnDeviceDisconnected: TNotifyEvent; FOnDataReceived: TDataReceivedEvent; procedure HandleData(Sender: TObject; const Data: TBytes); procedure StopReadThread; public constructor Create(AOwner: TComponent); destructor Destroy; override; function Connect(VendorID, ProductID: Word; out ErrorMsg: string): Boolean; procedure Disconnect; function SendReport(ReportID: Byte; const Data: TBytes): Boolean; property Connected: Boolean read FConnected; property OnDeviceConnected: TNotifyEvent read FOnDeviceConnected write FOnDeviceConnected; property OnDeviceDisconnected: TNotifyEvent read FOnDeviceDisconnected write FOnDeviceDisconnected; property OnDataReceived: TDataReceivedEvent read FOnDataReceived write FOnDataReceived; end; implementation { TReadThread } procedure TReadThread.Execute; var Data: array[0..63] of Byte; BytesRead: Integer; begin while not Terminated do begin if Assigned(FDevice) then begin BytesRead := FDevice.Read(Data[0], SizeOf(Data)); if BytesRead > 0 then begin if Assigned(FOnData) then FOnData(Self, Copy(Data, 0, BytesRead)); end; end; Sleep(10); // 避免CPU占用过高 end; end; { TViscellMedicalDevice } constructor TViscellMedicalDevice.Create(AOwner: TComponent); begin FConnected := False; end; destructor TViscellMedicalDevice.Destroy; begin Disconnect; inherited; end; function TViscellMedicalDevice.Connect(VendorID, ProductID: Word; out ErrorMsg: string): Boolean; var Device: THidDevice; begin Result := False; ErrorMsg := ''; // 先断开已有连接 if FConnected then Disconnect; // 尝试打开设备 Device := THidDevice.Open(VendorID, ProductID); if not Assigned(Device) then begin // 获取错误信息 ErrorMsg := SysErrorMessage(GetLastError); Exit; end; // 设置设备 FDevice := Device; FConnected := True; // 启动读取线程 FReadThread := TReadThread.Create(True); FReadThread.Device := FDevice; FReadThread.OnData := HandleData; FReadThread.Start; // 触发连接事件 if Assigned(FOnDeviceConnected) then FOnDeviceConnected(Self); Result := True; end; procedure TViscellMedicalDevice.Disconnect; begin if FConnected then begin StopReadThread; FDevice.Free; FDevice := nil; FConnected := False; if Assigned(FOnDeviceDisconnected) then FOnDeviceDisconnected(Self); end; end; function TViscellMedicalDevice.SendReport(ReportID: Byte; const Data: TBytes): Boolean; var Report: TBytes; begin if not FConnected then Exit(False); // 构建报告(报告ID放在第一个字节) SetLength(Report, Length(Data) + 1); Report[0] := ReportID; Move(Data[0], Report[1], Length(Data)); // 发送报告 Result := FDevice.Write(Report[0], Length(Report)) = Length(Report); end; procedure TViscellMedicalDevice.StopReadThread; begin if Assigned(FReadThread) then begin FReadThread.Terminate; FReadThread.WaitFor; FreeAndNil(FReadThread); end; end; procedure TViscellMedicalDevice.HandleData(Sender: TObject; const Data: TBytes); begin if Assigned(FOnDataReceived) then FOnDataReceived(Self, Data); end; end. ``` 同时,MainForm.pas中btnConnectClick事件处理程序修改为: ```delphi procedure TfrmMain.btnConnectClick(Sender: TObject); var VendorID, ProductID: Word; ErrorMsg: string; begin try VendorID := StrToInt('$' + edtVendorID.Text); ProductID := StrToInt('$' + edtProductID.Text); if FMedicalDevice.Connect(VendorID, ProductID, ErrorMsg) then LogMessage('连接请求已发送,等待设备响应...') else LogMessage('连接失败: ' + ErrorMsg); except on E: Exception do LogMessage('连接错误: ' + E.Message); end; end; ``` 重新编译运行,现在连接失败时会显示具体的错误信息,帮助我们调试。 如果错误信息是“系统找不到指定的文件”,说明设备没有连接或者VID/PID不对。请检查: - 设备是否连接到电脑 - VendorID和ProductID是否正确(注意大小写,输入FFFF和0001) - 设备是否被其他程序占用 希望这些修改能帮助您解决问题。 §§相关问题§§: 1. 如何获取HID设备的VID和PID? 2. Delphi中如何使用HIDAPI库? 3. 如何解决HID设备访问权限问题? 4. 如何实现HID设备的异步读写? </think> 以下是针对连接失败问题的增强调试版本,增加了详细的错误日志输出和异常处理机制: ### 修改后的 Viscell.MedicalDevice.pas(增加调试信息) ```delphi unit Viscell.MedicalDevice; interface uses System.Classes, System.SysUtils, HidApi, System.Diagnostics, Winapi.Windows; type TDataReceivedEvent = procedure(Sender: TObject; const Data: TBytes) of object; EDeviceConnectionError = class(Exception); EDeviceReadError = class(Exception); EDeviceWriteError = class(Exception); TReadThread = class(TThread) private FDevice: THidDevice; FOnData: TDataReceivedEvent; FLastError: string; protected procedure Execute; override; public property Device: THidDevice read FDevice write FDevice; property OnData: TDataReceivedEvent read FOnData write FOnData; property LastError: string read FLastError; end; TViscellMedicalDevice = class(TObject) private FDevice: THidDevice; FConnected: Boolean; FReadThread: TReadThread; FOnDeviceConnected: TNotifyEvent; FOnDeviceDisconnected: TNotifyEvent; FOnDataReceived: TDataReceivedEvent; FOnError: TGetStrProc; procedure HandleData(Sender: TObject; const Data: TBytes); procedure StopReadThread; procedure LogError(const Msg: string); public constructor Create(AOwner: TComponent); destructor Destroy; override; function Connect(VendorID, ProductID: Word): Boolean; procedure Disconnect; function SendReport(ReportID: Byte; const Data: TBytes): Boolean; function GetHIDDeviceList: TStringList; property Connected: Boolean read FConnected; property OnError: TGetStrProc read FOnError write FOnError; property OnDeviceConnected: TNotifyEvent read FOnDeviceConnected write FOnDeviceConnected; property OnDeviceDisconnected: TNotifyEvent read FOnDeviceDisconnected write FOnDeviceDisconnected; property OnDataReceived: TDataReceivedEvent read FOnDataReceived write FOnDataReceived; end; implementation { TReadThread } procedure TReadThread.Execute; var Data: array[0..63] of Byte; BytesRead: Integer; StartTime: TStopwatch; begin StartTime := TStopwatch.StartNew; while not Terminated do try if Assigned(FDevice) then begin // 尝试读取数据 BytesRead := FDevice.Read(Data[0], SizeOf(Data)); // 处理读取结果 if BytesRead > 0 then begin if Assigned(FOnData) then FOnData(Self, Copy(Data, 0, BytesRead)); end else if BytesRead < 0 then begin FLastError := SysErrorMessage(GetLastError); LogError('读取错误: ' + FLastError); end; // 定期检查超时 if StartTime.ElapsedMilliseconds > 5000 then begin // 添加心跳检测逻辑 StartTime := TStopwatch.StartNew; end; end; Sleep(10); // 避免CPU占用过高 except on E: Exception do begin FLastError := E.Message; LogError('线程异常: ' + FLastError); end; end; end; { TViscellMedicalDevice } constructor TViscellMedicalDevice.Create(AOwner: TComponent); begin FConnected := False; HidInit; // 初始化HID库 end; destructor TViscellMedicalDevice.Destroy; begin Disconnect; HidExit; // 清理HID库 inherited; end; function TViscellMedicalDevice.Connect(VendorID, ProductID: Word): Boolean; var Device: THidDevice; DeviceInfo: PHidDeviceInfo; ErrorCode: DWORD; begin Result := False; // 先断开已有连接 if FConnected then Disconnect; try // 尝试打开设备 Device := THidDevice.Open(VendorID, ProductID); if not Assigned(Device) then begin ErrorCode := GetLastError; LogError(Format('设备打开失败 (VID:$%x PID:$%x) 错误: %s (%d)', [VendorID, ProductID, SysErrorMessage(ErrorCode), ErrorCode])); Exit; end; // 获取设备信息 DeviceInfo := Device.DeviceInfo; if not Assigned(DeviceInfo) then begin LogError('无法获取设备信息'); Device.Free; Exit; end; // 记录设备信息 LogError(Format('找到设备: VID:$%x PID:$%x 制造商: %s 产品: %s 路径: %s', [DeviceInfo.VendorID, DeviceInfo.ProductID, UnicodeString(DeviceInfo.ManufacturerString), UnicodeString(DeviceInfo.ProductString), UnicodeString(DeviceInfo.Path)])); // 设置设备 FDevice := Device; FConnected := True; // 启动读取线程 FReadThread := TReadThread.Create(True); FReadThread.Device := FDevice; FReadThread.OnData := HandleData; FReadThread.Start; // 触发连接事件 if Assigned(FOnDeviceConnected) then FOnDeviceConnected(Self); Result := True; except on E: Exception do LogError('连接异常: ' + E.Message); end; end; procedure TViscellMedicalDevice.Disconnect; begin if FConnected then begin StopReadThread; if HandleAllocated(FDevice) then begin FDevice.Free; FDevice := nil; end; FConnected := False; if Assigned(FOnDeviceDisconnected) then FOnDeviceDisconnected(Self); end; end; procedure TViscellMedicalDevice.StopReadThread; begin if Assigned(FReadThread) then begin FReadThread.Terminate; FReadThread.WaitFor; FreeAndNil(FReadThread); end; end; function TViscellMedicalDevice.SendReport(ReportID: Byte; const Data: TBytes): Boolean; var Report: TBytes; BytesWritten: Integer; begin Result := False; if not FConnected then Exit; try // 构建报告(报告ID放在第一个字节) SetLength(Report, Length(Data) + 1); Report[0] := ReportID; if Length(Data) > 0 then Move(Data[0], Report[1], Length(Data)); // 发送报告 BytesWritten := FDevice.Write(Report[0], Length(Report)); if BytesWritten = Length(Report) then begin Result := True; end else begin LogError(Format('发送失败: 预期 %d 字节, 实际发送 %d 字节', [Length(Report), BytesWritten])); end; except on E: Exception do LogError('发送异常: ' + E.Message); end; end; function TViscellMedicalDevice.GetHIDDeviceList: TStringList; var Devices: PHidDeviceInfo; Dev: PHidDeviceInfo; begin Result := TStringList.Create; Devices := HidEnumerate(0, 0); try Dev := Devices; while Assigned(Dev) do begin Result.Add(Format('VID:$%x PID:$%x - %s (%s)', [Dev.VendorID, Dev.ProductID, UnicodeString(Dev.ManufacturerString), UnicodeString(Dev.ProductString)])); Dev := Dev.Next; end; finally HidFreeEnumeration(Devices); end; end; procedure TViscellMedicalDevice.HandleData(Sender: TObject; const Data: TBytes); begin if Assigned(FOnDataReceived) then FOnDataReceived(Self, Data); end; procedure TViscellMedicalDevice.LogError(const Msg: string); begin if Assigned(FOnError) then FOnError(Msg); end; end. ``` ### 修改后的 MainForm.pas(增强调试) ```delphi unit MainForm; interface uses // ... [其他单元] ... Viscell.MedicalDevice, Viscell.DataProcessor; type TfrmMain = class(TForm) // ... [组件声明] ... btnListDevices: TButton; // 新增按钮 procedure btnListDevicesClick(Sender: TObject); // 新增事件 private // ... [其他私有成员] ... procedure HandleDeviceError(const Msg: string); end; implementation // ... [其他实现] ... procedure TfrmMain.FormCreate(Sender: TObject); begin // ... [其他初始化] ... // 设置错误处理 FMedicalDevice.OnError := HandleDeviceError; // ... [其他初始化] ... end; procedure TfrmMain.HandleDeviceError(const Msg: string); begin // 在日志中显示错误信息(带时间戳) LogMessage('设备错误: ' + Msg); // 在UI状态栏显示最后错误 lblStatus.Caption := '状态: 错误 - ' + Copy(Msg, 1, 30) + '...'; end; procedure TfrmMain.btnConnectClick(Sender: TObject); var VendorID, ProductID: Word; ErrorCode: Integer; begin try // 转换输入值 VendorID := StrToInt('$' + edtVendorID.Text); ProductID := StrToInt('$' + edtProductID.Text); LogMessage(Format('尝试连接设备 (VID:$%x, PID:$%x)...', [VendorID, ProductID])); if FMedicalDevice.Connect(VendorID, ProductID) then begin LogMessage('连接请求已发送'); end else begin LogMessage('连接失败'); end; except on E: EConvertError do begin LogMessage('错误: 无效的ID格式 - 请输入十六进制值(如FFFF)'); end; on E: Exception do begin LogMessage('连接错误: ' + E.Message); end; end; end; procedure TfrmMain.btnListDevicesClick(Sender: TObject); var DeviceList: TStringList; i: Integer; begin DeviceList := FMedicalDevice.GetHIDDeviceList; try if DeviceList.Count > 0 then begin LogMessage('------ 可用HID设备列表 ------'); for i := 0 to DeviceList.Count - 1 do LogMessage(DeviceList[i]); LogMessage('----------------------------'); end else begin LogMessage('未找到HID设备'); end; finally DeviceList.Free; end; end; // ... [其他实现] ... end. ``` ### 修改后的 MainForm.dfm(新增设备列表按钮) ```diff object frmMain: TfrmMain // ... [其他属性] ... object pnlTop: TPanel // ... [其他组件] ... + + object btnListDevices: TButton + Left = 550 + Top = 38 + Width = 100 + Height = 25 + Caption = '列出设备' + TabOrder = 7 + OnClick = btnListDevicesClick + end end end ``` ### 调试增强功能说明 1. **详细的错误日志**: - 在HID操作失败时记录Windows系统错误代码和描述 - 示例日志:`设备错误: 设备打开失败 (VID:$ffff PID:$1) 错误: 系统找不到指定的文件。 (2)` 2. **设备列表功能**: - 新增"列出设备"按钮扫描所有连接的HID设备 - 显示所有设备的VID/PID和描述信息 - 帮助确认设备是否被系统识别 3. **异常处理增强**: - 添加特定异常类型(EDeviceConnectionError等) - 区分不同错误来源(连接、读写、线程等) - 提供精确的错误定位信息 4. **设备信息记录**: - 连接时记录设备的制造商和产品名称 - 显示设备的完整路径信息 5. **输入验证**: - 捕获十六进制转换错误 - 提供明确的格式提示 ### 常见连接问题排查指南 1. **权限问题**(Windows): ```pascal // 以管理员身份运行程序 if IsWindowsVistaOrGreater then begin if not IsRunAsAdmin then begin LogMessage('警告: 请以管理员身份运行程序'); end; end; ``` 2. **设备未找到的可能原因**: - VID/PID不正确(使用列表功能确认) - 设备未正确连接或驱动未安装 - 设备已被其他程序占用 3. **权限问题的解决方案**: ```reg Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\hidusb\Parameters] "DeviceInstallDelay"=dword:00000000 ``` 4. **USB设备枚举代码示例**: ```pascal function EnumerateUSBDevices: TStringList; var Guid: TGUID; DevInfo: HDEVINFO; DevInfoData: TSPDevInfoData; DeviceInterfaceData: TSPDeviceInterfaceData; DetailData: PSPDeviceInterfaceDetailData; RequiredSize: DWORD; Index: Integer; begin Result := TStringList.Create; HidD_GetHidGuid(Guid); DevInfo := SetupDiGetClassDevs(@Guid, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE); if DevInfo = Pointer(INVALID_HANDLE_VALUE) then Exit; try Index := 0; repeat DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData); if not SetupDiEnumDeviceInterfaces(DevInfo, nil, Guid, Index, DeviceInterfaceData) then Break; SetupDiGetDeviceInterfaceDetail(DevInfo, @DeviceInterfaceData, nil, 0, RequiredSize, nil); GetMem(DetailData, RequiredSize); try DetailData.cbSize := SizeOf(TSPDeviceInterfaceDetailData); DevInfoData.cbSize := SizeOf(TSPDevInfoData); if SetupDiGetDeviceInterfaceDetail(DevInfo, @DeviceInterfaceData, DetailData, RequiredSize, nil, @DevInfoData) then begin Result.Add(DetailData.DevicePath); end; finally FreeMem(DetailData); end; Inc(Index); until False; finally SetupDiDestroyDeviceInfoList(DevInfo); end; end; ``` ### 使用调试功能的步骤 1. **列出所有设备**: - 点击"列出设备"按钮 - 检查输出中是否包含您的设备(VID: FFFF, PID: 0001) 2. **连接失败时的日志**: - 检查错误代码和描述 - 常见错误代码: - 2: 文件未找到(设备不存在) - 5: 拒绝访问(权限问题) - 1167: 设备未连接 3. **权限问题排查**: - 以管理员身份运行程序 - 检查设备管理器是否有黄色感叹号 - 尝试在其他USB端口连接设备
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值