C#调用C++生成的dll获取CPU序列号(二)

         在前面一节,我们了解了如何用C++生成dll并返回字符串供C#接收;在这一节,我们将正式进入主题,用C++获取计算机的硬件信息,并生成dll。C#调用dll的方法跟前面一样。

1、新建项目,选择 Visual C++ 》 Win32项目 》 输入项目名称pcinfo,在向导里选择 "下一步" 》应用程序类型 》选择 "dll" 》 完成。

2、新建头文件pcinfo.h,声明导出函数:

extern "C" _declspec(dllexport) char* GetCPUID();

extern "C" _declspec(dllexport) char* GetAllHardId();

3、新建头文件ttype.h,定义类型:

#define  __T(x) L ## x
#define  _T(x) __T(x)

4、新建头文件hdtype.h,定义硬盘类型:

#define  IDE_ATAPI_IDENTIFY  0xA1
#define  IDE_ATA_IDENTIFY    0xEC
#define  DFP_RECEIVE_DRIVE_DATA   0x0007c088

5、打开pcinfo.cpp文件,在该文件下实现头文件里声明的函数体:

// pcinfo.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "pcinfo.h"
#include "hdtype.h"
#include "ttype.h"
#include <iostream>
#include <winioctl.h>

using namespace std;

BOOL __fastcall DoIdentify( HANDLE hPhysicalDriveIOCTL,
                            PSENDCMDINPARAMS pSCIP,
                            PSENDCMDOUTPARAMS pSCOP,
                            BYTE btIDCmd,
                            BYTE btDriveNum,
                            PDWORD pdwBytesReturned);
string GetHardId(int hdno);

//获取CPU序列号
char* GetCPUID()
{
    unsigned long s1,s2,s3,s4;
	char cpuid1[50] = {};
	char cpuid2[50] = {};

	__asm{
        mov eax,00h
        xor edx,edx
        cpuid
		mov s1,eax
		mov s2,ebx
		mov s3,ecx
		mov s4,edx
    }
	sprintf_s(cpuid1,"%X-%X-%X-%X-",s1,s2,s3,s4);

    __asm{
        mov eax,01h
        xor ecx,ecx
        xor edx,edx
        cpuid
		mov s1,eax
		mov s2,ebx
		mov s3,ecx
		mov s4,edx
    }
    sprintf_s(cpuid2,"%X-%X-%X",s1,s3,s4);

	string result = cpuid1;
	result.append(cpuid2);

	char* c;
	const int len = result.length();
	c = new char[len+1];
	strcpy_s(c,len+1,result.c_str());
	return c;
}

//取得所有的硬盘ID
char* GetAllHardId()
{
	string result = "";
	for(int i=0;i<4;i++)
	{
		string currId= GetHardId(i);
		if(!currId.empty())
		{
			result.append(currId);
			result.append(";");
		}
	}
	if(!result.empty())	//去掉最后的分号
		result.resize(result.length() - 1);
	
	char* c;
	const int len = result.length();
	c = new char[len+1];
	strcpy_s(c,len+1,result.c_str());
	return c;
}

