用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号

本文主要是介绍用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载与http://www.xdty.org/1692

在制作程序注册机的时候需要获取到机器的唯一编号,本文从硬盘、网卡硬件地址及文件版本生成一个4*7的序列号,形如 3CEA-82E6-1396-9C78-45C4-06C9-9564

1.获取硬盘物理地址(非逻辑分区序列号)
逻辑分区序列号获取很简单,但是这个编号不唯一,且可以轻易修改。如果ghost系统的话恐怕id也一样,所以获取硬盘的物理地址更合理一些。
需要的结构体及头文件

#include <winioctl.h>

#include <pshpack1.h>
#pragma pack(1)

typedef struct _IDENTIFY_DATA {
    USHORT GeneralConfiguration ;             // 00 00
    USHORT NumberOfCylinders ;               // 02  1
    USHORT Reserved1 ;                       // 04  2
    USHORT NumberOfHeads ;                   // 06  3
    USHORT UnformattedBytesPerTrack ;         // 08  4
    USHORT UnformattedBytesPerSector ;       // 0A  5
    USHORT SectorsPerTrack ;                 // 0C  6
    USHORT VendorUnique1 [ 3 ] ;                 // 0E  7-9
    USHORT SerialNumber [ 10 ] ;                 // 14  10-19
    USHORT BufferType ;                       // 28  20
    USHORT BufferSectorSize ;                 // 2A  21
    USHORT NumberOfEccBytes ;                 // 2C  22
    USHORT FirmwareRevision [ 4 ] ;             // 2E  23-26
    USHORT ModelNumber [ 20 ] ;                 // 36  27-46
    UCHAR  MaximumBlockTransfer ;             // 5E  47
    UCHAR  VendorUnique2 ;                   // 5F
    USHORT DoubleWordIo ;                     // 60  48
    USHORT Capabilities ;                     // 62  49
    USHORT Reserved2 ;                       // 64  50
    UCHAR  VendorUnique3 ;                   // 66  51
    UCHAR  PioCycleTimingMode ;               // 67
    UCHAR  VendorUnique4 ;                   // 68  52
    UCHAR  DmaCycleTimingMode ;               // 69
    USHORT TranslationFieldsValid : 1 ;         // 6A  53
    USHORT Reserved3 : 15 ;
    USHORT NumberOfCurrentCylinders ;         // 6C  54
    USHORT NumberOfCurrentHeads ;             // 6E  55
    USHORT CurrentSectorsPerTrack ;           // 70  56
    ULONG  CurrentSectorCapacity ;           // 72  57-58
    USHORT CurrentMultiSectorSetting ;       //     59
    ULONG  UserAddressableSectors ;           //     60-61
    USHORT SingleWordDMASupport : 8 ;         //     62
    USHORT SingleWordDMAActive : 8 ;
    USHORT MultiWordDMASupport : 8 ;         //     63
    USHORT MultiWordDMAActive : 8 ;
    USHORT AdvancedPIOModes : 8 ;             //     64
    USHORT Reserved4 : 8 ;
    USHORT MinimumMWXferCycleTime ;           //     65
    USHORT RecommendedMWXferCycleTime ;       //     66
    USHORT MinimumPIOCycleTime ;             //     67
    USHORT MinimumPIOCycleTimeIORDY ;         //     68
    USHORT Reserved5 [ 2 ] ;                     //     69-70
    USHORT ReleaseTimeOverlapped ;           //     71
    USHORT ReleaseTimeServiceCommand ;       //     72
    USHORT MajorRevision ;                   //     73
    USHORT MinorRevision ;                   //     74
    USHORT Reserved6 [ 50 ] ;                   //     75-126
    USHORT SpecialFunctionsEnabled ;         //     127
    USHORT Reserved7 [ 128 ] ;                   //     128-255
} IDENTIFY_DATA, *PIDENTIFY_DATA ;

#pragma pack()

实现函数

