.NET获取硬盘序列号的几个方法

news/2024/4/15 13:20:37

最近作软件注册,收集了很多.NET相关的获取硬盘物理序列号的方法,主要分为使用WMI方式和API方式。但这些方法均可能有问题。

1,使用WMI方式,有的机器根本取不到硬盘序列号,有的方式在Vista下面会报错。

常用的使用WMI的方式主要有下面一些方式:

  1. class HardDrive
  2.     {
  3.         private string model = null;
  4.         private string type = null;
  5.         private string serialNo = null;
  6.         public string Model
  7.         {
  8.             get {return model;}
  9.             set {model = value;}
  10.         }
  11.         public string Type
  12.         {
  13.             get {return type;}
  14.             set {type = value;}
  15.         }
  16.         public string SerialNo
  17.         {
  18.             get {return serialNo;}
  19.             set {serialNo = value;}
  20.         }
  21.     }
  22.     class TestProgram
  23.     {
  24.         /// <summary>
  25.         /// The main entry point for the application.
  26.         /// </summary>
  27.         [STAThread]
  28.         static void Main(string[] args)
  29.         {
  30.             //在Vista下面失败
  31.             ArrayList hdCollection = new ArrayList();
  32.             ManagementObjectSearcher searcher = new
  33.                 ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
  34.             foreach(ManagementObject wmi_HD in searcher.Get())
  35.             {
  36.                 HardDrive hd = new HardDrive();
  37.                 hd.Model    = wmi_HD["Model"].ToString();
  38.                 hd.Type     = wmi_HD["InterfaceType"].ToString();
  39.                 hdCollection.Add(hd);
  40.             }
  41.             searcher = new
  42.                 ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
  43.             int i = 0;
  44.             foreach(ManagementObject wmi_HD in searcher.Get())
  45.             {
  46.                 // get the hard drive from collection
  47.                 // using index
  48.                 HardDrive hd = (HardDrive)hdCollection[i];
  49.                 // get the hardware serial no.
  50.                 if (wmi_HD["SerialNumber"] == null)
  51.                     hd.SerialNo = "None";
  52.                 else
  53.                     hd.SerialNo = wmi_HD["SerialNumber"].ToString();
  54.                 ++i;
  55.             }
  56.             // Display available hard drives
  57.             foreach(HardDrive hd in hdCollection)
  58.             {
  59.                 Console.WriteLine("Model/t/t: " + hd.Model);
  60.                 Console.WriteLine("Type/t/t: " + hd.Type);
  61.                 Console.WriteLine("Serial No./t: " + hd.SerialNo);
  62.                 Console.WriteLine();
  63.             }
  64.             // Pause application
  65.             Console.WriteLine("Press [Enter] to exit...");
  66.             Console.ReadLine();
  67.         }
  68.     }

 上面的方式先查询Win32_DiskDrive,然后再查询 Win32_PhysicalMedia,经过测试,这种方式不能保证在所有机器上均取得硬盘序列号,而且在Vista下面还会出错,程序直接抛出无法处理的异常。

 

另外,还可以使用另外一WMI方式,就是查询 PNPDeviceID 的 signature,代码如下:

  1. /// <summary>
  2.        /// 获取硬盘唯一序列号(不是卷标号),可能需要以管理员身份运行程序
  3.        /// </summary>
  4.        /// <returns></returns>
  5.         public static string GetHdId()
  6.         {
  7.             ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher();
  8.             /*
  9.              * PNPDeviceID   的数据是由四部分组成的:   
  10.   1、接口,通常有   IDE,ATA,SCSI;   
  11.   2、型号   
  12.   3、(可能)驱动版本号   
  13.   4、(可能)硬盘的出厂序列号   
  14.              * 
  15.              * 
  16.              */
  17.             //signature 需要程序以管理员身份运行(经过测试,2003系统上非管理员身份也可以运行,查相关资料说,可能在2000系统上获取的值为空)
  18.             wmiSearcher.Query = new SelectQuery(
  19.             "Win32_DiskDrive",
  20.             "",
  21.             new string[] { "PNPDeviceID""signature" }
  22.             );
  23.             ManagementObjectCollection myCollection = wmiSearcher.Get();
  24.             ManagementObjectCollection.ManagementObjectEnumerator em =
  25.             myCollection.GetEnumerator();
  26.             em.MoveNext();
  27.             ManagementBaseObject mo = em.Current;
  28.             //string id = mo.Properties["PNPDeviceID"].Value.ToString().Trim();
  29.             string id = mo.Properties["signature"].Value.ToString().Trim();
  30.             return id;
  31.         }

 

