Hàm nào lấy thông số CPU hay thông số ổ đĩa hay thông số gì đó tương tự??? (1 người xem)

Người dùng đang xem chủ đề này

quangthanhdu

Thành viên chính thức
Tham gia
21/5/10
Bài viết
51
Được thích
4
Mỗi máy tính sẽ có một thông số khác nhau( thông số gì cũng được miễn sao khi mang file excel qua máy tính khác thì sẽ cho một thông số khác), mọi người chỉ giúp em có công thức excel nào lấy ra thông số đó. @#!^%
 
Tại 1 ô nào đó bạn nhập thế này coi ra cái gì nhé

=cell("filename")
 
Lấy ID của CPU:
Mã:
Sub GetCPUID()
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor")
For Each objItem In colItems
MsgBox "Processor Id: " & objItem.ProcessorId
Next
End Sub
Lấy serial number của ổ cứng:
Mã:
Option Explicit
Declare Function GetVolumeInformationA Lib "kernel32" _
(ByVal lpRootPathName As String, _
ByVal lpVolumeNameBuffer As String, _
ByVal nVolumeNameSize As Long, _
lpVolumeSerialNumber As Long, _
lpMaximumComponentLength As Long, _
lpFileSystemFlags As Long, _
ByVal lpFileSystemNameBuffer As String, _
ByVal nFileSystemNameSize As Long) As Long
Sub SeriesNumber()
Dim SerialNumber As Long
GetVolumeInformationA "C:\", vbNullString, 0, SerialNumber, _
0, 0, vbNullString, 0
MsgBox SerialNumber
End Sub
 
Lần chỉnh sửa cuối:
Lấy ID của CPU:
Mã:
Sub GetCPUID()
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor")
For Each objItem In colItems
MsgBox "Processor Id: " & objItem.ProcessorId
Next
End Sub
Lấy serial number của ổ cứng:
Mã:
Option Explicit
Declare Function GetVolumeInformationA Lib "kernel32" _
(ByVal lpRootPathName As String, _
ByVal lpVolumeNameBuffer As String, _
ByVal nVolumeNameSize As Long, _
lpVolumeSerialNumber As Long, _
lpMaximumComponentLength As Long, _
lpFileSystemFlags As Long, _
ByVal lpFileSystemNameBuffer As String, _
ByVal nFileSystemNameSize As Long) As Long
Sub SeriesNumber()
Dim SerialNumber As Long
GetVolumeInformationA "C:\", vbNullString, 0, SerialNumber, _
0, 0, vbNullString, 0
MsgBox SerialNumber
End Sub
Trong DOS có lệnh WMIC rất hay. Gần như nó có thể lấy mọi thông tin liên quan đến máy tính
Ví dụ lấy CPU ID là: WMIC CPU get ProcessorID
"Nhúng" câu lệnh này vào VB ta sẽ viết thế này
PHP:
Function GetCPUID() As String
  Dim sComm As String, tmpFile, Arr
  On Error Resume Next
  With CreateObject("Scripting.FileSystemObject")
    tmpFile = .GetTempName
    sComm = "wmic CPU get ProcessorID" & " > " & tmpFile
    CreateObject("Wscript.Shell").Run "cmd /c " & sComm, 0, True
    Arr = Split(.OpenTextFile(tmpFile, 1, 0, -1).ReadAll, vbCrLf)
  End With
  GetCPUID = Arr(1)
  Kill tmpFile
End Function
vân vân và vân vân
Cứ thí nghiệm bằng cách gõ vào cửa sổ CMD lệnh: WMIC /? sẽ phát hiện rất nhiều thứ thú vị
 
Lấy ID của CPU:
Mã:
Sub GetCPUID()
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor")
For Each objItem In colItems
MsgBox "Processor Id: " & objItem.ProcessorId
Next
End Sub
Lấy serial number của ổ cứng:
Mã:
Option Explicit
Declare Function GetVolumeInformationA Lib "kernel32" _
(ByVal lpRootPathName As String, _
ByVal lpVolumeNameBuffer As String, _
ByVal nVolumeNameSize As Long, _
lpVolumeSerialNumber As Long, _
lpMaximumComponentLength As Long, _
lpFileSystemFlags As Long, _
ByVal lpFileSystemNameBuffer As String, _
ByVal nFileSystemNameSize As Long) As Long
Sub SeriesNumber()
Dim SerialNumber As Long
GetVolumeInformationA "C:\", vbNullString, 0, SerialNumber, _
0, 0, vbNullString, 0
MsgBox SerialNumber
End Sub

Cái trên đâu có phải trả về thông số của đĩa cứng vật lý???.
Thứ nhất: ngay tên hàm API cho thấy là nó đọc thông số của partition / logical disk / phân vùng.
Thứ hai: nhìn cái "C:\" là biết nó đọc serial number của partition C
Bạn mua 1 đĩa cứng ở cửa hàng về. Cái đĩa vật lý này chỉ có 1. Nhưng bạn có thể chia nó thành vd. 3 "đĩa" / phân vùng / partition C, D, E. Bạn gọi hàm trên cho "C:\", "D:\", "E:\" thì sẽ có 3 số khác nhau. Vậy số nào là số của cái đĩa vật lý kia đây??? Một chút tư duy đủ thấy được vấn đề.
Cái nữa là nếu bạn Format C, D, E thì bạn sẽ đọc ra những số khác.
Kết luận: Hàm trên chỉ đọc serial number của phân vùng, mà số này cũng thay đổi khi Format phân vùng. Cái số của nhà sản xuất ghi trên đĩa vật lý và có nêu trong bảo hành đâu có đọc được bằng cái hàm kia.
 
