Project1

标题: 获取本机机器码 [打印本页]

作者: fux2    时间: 2013-12-11 19:37
标题: 获取本机机器码
本帖最后由 fux2 于 2013-12-15 14:21 编辑

最近看到有同学求,于是写了这个
感谢@orzfly @EngShun 的帮助。

Windows7及以上系统需要以管理员身份运行
范例程序内自带权限申请。

↓这是一个用于测试的范例
获取机器码.rar (574.96 KB, 下载次数: 303)
↑这是一个用于测试的范例

2013年12月14日22:25:26
修复了一个在1.9.3 ruby版本以下结果会返回nil的BUG


调用的时候用
RUBY 代码复制
  1. testid = Fux2::SystemInfo.GetCPUid
  2. p testid
  3. msgbox testid if defined?(msgbox)

即可获得本机第一个可用硬盘的SerialNumber

以下是代码
理论上插到任何地方都没问题。
  1. # 获取本机硬盘序列 by fux2
  2. # 感谢orzfly
  3. # 感谢EngShun

  4. module Fux2
  5.   module SystemInfo
  6.     VER_PLATFORM_WIN32_NT = 0x2
  7.     MAX_DRIVER = 8
  8.     GENERIC_READ = 0x80000000
  9.     GENERIC_WRITE = 0x40000000
  10.     FILE_SHARE_READ = 0x1
  11.     FILE_SHARE_WRITE = 0x2
  12.     OPEN_EXISTING = 0x3
  13.     CREATE_NEW = 0x1
  14.     INVALID_HANDLE_VALUE = -0x1
  15.     DFP_GET_VERSION = 0x74080
  16.     DFP_SEND_DRIVE_COMMAND = 0x7C084
  17.     DFP_RECEIVE_DRIVE_DATA = 0x7C088
  18.     SMART_ENABLE_SMART_OPERATIONS = 0xD8
  19.     SMART_CYL_LOW = 0x4F
  20.     SMART_CYL_HI = 0xC2
  21.     IDE_EXECUTE_SMART_FUNCTION = 0xB0
  22.     IDE_ID_FUNCTION = 0xEC
  23.     IDENTIFY_BUFFER_SIZE = 512
  24.     OUTPUT_DATA_SIZE = IDENTIFY_BUFFER_SIZE + 16
  25.     GetVersion = Win32API.new('kernel32','GetVersionExA','p','l')
  26.     CreateFile = Win32API.new('kernel32','CreateFileA','plllpll','l')
  27.     CloseHandle = Win32API.new('kernel32','CloseHandle','p','l')
  28.     DeviceIoControl = Win32API.new('kernel32','DeviceIoControl','plplplpp','l')
  29.     GetLastError = Win32API.new('kernel32','GetLastError','v','l')
  30.     CopyMemory = Win32API.new('kernel32','RtlMoveMemory','ppl','v')
  31.    
  32.     def self.IsWinNT4Plus
  33.       buffer = [148].pack("l") + "\0" * 144
  34.       if GetVersion.call(buffer) == 1
  35.         if buffer.unpack("c*")[16] == VER_PLATFORM_WIN32_NT && buffer[4,4].unpack("l")[0] >= 4
  36.           return true
  37.         else
  38.           return false
  39.         end
  40.       end
  41.       raise "error"
  42.     end
  43.    
  44.     def self.SmartGetVersion(hDrive)
  45.       buffer = "\0" * 4
  46.       gvop = "\0" * 24
  47.       ret = DeviceIoControl.call(hDrive,DFP_GET_VERSION,nil,0,gvop,24,[0].pack("l"),nil)
  48.       return ret == 0 ? false : true
  49.     end
  50.    
  51.     def self.SmartOpen(drvNumber)
  52.       ret = INVALID_HANDLE_VALUE
  53.       if self.IsWinNT4Plus
  54.         ret = CreateFile.call("\\\\.\\PhysicalDrive"+drvNumber.to_s,
  55.                               [GENERIC_READ | GENERIC_WRITE].pack("l").unpack("l")[0],
  56.                               [FILE_SHARE_READ | FILE_SHARE_WRITE].pack("l").unpack("l")[0],
  57.                               0,OPEN_EXISTING,0,0)
  58.    
  59.       else
  60.         ret = CreateFile.call("\\\\.\\SMARTVSD",0,0,0,CREATE_NEW,0,0)
  61.       end
  62.       return ret
  63.     end
  64.    
  65.     def self.SmartCheckEnabled(hDrive,drvNumber)
  66.       scip = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  67.       scop = "\0" * 20
  68.       scip[1] = SMART_ENABLE_SMART_OPERATIONS
  69.       scip[2] = 1
  70.       scip[3] = 1
  71.       scip[4] = SMART_CYL_LOW
  72.       scip[5] = SMART_CYL_HI
  73.       scip[6] = 0xA0
  74.       unless self.IsWinNT4Plus
  75.         scip[6] = scip[6] | ((drvNumber & 1) * 16)
  76.       end
  77.       scip[7] = IDE_EXECUTE_SMART_FUNCTION
  78.       scip[9] = drvNumber
  79.       scip = scip.pack("lcccccccccccclllll")
  80.       ipsize = 0
  81.       scip.each_byte{ipsize+=1}
  82.       opsize = 0
  83.       scop.each_byte{opsize+=1}
  84.       ret = DeviceIoControl.call( hDrive,
  85.                                   DFP_SEND_DRIVE_COMMAND,
  86.                                   scip,
  87.                                   ipsize - 4,
  88.                                   scop,
  89.                                   opsize - 4,
  90.                                   [0].pack("l"),
  91.                                   nil)
  92.       return ret == 0 ? false : true
  93.     end
  94.    
  95.     def self.IdentifyDrive(hDrive,idCmd,drvNumber)
  96.       scip = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  97.       idsec = "\0" * 256
  98.       bArrOut = "\0" * OUTPUT_DATA_SIZE

  99.       scip[0] = IDENTIFY_BUFFER_SIZE
  100.       scip[9] = drvNumber
  101.       
  102.       scip[1] = 0
  103.       scip[2] = 1
  104.       scip[3] = 1
  105.       scip[4] = 0
  106.       scip[5] = 0
  107.       scip[6] = 0xA0
  108.       unless self.IsWinNT4Plus
  109.         scip[6] = scip[6] | ((drvNumber & 1) * 16)
  110.       end
  111.       scip[7] = idCmd
  112.       scip = scip.pack("lcccccccccccclllll")
  113.       ipsize = 0
  114.       scip.each_byte{ipsize+=1}
  115.       ret = DeviceIoControl.call( hDrive,
  116.                                   DFP_RECEIVE_DRIVE_DATA,
  117.                                   scip,
  118.                                   ipsize - 4,
  119.                                   bArrOut,
  120.                                   OUTPUT_DATA_SIZE,
  121.                                   [0].pack("l"),
  122.                                   nil)
  123.       if ret != 0
  124.         CopyMemory.call(idsec, bArrOut, 256)
  125.         serialNumber = self.SwapBytes(idsec[36,20])
  126.         return serialNumber
  127.       end
  128.       return false
  129.     end
  130.    
  131.     def self.SwapBytes(b)
  132.       b = b.unpack("C*")
  133.       b.each_index do |i|
  134.         next if i%2!=0
  135.         b[i],b[i+1] = b[i+1],b[i]
  136.       end
  137.       return b.pack("C*")
  138.     end
  139.    
  140.     def self.GetDriveInfo(drvNumber)
  141.       hDrive = self.SmartOpen(drvNumber)
  142.       if hDrive != INVALID_HANDLE_VALUE
  143.         if self.SmartGetVersion(hDrive)
  144.           if self.SmartCheckEnabled(hDrive,drvNumber)
  145.             ret = self.IdentifyDrive(hDrive, IDE_ID_FUNCTION, drvNumber)
  146.             if ret
  147.               return ret
  148.             end
  149.           end
  150.         end
  151.       end
  152.       return nil
  153.       raise "error"
  154.     end

  155.     def self.GetCPUid
  156.       cpuid = nil
  157.       MAX_DRIVER.times do |drvNumber|
  158.         cpuid = self.GetDriveInfo(drvNumber)
  159.         if cpuid
  160.           break
  161.         end
  162.       end
  163.       return cpuid
  164.     end


  165.   end
  166. end