有人说,使用 signature 需要程序以管理员身份运行(经过测试,2003系统上非管理员身份也可以运行),而且查询相关资料说,可能在2000系统上获取的值为空。

使用这种方式,在Vista上面工作良好。

经过测试,使用 signature  均能够取得硬盘序列号,但是跟 Win32_PhysicalMedia 查询出来的号不一样。目前我也不能肯定 使用 signature  能够100%取道硬盘序列号。

 

使用WMI方式需要客户机开启WMI服务,但这个往往不能保证,所以使用这种方式有一定局限性。

 

2,使用API方式。

在网上找到一片资料,说使用 RING3调用 API DeviceIoControl()来获取硬盘信息,下面是原话:

硬盘序列号(Serial Number)不等于卷标号(Volume Name),后者虽然很容易得到,但是格式化分区后就会重写,不可靠。遗憾的是很多朋友往往分不清这一点。

要得到硬盘的物理序列号,可以通过WMI,也就是Win32_PhysicalMedia.SerialNumber。可惜的是Windows 98/ME的WMI并不支持这个类,访问时会出现异常。

受陆麟的例子的启发,我们还可以通过S.M.A.R.T.接口,直接从RING3调用 API DeviceIoControl()来获取硬盘信息,而不需要写VXD或者DRIVER。这样这个问题就解决了,我对它进行了封装,大量使用了 P/Invoke技术,一个完整的Library。支持Windows 98-2003。

使用上很简单:

HardDiskInfo hdd = AtapiDevice.GetHddInfo(0); // 第一个硬盘
Console.WriteLine("Module Number: {0}", hdd.ModuleNumber);
Console.WriteLine("Serial Number: {0}", hdd.SerialNumber);
Console.WriteLine("Firmware: {0}", hdd.Firmware);
Console.WriteLine("Capacity: {0} M", hdd.Capacity);

 

感谢原文作者的贡献,(在这里我已经不知道原文作者是谁了,网上的文章都是转载的),经过测试,这种方式比较准确,但是需要管理员权限运行。