//取得硬盘ID
string GetHardId(int hdno)
{
	//第一步:创建设备对象,得到设备句柄,设备为硬盘。
	wchar_t dev[50];
	wsprintf(dev,_T("\\\\.\\PHYSICALDRIVE%d"), hdno);
	HANDLE hFile=::CreateFile(dev,
                     GENERIC_READ | GENERIC_WRITE,
                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                     NULL, OPEN_EXISTING,
                     0, NULL);
	if(hFile==NULL)
	{
		return ""; 
	}

	DWORD dwBytesReturned;
	GETVERSIONINPARAMS gvopVersionParams;
	//向设备对象发送SMART_GET_VERSION设备请求,获取硬盘属性
	DeviceIoControl(hFile,       
					SMART_GET_VERSION,
					NULL,
					0,
					&gvopVersionParams,
					sizeof(gvopVersionParams),
					&dwBytesReturned, NULL);

	if(gvopVersionParams.bIDEDeviceMap <= 0)  
	{
		::CloseHandle(hFile);
		return ""; 
	}

	//第二步,发送SMART_RCV_DRIVE_DATA设备请求,获取硬盘详细信息。
    // IDE or ATAPI IDENTIFY cmd
    int btIDCmd = 0;
    SENDCMDINPARAMS InParams;
    int nDrive = 0 ;
    btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
    // 输出参数
    BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
    if(DoIdentify(hFile,
					&InParams,
                    (PSENDCMDOUTPARAMS)btIDOutCmd,
                    (BYTE)btIDCmd,
                    (BYTE)nDrive, &dwBytesReturned) == FALSE)    
	{
	    ::CloseHandle(hFile);
		return "";
	}

    ::CloseHandle(hFile);

	char *pIDSector = (char*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer;

	//取缓冲区详细信息----------------------------------------------------------------------------------
	char *p = pIDSector;
	for(int i=0;i<10;i++)
	{
		for(int j=0;j<10;j++)
		{
			char b[2] = {};
			b[0] = *p;
			if(b[0]<=32 || b[0]>=127)
			{
				char s[20]={};
				sprintf_s(s, "%i", b[0]);
			}
			p++;
		}	
	}
	//--------------------------------------------------------------------------------------------------

	char szSerialNumber[21] = {};
    memcpy(szSerialNumber, pIDSector+20, 20);
	for(int i=0;i<20;)
	{
		char c = szSerialNumber[i];
		szSerialNumber[i] = szSerialNumber[i+1];
		szSerialNumber[i+1] = c;
		i += 2;
	}
	char* psn = szSerialNumber;
	for(int i=0; i<20; i++)
	{
		if(*psn==NULL)
		{
			psn++;
		}
		else 
		{
			break;
		}
	}
	string str(psn);
	return str;
}

BOOL __fastcall DoIdentify( HANDLE hPhysicalDriveIOCTL,
                            PSENDCMDINPARAMS pSCIP,
                            PSENDCMDOUTPARAMS pSCOP,
                            BYTE btIDCmd,
                            BYTE btDriveNum,
                            PDWORD pdwBytesReturned)
{
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    pSCIP->irDriveRegs.bFeaturesReg = 0;
    pSCIP->irDriveRegs.bSectorCountReg  = 1;
    pSCIP->irDriveRegs.bSectorNumberReg = 1;
    pSCIP->irDriveRegs.bCylLowReg  = 0;
    pSCIP->irDriveRegs.bCylHighReg = 0;
    pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
    pSCIP->irDriveRegs.bCommandReg = btIDCmd;
    pSCIP->bDriveNumber = btDriveNum;
    pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
    return DeviceIoControl( hPhysicalDriveIOCTL,
                            SMART_RCV_DRIVE_DATA,
                            (LPVOID)pSCIP,
                            sizeof(SENDCMDINPARAMS) - 1,
                            (LPVOID)pSCOP,
                            sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
                            pdwBytesReturned, NULL);
}

6、编译项目,生成pcinfo.dll。

dll下载地址http://download.csdn.net/detail/sunny906/8150037

7、新建C#项目,把刚才生成的pcinfo.dll复制到目录bin\Debug下。

8、调用pcinfo.dll

        //引用dll
        [DllImport("pcinfo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        static extern IntPtr GetCPUID();

        [DllImport("pcinfo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        static extern IntPtr GetAllHardId();

            //调用
            IntPtr n = GetCPUID();
            string str = Marshal.PtrToStringAnsi(n);
            Console.WriteLine(str);

            n = GetAllHardId();
            str = Marshal.PtrToStringAnsi(n);
            Console.WriteLine(str);

        好了,到此,我们就完成了C++获取计算机硬件信息的dll的生成方法及调用过程,同时给有需要的童鞋们提供一点点参考。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值