获取硬盘物理序列号的delphi2010源码

xsmuhtar 2010-10-06 06:14:33
获取硬盘物理序列号的delphi2010源码 定价为:100元,,求获取硬盘物理序列号的delphi源码:

人品。据着理网

1、注意要的是硬盘出厂的序列号,而非硬盘卷的序列号;产事、过郑

2、对各种硬盘(IDE、SCSI、SATA)均要有效;键位房许到是由

3、在win98/win2000/xp/win2003/Vista/Win7各种操作系统下均要有效;配位出我职不,悬了

4、所获的序列号在操作系统重装或Ghost还原后不能产生改变;资们看受似

5、必须提供delphi下的源代码。找是己卖某求过

6、必须用delphi 2010开发。

平和标帮第关象这,

QQ:327873200

TEL:15199000068

以上是该任务的要求,欢迎大家积极参与威客任务-求获取硬盘物理序列号的delphi源码,大家还可以对该任务发表评论、评分,祝愿您能在该任务胜利中标!

...全文
1921 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
dongcijie 2013-04-12
  • 打赏
  • 举报
回复
http://download.csdn.net/detail/dongcijie/5249516不过不支持raid阵列读取。
guang168332 2011-10-05
  • 打赏
  • 举报
回复
貌似还是不行哦。。
weizhaom 2011-09-02
  • 打赏
  • 举报
回复
delphi调用wmi 获取好像很简单
xsmuhtar 2010-10-18
  • 打赏
  • 举报
回复
我试过了好多个硬盘序列号的代码,delphi 7 可以正常使用,但delphi 2009和delphi 2010力不能正常的读取序列号

这些代码如何转换成delphi 2010的代码了,


我看又有一些代码,和dll 文件 在delphi 2010上不能正常使用的,这些代码如何转换成delphi2010的代码呢?

zhoudongmeiyuanlin 2010-10-11
  • 打赏
  • 举报
回复
学习了 ...
lyhoo163 2010-10-11
  • 打赏
  • 举报
回复
至今沿无对所有硬盘有效的方法。只能对部份硬盘。
gary08 2010-10-10
  • 打赏
  • 举报
回复
说的有道理,还是兼容问题
liups 2010-10-09
  • 打赏
  • 举报
回复
很古老的资料了,终于在大富翁翻出来了,关于IDE硬盘参数的格式

-------------------------------------------------------------------------------
0170-0177 ---- HDC 2 (2nd Fixed Disk Controller) same as 01Fx (ISA, EISA)

-------------------------------------------------------------------------------
01F0-01F7 ---- HDC 1 (1st Fixed Disk Controller) same as 017x (ISA, EISA)

01F0 r/w data register

01F1 r error register
diagnostic mode errors:
bit 7-3 reserved
bit 2-1 = 001 no error detected
= 010 formatter device error
= 011 sector buffer error
= 100 ECC circuitry error
= 101 controlling microprocessor error
operation mode:
bit 7 = 1 bad block detected
= 0 block OK
bit 6 = 1 uncorrectable ECC error
= 0 no error
bit 5 reserved
bit 4 = 1 ID found
= 0 ID not found
bit 3 reserved
bit 2 = 1 command completed
= 0 command aborted
bit 1 = 1 track 000 not found
= 0 track 000 found
bit 0 = 1 DAM not found
= 0 DAM found (CP-3022 always 0)

01F1 w WPC/4 (Write Precompensation Cylinder divided by 4)

01F2 r/w sector count
01F3 r/w sector number
01F4 r/w cylinder low
01F5 r/w cylinder high

01F6 r/w drive/head
bit 7 = 1
bit 6 = 0
bit 5 = 1
bit 4 = 0 drive 0 select
= 1 drive 1 select
bit 3-0 head select bits

01F7 r status register
bit 7 = 1 controller is executing a command
bit 6 = 1 drive is ready
bit 5 = 1 write fault
bit 4 = 1 seek complete
bit 3 = 1 sector buffer requires servicing
bit 2 = 1 disk data read successfully corrected
bit 1 = 1 index - set to 1 each disk revolution
bit 0 = 1 previous command ended in an error