CString GetHardDiskSerialNumber ( )
{
    CString strHardDiskSerialNumber ;

    HANDLE hDrive = 0 ;

    CString szDriveName = _T ( "\\\\.\\PhysicalDrive0" ) ;

    hDrive = CreateFile (szDriveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ) ;
    if (hDrive ! = INVALID_HANDLE_VALUE )
    {
        DWORD cbBytesReturned = 0 ;

        GETVERSIONINPARAMS objVersionParams ;
        memset ( &objVersionParams, 0, sizeof (objVersionParams ) ) ;
        if (  DeviceIoControl (hDrive, SMART_GET_VERSION, NULL, 0, &objVersionParams, sizeof (GETVERSIONINPARAMS ), &cbBytesReturned, NULL ) )
        {        
            ULONG nCommandSize = sizeof (SENDCMDINPARAMS ) + IDENTIFY_BUFFER_SIZE ;
            PSENDCMDINPARAMS pSendCommands = (PSENDCMDINPARAMS ) malloc (nCommandSize ) ;

            pSendCommands - >irDriveRegs. bCommandReg = ID_CMD ;
            DWORD BytesReturned = 0 ;
            if (DeviceIoControl (hDrive, SMART_RCV_DRIVE_DATA, pSendCommands, sizeof (SENDCMDINPARAMS ), pSendCommands, nCommandSize, &BytesReturned, NULL ) )
            {
                WORD * pIdSector = (WORD * ) (PIDENTIFY_DATA ) ( (PSENDCMDOUTPARAMS ) pSendCommands ) - >bBuffer ;

                char szSerialNumber [ 100 ] = "" ;
                for ( int index = 10, position = 0 ; index <= 19 ; index ++ )
                {
                    szSerialNumber [position ] = ( char ) (pIdSector [index ] / 256 ) ;
                    position ++ ;

                    szSerialNumber [position ] = ( char ) (pIdSector [index ] % 256 ) ;
                    position ++ ;
                }

                strHardDiskSerialNumber = szSerialNumber ;
                strHardDiskSerialNumber. TrimLeft ( ) ;
                strHardDiskSerialNumber. TrimRight ( ) ;
            }

            CloseHandle (hDrive ) ;
            free (pSendCommands ) ;
            pSendCommands = NULL ;
        }
    }

    return strHardDiskSerialNumber ;
}

最后获取到的字串类似为 WD-WMAYUS743480 ,只需要取后八位就可以了。

CString GetHardDiskSerialID ( )
{
    CString serialId = GetHardDiskSerialNumber ( ) ;
    serialId. Remove ( '-' ) ;
    return serialId. Right ( 8 ) ;
}

2.获取以太网网卡地址

CString GetMacAddress ( bool format /*=false*/ )
{
    CString csMacAddress ;
    ULONG BufferLength = 0 ;
    BYTE * pBuffer = 0 ;
    if ( ERROR_BUFFER_OVERFLOW == GetAdaptersInfo ( 0, &BufferLength ) )
    {
        pBuffer = new BYTE [ BufferLength ] ;
    }

    PIP_ADAPTER_INFO pAdapterInfo =
        reinterpret_cast <PIP_ADAPTER_INFO > (pBuffer ) ;
    GetAdaptersInfo ( pAdapterInfo, &BufferLength ) ;

    while ( pAdapterInfo )
    {
        if (pAdapterInfo - >Type ==MIB_IF_TYPE_ETHERNET )
        {
            CString szFormat ;
            if (format )
            {
                szFormat = _T ( "%02x:%02x:%02x:%02x:%02x:%02x" ) ;
            }
            else
            {
                szFormat = _T ( "%02x%02x%02x%02x%02x%02x" ) ;
            }
            csMacAddress. Format (szFormat,
                pAdapterInfo - >Address [ 0 ],
                pAdapterInfo - >Address [ 1 ],
                pAdapterInfo - >Address [ 2 ],
                pAdapterInfo - >Address [ 3 ],
                pAdapterInfo - >Address [ 4 ],
                pAdapterInfo - >Address [ 5 ] ) ;
        }
        pAdapterInfo = pAdapterInfo - >Next ;
    }
    delete [ ] pBuffer ;

    return csMacAddress ;
}

3.获取程序版本号
需要在项目属性连接里引入Version.lib

