我正在寻找的方式来禁用系统设备(无论是USB或内部)在C#.NET给定的PID和VID或设备名称。
search后,我发现CodeProject上的C#硬件助手库 。
但是我需要能够在XP,Vista和Windows 7(包括x86和x64操作系统)上工作的东西… 我链接的项目只能在XP和Vista x86下运行…即使以pipe理员权限运行应用程序。
有谁知道可以在所有操作系统上工作的解决scheme吗?
C# – 方法必须有返回types
使用AsParallel()时无法获取与Windows应用程序关联的文件的文件图标
使用Thrift从.NET连接到Cassandra
定义不同types的二维dynamic数组
如何在使用IO.Directory.EnumerateDirectories时忽略Documents文件夹中的连接点
获取Windows凭据用作CRM的ClientCredentials(System.ServiceModel.ClientCredentials)
运行Mono的最佳Linux发行版
我应该怎样在C#程序中使用.NET Framework 3.5检测Windows 8.1的正确操作系统版本?
是否有可能确定哪个进程启动我的.Net应用程序?
使用C#如何检测是否安装了Windows Installer 4.5
看起来drf的版本中有两件事给你带来麻烦。 您的x64问题是由SP_DEVINFO_DATA具有一个需要IntPtr的uint引起的。 第二个是SetupDiGetDevicePropertyW函数是Vista +,不能在XP上运行。
这是一个更正了这两个问题的版本。 我测试了XPx86和Win7X64上的x86和Anycpu。
public static class disableHardware { const uint DIF_PROPERTYCHANGE = 0x12; const uint DICS_ENABLE = 1; const uint DICS_disABLE = 2; // disable device const uint DICS_FLAG_GLOBAL = 1; // not profile-specific const uint DIGCF_ALLCLASSES = 4; const uint DIGCF_PRESENT = 2; const uint ERROR_INVALID_DATA = 13; const uint ERROR_NO_MORE_ITEMS = 259; const uint ERROR_ELEMENT_NOT_FOUND = 1168; static DEVPROPKEY DEVPKEY_Device_DeviceDesc; static DEVPROPKEY DEVPKEY_Device_HardwareIds; [StructLayout(LayoutKind.Sequential)] struct SP_CLASSINSTALL_HEADER { public UInt32 cbSize; public UInt32 InstallFunction; } [StructLayout(LayoutKind.Sequential)] struct SP_PROPCHANGE_ParaMS { public SP_CLASSINSTALL_HEADER ClassInstallHeader; public UInt32 StateChange; public UInt32 Scope; public UInt32 HwProfile; } [StructLayout(LayoutKind.Sequential)] struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid classGuid; public UInt32 devInst; public IntPtr reserved; // CHANGE #1 - was UInt32 } [StructLayout(LayoutKind.Sequential)] struct DEVPROPKEY { public Guid fmtid; public UInt32 pid; } [DllImport("setupapi.dll",SetLastError = true)] static extern IntPtr SetupDiGetClassDevsW( [In] ref Guid ClassGuid,[MarshalAs(UnmanagedType.LPWStr)] string Enumerator,IntPtr parent,UInt32 flags); [DllImport("setupapi.dll",SetLastError = true)] static extern bool SetupDiDestroyDeviceInfoList(IntPtr handle); [DllImport("setupapi.dll",SetLastError = true)] static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet,UInt32 memberIndex,[Out] out SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll",SetLastError = true)] static extern bool SetupdisetClassInstallParams( IntPtr deviceInfoSet,[In] ref SP_DEVINFO_DATA deviceInfoData,[In] ref SP_PROPCHANGE_ParaMS classInstallParams,UInt32 ClassInstallParamsSize); [DllImport("setupapi.dll",SetLastError = true)] static extern bool SetupDiChangeState( IntPtr deviceInfoSet,[In] ref SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll",SetLastError = true)] static extern bool SetupDiGetDevicePropertyW( IntPtr deviceInfoSet,[In] ref SP_DEVINFO_DATA DeviceInfoData,[In] ref DEVPROPKEY propertyKey,[Out] out UInt32 propertyType,IntPtr propertyBuffer,UInt32 propertyBufferSize,out UInt32 requiredSize,SetLastError = true)] static extern bool SetupDiGetDeviceRegistryPropertyW( IntPtr DeviceInfoSet,UInt32 Property,[Out] out UInt32 PropertyRegDataType,IntPtr PropertyBuffer,UInt32 PropertyBufferSize,[In,Out] ref UInt32 requiredSize ); static disableHardware() { disableHardware.DEVPKEY_Device_DeviceDesc = new DEVPROPKEY(); DEVPKEY_Device_DeviceDesc.fmtid = new Guid( 0xa45c254e,0xdf1c,0x4efd,0x80,0x20,0x67,0xd1,0x46,0xa8,0x50,0xe0); DEVPKEY_Device_DeviceDesc.pid = 2; DEVPKEY_Device_HardwareIds = new DEVPROPKEY(); DEVPKEY_Device_HardwareIds.fmtid = new Guid( 0xa45c254e,0xe0); DEVPKEY_Device_HardwareIds.pid = 3; } public static void disableDevice(Func<string,bool> filter,bool disable = true) { IntPtr info = IntPtr.Zero; Guid NullGuid = Guid.Empty; try { info = SetupDiGetClassDevsW( ref NullGuid,null,IntPtr.Zero,DIGCF_ALLCLASSES); Checkerror("SetupDiGetClassDevs"); SP_DEVINFO_DATA devdata = new SP_DEVINFO_DATA(); devdata.cbSize = (UInt32)Marshal.SizeOf(devdata); // Get first device matching device criterion. for (uint i = 0; ; i++) { SetupDiEnumDeviceInfo(info,i,out devdata); // if no items match filter,throw if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS) Checkerror("No device found matching filter.",0xcffff); Checkerror("SetupDiEnumDeviceInfo"); string devicepath = GetStringPropertyForDevice(info,devdata,1); // SPDRP_HARDWAREID // Uncomment to print name/path //Console.WriteLine(GetStringPropertyForDevice(info,// devdata,DEVPKEY_Device_DeviceDesc)); //Console.WriteLine(" {0}",devicepath); if (devicepath != null && filter(devicepath)) break; } SP_CLASSINSTALL_HEADER header = new SP_CLASSINSTALL_HEADER(); header.cbSize = (UInt32)Marshal.SizeOf(header); header.InstallFunction = DIF_PROPERTYCHANGE; SP_PROPCHANGE_ParaMS propchangeparams = new SP_PROPCHANGE_ParaMS(); propchangeparams.ClassInstallHeader = header; propchangeparams.StateChange = disable ? DICS_disABLE : DICS_ENABLE; propchangeparams.Scope = DICS_FLAG_GLOBAL; propchangeparams.HwProfile = 0; SetupdisetClassInstallParams(info,ref devdata,ref propchangeparams,(UInt32)Marshal.SizeOf(propchangeparams)); Checkerror("SetupdisetClassInstallParams"); SetupDiChangeState( info,ref devdata); Checkerror("SetupDiChangeState"); } finally { if (info != IntPtr.Zero) SetupDiDestroyDeviceInfoList(info); } } private static void Checkerror(string message,int lasterror = -1) { int code = lasterror == -1 ? Marshal.GetLastWin32Error() : lasterror; if (code != 0) throw new ApplicationException( String.Format("Error disabling hardware device (Code {0}): {1}",code,message)); } private static string GetStringPropertyForDevice(IntPtr info,SP_DEVINFO_DATA devdata,uint propId) { uint proptype,outsize; IntPtr buffer = IntPtr.Zero; try { uint buflen = 512; buffer = Marshal.AllocHGlobal((int)buflen); outsize=0; // CHANGE #2 - Use this instead of SetupDiGetDeviceProperty SetupDiGetDeviceRegistryPropertyW( info,propId,out proptype,buffer,buflen,ref outsize); byte[] lbuffer = new byte[outsize]; Marshal.copy(buffer,lbuffer,(int)outsize); int errcode = Marshal.GetLastWin32Error(); if (errcode == ERROR_INVALID_DATA) return null; Checkerror("SetupDiGetDeviceProperty",errcode); return Encoding.Unicode.GetString(lbuffer); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } }
可以在Windows安装程序API上使用P / Invoke方法完成。 自W2K以来,API函数已经在Windows中。 API调用可能需要管理权限。 以下是使用这些API禁用(以及启用)C#中的设备的一些粗略代码,它允许调用:
disableDevice( n => n.toupperInvariant().Contains("VID_3F20&PID_8A1D"),true); // true disables the device,false enables it
第一个参数是通过硬件ID的过滤器。 这会禁用或启用与提供的过滤器匹配的第一个设备。 如果设备已经处于目标状态,则不起作用。
代码如下。
public static class disableHardware { const uint DIF_PROPERTYCHANGE = 0x12; const uint DICS_ENABLE = 1; const uint DICS_disABLE = 2; // disable device const uint DICS_FLAG_GLOBAL = 1; // not profile-specific const uint DIGCF_ALLCLASSES = 4; const uint DIGCF_PRESENT = 2; const uint ERROR_NO_MORE_ITEMS = 259; const uint ERROR_ELEMENT_NOT_FOUND = 1168; static DEVPROPKEY DEVPKEY_Device_DeviceDesc; static DEVPROPKEY DEVPKEY_Device_HardwareIds; [StructLayout(LayoutKind.Sequential)] struct SP_CLASSINSTALL_HEADER { public UInt32 cbSize; public UInt32 InstallFunction; } [StructLayout(LayoutKind.Sequential)] struct SP_PROPCHANGE_ParaMS { public SP_CLASSINSTALL_HEADER ClassInstallHeader; public UInt32 StateChange; public UInt32 Scope; public UInt32 HwProfile; } [StructLayout(LayoutKind.Sequential)] struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid classGuid; public UInt32 devInst; public UInt32 reserved; } [StructLayout(LayoutKind.Sequential)] struct DEVPROPKEY { public Guid fmtid; public UInt32 pid; } [DllImport("setupapi.dll",UInt32 flags); static disableHardware() { disableHardware.DEVPKEY_Device_DeviceDesc = new DEVPROPKEY(); DEVPKEY_Device_DeviceDesc.fmtid = new Guid( 0xa45c254e,DEVPKEY_Device_HardwareIds); // Uncomment to print name/path //Console.WriteLine(GetStringPropertyForDevice(info,DEVPROPKEY key) { uint proptype,outsize; IntPtr buffer = IntPtr.Zero; try { uint buflen = 512; buffer = Marshal.AllocHGlobal((int)buflen); SetupDiGetDevicePropertyW( info,ref key,out outsize,0); byte[] lbuffer = new byte[outsize]; Marshal.copy(buffer,(int)outsize); int errcode = Marshal.GetLastWin32Error(); if (errcode == ERROR_ELEMENT_NOT_FOUND) return null; Checkerror("SetupDiGetDeviceProperty",errcode); return Encoding.Unicode.GetString(lbuffer); } finally { if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer); } } }
我已经构建了XP兼容的答案,并通过添加一个SafeDevice@R_397_4045@ionSetHandle类并执行一些通用代码清理/重构来进一步改进,并将其添加到这里作为后代:
using System; using System.Text; using System.Security; using System.ComponentModel; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; public static class SetupApi { private const string SETUPAPI = "setupapi.dll"; private const int ERROR_INVALID_DATA = 13; private const int ERROR_INSUFFICIENT_BUFFER = 122; private class SafeDevice@R_397_4045@ionSetHandle : SafeHandleMinusOneIsInvalid { private SafeDevice@R_397_4045@ionSetHandle() : base(true) { } private SafeDevice@R_397_4045@ionSetHandle(IntPtr preexistingHandle,bool ownsHandle) : base(ownsHandle) { SetHandle(preexistingHandle); } [SecurityCritical] protected override bool ReleaseHandle() { return SetupDiDestroyDeviceInfoList(handle); } } #region Enumerations [Flags] private enum DIGCF : uint { DEFAULT = 0x00000001,PRESENT = 0x00000002,ALLCLASSES = 0x00000004,PROFILE = 0x00000008,DEVICEINTERFACE = 0x00000010 } private enum SPDRP : uint { /// <summary> /// DeviceDesc (R/W) /// </summary> DEVICEDESC = 0x00000000,/// <summary> /// HardwareID (R/W) /// </summary> HARDWAREID = 0x00000001,/// <summary> /// CompatibleIDs (R/W) /// </summary> COMPATIBLEIDS = 0x00000002,/// <summary> /// unused /// </summary> UNUSED0 = 0x00000003,/// <summary> /// Service (R/W) /// </summary> SERVICE = 0x00000004,/// <summary> /// unused /// </summary> UNUSED1 = 0x00000005,/// <summary> /// unused /// </summary> UNUSED2 = 0x00000006,/// <summary> /// Class (R--tied to ClassGUID) /// </summary> CLASS = 0x00000007,/// <summary> /// ClassGUID (R/W) /// </summary> CLASSGUID = 0x00000008,/// <summary> /// Driver (R/W) /// </summary> DRIVER = 0x00000009,/// <summary> /// ConfigFlags (R/W) /// </summary> CONfigFLAGS = 0x0000000A,/// <summary> /// Mfg (R/W) /// </summary> MFG = 0x0000000B,/// <summary> /// FriendlyName (R/W) /// </summary> FRIENDLYNAME = 0x0000000C,/// <summary> /// Location@R_397_4045@ion (R/W) /// </summary> LOCATION_@R_397_4045@ION = 0x0000000D,/// <summary> /// PhysicalDeviceObjectName (R) /// </summary> PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E,/// <summary> /// Capabilities (R) /// </summary> CAPABILITIES = 0x0000000F,/// <summary> /// UiNumber (R) /// </summary> UI_NUMBER = 0x00000010,/// <summary> /// UpperFilters (R/W) /// </summary> UPPERFILTERS = 0x00000011,/// <summary> /// LowerFilters (R/W) /// </summary> LOWERFILTERS = 0x00000012,/// <summary> /// BusTypeGUID (R) /// </summary> BUSTYPEGUID = 0x00000013,/// <summary> /// LegacyBusType (R) /// </summary> LEGACYBUSTYPE = 0x00000014,/// <summary> /// BusNumber (R) /// </summary> BUSNUMBER = 0x00000015,/// <summary> /// Enumerator Name (R) /// </summary> ENUMERATOR_NAME = 0x00000016,/// <summary> /// Security (R/W,binary form) /// </summary> Security = 0x00000017,/// <summary> /// Security (W,SDS form) /// </summary> Security_SDS = 0x00000018,/// <summary> /// Device Type (R/W) /// </summary> DEVTYPE = 0x00000019,/// <summary> /// Device is exclusive-access (R/W) /// </summary> EXCLUSIVE = 0x0000001A,/// <summary> /// Device characteristics (R/W) /// </summary> characteristics = 0x0000001B,/// <summary> /// Device Address (R) /// </summary> ADDRESS = 0x0000001C,/// <summary> /// UiNumberDescFormat (R/W) /// </summary> UI_NUMBER_DESC_FORMAT = 0X0000001D,/// <summary> /// Device Power Data (R) /// </summary> DEVICE_POWER_DATA = 0x0000001E,/// <summary> /// Removal Policy (R) /// </summary> REMoval_POLICY = 0x0000001F,/// <summary> /// Hardware Removal Policy (R) /// </summary> REMoval_POLICY_HW_DEFAULT = 0x00000020,/// <summary> /// Removal Policy Override (RW) /// </summary> REMoval_POLICY_OVERRIDE = 0x00000021,/// <summary> /// Device Install State (R) /// </summary> INSTALL_STATE = 0x00000022,/// <summary> /// Device Location Paths (R) /// </summary> LOCATION_PATHS = 0x00000023,} private enum DIF : uint { SELECTDEVICE = 0x00000001,INSTALLDEVICE = 0x00000002,ASSIGNRESOURCES = 0x00000003,PROPERTIES = 0x00000004,REMOVE = 0x00000005,FirsTTIMESETUP = 0x00000006,FOUNDDEVICE = 0x00000007,SELECTCLASSDRIVERS = 0x00000008,VALIDATECLASSDRIVERS = 0x00000009,INSTALLCLASSDRIVERS = 0x0000000A,CALCdisKSPACE = 0x0000000B,DESTROYPRIVATEDATA = 0x0000000C,VALIDATEDRIVER = 0x0000000D,DETECT = 0x0000000F,INSTALLWIZARD = 0x00000010,DESTROYWIZARDDATA = 0x00000011,PROPERTYCHANGE = 0x00000012,ENABLECLASS = 0x00000013,DETECTVERIFY = 0x00000014,INSTALLDEVICEFILES = 0x00000015,UNREMOVE = 0x00000016,SELECTBESTCOMPATDRV = 0x00000017,ALLOW_INSTALL = 0x00000018,REGISTERDEVICE = 0x00000019,NEWDEVICEWIZARD_PRESELECT = 0x0000001A,NEWDEVICEWIZARD_SELECT = 0x0000001B,NEWDEVICEWIZARD_PREANALYZE = 0x0000001C,NEWDEVICEWIZARD_POSTANALYZE = 0x0000001D,NEWDEVICEWIZARD_FINISHINSTALL = 0x0000001E,UNUSED1 = 0x0000001F,INSTALLINTERFACES = 0x00000020,DETECTCANCEL = 0x00000021,REGISTER_COINSTALLERS = 0x00000022,ADDPROPERTYPAGE_ADVANCED = 0x00000023,ADDPROPERTYPAGE_BASIC = 0x00000024,RESERVED1 = 0x00000025,TROUBLESHOOTER = 0x00000026,POWERMESSAGEWAKE = 0x00000027,ADDREMOTEPROPERTYPAGE_ADVANCED = 0x00000028,UPDATEDRIVER_UI = 0x00000029,FINISHINSTALL_ACTION = 0x0000002A,RESERVED2 = 0x00000030,} private enum DICS : uint { ENABLE = 0x00000001,disABLE = 0x00000002,PROPCHANGE = 0x00000003,START = 0x00000004,STOP = 0x00000005,} [Flags] private enum DICS_FLAG : uint { GLOBAL = 0x00000001,CONfigSPECIFIC = 0x00000002,CONfigGENERAL = 0x00000004,} #endregion #region Structures [StructLayout(LayoutKind.Sequential)] private struct SP_DEVINFO_DATA { public UInt32 cbSize; public Guid ClassGuid; public UInt32 DevInst; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential)] private struct SP_CLASSINSTALL_HEADER { public UInt32 cbSize; public DIF InstallFunction; } [StructLayout(LayoutKind.Sequential)] private struct SP_PROPCHANGE_ParaMS { public SP_CLASSINSTALL_HEADER ClassInstallHeader; public DICS StateChange; public DICS_FLAG Scope; public UInt32 HwProfile; } #endregion #region P/Invoke Functions [DllImport(SETUPAPI,SetLastError = true,CharSet = CharSet.Unicode)] private static extern SafeDevice@R_397_4045@ionSetHandle SetupDiGetClassDevs( [In] ref Guid ClassGuid,[In] string Enumerator,IntPtr hwndParent,DIGCF Flags ); [DllImport(SETUPAPI,SetLastError = true)] [ReliabilityContract(Consistency.WillNotCorruptState,Cer.Success)] private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); [DllImport(SETUPAPI,SetLastError = true)] private static extern bool SetupDiEnumDeviceInfo( SafeDevice@R_397_4045@ionSetHandle DeviceInfoSet,UInt32 MemberIndex,ref SP_DEVINFO_DATA DeviceInfoData ); [DllImport(SETUPAPI,SetLastError = true)] private static extern bool SetupdisetClassInstallParams( SafeDevice@R_397_4045@ionSetHandle DeviceInfoSet,UInt32 ClassInstallParamsSize ); [DllImport(SETUPAPI,SetLastError = true)] private static extern bool SetupDiChangeState( SafeDevice@R_397_4045@ionSetHandle DeviceInfoSet,Out] ref SP_DEVINFO_DATA DeviceInfoData ); [DllImport(SETUPAPI,CharSet = CharSet.Unicode)] private static extern bool SetupDiGetDeviceRegistryProperty( SafeDevice@R_397_4045@ionSetHandle DeviceInfoSet,SPDRP Property,out RegistryValueKind PropertyRegDataType,[Out] byte[] PropertyBuffer,out UInt32 requiredSize ); #endregion private static void CheckWin32CallSuccess(bool success) { if (!success) { throw new Win32Exception(); } } private static string GetStringPropertyForDevice(SafeDevice@R_397_4045@ionSetHandle infoSet,ref SP_DEVINFO_DATA devInfo,SPDRP property) { RegistryValueKind regType; UInt32 requiredSize; if (!SetupDiGetDeviceRegistryProperty(infoSet,ref devInfo,property,out regType,out requiredSize)) { switch (Marshal.GetLastWin32Error()) { case ERROR_INSUFFICIENT_BUFFER: break; case ERROR_INVALID_DATA: return string.Empty; default: throw new Win32Exception(); } } byte[] propertyBuffer = new byte[requiredSize]; CheckWin32CallSuccess(SetupDiGetDeviceRegistryProperty(infoSet,propertyBuffer,(uint)propertyBuffer.Length,out requiredSize)); return Encoding.Unicode.GetString(propertyBuffer); } public static void EnableDevice(Func<string,bool> hardwareIdFilter,bool enable) { Guid nullGuid = Guid.Empty; using (SafeDevice@R_397_4045@ionSetHandle infoSet = SetupDiGetClassDevs(ref nullGuid,DIGCF.ALLCLASSES)) { CheckWin32CallSuccess(!infoSet.IsInvalid); SP_DEVINFO_DATA devInfo = new SP_DEVINFO_DATA(); devInfo.cbSize = (UInt32) Marshal.SizeOf(devInfo); for (uint index = 0; ; ++index) { CheckWin32CallSuccess(SetupDiEnumDeviceInfo(infoSet,index,ref devInfo)); string hardwareId = GetStringPropertyForDevice(infoSet,SPDRP.HARDWAREID); if ((!string.IsNullOrEmpty(hardwareId)) && (hardwareIdFilter(hardwareId))) { break; } } SP_CLASSINSTALL_HEADER classinstallHeader = new SP_CLASSINSTALL_HEADER(); classinstallHeader.cbSize = (UInt32) Marshal.SizeOf(classinstallHeader); classinstallHeader.InstallFunction = DIF.PROPERTYCHANGE; SP_PROPCHANGE_ParaMS propchangeParams = new SP_PROPCHANGE_ParaMS { ClassInstallHeader = classinstallHeader,StateChange = enable ? DICS.ENABLE : DICS.disABLE,Scope = DICS_FLAG.GLOBAL,HwProfile = 0,}; CheckWin32CallSuccess(SetupdisetClassInstallParams(infoSet,ref propchangeParams,(UInt32)Marshal.SizeOf(propchangeParams))); CheckWin32CallSuccess(SetupDiChangeState(infoSet,ref devInfo)); } } }
可以在Windows安装程序API上使用P / Invoke方法完成。 自W2K以来,API函数已经在Windows中。 API调用可能需要管理权限。 以下是使用这些API禁用(以及启用)C#中的设备的一些粗略代码,它允许调用:
disableDevice( n => n.toupperInvariant().Contains("VID_3F20&PID_8A1D"),false enables it
这适用于Dell Inspi 15上的Windows 10。
我设法解决这个问题使用DevManView.exe(免费):
下载DevManView.exe并将.exe文件放在某处: http ://www.nirsoft.net/utils/device_manager_view.html
在C#中,创建并启动一个用于禁用设备的新进程(使用在设备管理器中找到的设备的名称)。
Process devManViewProc = new Process(); devManViewProc.StartInfo.FileName = @"<path to DevManView.exe>DevManView.exe"; devManViewProc.StartInfo.Arguments = "/disable "<name of the device>""; devManViewProc.Start(); devManViewProc.WaitForExit();
并再次启用它。
devManViewProc.StartInfo.Arguments = "/enable "<name of the device>""; devManViewProc.Start(); devManViewProc.WaitForExit();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。