這個問題首先得考慮的就是你的硬盤是不是SCSI硬盤
如果是,那麼根本不存在"物理序列號",只可能取得卷標的序列號
如果是卷標序列號,要注意的是每次格式化硬盤的時候這個序列號都會變
代碼可以參考:
http://www.csdn.net/Develop/Read_Article.asp?Id=25196
如果是物理序列號:
String HDid;
ManagementClass cimobject = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc = cimobject.GetInstances();
foreach(ManagementObject mo in moc)
{
HDid = (string)mo.Properties["Model"].Value;
MessageBox.Show(HDid );
}
如果是取得邏輯序列號(Format產生的那個),用WMI就可以,在引用中,添加system.mangement以後。
using System.Management;
.....
ManagementObject m_objDisk = new ManagementObject( "win32_logicaldisk.deviceid=\"c\"");
string strSN = (string)m_objDisk.GetPropertyValue( "VolumeSerialNumber ");
如果要取得物理分區號,看這個帖子:
關於硬盤序列號,高手請留步啊. (之一)
http://expert.csdn.net/Expert/TopicView3.asp?id=1143107
683E0480(第一種方案取得)
ST3160815AS (第二個方案取得的)
5239355835565745202020202020202020202020(第三種方案取得)
private string[] GetMoc()
{
string[] str = new string[3];
ManagementClass mcCpu = new ManagementClass("win32_Processor");
ManagementObjectCollection mocCpu = mcCpu.GetInstances();
foreach(ManagementObject m in mocCpu)
{
str[0] = m["ProcessorId"].ToString();
}
ManagementClass mcHD = new ManagementClass("win32_logicaldisk");
ManagementObjectCollection mocHD = mcHD.GetInstances();
foreach(ManagementObject m in mocHD)
{
if(m["DeviceID"].ToString() == "C:")
{
str[1] = m["VolumeSerialNumber"].ToString();
break;
}
}
ManagementClass mcMAC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection mocMAC = mcMAC.GetInstances();
foreach(ManagementObject m in mocMAC)
{
if((bool)m["IPEnabled"])
{
str[2] = m["MacAddress"].ToString();
break;
}
}
return str;
}
以上爲取硬盤邏輯分區序列號,重新格式化會改變
以下爲硬盤物理序列號,需管理員權限,wmi
複製代碼
using System;
using System.Management;
namespace HTSoft.Common.Register
{
/// <summary>
/// 計算機信息類
/// </summary>
internal class Computer
{
public string CpuID;
public string MacAddress;
public string DiskID;
public string IpAddress;
public string LoginUserName;
public string ComputerName;
public string SystemType;
public string TotalPhysicalMemory; //單位:M
private static Computer _instance;
internal static Computer Instance()
{
if (_instance == null)
_instance = new Computer();
return _instance;
}
internal Computer()
{
CpuID = GetCpuID();
MacAddress = GetMacAddress();
DiskID = GetDiskID();
IpAddress = GetIPAddress();
LoginUserName = GetUserName();
SystemType = GetSystemType();
TotalPhysicalMemory = GetTotalPhysicalMemory();
ComputerName = GetComputerName();
}
string GetCpuID()
{
try
{
//獲取CPU序列號代碼
string cpuInfo = "";//cpu序列號
ManagementClass mc = new ManagementClass("Win32_Processor");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
cpuInfo = mo.Properties["ProcessorId"].Value.ToString();
}
moc = null;
mc = null;
return cpuInfo;
}
catch
{
return "unknow";
}
finally
{
}
}
string GetMacAddress()
{
try
{
//獲取網卡硬件地址
string mac = "";
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"] == true)
{
mac = mo["MacAddress"].ToString();
break;
}
}
moc = null;
mc = null;
return mac;
}
catch
{
return "unknow";
}
finally
{
}
}
string GetIPAddress()
{
try
{
//獲取IP地址
string st = "";
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"] == true)
{
//st=mo["IpAddress"].ToString();
System.Array ar;
ar = (System.Array)(mo.Properties["IpAddress"].Value);
st = ar.GetValue(0).ToString();
break;
}
}
moc = null;
mc = null;
return st;
}
catch
{
return "unknow";
}
finally
{
}
}
string GetDiskID()
{
try
{
//獲取硬盤ID
String HDid = "";
ManagementClass mc = new ManagementClass("Win32_DiskDrive");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
HDid = (string)mo.Properties["Model"].Value;
}
moc = null;
mc = null;
return HDid;
}
catch
{
return "unknow";
}
finally
{
}
}
/// <summary>
/// 操作系統的登錄用戶名
/// </summary>
/// <returns></returns>
string GetUserName()
{
try
{
string st = "";
ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
st = mo["UserName"].ToString();
}
moc = null;
mc = null;
return st;
}
catch
{
return "unknow";
}
finally
{
}
}
/// <summary>
/// PC類型
/// </summary>
/// <returns></returns>
string GetSystemType()
{
try
{
string st = "";
ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
st = mo["SystemType"].ToString();
}
moc = null;
mc = null;
return st;
}
catch
{
return "unknow";
}
finally
{
}
}
/// <summary>
/// 物理內存
/// </summary>
/// <returns></returns>
string GetTotalPhysicalMemory()
{
try
{
string st = "";
ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
st = mo["TotalPhysicalMemory"].ToString();
}
moc = null;
mc = null;
return st;
}
catch
{
return "unknow";
}
finally
{
}
}
/// <summary>
/// 獲取計算機名稱
/// </summary>
/// <returns></returns>
string GetComputerName()
{
try
{
return System.Environment.GetEnvironmentVariable("ComputerName");
}
catch
{
return "unknow";
}
finally
{
}
}
}
}
複製代碼
第三種方案:
Code
一般軟件的註冊機制可以通過獲取硬件序列號,然後用非對稱加密算法生成相應的公鑰和私鑰。但是用Managed Code寫獲取硬盤序列號的代碼不能解決所有的問題,比如不能在非管理員的權限下使用,前幾天Sunmast在他的Blog上發佈了《如何得到硬盤序列號?.NET版本[C#]》,就是沒有解決這個問題,用WMI也有很多問題。
要想順利獲取硬盤的序列號,目前只能依靠非託管代碼了。DiskId32是一個源碼公開的C++程序,可以解決上述問題。由於代碼比較底層,我對VC和DDK不熟悉,沒有能力將其封裝爲DLL,希望各位幫忙!
還有,就算封裝好了這個Native DLL並可以使用了,但還有問題沒有解決。如果封裝到了Native DLL,該DLL很容易被人替換成另外一個,畢竟在Managed Code裏面可以看到調用Native DLL的函數聲明,別人只要模仿這些函數界面重新寫一個新的就很容易達到破解目的了。不過具體我沒有測試過,不知道行不行。
於是我又想到了另外一個方法,就是把獲取硬盤序列號的Native DLL作爲資源文件封裝到Managed Code中,然後在每次要調要該DLL時,先把該DLL寫入磁盤,再動態綁定。由於Managed Code可以通過混淆器來保護,以致不能對其進行修改,這個我在《如何保護我們的 .NET 程序集?》中已經給出了答案。動態綁定Native DLL又是另外一個技術難題,我已經找到了一些資料,與大家分享。
Late binding on native DLLs with C#
Late-Binding DLLs in C#
Using legacy plug-ins with .NET - Part 1
Using legacy plug-ins with .NET - Part 2
C-Function pointer for .NET
Dynamic PInvoke method calls
不過最牛的就是下面這一招了!直接把Native Code用字節數組保存在Managed Code中,然後調用,真是牛B,不過我還沒有完全弄懂,希望大家來實踐實踐。
Execute Native Code From .NET
另外還有一篇文章是關於加密字符串的,值得研究!
Poly-Engine Crypt String
希望各位多多交流.NET程序的保護問題,找出最好的解決方案!
http://www.winsim.com/diskid32/diskid32.html
複製代碼
這個問題我查找了一下,已經有很多很多很多人問過了,有給了一些相映的解答。
1)利用 WMI 讀取
2)有高人給了一個地址,http://www.winsim.com/diskid32/diskid32.html 。同時給了一大段代碼,代碼見後面。
但是沒有明確講出來如何使用。尤其是第二種方法,感覺不錯,只是不懂得如何使用,哪位指點小弟一二
public class IDE
{
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct IDSECTOR
{
public ushort wGenConfig;
public ushort wNumCyls;
public ushort wReserved;
public ushort wNumHeads;
public ushort wBytesPerTrack;
public ushort wBytesPerSector;
public ushort wSectorsPerTrack;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=3)]
public ushort [] wVendorUnique;
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=20)]
public string sSerialNumber;
public ushort wBufferType;
public ushort wBufferSize;
public ushort wECCSize;
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=8)]
public string sFirmwareRev;
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=40)]
public string sModelNumber;
public ushort wMoreVendorUnique;
public ushort wDoubleWordIO;
public ushort wCapabilities;
public ushort wReserved1;
public ushort wPIOTiming;
public ushort wDMATiming;
public ushort wBS;
public ushort wNumCurrentCyls;
public ushort wNumCurrentHeads;
public ushort wNumCurrentSectorsPerTrack;
public uint ulCurrentSectorCapacity;
public ushort wMultSectorStuff;
public uint ulTotalAddressableSectors;
public ushort wSingleWordDMA;
public ushort wMultiWordDMA;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=128 )]
public byte [] bReserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct DRIVERSTATUS
{
public byte bDriverError;
public byte bIDEStatus;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=2 )]
public byte [] bReserved;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=2 )]
public uint [] dwReserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SENDCMDOUTPARAMS
{
public uint cBufferSize;
public DRIVERSTATUS DriverStatus;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=513 )]
public byte [] bBuffer;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct SRB_IO_CONTROL
{
public uint HeaderLength;
[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=8 )]
public string Signature;
public uint Timeout;
public uint ControlCode;
public uint ReturnCode;
public uint Length;
}
[StructLayout(LayoutKind.Sequential)]
internal struct IDEREGS
{
public byte bFeaturesReg;
public byte bSectorCountReg;
public byte bSectorNumberReg;
public byte bCylLowReg;
public byte bCylHighReg;
public byte bDriveHeadReg;
public byte bCommandReg;
public byte bReserved;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SENDCMDINPARAMS
{
public uint cBufferSize;
public IDEREGS irDriveRegs;
public byte bDriveNumber;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=3 )]
public byte [] bReserved;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=4 )]
public uint [] dwReserved;
public byte bBuffer;
}
[StructLayout(LayoutKind.Sequential)]
internal struct GETVERSIONOUTPARAMS
{
public byte bVersion;
public byte bRevision;
public byte bReserved;
public byte bIDEDeviceMap;
public uint fCapabilities;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=4 )]
public uint [] dwReserved; // For future use.
}
[DllImport("kernel32.dll")]
private static extern int CloseHandle(uint hObject);
[DllImport("kernel32.dll")]
private static extern int DeviceIoControl(uint hDevice,
uint dwIoControlCode,
ref SENDCMDINPARAMS lpInBuffer,
int nInBufferSize,
ref SENDCMDOUTPARAMS lpOutBuffer,
int nOutBufferSize,
ref uint lpbytesReturned,
int lpOverlapped);
[DllImport("kernel32.dll")]
private static extern int DeviceIoControl(uint hDevice,
uint dwIoControlCode,
int lpInBuffer,
int nInBufferSize,
ref GETVERSIONOUTPARAMS lpOutBuffer,
int nOutBufferSize,
ref uint lpbytesReturned,
int lpOverlapped);
[DllImport("kernel32.dll")]
private static extern uint CreateFile(string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
int lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
int hTemplateFile);
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint INVALID_HANDLE_VALUE = 0xffffffff;
private const uint DFP_GET_VERSION = 0x00074080;
private const int IDE_ATAPI_IDENTIFY = 0xA1; // Returns ID sector for ATAPI.
private const int IDE_ATA_IDENTIFY = 0xEC; // Returns ID sector for ATA.
private const int IDENTIFY_BUFFER_SIZE = 512;
private const uint DFP_RECEIVE_DRIVE_DATA = 0x0007c088;
public static string Read(byte drive)
{
OperatingSystem os = Environment.OSVersion;
if (os.Platform != PlatformID.Win32NT) throw new NotSupportedException("僅支持WindowsNT/2000/XP");
//我沒有NT4,請哪位大大測試一下NT4下能不能用
//if (os.Version.Major < 5) throw new NotSupportedException("僅支持WindowsNT/2000/XP");
string driveName = "\\\\.\\PhysicalDrive" + drive.ToString();
uint device = CreateFile(driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
if (device == INVALID_HANDLE_VALUE) return "";
GETVERSIONOUTPARAMS verPara = new GETVERSIONOUTPARAMS();
uint bytRv = 0;
if (0 != DeviceIoControl(device, DFP_GET_VERSION,
0, 0, ref verPara, Marshal.SizeOf(verPara),
ref bytRv, 0))
{
if (verPara.bIDEDeviceMap > 0)
{
byte bIDCmd = (byte)(((verPara.bIDEDeviceMap >> drive & 0x10) != 0) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY);
SENDCMDINPARAMS scip = new SENDCMDINPARAMS();
SENDCMDOUTPARAMS scop = new SENDCMDOUTPARAMS();
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bFeaturesReg = 0;
scip.irDriveRegs.bSectorCountReg = 1;
scip.irDriveRegs.bCylLowReg = 0;
scip.irDriveRegs.bCylHighReg = 0;
scip.irDriveRegs.bDriveHeadReg = (byte)(0xA0 | ((drive & 1) << 4));
scip.irDriveRegs.bCommandReg = bIDCmd;
scip.bDriveNumber = drive;
if (0 != DeviceIoControl(device, DFP_RECEIVE_DRIVE_DATA,
ref scip, Marshal.SizeOf(scip), ref scop,
Marshal.SizeOf(scop), ref bytRv, 0))
{
StringBuilder s = new StringBuilder();
for (int i = 20; i < 40; i += 2)
{
s.Append((char)(scop.bBuffer[i+1]));
s.Append((char)scop.bBuffer[i]);
}
CloseHandle(device);
return s.ToString().Trim();
}
}
}
CloseHandle(device);
return "";
}
}