下面把代码分享:

  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Text;
  4. namespace HardwareUtility
  5. {
  6.     [Serializable]
  7.     public struct HardDiskInfo
  8.     {
  9.         /// <summary>
  10.         /// 型号
  11.         /// </summary>
  12.         public string ModuleNumber;
  13.         /// <summary>
  14.         /// 固件版本
  15.         /// </summary>
  16.         public string Firmware;
  17.         /// <summary>
  18.         /// 序列号
  19.         /// </summary>
  20.         public string SerialNumber;
  21.         /// <summary>
  22.         /// 容量,以M为单位
  23.         /// </summary>
  24.         public uint Capacity;
  25.     }
  26.     #region Internal Structs
  27.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  28.     internal struct GetVersionOutParams
  29.     {
  30.         public byte bVersion;
  31.         public byte bRevision;
  32.         public byte bReserved;
  33.         public byte bIDEDeviceMap;
  34.         public uint fCapabilities;
  35.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  36.         public uint[] dwReserved; // For future use.
  37.     }
  38.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  39.     internal struct IdeRegs
  40.     {
  41.         public byte bFeaturesReg;
  42.         public byte bSectorCountReg;
  43.         public byte bSectorNumberReg;
  44.         public byte bCylLowReg;
  45.         public byte bCylHighReg;
  46.         public byte bDriveHeadReg;
  47.         public byte bCommandReg;
  48.         public byte bReserved;
  49.     }
  50.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  51.     internal struct SendCmdInParams
  52.     {
  53.         public uint cBufferSize;
  54.         public IdeRegs irDriveRegs;
  55.         public byte bDriveNumber;
  56.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  57.         public byte[] bReserved;
  58.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  59.         public uint[] dwReserved;
  60.         public byte bBuffer;
  61.     }
  62.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  63.     internal struct DriverStatus
  64.     {
  65.         public byte bDriverError;
  66.         public byte bIDEStatus;
  67.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  68.         public byte[] bReserved;
  69.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  70.         public uint[] dwReserved;
  71.     }
  72.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  73.     internal struct SendCmdOutParams
  74.     {
  75.         public uint cBufferSize;
  76.         public DriverStatus DriverStatus;
  77.         public IdSector bBuffer;
  78.     }
  79.     [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 512)]
  80.     internal struct IdSector
  81.     {
  82.         public ushort wGenConfig;
  83.         public ushort wNumCyls;
  84.         public ushort wReserved;
  85.         public ushort wNumHeads;
  86.         public ushort wBytesPerTrack;
  87.         public ushort wBytesPerSector;
  88.         public ushort wSectorsPerTrack;
  89.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  90.         public ushort[] wVendorUnique;
  91.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
  92.         public byte[] sSerialNumber;
  93.         public ushort wBufferType;
  94.         public ushort wBufferSize;
  95.         public ushort wECCSize;
  96.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  97.         public byte[] sFirmwareRev;
  98.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
  99.         public byte[] sModelNumber;
  100.         public ushort wMoreVendorUnique;
  101.         public ushort wDoubleWordIO;
  102.         public ushort wCapabilities;
  103.         public ushort wReserved1;
  104.         public ushort wPIOTiming;
  105.         public ushort wDMATiming;
  106.         public ushort wBS;
  107.         public ushort wNumCurrentCyls;
  108.         public ushort wNumCurrentHeads;
  109.         public ushort wNumCurrentSectorsPerTrack;
  110.         public uint ulCurrentSectorCapacity;
  111.         public ushort wMultSectorStuff;
  112.         public uint ulTotalAddressableSectors;
  113.         public ushort wSingleWordDMA;
  114.         public ushort wMultiWordDMA;
  115.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
  116.         public byte[] bReserved;
  117.     }
  118.     #endregion
  119.     /// <summary>
  120.     /// ATAPI驱动器相关
  121.     /// </summary>
  122.     public class AtapiDevice
  123.     {
  124.         #region DllImport
  125.         [DllImport("kernel32.dll", SetLastError = true)]
  126.         static extern int CloseHandle(IntPtr hObject);
  127.         [DllImport("kernel32.dll", SetLastError = true)]
  128.         static extern IntPtr CreateFile(
  129.             string lpFileName,
  130.             uint dwDesiredAccess,
  131.             uint dwShareMode,
  132.             IntPtr lpSecurityAttributes,
  133.             uint dwCreationDisposition,
  134.             uint dwFlagsAndAttributes,
  135.             IntPtr hTemplateFile);
  136.         [DllImport("kernel32.dll")]
  137.         static extern int DeviceIoControl(
  138.             IntPtr hDevice,
  139.             uint dwIoControlCode,
  140.             IntPtr lpInBuffer,
  141.             uint nInBufferSize,
  142.             ref GetVersionOutParams lpOutBuffer,
  143.             uint nOutBufferSize,
  144.             ref uint lpBytesReturned,
  145.             [Out] IntPtr lpOverlapped);
  146.         [DllImport("kernel32.dll")]
  147.         static extern int DeviceIoControl(
  148.             IntPtr hDevice,
  149.             uint dwIoControlCode,
  150.             ref SendCmdInParams lpInBuffer,
  151.             uint nInBufferSize,
  152.             ref SendCmdOutParams lpOutBuffer,
  153.             uint nOutBufferSize,
  154.             ref uint lpBytesReturned,
  155.             [Out] IntPtr lpOverlapped);
  156.         const uint DFP_GET_VERSION = 0x00074080;
  157.         const uint DFP_SEND_DRIVE_COMMAND = 0x0007c084;
  158.         const uint DFP_RECEIVE_DRIVE_DATA = 0x0007c088;
  159.         const uint GENERIC_READ = 0x80000000;
  160.         const uint GENERIC_WRITE = 0x40000000;
  161.         const uint FILE_SHARE_READ = 0x00000001;
  162.         const uint FILE_SHARE_WRITE = 0x00000002;
  163.         const uint CREATE_NEW = 1;
  164.         const uint OPEN_EXISTING = 3;
  165.         #endregion
  166.         #region GetHddInfo
  167.         /// <summary>
  168.         /// 获得硬盘信息
  169.         /// </summary>
  170.         /// <param name="driveIndex">硬盘序号</param>
  171.         /// <returns>硬盘信息</returns>
  172.         /// <remarks>
  173.         /// 参考lu0的文章:http://lu0s1.3322.org/App/2k1103.html
  174.         /// by sunmast for everyone
  175.         /// thanks lu0 for his great works
  176.         /// 在Windows 98/ME中,S.M.A.R.T并不缺省安装,请将SMARTVSD.VXD拷贝到%SYSTEM%/IOSUBSYS目录下。
  177.         /// 在Windows 2000/2003下,需要Administrators组的权限。
  178.         /// </remarks>
  179.         /// <example>
  180.         /// AtapiDevice.GetHddInfo()
  181.         /// </example>
  182.         public static HardDiskInfo GetHddInfo(byte driveIndex)
  183.         {
  184.             switch (Environment.OSVersion.Platform)
  185.             {
  186.                 case PlatformID.Win32Windows:
  187.                     return GetHddInfo9x(driveIndex);
  188.                 case PlatformID.Win32NT:
  189.                     return GetHddInfoNT(driveIndex);
  190.                 case PlatformID.Win32S:
  191.                     throw new NotSupportedException("Win32s is not supported.");
  192.                 case PlatformID.WinCE:
  193.                     throw new NotSupportedException("WinCE is not supported.");
  194.                 default:
  195.                     throw new NotSupportedException("Unknown Platform.");
  196.             }
  197.         }
  198.         #region GetHddInfo9x
  199.         private static HardDiskInfo GetHddInfo9x(byte driveIndex)
  200.         {
  201.             GetVersionOutParams vers = new GetVersionOutParams();
  202.             SendCmdInParams inParam = new SendCmdInParams();
  203.             SendCmdOutParams outParam = new SendCmdOutParams();
  204.             uint bytesReturned = 0;
  205.             IntPtr hDevice = CreateFile(
  206.                 @"//./Smartvsd",
  207.                 0,
  208.                 0,
  209.                 IntPtr.Zero,
  210.                 CREATE_NEW,
  211.                 0,
  212.                 IntPtr.Zero);
  213.             if (hDevice == IntPtr.Zero)
  214.             {
  215.                 throw new Exception("Open smartvsd.vxd failed.");
  216.             }
  217.             if (0 == DeviceIoControl(
  218.                 hDevice,
  219.                 DFP_GET_VERSION,
  220.                 IntPtr.Zero,
  221.                 0,
  222.                 ref vers,
  223.                 (uint)Marshal.SizeOf(vers),
  224.                 ref bytesReturned,
  225.                 IntPtr.Zero))
  226.             {
  227.                 CloseHandle(hDevice);
  228.                 throw new Exception("DeviceIoControl failed:DFP_GET_VERSION");
  229.             }
  230.             // If IDE identify command not supported, fails
  231.             if (0 == (vers.fCapabilities & 1))
  232.             {
  233.                 CloseHandle(hDevice);
  234.                 throw new Exception("Error: IDE identify command not supported.");
  235.             }
  236.             if (0 != (driveIndex & 1))
  237.             {
  238.                 inParam.irDriveRegs.bDriveHeadReg = 0xb0;
  239.             }
  240.             else
  241.             {
  242.                 inParam.irDriveRegs.bDriveHeadReg = 0xa0;
  243.             }
  244.             if (0 != (vers.fCapabilities & (16 >> driveIndex)))
  245.             {
  246.                 // We don't detect a ATAPI device.
  247.                 CloseHandle(hDevice);
  248.                 throw new Exception(string.Format("Drive {0} is a ATAPI device, we don't detect it", driveIndex + 1));
  249.             }
  250.             else
  251.             {
  252.                 inParam.irDriveRegs.bCommandReg = 0xec;
  253.             }
  254.             inParam.bDriveNumber = driveIndex;
  255.             inParam.irDriveRegs.bSectorCountReg = 1;
  256.             inParam.irDriveRegs.bSectorNumberReg = 1;
  257.             inParam.cBufferSize = 512;
  258.             if (0 == DeviceIoControl(
  259.                 hDevice,
  260.                 DFP_RECEIVE_DRIVE_DATA,
  261.                 ref inParam,
  262.                 (uint)Marshal.SizeOf(inParam),
  263.                 ref outParam,
  264.                 (uint)Marshal.SizeOf(outParam),
  265.                 ref bytesReturned,
  266.                 IntPtr.Zero))
  267.             {
  268.                 CloseHandle(hDevice);
  269.                 throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA");
  270.             }
  271.             CloseHandle(hDevice);
  272.             return GetHardDiskInfo(outParam.bBuffer);
  273.         }
  274.         #endregion
  275.         #region GetHddInfoNT
  276.         private static HardDiskInfo GetHddInfoNT(byte driveIndex)
  277.         {
  278.             GetVersionOutParams vers = new GetVersionOutParams();
  279.             SendCmdInParams inParam = new SendCmdInParams();
  280.             SendCmdOutParams outParam = new SendCmdOutParams();
  281.             uint bytesReturned = 0;
  282.             // We start in NT/Win2000
  283.             IntPtr hDevice = CreateFile(
  284.                 string.Format(@"//./PhysicalDrive{0}", driveIndex),
  285.                 GENERIC_READ | GENERIC_WRITE,
  286.                 FILE_SHARE_READ | FILE_SHARE_WRITE,
  287.                 IntPtr.Zero,
  288.                 OPEN_EXISTING,
  289.                 0,
  290.                 IntPtr.Zero);
  291.             if (hDevice == IntPtr.Zero)
  292.             {
  293.                 throw new Exception("CreateFile faild.");
  294.             }
  295.             if (0 == DeviceIoControl(
  296.                 hDevice,
  297.                 DFP_GET_VERSION,
  298.                 IntPtr.Zero,
  299.                 0,
  300.                 ref vers,
  301.                 (uint)Marshal.SizeOf(vers),
  302.                 ref bytesReturned,
  303.                 IntPtr.Zero))
  304.             {
  305.                 CloseHandle(hDevice);
  306.                 throw new Exception(string.Format("Drive {0} may not exists.", driveIndex + 1));
  307.             }
  308.             // If IDE identify command not supported, fails
  309.             if (0 == (vers.fCapabilities & 1))
  310.             {
  311.                 CloseHandle(hDevice);
  312.                 throw new Exception("Error: IDE identify command not supported.");
  313.             }
  314.             // Identify the IDE drives
  315.             if (0 != (driveIndex & 1))
  316.             {
  317.                 inParam.irDriveRegs.bDriveHeadReg = 0xb0;
  318.             }
  319.             else
  320.             {
  321.                 inParam.irDriveRegs.bDriveHeadReg = 0xa0;
  322.             }
  323.             if (0 != (vers.fCapabilities & (16 >> driveIndex)))
  324.             {
  325.                 // We don't detect a ATAPI device.
  326.                 CloseHandle(hDevice);
  327.                 throw new Exception(string.Format("Drive {0} is a ATAPI device, we don't detect it.", driveIndex + 1));
  328.             }
  329.             else
  330.             {
  331.                 inParam.irDriveRegs.bCommandReg = 0xec;
  332.             }
  333.             inParam.bDriveNumber = driveIndex;
  334.             inParam.irDriveRegs.bSectorCountReg = 1;
  335.             inParam.irDriveRegs.bSectorNumberReg = 1;
  336.             inParam.cBufferSize = 512;
  337.             if (0 == DeviceIoControl(
  338.                 hDevice,
  339.                 DFP_RECEIVE_DRIVE_DATA,
  340.                 ref inParam,
  341.                 (uint)Marshal.SizeOf(inParam),
  342.                 ref outParam,
  343.                 (uint)Marshal.SizeOf(outParam),
  344.                 ref bytesReturned,
  345.                 IntPtr.Zero))
  346.             {
  347.                 CloseHandle(hDevice);
  348.                 throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA");
  349.             }
  350.             CloseHandle(hDevice);
  351.             return GetHardDiskInfo(outParam.bBuffer);
  352.         }
  353.         #endregion
  354.         private static HardDiskInfo GetHardDiskInfo(IdSector phdinfo)
  355.         {
  356.             HardDiskInfo hddInfo = new HardDiskInfo();
  357.             ChangeByteOrder(phdinfo.sModelNumber);
  358.             hddInfo.ModuleNumber = Encoding.ASCII.GetString(phdinfo.sModelNumber).Trim();
  359.             ChangeByteOrder(phdinfo.sFirmwareRev);
  360.             hddInfo.Firmware = Encoding.ASCII.GetString(phdinfo.sFirmwareRev).Trim();
  361.             ChangeByteOrder(phdinfo.sSerialNumber);
  362.             hddInfo.SerialNumber = Encoding.ASCII.GetString(phdinfo.sSerialNumber).Trim();
  363.             hddInfo.Capacity = phdinfo.ulTotalAddressableSectors / 2 / 1024;
  364.             return hddInfo;
  365.         }
  366.         private static void ChangeByteOrder(byte[] charArray)
  367.         {
  368.             byte temp;
  369.             for (int i = 0; i < charArray.Length; i += 2)
  370.             {
  371.                 temp = charArray[i];
  372.                 charArray[i] = charArray[i + 1];
  373.                 charArray[i + 1] = temp;
  374.             }
  375.         }
  376.         #endregion
  377.     }
  378. }