Cái trên đâu có phải trả về thông số của đĩa cứng vật lý???.
Thứ nhất: ngay tên hàm API cho thấy là nó đọc thông số của partition / logical disk / phân vùng.
Thứ hai: nhìn cái "C:\" là biết nó đọc serial number của partition C
Bạn mua 1 đĩa cứng ở cửa hàng về. Cái đĩa vật lý này chỉ có 1. Nhưng bạn có thể chia nó thành vd. 3 "đĩa" / phân vùng / partition C, D, E. Bạn gọi hàm trên cho "C:\", "D:\", "E:\" thì sẽ có 3 số khác nhau. Vậy số nào là số của cái đĩa vật lý kia đây??? Một chút tư duy đủ thấy được vấn đề.
Cái nữa là nếu bạn Format C, D, E thì bạn sẽ đọc ra những số khác.
Kết luận: Hàm trên chỉ đọc serial number của phân vùng, mà số này cũng thay đổi khi Format phân vùng. Cái số của nhà sản xuất ghi trên đĩa vật lý và có nêu trong bảo hành đâu có đọc được bằng cái hàm kia.
Tôi thật sự cũng không biết Hard Disk Serial Number là cái gì nữa
Bạn cho hỏi dòng lệnh này: WMIC DiskDrive Get Signature liệu có phải là Serial Number không?
 
Tôi thật sự cũng không biết Hard Disk Serial Number là cái gì nữa
Bạn cho hỏi dòng lệnh này: WMIC DiskDrive Get Signature liệu có phải là Serial Number không?

Tôi cũng không rõ nữa. Cái thời tôi cũng tò mò thì chưa có WMIC. WMIC có trong Win 7, không có trong XP. Tôi dùng XP. Thời xưa, tôi còn nhớ, tôi có 1 code trong Delphi. Cũng chỉ là tò mò thôi chứ chả quan tâm đến những trò này. Chắc chắn tìm trên mạng sẽ có nhiều giải pháp.
Ý tôi muốn nói là phải đọc được serial của nhà sx chứ serial partition thì thay đổi được mà, đâu có là unique
Nói chung tôi không thích những trò này. Anh bán cho người ta phần mềm rồi anh chỉ cho chạy khi có số ở đĩa như thế này? Thế nếu tôi thay đĩa vì đĩa cũ nhỏ, hỏng thì sao? Gọi điện, viết thư đăng ký lại? Thế nếu anh phá sản làm việc khác thì tôi chào tạm biệt phần mềm tôi bỏ tiền ra mua?
 
Lần chỉnh sửa cuối:
WMIC có trong Win 7, không có trong XP. Tôi dùng XP.
Ủa kỳ vậy ta? Tôi thử dùng WMIC trên máy của thằng bạn (WinXP) vẫn chạy được mà bạn
Có điều khi gõ WMIC /? xong, nó hiện ra 1 thông báo đại khái bảo "vui lòng đợi, đang install.. cái gì đó" ---> Xong, chạy bình thường
Hỏi thêm: Liệu code dưới đây có phải là lấy HDD Serial number khộng?
PHP:
Function GetDiskSN() As String
  Dim tmp, objItem As Object
  'On Error Resume Next
  With GetObject("winmgmts:\\.\root\cimv2")
    For Each objItem In .ExecQuery("SELECT * FROM Win32_PhysicalMedia")
      tmp = objItem.SerialNumber
      If TypeName(tmp) = "String" Then
        If Len(tmp) > 1 Then
          GetDiskSN = Trim(tmp)
          Exit Function
        End If
      End If
    Next
  End With
End Function
Nói chung chỉ là nghiên cứu chơi thôi cứ tôi cũng không thích trò này (vì biết chắc người ta dùng để tạo "phần mềm dùng thử" gì đó trên Excel...)
 
Ủa kỳ vậy ta? Tôi thử dùng WMIC trên máy của thằng bạn (WinXP) vẫn chạy được mà bạn
Có điều khi gõ WMIC /? xong, nó hiện ra 1 thông báo đại khái bảo "vui lòng đợi, đang install.. cái gì đó" ---> Xong, chạy bình thường
Hỏi thêm: Liệu code dưới đây có phải là lấy HDD Serial number khộng?
PHP:
........................................
Nói chung chỉ là nghiên cứu chơi thôi cứ tôi cũng không thích trò này (vì biết chắc người ta dùng để tạo "phần mềm dùng thử" gì đó trên Excel...)[/QUOTE]

Máy mình dùng Wind XP chép code trên vào Test là được ngay.
 
Ủa kỳ vậy ta? Tôi thử dùng WMIC trên máy của thằng bạn (WinXP) vẫn chạy được mà bạn
Có điều khi gõ WMIC /? xong, nó hiện ra 1 thông báo đại khái bảo "vui lòng đợi, đang install.. cái gì đó" ---> Xong, chạy bình thường
Hỏi thêm: Liệu code dưới đây có phải là lấy HDD Serial number khộng?
PHP:
Function GetDiskSN() As String
  Dim tmp, objItem As Object
  'On Error Resume Next
  With GetObject("winmgmts:\\.\root\cimv2")
    For Each objItem In .ExecQuery("SELECT * FROM Win32_PhysicalMedia")
      tmp = objItem.SerialNumber
      If TypeName(tmp) = "String" Then
        If Len(tmp) > 1 Then
          GetDiskSN = Trim(tmp)
          Exit Function
        End If
      End If
    Next
  End With
End Function
Nói chung chỉ là nghiên cứu chơi thôi cứ tôi cũng không thích trò này (vì biết chắc người ta dùng để tạo "phần mềm dùng thử" gì đó trên Excel...)

Rất có thể WMIC có trong XP professional, tôi dùng Home không thấy.
Tôi cũng không rõ là code trên có thực sự đọc được serial của nhà sản xuất không. Để biết chắc chắn 100 % thì chỉ còn nước là khi mua đĩa thì ghi serial rồi sau đó đọc bằng code xem thế nào. Hoặc phải "lục kỹ" internet. Lục kỹ bởi đầy rẫy những code kiểu "GetVolumeInformation".
Có thời tôi tò mò về WMI. Tò mò và tìm hiểu chút về bản thân WMI chứ không phải tò mò là nó đọc disk serial như thế nào. Bởi thực ra rất nhiều thông tin có thể đọc trực tiếp từ system, từ registry. Chẳng hạn dùng method của WMI có thể tắt máy, nhưng dùng nó làm gì khi có thể làm đơn giản hơn. Có thể dùng method của WMI để khởi động notepad chẳng hạn nhưng dùng làm gì khi mà có thể làm đơn giản hơn. Trong code có thể gọi hàm của system để làm những chuyện vd. như trên.
----------------
To sealand:
code "winmgmts:\\.\root\cimv2" chạy được thì đúng rồi. Nó dùng WMI (Windows Management Instrumentation) để đọc thông tin. WMI thì có trong Windows từ lâu rồi, tôi cũng có. Cái tôi không có là WMIC (Windows Management Instrumentation Command-line). Khi viết trong cửa sổ dòng lệnh wmic /? thì cũng chỉ được báo là "Tên "wmic" không là lệnh, phần mềm thực thi, ..." Cũng chả có: "Ông có muốn cài ...?" để mà "ừ". Do tôi có XP chỉ Home chăng? Tôi cũng không tìm hiểu thêm vì chả quan tâm.
---------------
Ở dưới tôi đính kèm ví dụ dùng WMI trong Delphi cho ai tò mò. Có WMI.exe để kích hoạt luôn và chọn trong combobox mục cần đọc thông tin. Có cả source code cho ai có Delphi mà sợ tôi cài virút.
 

