用硬盘物理编号(序列号)、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

相关文章

Ubuntu如何升级Python版本

《Ubuntu如何升级Python版本》Ubuntu22.04Docker中,安装Python3.11后,使用update-alternatives设置为默认版本,最后用python3-V验证... 目China编程录问题描述前提环境解决方法总结问题描述Ubuntu22.04系统自带python3.10,想升级

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

Mac电脑如何通过 IntelliJ IDEA 远程连接 MySQL

《Mac电脑如何通过IntelliJIDEA远程连接MySQL》本文详解Mac通过IntelliJIDEA远程连接MySQL的步骤,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友跟... 目录MAC电脑通过 IntelliJ IDEA 远程连接 mysql 的详细教程一、前缀条件确认二、打开 ID

MySQL按时间维度对亿级数据表进行平滑分表

《MySQL按时间维度对亿级数据表进行平滑分表》本文将以一个真实的4亿数据表分表案例为基础,详细介绍如何在不影响线上业务的情况下,完成按时间维度分表的完整过程,感兴趣的小伙伴可以了解一下... 目录引言一、为什么我们需要分表1.1 单表数据量过大的问题1.2 分表方案选型二、分表前的准备工作2.1 数据评估

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Python使用python-pptx自动化操作和生成PPT

《Python使用python-pptx自动化操作和生成PPT》这篇文章主要为大家详细介绍了如何使用python-pptx库实现PPT自动化,并提供实用的代码示例和应用场景,感兴趣的小伙伴可以跟随小编... 目录使用python-pptx操作PPT文档安装python-pptx基础概念创建新的PPT文档查看

Linux查询服务器 IP 地址的命令详解

《Linux查询服务器IP地址的命令详解》在服务器管理和网络运维中,快速准确地获取服务器的IP地址是一项基本但至关重要的技能,下面我们来看看Linux中查询服务器IP的相关命令使用吧... 目录一、hostname 命令:简单高效的 IP 查询工具命令详解实际应用技巧注意事项二、ip 命令:新一代网络配置全

在ASP.NET项目中如何使用C#生成二维码

《在ASP.NET项目中如何使用C#生成二维码》二维码(QRCode)已广泛应用于网址分享,支付链接等场景,本文将以ASP.NET为示例,演示如何实现输入文本/URL,生成二维码,在线显示与下载的完整... 目录创建前端页面(Index.cshtml)后端二维码生成逻辑(Index.cshtml.cs)总结

Python实现数据可视化图表生成(适合新手入门)

《Python实现数据可视化图表生成(适合新手入门)》在数据科学和数据分析的新时代,高效、直观的数据可视化工具显得尤为重要,下面:本文主要介绍Python实现数据可视化图表生成的相关资料,文中通过... 目录前言为什么需要数据可视化准备工作基本图表绘制折线图柱状图散点图使用Seaborn创建高级图表箱线图热