http://www.ppmy.cn/news/640546.html

相关文章

全网采集工具(msray)-百度搜索引擎关键词全网采集

全网采集工具&#xff08;msray&#xff09;-百度搜索引擎进行全网采集 Msray-plus&#xff0c;是一款采用GO语言开发的企业级综合性爬虫/采集软件。 支持&#xff1a;搜索引擎结果采集、域名采集、URL采集、网址采集、全网域名采集、CMS采集、联系信息采集 支持亿级数据存储、…

CCPD数据集 不限速 夸克云盘下载 车牌数据集 40G

原始公开数据中提供了谷歌云与百度网盘的链接&#xff0c;在此补充夸克云盘下载链接&#xff08;不限速下载&#xff09; 我用夸克网盘分享了「CCPD2019.tar」&#xff0c;点击链接即可保存。打开「夸克APP」 链接&#xff1a;https://pan.quark.cn/s/e9b6cff18e7c 提取码&a…

怎样获取计算机硬盘号,电脑硬盘序列号读取工具

电脑硬盘序列号读取工具是一款电脑序列号获取工具&#xff0c;能一键获取支持各种电脑序列号获取&#xff0c;需要的获取序列号的朋友快来下载吧&#xff01; 软件介绍 靖源磁盘管理单元测试(电脑硬盘序列号读取工具)是一款非常实用的硬盘序列号获取软件。比较强大&#xff0c;…