File đính kèm

Lần chỉnh sửa cuối:
Nói chung chỉ là nghiên cứu chơi thôi cứ tôi cũng không thích trò này (vì biết chắc người ta dùng để tạo "phần mềm dùng thử" gì đó trên Excel...)
-Mình nghĩ diễn đàn ta nên hỗ trợ và khuyến khích việc dùng excel để viết phần mềm thương mại. Bản thân việc này xét cho cùng vẫn có lợi cho việc học tập, nghiên cứu và không đi ngược với tôn chỉ của GPE.
Nguyên văn bởi siwtom
Nói chung tôi không thích những trò này. Anh bán cho người ta phần mềm rồi anh chỉ cho chạy khi có số ở đĩa như thế này? Thế nếu tôi thay đĩa vì đĩa cũ nhỏ, hỏng thì sao? Gọi điện, viết thư đăng ký lại? Thế nếu anh phá sản làm việc khác thì tôi chào tạm biệt phần mềm tôi bỏ tiền ra mua?
Cám ơn bạn đã cho biết những bất lợi của việc dùng S/N của phân vùng thay vì S/N ổ đĩa của nhà sản xuất. Nên vấn đề là làm sao tìm cho được S/N của ổ đĩa.
Đoạn code sau ( sưu tầm) lấy được chính xác Model và S/N của tất cả ổ cứng trong máy.
Mã:
Option Explicit
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_SHARE_READ = &H1
Private Const FILE_SHARE_WRITE = &H2
Private Const OPEN_EXISTING = 3
Private Const CREATE_NEW = 1
Private Const INVALID_HANDLE_VALUE = -1
Private Const VER_PLATFORM_WIN32_NT = 2
Private Const IDENTIFY_BUFFER_SIZE = 512
Private Const OUTPUT_DATA_SIZE = IDENTIFY_BUFFER_SIZE + 16
'GETVERSIONOUTPARAMS contains the data returned
'from the Get Driver Version function
Private Type GETVERSIONOUTPARAMS
   bVersion       As Byte 'Binary driver version.
   bRevision      As Byte 'Binary driver revision
   bReserved      As Byte 'Not used
   bIDEDeviceMap  As Byte 'Bit map of IDE devices
   fCapabilities  As Long 'Bit mask of driver capabilities
   dwReserved(3)  As Long 'For future use
End Type
'IDE registers
Private Type IDEREGS
   bFeaturesReg     As Byte 'Used for specifying SMART "commands"
   bSectorCountReg  As Byte 'IDE sector count register
   bSectorNumberReg As Byte 'IDE sector number register
   bCylLowReg       As Byte 'IDE low order cylinder value
   bCylHighReg      As Byte 'IDE high order cylinder value
   bDriveHeadReg    As Byte 'IDE drive/head register
   bCommandReg      As Byte 'Actual IDE command
   bReserved        As Byte 'reserved for future use - must be zero
End Type
'SENDCMDINPARAMS contains the input parameters for the
'Send Command to Drive function
Private Type SENDCMDINPARAMS
   cBufferSize     As Long     'Buffer size in bytes
   irDriveRegs     As IDEREGS  'Structure with drive register values.
   bDriveNumber    As Byte     'Physical drive number to send command to (0,1,2,3).
   bReserved(2)    As Byte     'Bytes reserved
   dwReserved(3)   As Long     'DWORDS reserved
   bBuffer()      As Byte      'Input buffer.
End Type
'Valid values for the bCommandReg member of IDEREGS.
Private Const IDE_ID_FUNCTION = &HEC            'Returns ID sector for ATA.
Private Const IDE_EXECUTE_SMART_FUNCTION = &HB0 'Performs SMART cmd.
                                                'Requires valid bFeaturesReg,
                                                'bCylLowReg, and bCylHighReg
 
'Cylinder register values required when issuing SMART command
Private Const SMART_CYL_LOW = &H4F
Private Const SMART_CYL_HI = &HC2
'Status returned from driver
Private Type DRIVERSTATUS
   bDriverError  As Byte          'Error code from driver, or 0 if no error
   bIDEStatus    As Byte          'Contents of IDE Error register
                                  'Only valid when bDriverError is SMART_IDE_ERROR
   bReserved(1)  As Byte
   dwReserved(1) As Long
 End Type
Private Type IDSECTOR
   wGenConfig                 As Integer
   wNumCyls                   As Integer
   wReserved                  As Integer
   wNumHeads                  As Integer
   wBytesPerTrack             As Integer
   wBytesPerSector            As Integer
   wSectorsPerTrack           As Integer
   wVendorUnique(2)           As Integer
   sSerialNumber(19)          As Byte
   wBufferType                As Integer
   wBufferSize                As Integer
   wECCSize                   As Integer
   sFirmwareRev(7)            As Byte
   sModelNumber(39)           As Byte
   wMoreVendorUnique          As Integer
   wDoubleWordIO              As Integer
   wCapabilities              As Integer
   wReserved1                 As Integer
   wPIOTiming                 As Integer
   wDMATiming                 As Integer
   wBS                        As Integer
   wNumCurrentCyls            As Integer
   wNumCurrentHeads           As Integer
   wNumCurrentSectorsPerTrack As Integer
   ulCurrentSectorCapacity    As Long
   wMultSectorStuff           As Integer
   ulTotalAddressableSectors  As Long
   wSingleWordDMA             As Integer
   wMultiWordDMA              As Integer
   bReserved(127)             As Byte
