在前面一节,我们了解了如何用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的生成方法及调用过程,同时给有需要的童鞋们提供一点点参考。