单点登录原理

单点登录原理 一、什么是单点登录 单点登录英文全称Single Sign On&#xff0c;简称SSO。指在多系统应用群中登录一个系统&#xff0c;便可在其他所有系统中得到授权而无需再次登录&#xff0c;包括单点登录与单点注销两部分。 二、为什么需要单点登录 在一些子系统用户信息…

使用 ArrayList 应当避免的坑

大家都知道 ArrayList 是由数组实现&#xff0c;而数据的长度有限&#xff0c;需要在合适的时机对数组扩容。 当我们初始化一个长度为 2 的 ArrayList &#xff0c;并往里边写入三条数据时 ArrayList 就得扩容了&#xff0c;也就是将之前的数据复制一份到新的数组长度为 3 的数…

桃核做口哨

小时候,我们都很会玩,记得我们常常把桃核从一面的中间挖个圆形小孔,把里面的桃核仁一点一点弄出来.让里面成为中空,这样就可以当哨子用了,声音非常悦耳

微信小程序:王者荣耀出装与铭文推荐助手

这是一款王者荣耀助手的一款小程序源码 该小程序主要功能就是提供各个英雄出装和铭文查询 功能虽然单调但是对于玩王者的朋友来说还是挺实用的! 目前该小程序源码已支持多种流量主模式 小程序源码下载地址&#xff1a; 微信小程序&#xff1a;王者荣耀出装与铭文推荐助手-小程…