End Type
 
'Structure returned by SMART IOCTL commands
Private Type SENDCMDOUTPARAMS
  cBufferSize   As Long         'Size of Buffer in bytes
  DRIVERSTATUS  As DRIVERSTATUS 'Driver status structure
  bBuffer()    As Byte          'Buffer of arbitrary length for data read from drive
End Type
 
'Vendor specific feature register defines
'for SMART "sub commands"
Private Const SMART_ENABLE_SMART_OPERATIONS = &HD8
 
'Status Flags Values
Public Enum STATUS_FLAGS
   PRE_FAILURE_WARRANTY = &H1
   ON_LINE_COLLECTION = &H2
   PERFORMANCE_ATTRIBUTE = &H4
   ERROR_RATE_ATTRIBUTE = &H8
   EVENT_COUNT_ATTRIBUTE = &H10
   SELF_PRESERVING_ATTRIBUTE = &H20
End Enum
 
'IOCTL commands
Private Const DFP_GET_VERSION = &H74080
Private Const DFP_SEND_DRIVE_COMMAND = &H7C084
Private Const DFP_RECEIVE_DRIVE_DATA = &H7C088
 
Private Type ATTR_DATA
   AttrID As Byte
   AttrName As String
   AttrValue As Byte
   ThresholdValue As Byte
   WorstValue As Byte
   StatusFlags As STATUS_FLAGS
End Type
Private Type DRIVE_INFO
   bDriveType As Byte
   SerialNumber As String
   Model As String
   FirmWare As String
   Cilinders As Long
   Heads As Long
   SecPerTrack As Long
   BytesPerSector As Long
   BytesperTrack As Long
   NumAttributes As Byte
   Attributes() As ATTR_DATA
End Type
Private Enum IDE_DRIVE_NUMBER
   PRIMARY_MASTER
   PRIMARY_SLAVE
   SECONDARY_MASTER
   SECONDARY_SLAVE
   TERTIARY_MASTER
   TERTIARY_SLAVE
   QUARTIARY_MASTER
   QUARTIARY_SLAVE
