初学C++ Builder遇到的问题,问题描述如下:
个人发帖:
https://bbs.csdn.net/topics/391999974
1. 本人机器以前用过许多COM设备,使得再接入COM设备时,COM号不从最小的顺序开始,而是从之前使用过的开始。比如之前我使用了COM3/4/5/6,然后使用过以后,取下设备,再接其他COM设备时便从COM7/8/9 开始,COM7之前的COM号显示在使用中(而实际没有使用)。
2. 为解决以上问题,我尝试再注册表里清空注册表值,然后再试。结果COM7 之前的COM都被释放了(再没有显示折正在使用),但是COM设备的COM号依旧为 COM7/8/9。于是我在 设备管理器中 通过找到COM7/8/9并且手动卸载了COM设备,然后再选择 扫描检测硬件改动,发现COM设备 COM号正常的从 COM3/4/5/6 开始。
3. 综上,需要手动去点击卸载。因此在此请教 是否有WINDOWS 命令或者 可以用 API 函数来代替 卸载 COM设备。
----完整工程后续上传~
解决代码:
... ...
//---------------------------------------------------------------------------
#include
#pragma hdrstop#include "Unit1.h"
#pragma comment(lib, "newdev.lib")
#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "cfgmgr32.lib")
//#include
#include
#include "cfgmgr32.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::EnumDevices(HDEVINFO hDevInfo)
{
//TODO: Add your source code hereSP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};
// LPOLESTR guid;
char devName[128];
char instanceId[128];
char DeviceName[128];
char LocationDers[1024];
int Dev_i = 0;for (int i=0;SetupDiEnumDeviceInfo(hDevInfo,i,&DeviceInfoData);i++)
{
SetupDiGetDeviceInstanceId(hDevInfo,&DeviceInfoData,instanceId,128,NULL);
M1: Memo1->Lines->Add("M1: "+AnsiString(instanceId));
SetupDiClassNameFromGuid(&DeviceInfoData.ClassGuid,devName,128,NULL);
AnsiString TarGetDeviceGUID = GUIDToString(DeviceInfoData.ClassGuid);
M2: Memo1->Lines->Add("M2: "+GUIDToString(DeviceInfoData.ClassGuid));
AnsiString TarGetDeviceType = AnsiString(devName);
M3: Memo1->Lines->Add("M3: "+AnsiString(devName));
SetupDiGetDeviceRegistryProperty(hDevInfo,&DeviceInfoData,SPDRP_DEVICEDESC,NULL,DeviceName,128,NULL);
AnsiString TarGetDeviceName = AnsiString(DeviceName);
M4: Memo1->Lines->Add("M4: "+AnsiString(DeviceName));
SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_LOCATION_INFORMATION, NULL, LocationDers, 1024, NULL);
M5: Memo1->Lines->Add("M5: "+AnsiString(LocationDers));
Memo1->Lines->Add("");
TarGetDeviceType = TarGetDeviceType.UpperCase();
IniCfg.DeviceType = IniCfg.DeviceType.UpperCase();
if(0 == TarGetDeviceType.AnsiCompare(IniCfg.DeviceType)&& 0 == TarGetDeviceName.AnsiCompare(IniCfg.DeviceName) )
{
AnsiString DeviceNum = "Device "+IntToStr(++Dev_i);
Report->Lines->Add(DeviceNum+" GUID: "+TarGetDeviceGUID);
Report->Lines->Add(DeviceNum+" Type: "+TarGetDeviceType);
Report->Lines->Add(DeviceNum+" Name: "+TarGetDeviceName);
if (0 != SetupDiRemoveDevice(hDevInfo, &DeviceInfoData)) //移除设备
Report->Lines->Add("Remove "+DeviceNum+" Success");
}
Application->ProcessMessages();
}
if(0 == Dev_i)
{
Report->Lines->Add("##Don't Find The COM Device");
AllFlag = false;
return false;
}
else
return true;
}void __fastcall TForm1::Button1Click(TObject *Sender)
{
AllFlag = true;
Panel1->Color = clBtnFace;
Button1->Enabled = false;
Button2->Enabled = false;HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
hDevInfo = SetupDiGetClassDevs(NULL,NULL,NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
if(INVALID_HANDLE_VALUE == hDevInfo)
ShowMessage("hDevInfo Fail!");
if(false == EnumDevices(hDevInfo)) //查找设备
{
Report->Lines->Add("##Uninstall COM Device Fail");
AllFlag = false;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
EditRegister(); // 清理注册表
UpdateDevice(); //更新设别 扫描检测硬件改动
if(true == AllFlag)
{
Report->Lines->Add("#All Operation PASS");
PassFun(Report,Panel1);
}
else
{
Report->Lines->Add("###All Test FAIL");
FailFun(Report,Panel1);
}if(1 == IniCfg.MRestart && true == AllFlag)
{
int t = Application->MessageBox("需要重启设备才能正常使用设备,是允许系统立即重启?","请做以下确认",MB_YESNO) ;
if(ID_YES == t)
{
Report->Lines->Add("!!!!The system will restart");
Shutdown();
}
else
Report->Lines->Add("!!!!To cancel the restart");
}
else if(1 == IniCfg.AutoShowDown && true == AllFlag )
{
Report->Lines->Add("!!!!The system will restart");
TmrDown->Enabled =true;
}Button1->Enabled = true;
Button2->Enabled = true;
Report->Lines->Add("");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
this->Close();
}
//---------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender)
{
if(FileExists("DeviceList.txt"))
DeleteFile("DeviceList.txt");
Memo1->Lines->SaveToFile("DevList.txt");
ShowMessage("Save reslut success");
}
//---------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender)
{
Report->Clear();
Memo1->Clear();
TmrDown->Enabled = false;
Timer1->Enabled = false;
Timer2->Enabled = false;
Panel1->Caption ="";
Panel1->Color = clBtnFace;AnsiString BasePath = GetCurrentDir();
TIniFile *Ini = new TIniFile(BasePath + "\\Setup.ini");
IniCfg.AutoRun = Ini->ReadInteger("CfgIni","AutoRun",0);
IniCfg.AutoClose = Ini->ReadInteger("CfgIni","AutoClose",0);
IniCfg.AutoShowDown =Ini->ReadInteger("CfgIni","AutoRestart",0);
IniCfg.ShutDownTime = Ini->ReadInteger("CfgIni","RestartTime",2);
IniCfg.MRestart = Ini->ReadInteger("CfgIni","ManuallyRestart",1);
IniCfg.DeveloperMode = Ini->ReadInteger("CfgIni","DeveloperMode",0);IniCfg.DeviceType = Ini->ReadString("CfgDevice","DeviceType","Ports");
IniCfg.DeviceName = Ini->ReadString("CfgDevice","DeviceName","通信端口");
delete Ini;
Report->Lines->Add("Cfgini: ");
Report->Lines->Add("AutoRun = "+IntToStr(IniCfg.AutoRun) );
Report->Lines->Add("AutoClose = "+IntToStr(IniCfg.AutoClose) );
Report->Lines->Add("AutoShowDown = "+IntToStr(IniCfg.AutoShowDown) );
Report->Lines->Add("ShutDownTime = "+IntToStr(IniCfg.ShutDownTime+3)+"s" );
Report->Lines->Add("CfgDevice: ");
Report->Lines->Add("DeviceType = "+IniCfg.DeviceType );
Report->Lines->Add("DeviceName = "+IniCfg.DeviceName );
Report->Lines->Add("");if( 0 != IniCfg.DeveloperMode)
{
Form1->AutoSize = true;
}
if(1 == IniCfg.AutoRun)
{
Timer1->Enabled = true;
}
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::EditRegister()
{
HKEY key;
DWORD dispos=0;
SECURITY_ATTRIBUTES sa;
AnsiString skey = "SYSTEM\\CurrentControlSet\\Control\\COM Name Arbiter";
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
long iret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, //主键 的值
skey.c_str(), //子键 的值
NULL, //保留,必须设置为0
NULL, //一个指向包含键类型的字符串。如果该键已经存在,则忽略该参数。
REG_OPTION_NON_VOLATILE, //为新创建的键设置一定的属性
KEY_ALL_ACCESS, //用来设置对键访问的权限
&sa, //为一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否被子处理过程继承。如果该参数为NULL,则句柄不可以被继承。
&key, //为一个指向新创建或打开的键的句柄的指针,指向该键
&dispos); //指明键是被创建还是被打开的
if(ERROR_SUCCESS == iret)
{
RegDeleteValue(key,"ComDB"); //删除项值名为ComDB的项值
RegCloseKey(key);
Report->Lines->Add("#Delete Register Value Success");
return true;
}
else
{
AllFlag = false;
Report->Lines->Add("##Delete Register Value Fail");
return false;
}
}void __fastcall TForm1::UpdateDevice()
{
DEVINST DevInst;
if(CR_SUCCESS == CM_Locate_DevNodeA(&DevInst,NULL,CM_LOCATE_DEVNODE_NORMAL) )
{
if(CR_SUCCESS != CM_Reenumerate_DevNode(DevInst,CM_REENUMERATE_NORMAL) )
{
ShowMessage("扫描检测硬件改动失败,请手动尝试");
Report->Lines->Add("##Restart COM Devcie Fail");
AllFlag = false;
}
else
{
Report->Lines->Add("#Restart COM Devcie Success");
Sleep(1000);
}
}
else
{
ShowMessage("扫描检测硬件改动失败,请手动尝试");
Report->Lines->Add("##Restart COM Devcie Fail");
// Sleep(1000);
AllFlag = false;
}
}
void __fastcall TForm1::Shutdown()
{
// AnsiString sss = "cmd"; //
AnsiString sss = "Shutdown -r -t "+IntToStr(IniCfg.ShutDownTime+3);
system(sss.c_str() ); //发出一个DOS命令 ,头文件
}
void __fastcall TForm1::PassFun(TMemo *MemoRepot,TPanel *PanelReport)
{
AnsiString CFGPath = GetCurrentDir() + "\\userdefineresult.log";
TIniFile *ini = new TIniFile(CFGPath);
ini->WriteString("Response","Result","PASS");
delete ini;AnsiString SaveLog = GetCurrentDir() + "\\userdefinelog.log";
if(FileExists(SaveLog)) //FileExists检查SaveLog路径下文件或目录是否存在
DeleteFile(SaveLog); //删除 SaveLog 路径文件
MemoRepot->Lines->SaveToFile(SaveLog); // 新建文件AnsiString CFGPath1 = GetCurrentDir() + "\\userdefinelog.log";
TIniFile *ini1 = new TIniFile(CFGPath1);
ini1->WriteString("Response","Result","PASS"); //写入相关信息
delete ini1;PanelReport->Caption = "PASS";
PanelReport->Color = clGreen;if(1 == IniCfg.AutoClose)
{
Sleep(1000);
this->Close();
}
}void __fastcall TForm1::FailFun(TMemo *MemoRepot,TPanel *PanelReport)
{
AnsiString CFGPath = GetCurrentDir() + "\\userdefineresult.log";
TIniFile *ini = new TIniFile(CFGPath);
ini->WriteString("Response","Result","FAIL");
delete ini;
AnsiString SaveLog = GetCurrentDir() + "\\userdefinelog.log";
if(FileExists(SaveLog))
DeleteFile(SaveLog);
MemoRepot->Lines->SaveToFile(SaveLog);AnsiString CFGPath1 = GetCurrentDir() + "\\userdefinelog.log";
TIniFile *ini1 = new TIniFile(CFGPath1);
ini1->WriteString("Response","Result","FAIL");
delete ini1;
PanelReport->Caption = "FAIL";
PanelReport->Color = clRed;}
void __fastcall TForm1::Button4Click(TObject *Sender)
{
AnsiString sss = "Shutdown -a";
char buffer[512];
sprintf(buffer,"%s",sss);
// system(sss.c_str() );
system(buffer); //发出一个DOS命令 ,头文件
}
//---------------------------------------------------------------------------void __fastcall TForm1::TmrDownTimer(TObject *Sender)
{
TmrDown->Enabled = false;
Shutdown(); //关机操作
}
//---------------------------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Timer1->Enabled =false;
Button1->Click();
}
//---------------------------------------------------------------------------void __fastcall TForm1::Timer2Timer(TObject *Sender)
{
Timer2->Enabled =false;
Button2->Click();
}
//---------------------------------------------------------------------------void __fastcall TForm1::Button5Click(TObject *Sender)
{
int t = Application->MessageBox("确定立即重启系统?","请做以下确认",MB_YESNO) ;
if(ID_YES == t)
{
Report->Lines->Add("!!!!The system will restart");
Shutdown();
}
else
Report->Lines->Add("!!!!To cancel the restart");
}
//---------------------------------------------------------------------------
后续补充:
工程源码已上传,请转移此处下载
https://download.csdn.net/download/ailong91/12004315
完结!!