直播过程中的掌声,口哨,背景音等音效怎么实现

大家有没有想过在直播过程中的掌声&#xff0c;口哨&#xff0c;背景音等音效是怎么实现的吗?这些功能都是可以通过混音来实现的。本篇文章介绍即构科技音视频SDK高级功能第五篇&#xff0c;ZegoLiveRoom SDK 混音功能&#xff0c;还是以iOS环境为例。 混音 1、功能简介 Ze…

王者荣耀故事站小程序源码/含vue后台

王者荣耀故事站小程序源码/含vue后台-PHP文档类资源-CSDN下载王者荣耀故事站小程序源码/含vue后台更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/swich_case/85068214

6.redis-哨兵

一.实战 1./myredis目录下放sentinel.conf文件 1) sentinel26379.conf 2) sentinel26380.conf 3) sentinel26381.conf 2.重点参数说明 bind 0.0.0.0 #服务监听位置 daemonize yes #后台运行 protected-mode no #安全保护模式 port 26379 …

微信小程序:王者荣耀改名神器

这是一款王者改名小程序 支持重复名改名 支持空白名改名 另外也支持特殊符合随机生成改名等等 该款小程序引流裂变的效果非常的好 支持流量主收益如激励视频获取改名次数等等 另外该小程序还有更多,支持推荐其它小程序形成一个轮廓 另外该小程序成本比较低,无需服务器无需…