End Enum
Private Declare Function CreateFile Lib "kernel32" _
   Alias "CreateFileA" _
  (ByVal lpFileName As String, _
   ByVal dwDesiredAccess As Long, _
   ByVal dwShareMode As Long, _
   lpSecurityAttributes As Any, _
   ByVal dwCreationDisposition As Long, _
   ByVal dwFlagsAndAttributes As Long, _
   ByVal hTemplateFile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
  (ByVal hObject As Long) As Long
  Private Declare Function DeviceIoControl Lib "kernel32" _
  (ByVal hDevice As Long, _
   ByVal dwIoControlCode As Long, _
   lpInBuffer As Any, _
   ByVal nInBufferSize As Long, _
   lpOutBuffer As Any, _
   ByVal nOutBufferSize As Long, _
   lpBytesReturned As Long, _
   lpOverlapped As Any) As Long
  Private Declare Sub CopyMemory Lib "kernel32" _
   Alias "RtlMoveMemory" _
  (hpvDest As Any, _
   hpvSource As Any, _
   ByVal cbCopy As Long)
  Private Type OSVERSIONINFO
   OSVSize As Long
   dwVerMajor As Long
   dwVerMinor As Long
   dwBuildNumber As Long
   PlatformID As Long
   szCSDVersion As String * 128
End Type
Private Declare Function GetVersionEx Lib "kernel32" _
   Alias "GetVersionExA" _
  (LpVersionInformation As OSVERSIONINFO) As Long
Private Sub Command1_Click()
Dim di As DRIVE_INFO
   Dim drvNumber As Long
   For drvNumber = PRIMARY_MASTER To QUARTIARY_SLAVE
   di = GetDriveInfo(drvNumber)
      List1.AddItem "Drive " & drvNumber
       With di
      Select Case .bDriveType
            Case 0
               List1.AddItem vbTab & "[Not present]"
            Case 1
               List1.AddItem vbTab & "Model:" & vbTab & Trim$(.Model)
               List1.AddItem vbTab & "Serial No:" & vbTab & Trim$(.SerialNumber)
            Case 2
               List1.AddItem vbTab & "[ATAPI drive - info not available]"
            Case Else
               List1.AddItem vbTab & "[drive type not known]"
         End Select
          End With
      Next
   End Sub
Private Function GetDriveInfo(drvNumber As IDE_DRIVE_NUMBER) As DRIVE_INFO
    Dim hDrive As Long
   Dim di As DRIVE_INFO
   hDrive = SmartOpen(drvNumber)
   If hDrive <> INVALID_HANDLE_VALUE Then
   If SmartGetVersion(hDrive) = True Then
      With di
            .bDriveType = 0
            .NumAttributes = 0
            ReDim .Attributes(0)
            .bDriveType = 1
         End With
         If SmartCheckEnabled(hDrive, drvNumber) Then
            If IdentifyDrive(hDrive, IDE_ID_FUNCTION, drvNumber, di) = True Then
         GetDriveInfo = di
               End If   'IdentifyDrive
         End If   'SmartCheckEnabled
      End If   'SmartGetVersion
   End If   'hDrive <> INVALID_HANDLE_VALUE
    CloseHandle hDrive
   End Function
Private Function IdentifyDrive(ByVal hDrive As Long, _
                               ByVal IDCmd As Byte, _
                               ByVal drvNumber As IDE_DRIVE_NUMBER, _
                               di As DRIVE_INFO) As Boolean
    
  'Function: Send an IDENTIFY command to the drive
  'drvNumber = 0-3
  'IDCmd = IDE_ID_FUNCTION or IDE_ATAPI_ID
   Dim SCIP As SENDCMDINPARAMS
   Dim IDSEC As IDSECTOR
   Dim bArrOut(OUTPUT_DATA_SIZE - 1) As Byte
   Dim cbBytesReturned As Long
   With SCIP
      .cBufferSize = IDENTIFY_BUFFER_SIZE
      .bDriveNumber = CByte(drvNumber)
         With .irDriveRegs
         .bFeaturesReg = 0
         .bSectorCountReg = 1
         .bSectorNumberReg = 1
         .bCylLowReg = 0
         .bCylHighReg = 0
         .bDriveHeadReg = &HA0 'compute the drive number
         If Not IsWinNT4Plus Then
            .bDriveHeadReg = .bDriveHeadReg Or ((drvNumber And 1) * 16)
         End If
         'the command can either be IDE
         'identify or ATAPI identify.
         .bCommandReg = CByte(IDCmd)
      End With
   End With
    If DeviceIoControl(hDrive, _
                      DFP_RECEIVE_DRIVE_DATA, _
                      SCIP, _
                      Len(SCIP) - 4, _
                      bArrOut(0), _
                      OUTPUT_DATA_SIZE, _
                      cbBytesReturned, _
                      ByVal 0&) Then
                      
      CopyMemory IDSEC, bArrOut(16), Len(IDSEC)
 
      di.Model = StrConv(SwapBytes(IDSEC.sModelNumber), vbUnicode)
      di.SerialNumber = StrConv(SwapBytes(IDSEC.sSerialNumber), vbUnicode)
       IdentifyDrive = True
      End If
    End Function
Private Function IsWinNT4Plus() As Boolean
'returns True if running Windows NT4 or later
   Dim osv As OSVERSIONINFO
 osv.OSVSize = Len(osv)
If GetVersionEx(osv) = 1 Then
   IsWinNT4Plus = (osv.PlatformID = VER_PLATFORM_WIN32_NT) And _
                     (osv.dwVerMajor >= 4)
 
   End If
End Function
Private Function SmartCheckEnabled(ByVal hDrive As Long, _
                                   drvNumber As IDE_DRIVE_NUMBER) As Boolean
   'SmartCheckEnabled - Check if SMART enable
  'FUNCTION: Send a SMART_ENABLE_SMART_OPERATIONS command to the drive
  'bDriveNum = 0-3
   Dim SCIP As SENDCMDINPARAMS
   Dim SCOP As SENDCMDOUTPARAMS
   Dim cbBytesReturned As Long
   With SCIP
   .cBufferSize = 0
      With .irDriveRegs
           .bFeaturesReg = SMART_ENABLE_SMART_OPERATIONS
           .bSectorCountReg = 1
           .bSectorNumberReg = 1
           .bCylLowReg = SMART_CYL_LOW
           .bCylHighReg = SMART_CYL_HI
            .bDriveHeadReg = &HA0
            If Not IsWinNT4Plus Then
               .bDriveHeadReg = .bDriveHeadReg Or ((drvNumber And 1) * 16)
            End If
           .bCommandReg = IDE_EXECUTE_SMART_FUNCTION
           End With
       .bDriveNumber = drvNumber
       End With
   SmartCheckEnabled = DeviceIoControl(hDrive, _
                                      DFP_SEND_DRIVE_COMMAND, _
                                      SCIP, _
                                      Len(SCIP) - 4, _
                                      SCOP, _
                                      Len(SCOP) - 4, _
                                      cbBytesReturned, _
                                      ByVal 0&)
End Function
Private Function SmartGetVersion(ByVal hDrive As Long) As Boolean
   Dim cbBytesReturned As Long
   Dim GVOP As GETVERSIONOUTPARAMS
   SmartGetVersion = DeviceIoControl(hDrive, _
                                     DFP_GET_VERSION, _
                                     ByVal 0&, 0, _
                                     GVOP, _
                                     Len(GVOP), _
                                     cbBytesReturned, _
                                     ByVal 0&)
   End Function
Private Function SmartOpen(drvNumber As IDE_DRIVE_NUMBER) As Long
'Open SMART to allow DeviceIoControl
  'communications and return SMART handle
If IsWinNT4Plus() Then
      SmartOpen = CreateFile("[URL="file://\\.\PhysicalDrive"]\\.\PhysicalDrive[/URL]" & CStr(drvNumber), _
                             GENERIC_READ Or GENERIC_WRITE, _
                             FILE_SHARE_READ Or FILE_SHARE_WRITE, _
                             ByVal 0&, _
                             OPEN_EXISTING, _
                             0&, _
                             0&)
 
   Else
      SmartOpen = CreateFile("[URL="file://\\.\SMARTVSD"]\\.\SMARTVSD[/URL]", _
                              0&, 0&, _
                              ByVal 0&, _
                              CREATE_NEW, _
                              0&, _
                              0&)
   End If
   End Function
Private Function SwapBytes(b() As Byte) As Byte()
   'Note: VB4-32 and VB5 do not support the
  'return of arrays from a function. For
  'developers using these VB versions there
  'are two workarounds to this restriction:
  '
  '1) Change the return data type ( As Byte() )
  '   to As Variant (no brackets). No change
  '   to the calling code is required.
  '
  '2) Change the function to a sub, remove
  '   the last line of code (SwapBytes = b()),
  '   and take advantage of the fact the
  '   original byte array is being passed
  '   to the function ByRef, therefore any
  '   changes made to the passed data are
  '   actually being made to the original data.
  '   With this workaround the calling code
  '   also requires modification:
  '
  '      di.Model = StrConv(SwapBytes(IDSEC.sModelNumber), vbUnicode)
  '
  '   ... to ...
  '
  '      Call SwapBytes(IDSEC.sModelNumber)
  '      di.Model = StrConv(IDSEC.sModelNumber, vbUnicode)
    Dim bTemp As Byte
   Dim cnt As Long
For cnt = LBound(b) To UBound(b) Step 2
      bTemp = b(cnt)
      b(cnt) = b(cnt + 1)
      b(cnt + 1) = bTemp
   Next cnt
      SwapBytes = b()
      End Function
 

File đính kèm

-Mình nghĩ diễn đàn ta nên hỗ trợ và khuyến khích việc dùng excel để viết phần mềm thương mại. Bản thân việc này xét cho cùng vẫn có lợi cho việc học tập, nghiên cứu và không đi ngược với tôn chỉ của GPE.
Thì cái chuyện 1 người thích cái này và không thích cái khác là quan điểm của từng người, đâu có liên quan gì đến tôn chỉ của GPE
Các bạn thắc mắc vẫn có người trả lời đấy thôi
Cám ơn bạn đã cho biết những bất lợi của việc dùng S/N của phân vùng thay vì S/N ổ đĩa của nhà sản xuất. Nên vấn đề là làm sao tìm cho được S/N của ổ đĩa.
Đoạn code sau ( sưu tầm) lấy được chính xác Model và S/N của tất cả ổ cứng trong máy.
Thấy kết quả code của bạn cũng y chang với kết quả khi dùng code ở bài 8 ---> Bạn test thử xem
 
-
Cám ơn bạn đã cho biết những bất lợi của việc dùng S/N của phân vùng thay vì S/N ổ đĩa của nhà sản xuất. Nên vấn đề là làm sao tìm cho được S/N của ổ đĩa.
Đoạn code sau ( sưu tầm) lấy được chính xác Model và S/N của tất cả ổ cứng trong máy
Hồi xưa tôi tìm được code trong Delphi đọc serial trong các hđh kể cả 9x. Code đó đọc đĩa của tôi ra kết quả:
PHP:
Primary Controller - Master drive
Drive Model Number              : SAMSUNG SV0412H                         
Drive Serial Number             : 0536J1FT927540      
Drive Controller Revision Number: SK100-21
Controller Buffer Size on Drive : 2097152 bytes
Drive Type: Fixed
Physical Geometry: 16383 Cylinders, 16 Heads, 63 Sectors per track
Code của bạn trông giống giống về hướng đi. Đĩa của tôi nó đọc là:
PHP:
Model: SAMSUNG SV0412H
Serial No: 0536J1FT927540
Như thế code trong Delphi của tôi (ai cần thì cứ "gõ" cửa) và của bạn cho kết quả như nhau. Vậy có vẻ đáng tin.
Tôi cũng biết thế thôi. Chắc chắn 100 % thì phải đợi lúc có dịp so sánh với số của nhà sx.
 
Thì cái chuyện 1 người thích cái này và không thích cái khác là quan điểm của từng người, đâu có liên quan gì đến tôn chỉ của GPE
Các bạn thắc mắc vẫn có người trả lời đấy thôi

Thấy kết quả code của bạn cũng y chang với kết quả khi dùng code ở bài 8 ---> Bạn test thử xem

Đúng là cái code ngắn gọn của bạn nó cho ra cùng kết quả. Cũng cùng với kết quả mà code Delphi tôi tìm được hồi xưa trả về. Như thế chắc chắn là 90 %. Tôi sẽ có 100 % chắc chắn khi có dịp so sánh nó với số của nhà sản xuất.
 
Đúng là cái code ngắn gọn của bạn nó cho ra cùng kết quả. Cũng cùng với kết quả mà code Delphi tôi tìm được hồi xưa trả về. Như thế chắc chắn là 90 %. Tôi sẽ có 100 % chắc chắn khi có dịp so sánh nó với số của nhà sản xuất.
Trước khi post bài, mình đã tháo ổ cứng ra đối chiếu với kết quả trên. Như thế kết quả đó là chính xác 100%. Code của bạn ndu quả là ngắn gọn dù chưa lấy được model của ổ cứng. Không biết nếu máy có trên 1 ổ cứng thì nó lấy thông số của ổ nào?
 
Lần chỉnh sửa cuối:
Nếu mọi người thực sự muốn biết code của mình đáng tin cậy dùng cho các HĐH thì thử các tình huống test dưới đây nhé.

1. WinXP trở về trước - Cái này thường là lấy HDD SN không khó.
2. Win Vista, 7, 8 hay các phiên bản sau này. Chạy ở hai chế độ UAC ON và UAC OFF.
3. Nếu qua được bước 2 thì test trên Win 64-bit.
 
Trước khi post bài, mình đã tháo ổ cứng ra đối chiếu với kết quả trên. Như thế kết quả đó là chính xác 100%. Code của bạn ndu quả là ngắn gọn dù chưa lấy được model của ổ cứng. Không biết nếu máy có trên 1 ổ cứng thì nó lấy thông số của ổ nào?
Tiếc là tôi không có 2 ổ cứng gắn trong để thử, nhưng tôi tin chắc rằng code ấy cũng lấy được
Code là do tôi tự thí nghiệm mà ra ---> Quá trình duyệt qua vòng lập có khá nhiều "rác" nên tôi phải lọc để lấy cái cần lấy... lấy được rồi, tôi Exit Function luôn... Vậy nên tôi "đoán" nếu có trên 1 ổ cứng thì kết quả cũng sẽ được vòng lập "quét sạch" thôi
(đương nhiên khi ấy ta sẽ cho kết quả hàm vào 1 mảng)
Bạn tintam nếu có điều kiện hãy test thử xem (sửa code, đừng cho nó Exit Function)
(Hổng hiểu sao nghiên cứu lệnh WMIC trong DOS từ hôm qua đến giờ mà vẫn hổng biết cái nào là lấy HDD Serial Number... Hic... chắc tại mình ngu quá)
 
Vậy nên tôi "đoán" nếu có trên 1 ổ cứng thì kết quả cũng sẽ được vòng lập "quét sạch" thôi
(đương nhiên khi ấy ta sẽ cho kết quả hàm vào 1 mảng)
Mình đã test với 2 ổ cứng. Kết quả như bạn đã "đoán". Vòng lặp For Each objItem... duyệt và lấy S/N của cả 2 ổ cứng. Đoạn code thật ngắn gọn và hiệu quả. Tuy nhiên, có chỗ mình chưa hiểu lắm. Tại sao nó lặp 3 lần? Tại sao không ít hơn hoặc nhiều hơn?
 
Theo tôi thì không cần hàm gì cho phức tạp
Chỉ cần dùng các phần mềm có sẵn trong Win. Ví dụ như My Computer/Manage
 
Theo tôi thì không cần hàm gì cho phức tạp
Chỉ cần dùng các phần mềm có sẵn trong Win. Ví dụ như My Computer/Manage

Bạn nói cái gì vậy? Cái này là người ta viết chương trình trong VBA và trong chương trình sẽ có công đoạn cần lấy HDD SN ---> Vậy bạn bảo "tạm ngưng chương trình" rồi ra ngoài tự tìm bằng tay à?
Mà ngay cả tìm bằng tay thì tôi cũng không biết cách luôn... Bạn nói vào Computer/Manage gì gì đó.. Hổng ấy bạn mô tả cụ thể luôn đi cho anh em học hỏi
-----------------------
Mình đã test với 2 ổ cứng. Kết quả như bạn đã "đoán". Vòng lặp For Each objItem... duyệt và lấy S/N của cả 2 ổ cứng. Đoạn code thật ngắn gọn và hiệu quả. Tuy nhiên, có chỗ mình chưa hiểu lắm. Tại sao nó lặp 3 lần? Tại sao không ít hơn hoặc nhiều hơn?
Vọc chơi thôi chứ thú thật là tôi chưa hiểu hết về WMI đâu
 
Vọc chơi thôi chứ thú thật là tôi chưa hiểu hết về WMI đâu

Cái này không liên quan gì tới WMI

Nguyên văn bởi tintam7251
Vòng lặp For Each objItem... duyệt và lấy S/N của cả 2 ổ cứng. Đoạn code thật ngắn gọn và hiệu quả. Tuy nhiên, có chỗ mình chưa hiểu lắm. Tại sao nó lặp 3 lần?
Không phải là vòng lặp For được lặp lại 3 lần mà hàm được gọi 3 lần.

Bạn hãy thay GetDiskSN = Trim(tmp) bằng Debug.Print Trim(tmp)

1. Khi bạn chạy code trong VBE (Run) thì bạn sẽ có 1 dòng số
2. Bạn thêm nút để kích hoạt macro GetDiskSN. Khi bạn Click nút thì bạn cũng chỉ có 1 dòng số.
3. Nếu trong sheet bạn chọn 1 cell và chọn Insert Function rồi chọn GetDiskSN (tức công thức cho cell là =GetDiskSN) thì sau khi hoàn tất bạn có 3 dòng số.

Như vậy Excel đã gọi hàm GetDiskSN 3 lần khi bạn nhập công thức vào cell. Điều này chứng tỏ số lần gọi hàm dính dáng tới chuyện "làm mới", "tính toán" của bảng tính.
Trong 2 th đầu hàm chỉ được gọi 1 lần vì nó chả dính dáng gì tới bảng tính cả.
 
Lần chỉnh sửa cuối:
Cái này không liên quan gì tới WMI
Không phải là vòng lặp For được lặp lại 3 lần mà hàm được gọi 3 lần.
1.Mình đã làm theo hướng dẫn, và kết quả đúng như ý của bạn. Khi insert vào sheet, hàm"bị" excel gọi 3 lần. Nhờ câu lệnh Debug.Print ta mới biết được. Xưa nay dùng hàm giờ mới biết. Cám ơn bạn nhiều.
2. Vấn đề mình nêu ra hoàn toàn khác. Mấu chốt ở câu lệnh: For Each objItem...Vòng lặp này gọi từng objItem của máy. Mỗi obj tương ứng với 1 ổ cứng. ( Không biết nó còn tương ứng với phần cứng nào nữa không?)Vòng For Each...Next này chỉ lặp 3 lần, có nghĩa nó chỉ lấy thông số của 3 ổ cứng. Trường hợp máy có nhiều hơn 3 ổ cứng thì sao? Tiếc là mình không có điều kiện để test trường hợp này.
 
1.Mình đã làm theo hướng dẫn, và kết quả đúng như ý của bạn. Khi insert vào sheet, hàm"bị" excel gọi 3 lần. Nhờ câu lệnh Debug.Print ta mới biết được. Xưa nay dùng hàm giờ mới biết. Cám ơn bạn nhiều.
2. Vấn đề mình nêu ra hoàn toàn khác. Mấu chốt ở câu lệnh: For Each objItem...Vòng lặp này gọi từng objItem của máy. Mỗi obj tương ứng với 1 ổ cứng. ( Không biết nó còn tương ứng với phần cứng nào nữa không?)Vòng For Each...Next này chỉ lặp 3 lần, có nghĩa nó chỉ lấy thông số của 3 ổ cứng. Trường hợp máy có nhiều hơn 3 ổ cứng thì sao? Tiếc là mình không có điều kiện để test trường hợp này.

Từ đâu bạn biết là nó chỉ lấy thông số của 3 ổ cứng? Bạn đã thử với 4, 5, 6 ổ chưa mà kết luận là nó chỉ lấy thông số của 3 ổ cứng?
Mà bạn nói FOR lặp 3 lần là không đúng. Vòng lặp FOR của tôi chỉ lặp có 2 lần thôi.- tôi đặt Debug.Print tmp ngay sau dòng For Each và chỉ có 2 dòng (tôi chỉ có 1 ổ cứng) - dòng serial và dòng có nội dung Null. Tôi nghĩ là nó sẽ lặp cho tất cả các Item trong Collection mà phương thức ExecQuery trả về. Tức có bao nhiêu đĩa thì trả về bấy nhiêu.
Còn chuyện 1, 2, 3, 4 đĩa thì tìm hiểu thêm. Nếu tôi không lầm thì không phải muốn mua và cài thêm bao nhiêu đĩa cũng được.
Và nếu thế thì con số 3, 4 không phải là nó không muốn làm thêm mà nó biết là system không phục vụ, không cho phép lắp nhiều đĩa hơn. Tôi nhấn mạnh "Và nếu thế".
 
Từ đâu bạn biết là nó chỉ lấy thông số của 3 ổ cứng? Bạn đã thử với 4, 5, 6 ổ chưa mà kết luận là nó chỉ lấy thông số của 3 ổ cứng?
Vì mình test trên máy mình, dù có 1 hay 2 ổ cứng, vòng For...luôn lặp lại 3 lần. Từ đó suy ra vòng lặp này có bước lặp cố định ( không phụ thuộc vào các Item trong Collection). Máy bạn có 1 ổ cứng mà nó lặp 2 lần, rõ ràng không phụ thuộc vào các Item do phương thức ExecQ trả về.
Mà bạn nói FOR lặp 3 lần là không đúng. Vòng lặp FOR của tôi chỉ lặp có 2 lần thôi.- tôi đặt Debug.Print tmp ngay sau dòng For Each và chỉ có 2 dòng (tôi chỉ có 1 ổ cứng) - dòng serial và dòng có nội dung Null. Tôi nghĩ là nó sẽ lặp cho tất cả các Item trong Collection mà phương thức ExecQuery trả về. Tức có bao nhiêu đĩa thì trả về bấy nhiêu.
Bạn nên đặt tmp = objItem.SerialNumber trước dòng Debug.Print tmp, mới có kết quả chính xác. Nếu lệnh Debug.Print tmp đặt trước sẽ cho một dòng trống đầu tiên. Nên kết quả chỉ còn 2 dòng
 
Vì mình test trên máy mình, dù có 1 hay 2 ổ cứng, vòng For...luôn lặp lại 3 lần. Từ đó suy ra vòng lặp này có bước lặp cố định ( không phụ thuộc vào các Item trong Collection). Máy bạn có 1 ổ cứng mà nó lặp 2 lần, rõ ràng không phụ thuộc vào các Item do phương thức ExecQ trả về.
Bạn nên đặt tmp = objItem.SerialNumber trước dòng Debug.Print tmp, mới có kết quả chính xác. Nếu lệnh Debug.Print tmp đặt trước sẽ cho một dòng trống đầu tiên. Nên kết quả chỉ còn 2 dòng
Tôi viết nhầm. Tôi đặt ngay sau tmp = objItem.SerialNumber, vì đặt trong IF thì nó bỏ những Item không là String.
Và tôi được serial và Null
Bạn không cho Null cũng là Item à? Thế thì bạn hiểu sai. Null cũng là 1 Item. Còn chuyện tại sao hàm trả về thì lại chuyện khác. Tóm lại tôi chỉ có 2 vòng lặp = 1 serial + Null. Bạn có 3 vòng do bạn có 2 đĩa, 2 serial + Null. Đâu cứ phải luôn có 3 vòng lặp?

Bạn chú ý nhé. Tôi viết 1 dòng serial + 1 dòng Null nghĩa là 1 dòng có giá trị serial và 1 dòng có giá trị Null, chứ không phải dòng trống đâu nhé. Serial là 1 item và Null là 1 item.

Tôi luôn kiểm nghiệm trước, mắt thấy, có chứng cớ tôi mới viết. Vì đó là văn hóa tối thiểu trong tranh luận.
Tôi chỉ có 2 vòng lặp chứ không phải luôn là 3, như hình đính kèm.
 
Lần chỉnh sửa cuối:
Sao lạ thế này!!!




4d0ec78f.jpg


Nguyên văn bởi siwtom
Bạn không cho Null cũng là Item à? Thế thì bạn hiểu sai. Null cũng là 1 Item. Còn chuyện tại sao hàm trả về thì lại chuyện khác. Tóm lại tôi chỉ có 2 vòng lặp = 1 serial + Null. Bạn có 3 vòng do bạn có 2 đĩa, 2 serial + Null. Đâu cứ phải luôn có 3 vòng lặp?
Bạn chú ý nhé. Tôi viết 1 dòng serial + 1 dòng Null nghĩa là 1 dòng có giá trị serial và 1 dòng có giá trị Null, chứ không phải dòng trống đâu nhé. Serial là 1 item và Null là 1 item.
Item là do nói tắt thôi, đúng là ObjItem. Vòng lặp duyệt qua từng Object ( đĩa cứng). Null là một giá trị không thế là objitem được. Bạn nói "Null cũng là 1 Item" và " 1 dòng có giá trị Null. Như thế có mâu thuẫn không?
 
Lần chỉnh sửa cuối:
Sao lạ thế này!!!




4d0ec78f.jpg



Item là do nói tắt thôi, đúng là ObjItem. Vòng lặp duyệt qua từng Object ( đĩa cứng). Null là một giá trị không thế là objitem được. Bạn nói "Null cũng là 1 Item" và " 1 dòng có giá trị Null. Như thế có mâu thuẫn không?

Bạn buồn cười thật. Tôi không dùng "objitem" mà dùng "item" với nghĩa tiếng Anh là "khoản", "mục", "món"
Bây giờ bạn cố gán cho tôi là ý tôi muốn nói tới "objitem" rồi "trừng mất": "Null là một giá trị không thế là objitem (hàm ý object?)"
Bạn a, bạn có thấy là FOR của tôi được lặp 2 chứ không phải 3 lần? Thế là đủ, vì tranh luận chỉ về vấn đề này.
Tôi không có thời gian và hứng để đôi co, chầy bửa, bới bèo ra bọ.
Qua một loạt bài tôi chỉ muốn nói là FOR của tôi được lặp 2 lần chứ không phải là luôn luôn 3 lần.
Chấm hết. Tôi sẽ không viết gì nữa vì chỉ mất thời gian thôi chứ chả có ích gì nữa. Bạn thích thì xin mời.
 
Bạn đã nói thế thì mình chấm dứt ở đây. Bài trên, bạn đã hiểu nhầm ý mình. Mình không gán cho bạn cái gì cả bởi vì gán là không thực tâm, ý đồ không tốt. Mình cũng hiểu nghĩa chung của item là "khoản", "mục", "món". Nhưng chữ này luôn có nghĩa cụ thể khi dùng trong hoàn cảnh cụ thể. Trong trường hợp này, "khoản", "mục" , "món" đó là Object, là ổ cứng. Bây giờ mình vẫn hiểu như vây. Nói thế để bạn thấy mình không có ý đồ gì ngoài việc trao đổi học tập khi tranh luận. Tranh luận trong thế giới ảo này dễ gây hiểu nhầm vì chỉ viết và đọc thôi, không nghe được giọng nói, nhìn được cử chỉ và hiểu cá tính của nhau. Thôi mình kết ở đây vậy.
 
Lần chỉnh sửa cuối:

Bài viết mới nhất

Back
Top Bottom