bool GetProductAndVersion (CString &strProductName, CString &strProductVersion )
{
    TCHAR szFilename [MAX_PATH + 1 ] = { 0 } ;
    if (GetModuleFileName ( NULL, szFilename, MAX_PATH ) == 0 )
    {
        return false ;
    }

    DWORD dummy ;
    DWORD dwSize = GetFileVersionInfoSize (szFilename, &dummy ) ;
    if (dwSize == 0 )
    {
        return false ;
    }
    std :: vector <BYTE > data (dwSize ) ;

    if ( !GetFileVersionInfo (szFilename, NULL, dwSize, &data [ 0 ] ) )
    {
        return false ;
    }

    LPVOID pvProductName = NULL ;
    unsigned int iProductNameLen = 0 ;
    LPVOID pvProductVersion = NULL ;
    unsigned int iProductVersionLen = 0 ;

    if ( !VerQueryValue ( &data [ 0 ], _T ( "\\StringFileInfo\\080404b0\\ProductName" ), &pvProductName, &iProductNameLen ) ||
        !VerQueryValue ( &data [ 0 ], _T ( "\\StringFileInfo\\080404b0\\ProductVersion" ), &pvProductVersion, &iProductVersionLen ) )
    {
        return false ;
    }

    strProductName. SetString ( (LPCTSTR )pvProductName, iProductNameLen ) ;
    strProductVersion. SetString ( (LPCTSTR )pvProductVersion, iProductVersionLen ) ;

    return true ;
}

CString GetFileVersion ( )
{
    CString strProductName, strProductVersion ;
    GetProductAndVersion (strProductName, strProductVersion ) ;

    return strProductVersion. Left (strProductVersion. ReverseFind ( '.' ) ) ;
}

4.生成序列号

CString CKeyController :: GenerateMachineID ( )
{
    CString serialID = GetHardDiskSerialID ( ) ;
    CString timeID ;
    timeID. Format (_T ( "%lx" ), time ( NULL ) ) ;
    timeID. Delete ( 6, 3 ) ;
    return serialID +timeID +GetMacAddress ( ) ;
}

CString CKeyController :: GenerateSerialNumber ( )
{
    CString serialNumber = GenerateMachineID ( ) ;
    for ( int i = 0 ; i < 6 ; i ++ )
    {
        serialNumber. Insert (i * 5 + 4, _T ( "-" ) ) ;
    }
    CString version = GetFileVersion ( ) ;
    version. Delete ( 1, 1 ) ;
    version. Delete ( 2, 1 ) ;
    version. Format (_T ( "%2x" ), _ttoi (version ) ) ;
    serialNumber. Append (version ) ;
    serialNumber. MakeUpper ( ) ;
    return serialNumber ;
}

最后调用GenerateSerialNumber()即可生成序列号。

这篇关于用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062096

相关文章

go中的时间处理过程

《go中的时间处理过程》:本文主要介绍go中的时间处理过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 获取当前时间2 获取当前时间戳3 获取当前时间的字符串格式4 相互转化4.1 时间戳转时间字符串 (int64 > string)4.2 时间字符串转时间

Golang如何对cron进行二次封装实现指定时间执行定时任务

《Golang如何对cron进行二次封装实现指定时间执行定时任务》:本文主要介绍Golang如何对cron进行二次封装实现指定时间执行定时任务问题,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录背景cron库下载代码示例【1】结构体定义【2】定时任务开启【3】使用示例【4】控制台输出总结背景

如何在Mac上彻底删除Edge账户? 手动卸载Edge浏览器并清理残留文件技巧

《如何在Mac上彻底删除Edge账户?手动卸载Edge浏览器并清理残留文件技巧》Mac上的Edge账户里存了不少网站密码和个人信息,结果同事一不小心打开了,简直尴尬到爆炸,想要卸载edge浏览器并清... 如果你遇到 Microsoft Edge 浏览器运行迟缓、频繁崩溃或网页加载异常等问题,可以尝试多种方

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

SQL Server修改数据库名及物理数据文件名操作步骤

《SQLServer修改数据库名及物理数据文件名操作步骤》在SQLServer中重命名数据库是一个常见的操作,但需要确保用户具有足够的权限来执行此操作,:本文主要介绍SQLServer修改数据... 目录一、背景介绍二、操作步骤2.1 设置为单用户模式(断开连接)2.2 修改数据库名称2.3 查找逻辑文件名

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

使用jenv工具管理多个JDK版本的方法步骤

《使用jenv工具管理多个JDK版本的方法步骤》jenv是一个开源的Java环境管理工具,旨在帮助开发者在同一台机器上轻松管理和切换多个Java版本,:本文主要介绍使用jenv工具管理多个JD... 目录一、jenv到底是干啥的?二、jenv的核心功能(一)管理多个Java版本(二)支持插件扩展(三)环境隔

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地