01F7 w command register
commands:
98 E5 check power mode (IDE)
90 execute drive diagnostics
50 format track
EC identify drive (IDE)
97 E3 idle (IDE)
95 E1 idle immediatete (IDE)
91 initialize drive parameters
1x recalibrate
E4 read buffer (IDE)
C8 read DMA with retry (IDE)
C9 read DMA without retry (IDE)
C4 read multiplec (IDE)
20 read sectors with retry
21 read sectors without retry
22 read long with retry
23 read long without retry
40 read verify sectors with retry
41 read verify sectors without retry
7x seek
EF set features (IDE)
C6 set multiple mode (IDE)
99 E6 set sleep mode (IDE)
96 E2 standby (IDE)
94 E0 standby immediate (IDE)
E8 write buffer (IDE)
CA write DMA with retry (IDE)
CB write DMA with retry (IDE)
C5 write multiple (IDE)
E9 write same (IDE)
30 write sectors with retry
31 write sectors without retry
32 write long with retry
33 write long without retry
3C write verify (IDE)
9A vendor unique (IDE)
C0-C3 vendor unique (IDE)
8x vendor unique (IDE)
F0-F4 EATA standard (IDE)
F5-FF vendor unique (IDE)


-------------------------------------------------------------------------------
liups 2010-10-09
  • 打赏
  • 举报
回复
本人从DOS时代就研究这个了,可以这样告诉楼主:全部的要求都要达到基本上是不可能的,但是常见硬盘获取序列号还是比较容易的。

一、硬盘物理序列号的由来:
IDE接口的硬盘有一个标准,就是其中指定位置有512字节存放硬盘本身的信息,其中20个字节(SerialNumber部分)就是硬盘物理序列号,每个硬盘都应该不一样的。可见只有IDE或兼容的硬盘才有这个东东(SATA一般是兼容的),SCSI和SAS的就是没有这个东东的,也许他们有自己类似的东东,但是目前没有这方面的资料,也没有人宣称能获取这种硬盘的序列号。所以指望适合所有硬盘是不现实的!
二、获取这512字节或序列号的方法:
由一可以知道,获取序列号的一般方法就是读取这512个字节并加以截取和转换。如果学习过接口与通信或微机原理之类的课程,就知道PC上实际是通过往某些端口写入和读取来实现的,DOS下面就是这样获取序列号的。windows 9X开始,不能直接访问硬件了,所以windows 9x中一般需要使用Vxd技术实现对端口的访问,而NT系列的则又需要使用其他方法才能访问端口,5、6楼的方法就是这样的,注意程序中应当先判断用的是哪种windows。
另外一个方法是使用微软的wmi,但是wmi也有些问题:1、早期windows没有这个东东,需要单独安装;2、2000、XP、2003的wmi和vista、windows7的wmi有区别,实际上wmi中有两种方法,结果的格式也是有区别的,所以仍然需要判断是何种windows。所以单独使用wmi也不是完美的方法。
可能有人觉得不需要使用wmi,其实我这里提到它是因为在vista或WIN7下面,传统方法需要关闭UAC才能得到正确结果,这个问题楼主可能还没有考虑过但是却不能忽略。比较完美的方案应该是在5、6楼的方法中增加判断vista和win7的代码,如果是这两种则采用wmi来获取。
三、关于有些IDE兼容的硬盘不能获取序列号
有资料说是它们就没有序列号或者说是空白的,但是根据本人的经验来看,还没有碰到过这样的硬盘,主要问题出在有些硬盘的序列号的20个字节是空格前导的,有些程序中没有考虑到此种情况,导致取出的序列号是空的。
四、关于delphi2010不能获取序列号
实际上传统方法是牵涉到对字节进行操作的,而在delphi2009开始引入了对unicode的支持,所以char不再等同于byte,如果使用delphi2009及以后的版本照搬5、6楼的代码不会成功的,因为那些代码认为char等同于byte!只要根据这个进行简单的修改就可用于delphi2009和2010了。
lphj07 2010-10-08
  • 打赏
  • 举报