复制代码

作者: 你最珍贵    时间: 2013-12-11 20:14
{:2_282:}大触手出没
作者: ky52879    时间: 2013-12-12 20:58
经测试:win7返回nil,XP暂时未测试。。。
作者: fux2    时间: 2013-12-13 14:30
ky52879 发表于 2013-12-12 20:58
经测试:win7返回nil,XP暂时未测试。。。

改了一下,你再试试?
作者: ky52879    时间: 2013-12-13 21:18
fux2 发表于 2013-12-13 14:30
改了一下,你再试试?

依然是nil,附件和脚本我都试了,还是nil,我用XP虚拟机也测试了,也同样是nil。。。。
PS:是我机器问题吗?有人成功了没呢,能发下看看嘛?
作者: chd114    时间: 2013-12-14 20:43
读出来是nil```(PS:网吧标配)
作者: fux2    时间: 2013-12-14 22:20
@ky52879 @chd114 巨巨,已修复。
作者: chd114    时间: 2013-12-14 23:38
fux2 发表于 2013-12-14 22:20
@ky52879 @chd114 巨巨,已修复。

表示再次试了下```如果你的脚本没错,那就是这个脚本有限制```反正我在网吧里面用这个只能读出nil```
作者: taroxd    时间: 2013-12-15 11:00
用了一下,貌似读出来的东西一开始有很多空格。这是正常现象?
作者: fux2    时间: 2013-12-15 12:38
taroxd 发表于 2013-12-15 11:00
用了一下,貌似读出来的东西一开始有很多空格。这是正常现象?

空格是正常的,因为机器码是固定长度的字符串。
正好便于序列号的生成,长度不一的话生成也头疼吧。
作者: 火烧兔子    时间: 2013-12-15 15:46
RM何其强大
作者: chd114    时间: 2013-12-16 14:57
fux2 发表于 2013-12-15 12:38
空格是正常的,因为机器码是固定长度的字符串。
正好便于序列号的生成,长度不一的话生成也头疼吧。 ...

话说这个脚本只能是个人机子+管理员身份采用得了···在学校也玩了下···发现也不能获得···如果能改进成破权限获得就好了···那样管理员就废了···
作者: 英顺的马甲    时间: 2013-12-17 08:56
其实不需要以管理员身份运行的说...好吧,其实是我把uac关了==
作者: eve592370698    时间: 2013-12-24 01:44
版主回归了?获取本地日期和时间应该比获取机器码更容易吧?
作者: fux2    时间: 2013-12-24 01:49
eve592370698 发表于 2013-12-24 01:44
版主回归了?获取本地日期和时间应该比获取机器码更容易吧?

时间的话。。。一句话
Time.now
作者: eve592370698    时间: 2013-12-24 01:57
fux2 发表于 2013-12-24 01:49
时间的话。。。一句话
Time.now

主要是我在弄一个类似SFC《天外魔镜》的日期识别功能,想把这个加入到一些年头久远的老游戏中,毕竟我现在在维护一些古老的RMXP游戏。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1