using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management; /* System.Management referenced */
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace TestBoardDriver
{
public class DevManager
{
private static List portNums = new List();
private static List portIds = new List();
private static string GetPortId(int portNum)
{
for (int i = 0; i < portNums.Count; i++)
{
if (portNums[i] == portNum)
{
return portIds[i];
}
}
return "NA";
}
/*
自动查找VID/PID匹配的USB设备当作Virutal COM Port口
输入值: 字符串,如VID_0483&PID_5740
返回值: 0 - 没有找到对应设备
*/
public static List GetPortNum(String vid_pid)
{
ManagementObjectCollection USBControllerDeviceCollection
= new ManagementObjectSearcher("SELECT * FROM Win32_USBControllerDevice").Get();
if (USBControllerDeviceCollection != null)
{
foreach (ManagementObject USBControllerDevice in USBControllerDeviceCollection)
{
String Dependent = (USBControllerDevice["Dependent"] as String).Split(new Char[] { '=' })[1];
if (Dependent.Contains(vid_pid))
{
ManagementObjectCollection PnPEntityCollection
= new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE DeviceID=" + Dependent).Get();
if (PnPEntityCollection != null)
{
foreach (ManagementObject Entity in PnPEntityCollection)
{
String PortId = Dependent.Split('\\')[4]; //Dependent = ""USB\\VID_0483&PID_5740\\6D8D108F5750""
PortId = PortId.Substring(0, PortId.Length - 1);
String DevName = Entity["Name"] as String; // 设备名称 = "STMicroelectronics Virtual COM Port (COM9)"
String PortNum = Regex.Replace(DevName, @"[^\d.\d]", "");
try
{/*安装驱动程序过慢会导致DevName中不含COM号(出现概率小)*/
portNums.Add( Convert.ToInt32(PortNum) );
portIds.Add(PortId);
}
catch(Exception)
{
return GetPortNum(vid_pid);
}
}
}
}
}
}
return portNums;
}
/*
删除指定设备
输入值: 设备管理器下的设备名称,不包括后面的(COMXX)
返回值: 成功/失败
*/
public static bool DeletePort(String vidpid, int comNum)
{
bool ret = false;
Guid classGuid = Guid.Empty;
IntPtr hDevInfo = Win32.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, Win32.DIGCF_ALLCLASSES | Win32.DIGCF_PRESENT);
if (hDevInfo.ToInt32() == Win32.INVALID_HANDLE_VALUE)
{
Console.WriteLine("访问硬件设备失败");
}
else
{
string portId = GetPortId(comNum);
int i = 0;
int selected = 0;
StringBuilder deviceName = new StringBuilder();
deviceName.Capacity = Win32.MAX_DEV_LEN;
do
{
Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA();
StringBuilder _DeviceName = new StringBuilder("");
_DeviceName.Capacity = 1000;
devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
devInfoData.classGuid = Guid.Empty;
devInfoData.devInst = 0;
devInfoData.reserved = IntPtr.Zero;
bool result = Win32.SetupDiEnumDeviceInfo(hDevInfo, i, devInfoData);
if (false == result)
{
break;
}
Win32.SetupDiGetDeviceRegistryProperty(hDevInfo, devInfoData, 0, 0, _DeviceName, (uint)_DeviceName.Capacity, IntPtr.Zero);
string devId = GetDeviceInstanceId(hDevInfo, devInfoData);
if (devId.Contains(vidpid))
{
if (devId.Contains(portId))
{
Log.Show(Log.Level.Operation, "Deleting " + _DeviceName.ToString() + " " + comNum + " :" + devId);
selected = i;
}
}
++i;
} while (true);
ret = Remove(selected, hDevInfo);
}
Win32.SetupDiDestroyDeviceInfoList(hDevInfo);
return ret;
}
/*
重新扫描硬件
输入值: 无
返回值: 成功/失败
*/
public static bool Rescan()
{
UInt32 devRoot = 0;
if (Win32.CM_Locate_DevNode_Ex(ref devRoot, null, 0, IntPtr.Zero) != Win32.CR_SUCCESS)
{
return false;
}
if (Win32.CM_Reenumerate_DevNode_Ex(devRoot, 0, IntPtr.Zero) != Win32.CR_SUCCESS)
{
return false;
}
return true;
}
/*
禁用指定设备
输入值: 设备管理器下的设备名称,不包括后面的(COMXX)
返回值: 成功/失败
*/
public static bool DisablePort(String portName = null)
{
bool ret = false;
Guid classGuid = Guid.Empty;
IntPtr hDevInfo = Win32.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, Win32.DIGCF_ALLCLASSES | Win32.DIGCF_PRESENT);
if (hDevInfo.ToInt32() == Win32.INVALID_HANDLE_VALUE)
{
Console.WriteLine("访问硬件设备失败");
}
else
{
int i = 0;
int selected = 0;
StringBuilder deviceName = new StringBuilder();
deviceName.Capacity = Win32.MAX_DEV_LEN;
do
{
Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA();
StringBuilder _DeviceName = new StringBuilder("");
_DeviceName.Capacity = 1000;
devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
devInfoData.classGuid = Guid.Empty;
devInfoData.devInst = 0;
devInfoData.reserved = IntPtr.Zero;
bool result = Win32.SetupDiEnumDeviceInfo(hDevInfo, i, devInfoData);
if (false == result)
{
break;
}
Win32.SetupDiGetDeviceRegistryProperty(hDevInfo, devInfoData, 0, 0, _DeviceName, (uint)_DeviceName.Capacity, IntPtr.Zero);
if (_DeviceName.ToString().Equals(portName))
{
Log.Show(Log.Level.Operation, _DeviceName.ToString());
selected = i;
}
++i;
} while (true);
ret = StateChange(false, selected, hDevInfo);
}
Win32.SetupDiDestroyDeviceInfoList(hDevInfo);
return ret;
}
private static bool Remove(int SelectedItem, IntPtr DevInfo)
{
bool result = false;
Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA(); ;
devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
if (true == Win32.SetupDiEnumDeviceInfo(DevInfo, SelectedItem, devInfoData))
{
if (true == Win32.SetupDiCallClassInstaller(Win32.DIF_REMOVE, DevInfo, devInfoData))
{
result = true;
}
else
{
uint ret = (uint)Win32.GetLastError();
Log.Show(Log.Level.Operation, "删除硬件设备失败(" + ret.ToString() + ")");
}
}
return result;
}
private static bool StateChange(bool Enable, int SelectedItem, IntPtr DevInfo)
{
bool result = false;
Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA(); ;
devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
if (true == Win32.SetupDiEnumDeviceInfo(DevInfo, SelectedItem, devInfoData))
{
Win32.SP_PROPCHANGE_PARAMS pcp = new Win32.SP_PROPCHANGE_PARAMS(); ;
pcp.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(Win32.SP_CLASSINSTALL_HEADER));
pcp.ClassInstallHeader.InstallFunction = Win32.DIF_PROPERTYCHANGE;
pcp.Scope = Win32.DICS_FLAG_CONFIGSPECIFIC;
pcp.StateChange = (Enable ? Win32.DICS_ENABLE : Win32.DICS_DISABLE);
if (true == Win32.SetupDiSetClassInstallParams(DevInfo, devInfoData, pcp, Marshal.SizeOf(pcp)))
{
if (true == Win32.SetupDiCallClassInstaller(Win32.DIF_PROPERTYCHANGE, DevInfo, devInfoData))
{
result = true;
}
else
{
uint ret = (uint)Win32.GetLastError();
Log.Show(Log.Level.Operation, "禁用硬件设备失败(" + ret.ToString() + ")");
}
}
}
return result;
}
protected static String GetClassNameFromGuid(Guid guid)
{
String result = String.Empty;
StringBuilder className = new StringBuilder();
Int32 iRequiredSize = 0;
Int32 iSize = 0;
bool b = Win32.SetupDiClassNameFromGuid(ref guid, className, iSize, ref iRequiredSize);
className = new StringBuilder(iRequiredSize);
iSize = iRequiredSize;
b = Win32.SetupDiClassNameFromGuid(ref guid, className, iSize, ref iRequiredSize);
if (true == b)
{
result = className.ToString();
}
return result;
}
protected static String GetClassDescriptionFromGuid(Guid guid)
{
String result = String.Empty;
StringBuilder classDesc = new StringBuilder(0);
Int32 iRequiredSize = 0;
Int32 iSize = 0;
bool b = Win32.SetupDiGetClassDescription(ref guid, classDesc, iSize, ref iRequiredSize);
classDesc = new StringBuilder(iRequiredSize);
iSize = iRequiredSize;
b = Win32.SetupDiGetClassDescription(ref guid, classDesc, iSize, ref iRequiredSize);
if (true == b)
{
result = classDesc.ToString();
}
return result;
}
protected static String GetDeviceInstanceId(IntPtr DeviceInfoSet, Win32.SP_DEVINFO_DATA DeviceInfoData)
{
String result = String.Empty;
StringBuilder id = new StringBuilder(0);
Int32 iRequiredSize = 0;
Int32 iSize = 0;
bool b = Win32.SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfoData, id, iSize, ref iRequiredSize);
id = new StringBuilder(iRequiredSize);
iSize = iRequiredSize;
b = Win32.SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfoData, id, iSize, ref iRequiredSize);
if (true == b)
{
result = id.ToString();
}
return result;
}
/* setupapi.dll elements */
public class Win32
{
[StructLayout(LayoutKind.Sequential)]
public struct SP_BROADCAST_HANDLE
{
public int dbch_size;
public int dbch_devicetype;
public int dbch_reserved;
public IntPtr dbch_handle;
public IntPtr dbch_hdevnotify;
public Guid dbch_eventguid;
public long dbch_nameoffset;
public byte dbch_data;
public byte dbch_data1;
}
[StructLayout(LayoutKind.Sequential)]
public class DEV_BROADCAST_DEVICEINTERFACE
{
public int dbcc_size;
public int dbcc_devicetype;
public int dbcc_reserved;
}
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
{
public int cbSize;
public Guid classGuid;
public int devInst;
public IntPtr reserved;
};
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINSTALL_PARAMS
{
public int cbSize;
public int Flags;
public int FlagsEx;
public IntPtr hwndParent;
public IntPtr InstallMsgHandler;
public IntPtr InstallMsgHandlerContext;
public IntPtr FileQueue;
public IntPtr ClassInstallReserved;
public int Reserved;
[MarshalAs(UnmanagedType.LPTStr)]
public string DriverPath;
};
[StructLayout(LayoutKind.Sequential)]
public class SP_PROPCHANGE_PARAMS
{
public SP_CLASSINSTALL_HEADER ClassInstallHeader = new SP_CLASSINSTALL_HEADER();
public int StateChange;
public int Scope;
public int HwProfile;
};
[StructLayout(LayoutKind.Sequential)]
public class SP_CLASSINSTALL_HEADER
{
public int cbSize;
public int InstallFunction;
};
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, DEV_BROADCAST_DEVICEINTERFACE NotificationFilter, UInt32 Flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern UInt32 UnregisterDeviceNotification(IntPtr hHandle);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPStr)]String Enumerator, IntPtr hwndParent, Int32 Flags);
[DllImport("setupapi.dll")]
public static extern IntPtr SetupDiGetClassDevsEx(ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPStr)]String Enumerator,
IntPtr hwndParent, Int32 Flags, IntPtr DeviceInfoSet,
[MarshalAs(UnmanagedType.LPStr)]String MachineName,
IntPtr Reserved);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern Boolean SetupDiEnumDeviceInfo(IntPtr lpInfoSet, Int32 dwIndex, SP_DEVINFO_DATA devInfoData);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern Boolean SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet, SP_DEVINFO_DATA DeviceInfoData, UInt32 Property,
UInt32 PropertyRegDataType, StringBuilder PropertyBuffer, UInt32 PropertyBufferSize, IntPtr RequiredSize);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern Boolean SetupDiSetClassInstallParams(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, SP_PROPCHANGE_PARAMS ClassInstallParams, int ClassInstallParamsSize);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiCallClassInstaller(UInt32 InstallFunction, IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);
[DllImport("newdev.dll", CharSet = CharSet.Auto)]
public static extern Boolean DiUninstallDevice(IntPtr parent, IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, IntPtr flag, bool reboot);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiRemoveDevice(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiUnremoveDevice(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiClassNameFromGuid(ref Guid ClassGuid, StringBuilder className, Int32 ClassNameSize, ref Int32 RequiredSize);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiGetClassDescription(ref Guid ClassGuid, StringBuilder classDescription, Int32 ClassDescriptionSize, ref Int32 RequiredSize);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
public static extern Boolean SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, Int32 DeviceInstanceIdSize, ref Int32 RequiredSize);
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, int Property, uint PropertyRegDataType, StringBuilder PropertyBuffer, uint PropertyBufferSize, IntPtr RequiredSize);
public const int DIGCF_ALLCLASSES = (0x00000004);
public const int DIGCF_PRESENT = (0x00000002);
public const int INVALID_HANDLE_VALUE = -1;
public const int SPDRP_DEVICEDESC = (0x00000000);
public const int MAX_DEV_LEN = 200;
public const int DEVICE_NOTIFY_WINDOW_HANDLE = (0x00000000);
public const int DEVICE_NOTIFY_SERVICE_HANDLE = (0x00000001);
public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = (0x00000004);
public const int DBT_DEVTYP_DEVICEINTERFACE = (0x00000005);
public const int DBT_DEVNODES_CHANGED = (0x0007);
public const int WM_DEVICECHANGE = (0x0219);
public const int DIF_REMOVE = (0x00000005);
public const int DIF_PROPERTYCHANGE = (0x00000012);
public const int DICS_FLAG_GLOBAL = (0x00000001);
public const int DICS_FLAG_CONFIGSPECIFIC = (0x00000002);
public const int DICS_ENABLE = (0x00000001);
public const int DICS_DISABLE = (0x00000002);
[DllImport("setupapi.dll", SetLastError = true)]
static public extern int CM_Locate_DevNode_Ex(ref UInt32 pdnDevInst, string pDeviceID, int ulFlags, IntPtr hMachine);
[DllImport("setupapi.dll")]
static public extern UInt32 CM_Reenumerate_DevNode_Ex(UInt32 dnDevInst, UInt32 ulFlags, IntPtr hMachine);
public const uint CR_SUCCESS = 0x00000000;
}
}
}