回复
这个比较困难,普通的IDE、SATA还比较容易实现,但是SCSI和SAS卡硬盘,我弄了很久都读不出来
xsmuhtar 2010-10-08
  • 打赏
  • 举报
回复
楼上写的方法不能用Delphi 2010 不能用,读不出来硬盘物理序列号,delphi的低版本可以。

这些方法最新的delphi 2010,或者delphi.net里如何实现?



如果你们说的这个价格少的话,我可以给你们加钱。
7030 2010-10-08
  • 打赏
  • 举报
回复
测试结果 RAID 0硬盘序列号取不出
贝隆 2010-10-07
  • 打赏
  • 举报
回复
100块,随礼都不是这个价格了。。。
kye_jufei 2010-10-07
  • 打赏
  • 举报
回复
不過我一直使用的是MSI GUI和MiTeC組件聯合,可獲取不同型號的電腦硬件設備信息,效果還理想。。。
kye_jufei 2010-10-07
  • 打赏
  • 举报
回复
之前看見過網上有一段牛人發的DISKSN.PAS文件,可支持IDE、SCSI、SATA多種格式。。。

http://www.docin.com/p-5408843.html
lyhoo163 2010-10-07
  • 打赏
  • 举报
回复
100元是少了,可能无人操作。
bdmh 2010-10-07
  • 打赏
  • 举报
回复
楼上的方法只对部分硬盘有效,我也在找能够兼容多种硬盘的方法,有知道的就传授一下
kye_jufei 2010-10-07
  • 打赏
  • 举报
回复
function   GetIdeDiskSerialNumber()   :   String; 
type
TSrbIoControl = packed record
HeaderLength : ULONG;
Signature : Array[0..7] of Char;
Timeout : ULONG;
ControlCode : ULONG;
ReturnCode : ULONG;
Length : ULONG;
end;
SRB_IO_CONTROL = TSrbIoControl;
PSrbIoControl = ^TSrbIoControl;

TIDERegs = packed record
bFeaturesReg : Byte; // Used for specifying SMART "commands ".
bSectorCountReg : Byte; // IDE sector count register
bSectorNumberReg : Byte; // IDE sector number register
bCylLowReg : Byte; // IDE low order cylinder value
bCylHighReg : Byte; // IDE high order cylinder value
bDriveHeadReg : Byte; // IDE drive/head register
bCommandReg : Byte; // Actual IDE command.
bReserved : Byte; // reserved. Must be zero.
end;
IDEREGS = TIDERegs;
PIDERegs = ^TIDERegs;

TSendCmdInParams = packed record
cBufferSize : DWORD;
irDriveRegs : TIDERegs;
bDriveNumber : Byte;
bReserved : Array[0..2] of Byte;
dwReserved : Array[0..3] of DWORD;
bBuffer : Array[0..0] of Byte;
end;
SENDCMDINPARAMS = TSendCmdInParams;
PSendCmdInParams = ^TSendCmdInParams;

TIdSector = packed record
wGenConfig : Word;
wNumCyls : Word;
wReserved : Word;
wNumHeads : Word;
wBytesPerTrack : Word;
wBytesPerSector : Word;
wSectorsPerTrack : Word;
wVendorUnique : Array[0..2] of Word;
sSerialNumber : Array[0..19] of Char;
wBufferType : Word;
wBufferSize : Word;
wECCSize : Word;
sFirmwareRev : Array[0..7] of Char;
sModelNumber : Array[0..39] of Char;
wMoreVendorUnique : Word;
wDoubleWordIO : Word;
wCapabilities : Word;
wReserved1 : Word;
wPIOTiming : Word;
wDMATiming : Word;
wBS : Word;
wNumCurrentCyls : Word;
wNumCurrentHeads : Word;
wNumCurrentSectorsPerTrack : Word;
ulCurrentSectorCapacity : ULONG;
wMultSectorStuff : Word;
ulTotalAddressableSectors : ULONG;
wSingleWordDMA : Word;
wMultiWordDMA : Word;
bReserved : Array[0..127] of Byte;
end;
PIdSector = ^TIdSector;