【Redis—哨兵机制】

文章目录 概念哨兵机制如何工作的监控&#xff08;如何判断主节点真的故障了&#xff09;哪个哨兵进行主从故障转移&#xff1f;故障转移流程哨兵集群 概念 当进行主从复制时&#xff0c;如果主节点挂掉了&#xff0c;那么没有主节点来服务客户端的写操作请求了&#xff0c;也…

接口性能优化的11个小技巧(荣耀典藏版)

目录 前言 1.索引 1.1 没加索引 1.2 索引没生效 1.3 选错索引 2. sql优化 3. 远程调用 3.1 并行调用 3.2 数据异构 4. 重复调用 4.1 循环查数据库 4.2 死循环 4.3 无限递归 5. 异步处理 5.1 线程池 5.2 MQ 6. 避免大事务 7. 锁粒度 7.1 synchronized 7.2 r…

jQuery小项目之王者荣耀手风琴,有图片素材

王者荣耀手风琴效果 代码示例图片素材 代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>王者荣耀手风琴效果</title><style>*{margin: 0;padding: 0;}.box{width: 769px;height:…

Python实现王者荣耀小助手(二)

接下来我们获取英雄和武器信息&#xff0c;详细代码KingGlory.py如下&#xff08;代码中有详细注解&#xff09;&#xff1a; # -*- coding: utf-8 -*- #!/usr/bin/env python # Time : 2018/6/15 17:12 # Desc : # File : KingGlory.py # Software: PyCharm "…

声音传感器模块FC-04 口哨开关

模块描述 可以检测到周围环境的声音强度&#xff0c;只能识别声音的有无&#xff08;根据震动原理&#xff09;&#xff0c;不能识别声音的大小或特定频率的声音阈值可调&#xff1a;通过蓝色电位器调节工作电压&#xff1a; 3.3V~5V输出形式&#xff1a;数字开关量输出&#…

王者荣耀游戏中的这些小细节,你知道吗?

本人玩王者荣耀的第四个赛季&#xff0c;目前才王者27星&#xff0c;不过最近看到了一些小细节&#xff0c;大家看下是不是都知道了&#xff1f; 1&#xff0c;讲一个奇怪的知识&#xff0c;好像是一诺说的&#xff0c;射手出门先买鞋&#xff0c;到高地卖了&#xff0c;节约一…

redis 哨兵

哨兵可以帮助我们解决主从架构中的单点故障问题 哨兵的配置&#xff1a; 新建目录&#xff1a;usr/local/docker/redis/sen/ docker-compose.yml文件如下 version: "3.1" services:redis1:image: daocloud.io/library/redis:5.0.7restart: alwayscontainer_name: …

AI听曲识歌!哼曲、口哨吹,都能秒识!

&#x1f4a1; 作者&#xff1a;韩信子ShowMeAI &#x1f4d8; 深度学习实战系列&#xff1a;https://www.showmeai.tech/tutorials/42 &#x1f4d8; 自然语言处理实战系列&#xff1a;https://www.showmeai.tech/tutorials/45 &#x1f4d8; 本文地址&#xff1a;https://www…

小刘总——王者荣耀抽荣耀水晶玄学

转眼间打王者四年多了&#xff0c;也上了三赛季王者&#xff0c;各种模式都打烂了&#xff0c;但惟有一个领域没有触及&#xff0c;就是荣耀水晶&#xff0c;我向来不屑于抽奖&#xff0c;虽然贵族等级马上v7了&#xff0c;但是基本从来没有用点券买积分去抽水晶&#xff0c;只…
最新文章