const
IDE_ID_FUNCTION = $EC;
IDENTIFY_BUFFER_SIZE = 512;
DFP_RECEIVE_DRIVE_DATA = $0007c088;
IOCTL_SCSI_MINIPORT = $0004d008;
IOCTL_SCSI_MINIPORT_IDENTIFY = $001b0501;
DataSize = sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
BufferSize = SizeOf(SRB_IO_CONTROL)+DataSize;
W9xBufferSize = IDENTIFY_BUFFER_SIZE+16;
var
hDevice : THandle;
cbBytesReturned : DWORD;
pInData : PSendCmdInParams;
pOutData : Pointer; // PSendCmdOutParams
Buffer : Array[0..BufferSize-1] of Byte;
srbControl : TSrbIoControl absolute Buffer;

procedure ChangeByteOrder( var Data; Size : Integer );
var ptr : PChar;
i : Integer;
c : Char;
begin
ptr := @Data;
for i := 0 to (Size shr 1)-1 do
begin
c := ptr^;
ptr^ := (ptr+1)^;
(ptr+1)^ := c;
Inc(ptr,2);
end;
end;

begin
Result := ' ';
FillChar(Buffer,BufferSize,#0);
if Win32Platform=VER_PLATFORM_WIN32_NT then
begin // Windows NT, Windows 2000
// Get SCSI port handle
hDevice := CreateFile( '\\.\Scsi0: ', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
if hDevice=INVALID_HANDLE_VALUE then Exit;
try
srbControl.HeaderLength := SizeOf(SRB_IO_CONTROL);
System.Move( 'SCSIDISK ',srbControl.Signature,8);
srbControl.Timeout := 2;
srbControl.Length := DataSize;
srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;
pInData := PSendCmdInParams(PChar(@Buffer)
+SizeOf(SRB_IO_CONTROL));
pOutData := pInData;
with pInData^ do
begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
bDriveNumber := 0;
with irDriveRegs do
begin
bFeaturesReg := 0;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := 0;
bCylHighReg := 0;
bDriveHeadReg := $A0;
bCommandReg := IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl( hDevice, IOCTL_SCSI_MINIPORT,
@Buffer, BufferSize, @Buffer, BufferSize,
cbBytesReturned, nil ) then
Exit;
finally
CloseHandle(hDevice);
end;
end
else
begin // Windows 95 OSR2, Windows 98
hDevice := CreateFile( '\\.\SMARTVSD ', 0, 0, nil, CREATE_NEW, 0, 0 );
if hDevice=INVALID_HANDLE_VALUE then Exit;
try
pInData := PSendCmdInParams(@Buffer);
pOutData := @pInData^.bBuffer;
with pInData^ do
begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
bDriveNumber := 0;
with irDriveRegs do
begin
bFeaturesReg := 0;
bSectorCountReg := 1;
bSectorNumberReg := 1;
bCylLowReg := 0;
bCylHighReg := 0;
bDriveHeadReg := $A0;
bCommandReg := IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl( hDevice, DFP_RECEIVE_DRIVE_DATA,
pInData, SizeOf(TSendCmdInParams)-1, pOutData,
W9xBufferSize, cbBytesReturned, nil ) then
Exit;
finally
CloseHandle(hDevice);
end;
end;
with PIdSector(PChar(pOutData)+16)^ do
begin
ChangeByteOrder(sSerialNumber,Sizeof(sSerialNumber));
SetString(Result,sSerialNumber,Sizeof(sSerialNumber));
Result := Trim(Result);
end;
end;
kye_jufei 2010-10-07
  • 打赏
  • 举报
回复
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
end;

//获得硬盘序列号
function GetIdeSerialNumber: pchar;
const IDENTIFY_BUFFER_SIZE = 512;
type
TIDERegs = packed record
bFeaturesReg: BYTE; // Used for specifying SMART "commands".
bSectorCountReg: BYTE; // IDE sector count register
bSectorNumberReg: BYTE; // IDE sector number register
bCylLowReg: BYTE; // IDE low order cylinder value
bCylHighReg: BYTE; // IDE high order cylinder value
bDriveHeadReg: BYTE; // IDE drive/head register
bCommandReg: BYTE; // Actual IDE command.
bReserved: BYTE; // reserved for future use. Must be zero.
end;
TSendCmdInParams = packed record
// Buffer size in bytes
cBufferSize: DWORD;
// Structure with drive register values.
irDriveRegs: TIDERegs;
// Physical drive number to send command to (0,1,2,3).
bDriveNumber: BYTE;
bReserved: array[0..2] of Byte;
dwReserved: array[0..3] of DWORD;
bBuffer: array[0..0] of Byte; // Input buffer.
end;
TIdSector = packed record
wGenConfig: Word;
wNumCyls: Word;
wReserved: Word;
wNumHeads: Word;
wBytesPerTrack: Word;
wBytesPerSector: Word;
wSectorsPerTrack: Word;
wVendorUnique: array[0..2] of Word;
sSerialNumber: array[0..19] of CHAR;
wBufferType: Word;
wBufferSize: Word;
wECCSize: Word;
sFirmwareRev: array[0..7] of Char;
sModelNumber: array[0..39] of Char;
wMoreVendorUnique: Word;
wDoubleWordIO: Word;
wCapabilities: Word;
wReserved1: Word;
wPIOTiming: Word;
wDMATiming: Word;
wBS: Word;
wNumCurrentCyls: Word;
wNumCurrentHeads: Word;
wNumCurrentSectorsPerTrack: Word;
ulCurrentSectorCapacity: DWORD;
wMultSectorStuff: Word;
ulTotalAddressableSectors: DWORD;
wSingleWordDMA: Word;
wMultiWordDMA: Word;
bReserved: array[0..127] of BYTE;
end;
PIdSector = ^TIdSector;
TDriverStatus = packed record
// 驱动器返回的错误代码,无错则返回0
bDriverError: Byte;
// IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效
bIDEStatus: Byte;
bReserved: array[0..1] of Byte;
dwReserved: array[0..1] of DWORD;
end;
TSendCmdOutParams = packed record
// bBuffer的大小
cBufferSize: DWORD;
// 驱动器状态
DriverStatus: TDriverStatus;
// 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定
bBuffer: array[0..0] of BYTE;
end;
var
hDevice: Thandle;
cbBytesReturned: DWORD;
SCIP: TSendCmdInParams;
aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE - 1) - 1] of Byte;
IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;
procedure ChangeByteOrder(var Data; Size: Integer);
var
ptr: Pchar;
i: Integer;
c: Char;
begin
ptr := @Data;
for I := 0 to (Size shr 1) - 1 do begin
c := ptr^;
ptr^ := (ptr + 1)^;
(ptr + 1)^ := c;
Inc(ptr, 2);
end;
end;
begin
Result := ''; // 如果出错则返回空串
if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000
// 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
end else // Version Windows 95 OSR2, Windows 98
hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
if hDevice = INVALID_HANDLE_VALUE then Exit;
try
FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);
FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
cbBytesReturned := 0;
// Set up data structures for IDENTIFY command.
with SCIP do begin
cBufferSize := IDENTIFY_BUFFER_SIZE;
// bDriveNumber := 0;
with irDriveRegs do begin
bSectorCountReg := 1;
bSectorNumberReg := 1;
// if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
// else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
bDriveHeadReg := $A0;
bCommandReg := $EC;
end;
end;
if not DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) - 1,
@aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;
finally
CloseHandle(hDevice);
end;
with PIdSector(@IdOutCmd.bBuffer)^ do begin
ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
(Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^ := #0;
Result := Pchar(@sSerialNumber);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Edit1.Text := strpas(GetIdeSerialNumber);
end;

end.
SQLDebug_Fan 2010-10-06
  • 打赏
  • 举报
回复
100元太少了,不过帮顶
加载更多回复(1)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