If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. |
|
|
|
Thread Tools | Display Modes |
#1
|
|||
|
|||
Get the Serial Number with Visual Basic
Hi folks,
I have to write a Visual Basic 6.0 Program and need to uniquely identify a computer in a network and the user mustn't be able to change that id while my program is running. So the Volume Serial Number of the HDD isn't a possibility, because you can set the Volume SN whatever you want and therefore it's not unique in a Network. I heard that there's a manufacturer's Serial Number on the HDD that can't be changed and that is unique (worldwide?). How can I get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? Thanks a lot in advance, Michael PS: Answer in German is ok. |
#2
|
|||
|
|||
On Thu, 13 Nov 2003 13:38:13 +0100, "Michael Wittmann"
wrote: Hi folks, I have to write a Visual Basic 6.0 Program and need to uniquely identify a computer in a network and the user mustn't be able to change that id while my program is running. So the Volume Serial Number of the HDD isn't a possibility, because you can set the Volume SN whatever you want and therefore it's not unique in a Network. I heard that there's a manufacturer's Serial Number on the HDD that can't be changed and that is unique (worldwide?). How can I get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? I've tried the Disk Serial number stuff, I think it is called SMART - it does not work on one of my older disks You could get the MAC address from the network card - the API seems to be GetAdaptersInfo - but it requires Win98+ or W2k+ (info in the downloadable API Guide from www.AllAPI.net ) Personally I am not so sure about this 'unique' hardware stuff To me the only thing that is 'unique' is something that I issue, and I *never* issue more than one of them You only seem to be worried about keeping it 'unique' while your App is running - this makes things simpler - the 'unique' ID is unique to the session Cannot you request a unique ID from a server when your App starts - the server dishes up a 'number' which it will never dish up again For security, I would also use an additional sequence number Yet again, I would be inclined to go for a longer term 'unique naming' approach - the 'client' requests a unique ID - the server gives one - that remains with the Client for life - along with a Client and Server sequence number Should the Client be cloned, then the sequence numbers are guaranteed to fail - which is a pretty good indicator that something fishy is going on - also - just one of the clients will be able to continue IMO tying a stream of transactions is safer if it is tied to data - hardware can change - but your server will never issue the same code twice However here is the code I snipped some time ago for SMART - credits unknown - also ignore the stuff about the FSO A small snippet in a Form and a monster in a .BAS module ======== STUFF IN FORM ========== Option Explicit Private Sub Command1_Click() Dim drv_info As DRIVE_INFO drv_info = GetDriveInfo(0) With drv_info If .bDriveType = 0 Then Label1.Caption = "[Not present]" If .bDriveType = 2 Then Label1.Caption = "[ATAPI drive - info not available]" If .bDriveType = 1 Then Label1.Caption = Trim(.SerialNumber) End If End With End Sub ====== STUFF IN .BAS MODULE ======= ' 20th July 2002 from NG ' Works for Drive 0 - not 1 'Hi, ' 'Most hard disks sold in the last few years support SMART (Self-Monitoring, 'Analysis, and Reporting Technology) using Microsoft scripting you can use 'this to return the hard disk physical serial number, NOT the volume serial 'number. This will not change with a reformat, re-install of OS etc, etc. It 'will ONLY change if you replace the hard disk. ' 'To do this, use add a reference for Microsoft Scripting Runtime. ' 'Add the following to a .bas module (this was assembled from MSDN online 'somewhere...) '********************START OF BAS MODULE******************** Option Explicit Private Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 End Type Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (LpVersionInformation As OSVERSIONINFO) As Long 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 Public 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 Public Enum IDE_DRIVE_NUMBER PRIMARY_MASTER PRIMARY_SLAVE SECONDARY_MASTER SECONDARY_SLAVE End Enum Private Declare Function CreateFile _ Lib "kernel32" Alias "CreateFileA" _ (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, _ 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, _ ByVal lpOverlapped As Long) As Long Public Declare Sub CopyMemory _ Lib "kernel32" _ Alias "RtlMoveMemory" (Destination As Any, _ Source As Any, ByVal Length As Long) 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 FILE_ATTRIBUTE_SYSTEM = &H4 Private Const CREATE_NEW = 1 Private Const INVALID_HANDLE_VALUE = -1 Dim di As DRIVE_INFO Public Const MAX_IDE_DRIVES = 4 ' // Max number of drives assuming primary/secondary, master/slave topology Public Const READ_ATTRIBUTE_BUFFER_SIZE = 512 Public Const IDENTIFY_BUFFER_SIZE = 512 Public Const READ_THRESHOLD_BUFFER_SIZE = 512 Public Const OUTPUT_DATA_SIZE = IDENTIFY_BUFFER_SIZE + 16 'IOCTL commands Public Const DFP_GET_VERSION = &H74080 Public Const DFP_SEND_DRIVE_COMMAND = &H7C084 Public Const DFP_RECEIVE_DRIVE_DATA = &H7C088 '--------------------------------------------------------------------- ' GETVERSIONOUTPARAMS contains the data returned from the ' Get Driver Version function. '--------------------------------------------------------------------- Public 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 'Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS Public Const CAP_IDE_ID_FUNCTION = 1 ' ATA ID command supported Public Const CAP_IDE_ATAPI_ID = 2 ' ATAPI ID command supported Public Const CAP_IDE_EXECUTE_SMART_FUNCTION = 4 ' SMART commannds supported '--------------------------------------------------------------------- ' IDE registers '--------------------------------------------------------------------- Public 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. '--------------------------------------------------------------------- Public 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. Public Const IDE_ATAPI_ID = &HA1 ' Returns ID sector for ATAPI. Public Const IDE_ID_FUNCTION = &HEC ' Returns ID sector for ATA. Public Const IDE_EXECUTE_SMART_FUNCTION = &HB0 ' Performs SMART cmd. ' Requires valid bFeaturesReg, ' bCylLowReg, and bCylHighReg ' Cylinder register values required when issuing SMART command Public Const SMART_CYL_LOW = &H4F Public Const SMART_CYL_HI = &HC2 '--------------------------------------------------------------------- ' Status returned from driver '--------------------------------------------------------------------- Public 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 ' bDriverError values Public Enum DRIVER_ERRORS SMART_NO_ERROR = 0 ' No error SMART_IDE_ERROR = 1 ' Error from IDE controller SMART_INVALID_FLAG = 2 ' Invalid command flag SMART_INVALID_COMMAND = 3 ' Invalid command byte SMART_INVALID_BUFFER = 4 ' Bad buffer (null, invalid addr..) SMART_INVALID_DRIVE = 5 ' Drive number not valid SMART_INVALID_IOCTL = 6 ' Invalid IOCTL SMART_ERROR_NO_MEM = 7 ' Could not lock user's buffer SMART_INVALID_REGISTER = 8 ' Some IDE Register not valid SMART_NOT_SUPPORTED = 9 ' Invalid cmd flag set SMART_NO_IDE_DEVICE = 10 ' Cmd issued to device not present ' although drive number is valid ' 11-255 reserved End Enum '--------------------------------------------------------------------- ' The following struct defines the interesting part of the IDENTIFY ' buffer: '--------------------------------------------------------------------- Public 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 for several commands '--------------------------------------------------------------------- Public Type SENDCMDOUTPARAMS cBufferSize As Long ' Size of bBuffer in bytes(IDENTIFY_BUFFER_SIZE in our case) DRIVERSTATUS As DRIVERSTATUS ' Driver status structure. bBuffer() As Byte ' Buffer of arbitrary length in which to store the data read from the drive. End Type '--------------------------------------------------------------------- ' Feature register defines for SMART "sub commands" '--------------------------------------------------------------------- Public Const SMART_READ_ATTRIBUTE_VALUES = &HD0 Public Const SMART_READ_ATTRIBUTE_THRESHOLDS = &HD1 Public Const SMART_ENABLE_DISABLE_ATTRIBUTE_AUTOSAVE = &HD2 Public Const SMART_SAVE_ATTRIBUTE_VALUES = &HD3 Public Const SMART_EXECUTE_OFFLINE_IMMEDIATE = &HD4 ' Vendor specific commands: Public Const SMART_ENABLE_SMART_OPERATIONS = &HD8 Public Const SMART_DISABLE_SMART_OPERATIONS = &HD9 Public Const SMART_RETURN_SMART_STATUS = &HDA '--------------------------------------------------------------------- ' The following structure defines the structure of a Drive Attribute '--------------------------------------------------------------------- Public Const NUM_ATTRIBUTE_STRUCTS = 30 Public Type DRIVEATTRIBUTE bAttrID As Byte ' Identifies which attribute wStatusFlags As Integer 'Integer ' see bit definitions below bAttrValue As Byte ' Current normalized value bWorstValue As Byte ' How bad has it ever been? bRawValue(5) As Byte ' Un-normalized value bReserved As Byte ' ... End Type '--------------------------------------------------------------------- ' 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 '--------------------------------------------------------------------- ' The following structure defines the structure of a Warranty Threshold ' Obsoleted in ATA4! '-------------------------------------------------------------------- Public Type ATTRTHRESHOLD bAttrID As Byte ' Identifies which attribute bWarrantyThreshold As Byte ' Triggering value bReserved(9) As Byte ' ... End Type '--------------------------------------------------------------------- ' Valid Attribute IDs '--------------------------------------------------------------------- Public Enum ATTRIBUTE_ID ATTR_INVALID = 0 ATTR_READ_ERROR_RATE = 1 ATTR_THROUGHPUT_PERF = 2 ATTR_SPIN_UP_TIME = 3 ATTR_START_STOP_COUNT = 4 ATTR_REALLOC_SECTOR_COUNT = 5 ATTR_READ_CHANNEL_MARGIN = 6 ATTR_SEEK_ERROR_RATE = 7 ATTR_SEEK_TIME_PERF = 8 ATTR_POWER_ON_HRS_COUNT = 9 ATTR_SPIN_RETRY_COUNT = 10 ATTR_CALIBRATION_RETRY_COUNT = 11 ATTR_POWER_CYCLE_COUNT = 12 ATTR_SOFT_READ_ERROR_RATE = 13 ATTR_G_SENSE_ERROR_RATE = 191 ATTR_POWER_OFF_RETRACT_CYCLE = 192 ATTR_LOAD_UNLOAD_CYCLE_COUNT = 193 ATTR_TEMPERATURE = 194 ATTR_REALLOCATION_EVENTS_COUNT = 196 ATTR_CURRENT_PENDING_SECTOR_COUNT = 197 ATTR_UNCORRECTABLE_SECTOR_COUNT = 198 ATTR_ULTRADMA_CRC_ERROR_RATE = 199 ATTR_WRITE_ERROR_RATE = 200 ATTR_DISK_SHIFT = 220 ATTR_G_SENSE_ERROR_RATEII = 221 ATTR_LOADED_HOURS = 222 ATTR_LOAD_UNLOAD_RETRY_COUNT = 223 ATTR_LOAD_FRICTION = 224 ATTR_LOAD_UNLOAD_CYCLE_COUNTII = 225 ATTR_LOAD_IN_TIME = 226 ATTR_TORQUE_AMPLIFICATION_COUNT = 227 ATTR_POWER_OFF_RETRACT_COUNT = 228 ATTR_GMR_HEAD_AMPLITUDE = 230 ATTR_TEMPERATUREII = 231 ATTR_READ_ERROR_RETRY_RATE = 250 End Enum Dim colAttrNames As Collection '************************************************* ************************** ' Open SMART to allow DeviceIoControl communications. Return SMART handle '************************************************* ************************** Private Function OpenSmart(drv_num As IDE_DRIVE_NUMBER) As Long If IsWindowsNT Then OpenSmart = CreateFile("\\.\PhysicalDrive" _ & CStr(drv_num), _ GENERIC_READ Or GENERIC_WRITE, _ FILE_SHARE_READ Or FILE_SHARE_WRITE, _ ByVal 0&, OPEN_EXISTING, 0, 0) Else OpenSmart = CreateFile("\\.\SMARTVSD", _ 0, 0, ByVal 0&, CREATE_NEW, 0, 0) End If End Function '************************************************* ************************** ' CheckSMARTEnable - Check if SMART enable ' FUNCTION: Send a SMART_ENABLE_SMART_OPERATIONS command to the drive ' bDriveNum = 0-3 '************************************************* ************************** Private Function CheckSMARTEnable(ByVal hDrive As Long, _ DriveNum As IDE_DRIVE_NUMBER) As Boolean 'Set up data structures for Enable SMART Command. Dim SCIP As SENDCMDINPARAMS Dim SCOP As SENDCMDOUTPARAMS Dim lpcbBytesReturned 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 'Compute the drive number. .bDriveHeadReg = &HA0 ' Or (DriveNum And 1) * 16 .bCommandReg = IDE_EXECUTE_SMART_FUNCTION End With .bDriveNumber = DriveNum End With CheckSMARTEnable = DeviceIoControl(hDrive, _ DFP_SEND_DRIVE_COMMAND, SCIP, _ Len(SCIP) - 4, _ SCOP, Len(SCOP) - 4, lpcbBytesReturned, ByVal 0&) End Function '************************************************* ************************** ' DoIdentify ' Function: Send an IDENTIFY command to the drive ' DriveNum = 0-3 ' IDCmd = IDE_ID_FUNCTION or IDE_ATAPI_ID '************************************************* ************************** Private Function IdentifyDrive(ByVal hDrive As Long, _ ByVal IDCmd As Byte, _ ByVal DriveNum As IDE_DRIVE_NUMBER) As Boolean Dim SCIP As SENDCMDINPARAMS Dim IDSEC As IDSECTOR Dim bArrOut(OUTPUT_DATA_SIZE - 1) As Byte Dim sMsg As String Dim lpcbBytesReturned As Long Dim barrfound(100) As Long Dim i As Long Dim lng As Long ' Set up data structures for IDENTIFY command. With SCIP .cBufferSize = IDENTIFY_BUFFER_SIZE .bDriveNumber = CByte(DriveNum) With .irDriveRegs .bFeaturesReg = 0 .bSectorCountReg = 1 .bSectorNumberReg = 1 .bCylLowReg = 0 .bCylHighReg = 0 ' Compute the drive number. .bDriveHeadReg = &HA0 If Not IsWindowsNT Then _ .bDriveHeadReg = .bDriveHeadReg _ Or (DriveNum And 1) * 16 ' 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, _ lpcbBytesReturned, ByVal 0&) Then IdentifyDrive = True CopyMemory IDSEC, bArrOut(16), Len(IDSEC) di.Model = SwapStringBytes(StrConv(IDSEC.sModelNumber, vbUnicode)) di.FirmWare = SwapStringBytes(StrConv(IDSEC.sFirmwareRev, vbUnicode)) di.SerialNumber = SwapStringBytes(StrConv(IDSEC.sSerialNumber, vbUnicode)) di.Cilinders = IDSEC.wNumCyls di.Heads = IDSEC.wNumHeads di.SecPerTrack = IDSEC.wSectorsPerTrack End If End Function '************************************************* ************************** ' ReadAttributesCmd ' FUNCTION: Send a SMART_READ_ATTRIBUTE_VALUES command to the drive ' bDriveNum = 0-3 '************************************************* ************************** Private Function ReadAttributesCmd(ByVal hDrive As Long, _ DriveNum As IDE_DRIVE_NUMBER) As Boolean Dim cbBytesReturned As Long Dim SCIP As SENDCMDINPARAMS Dim drv_attr As DRIVEATTRIBUTE Dim bArrOut(OUTPUT_DATA_SIZE - 1) As Byte Dim sMsg As String Dim i As Long With SCIP ' Set up data structures for Read Attributes SMART Command. .cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE .bDriveNumber = DriveNum With .irDriveRegs .bFeaturesReg = SMART_READ_ATTRIBUTE_VALUES .bSectorCountReg = 1 .bSectorNumberReg = 1 .bCylLowReg = SMART_CYL_LOW .bCylHighReg = SMART_CYL_HI ' Compute the drive number. .bDriveHeadReg = &HA0 If Not IsWindowsNT Then _ .bDriveHeadReg = .bDriveHeadReg Or _ (DriveNum And 1) * 16 .bCommandReg = IDE_EXECUTE_SMART_FUNCTION End With End With ReadAttributesCmd = DeviceIoControl(hDrive, DFP_RECEIVE_DRIVE_DATA, _ SCIP, Len(SCIP) - 4, _ bArrOut(0), _ OUTPUT_DATA_SIZE, _ cbBytesReturned, ByVal 0&) On Error Resume Next For i = 0 To NUM_ATTRIBUTE_STRUCTS - 1 If bArrOut(18 + i * 12) 0 Then di.Attributes(di.NumAttributes).AttrID = bArrOut(18 + i * 12) di.Attributes(di.NumAttributes).AttrName _ = "Unknown value (" & bArrOut(18 + i * 12) & ")" ' di.Attributes(di.NumAttributes).AttrName = colAttrNames (CStr(bArrOut(18 + i * 12))) di.NumAttributes = di.NumAttributes + 1 ReDim Preserve di.Attributes(di.NumAttributes) CopyMemory di.Attributes(di.NumAttributes).StatusFlags, _ bArrOut(19 + i * 12), 2 di.Attributes(di.NumAttributes).AttrValue = bArrOut(21 + i * 12) di.Attributes(di.NumAttributes).WorstValue = bArrOut(22 + i * 12) End If Next i End Function Private Function ReadThresholdsCmd(ByVal hDrive As Long, _ DriveNum As IDE_DRIVE_NUMBER) As Boolean Dim cbBytesReturned As Long Dim SCIP As SENDCMDINPARAMS Dim IDSEC As IDSECTOR Dim bArrOut(OUTPUT_DATA_SIZE - 1) As Byte Dim sMsg As String Dim thr_attr As ATTRTHRESHOLD Dim i As Long, j As Long With SCIP ' Set up data structures for Read Attributes SMART Command. .cBufferSize = READ_THRESHOLD_BUFFER_SIZE .bDriveNumber = DriveNum With .irDriveRegs .bFeaturesReg = SMART_READ_ATTRIBUTE_THRESHOLDS .bSectorCountReg = 1 .bSectorNumberReg = 1 .bCylLowReg = SMART_CYL_LOW .bCylHighReg = SMART_CYL_HI ' Compute the drive number. .bDriveHeadReg = &HA0 If Not IsWindowsNT Then _ .bDriveHeadReg = .bDriveHeadReg Or _ (DriveNum And 1) * 16 .bCommandReg = IDE_EXECUTE_SMART_FUNCTION End With End With ReadThresholdsCmd = DeviceIoControl(hDrive, _ DFP_RECEIVE_DRIVE_DATA, SCIP, _ Len(SCIP) - 4, bArrOut(0), _ OUTPUT_DATA_SIZE, cbBytesReturned, ByVal 0&) For i = 0 To NUM_ATTRIBUTE_STRUCTS - 1 CopyMemory thr_attr, bArrOut(18 + i * Len(thr_attr)), Len(thr_attr) If thr_attr.bAttrID 0 Then For j = 0 To UBound(di.Attributes) If thr_attr.bAttrID = di.Attributes(j).AttrID Then di.Attributes(j).ThresholdValue = thr_attr.bWarrantyThreshold Exit For End If Next j End If Next i End Function Private Function GetSmartVersion(ByVal hDrive As Long, VersionParams As GETVERSIONOUTPARAMS) As Boolean Dim cbBytesReturned As Long GetSmartVersion = DeviceIoControl(hDrive, _ DFP_GET_VERSION, ByVal 0&, 0, _ VersionParams, _ Len(VersionParams), _ cbBytesReturned, ByVal 0&) End Function Public Function GetDriveInfo(DriveNum As IDE_DRIVE_NUMBER) As DRIVE_INFO Dim hDrive As Long Dim VerParam As GETVERSIONOUTPARAMS Dim cb As Long di.bDriveType = 0 di.NumAttributes = 0 ReDim di.Attributes(0) hDrive = OpenSmart(DriveNum) If hDrive = INVALID_HANDLE_VALUE Then Exit Function If Not GetSmartVersion(hDrive, VerParam) Then Exit Function If Not IsBitSet(VerParam.bIDEDeviceMap, DriveNum) Then Exit Function di.bDriveType = 1 + Abs(IsBitSet(VerParam.bIDEDeviceMap, DriveNum + 4)) If Not CheckSMARTEnable(hDrive, DriveNum) Then Exit Function FillAttrNameCollection Call IdentifyDrive(hDrive, IDE_ID_FUNCTION, DriveNum) Call ReadAttributesCmd(hDrive, DriveNum) Call ReadThresholdsCmd(hDrive, DriveNum) GetDriveInfo = di CloseHandle hDrive Set colAttrNames = Nothing End Function Private Function IsWindowsNT() As Boolean Dim verinfo As OSVERSIONINFO verinfo.dwOSVersionInfoSize = Len(verinfo) If (GetVersionEx(verinfo)) = 0 Then Exit Function If verinfo.dwPlatformId = 2 Then IsWindowsNT = True End Function Private Function IsBitSet(iBitString As Byte, ByVal lBitNo As Integer) As Boolean If lBitNo = 7 Then IsBitSet = iBitString 0 Else IsBitSet = iBitString And (2 ^ lBitNo) End If End Function Private Function SwapStringBytes(ByVal sIn As String) As String Dim sTemp As String Dim i As Integer sTemp = Space(Len(sIn)) For i = 1 To Len(sIn) - 1 Step 2 Mid(sTemp, i, 1) = Mid(sIn, i + 1, 1) Mid(sTemp, i + 1, 1) = Mid(sIn, i, 1) Next i SwapStringBytes = sTemp End Function Public Sub FillAttrNameCollection() Set colAttrNames = New Collection With colAttrNames .Add "ATTR_INVALID", "0" .Add "READ_ERROR_RATE", "1" .Add "THROUGHPUT_PERF", "2" .Add "SPIN_UP_TIME", "3" .Add "START_STOP_COUNT", "4" .Add "REALLOC_SECTOR_COUNT", "5" .Add "READ_CHANNEL_MARGIN", "6" .Add "SEEK_ERROR_RATE", "7" .Add "SEEK_TIME_PERF", "8" .Add "POWER_ON_HRS_COUNT", "9" .Add "SPIN_RETRY_COUNT", "10" .Add "CALIBRATION_RETRY_COUNT", "11" .Add "POWER_CYCLE_COUNT", "12" .Add "SOFT_READ_ERROR_RATE", "13" .Add "G_SENSE_ERROR_RATE", "191" .Add "POWER_OFF_RETRACT_CYCLE", "192" .Add "LOAD_UNLOAD_CYCLE_COUNT", "193" .Add "TEMPERATURE", "194" .Add "REALLOCATION_EVENTS_COUNT", "196" .Add "CURRENT_PENDING_SECTOR_COUNT", "197" .Add "UNCORRECTABLE_SECTOR_COUNT", "198" .Add "ULTRADMA_CRC_ERROR_RATE", "199" .Add "WRITE_ERROR_RATE", "200" .Add "DISK_SHIFT", "220" .Add "G_SENSE_ERROR_RATEII", "221" .Add "LOADED_HOURS", "222" .Add "LOAD_UNLOAD_RETRY_COUNT", "223" .Add "LOAD_FRICTION", "224" .Add "LOAD_UNLOAD_CYCLE_COUNTII", "225" .Add "LOAD_IN_TIME", "226" .Add "TORQUE_AMPLIFICATION_COUNT", "227" .Add "POWER_OFF_RETRACT_COUNT", "228" .Add "GMR_HEAD_AMPLITUDE", "230" .Add "TEMPERATUREII", "231" .Add "READ_ERROR_RETRY_RATE", "250" End With End Sub '********************END OF BAS MODULE******************** 'In the example assume a label called label2 on a form, could easily be a 'string etc etc.... 'Add the following to your code: ' Dim drv_info As DRIVE_INFO ' ' drv_info = GetDriveInfo(0) ' With drv_info ' If .bDriveType = 0 Then Label2.Caption = "[Not present]" ' If .bDriveType = 2 Then Label2.Caption = "[ATAPI drive - info not available]" ' If .bDriveType = 1 Then ' Label2.Caption = Trim(.SerialNumber) ' End If ' End With ' 'Label2 will display the actual physical serial number of the drive, NOT the 'volume number. |
#3
|
|||
|
|||
"Michael Wittmann" wrote in message
... Hi folks, I have to write a Visual Basic 6.0 Program and need to uniquely identify a computer in a network and the user mustn't be able to change that id while my program is running. So the Volume Serial Number of the HDD isn't a possibility, because you can set the Volume SN whatever you want and therefore it's not unique in a Network. I heard that there's a manufacturer's Serial Number on the HDD that can't be changed and that is unique (worldwide?). How can I get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? What's wrong with the NIC's MAC address? @drian. |
#4
|
|||
|
|||
What's wrong with the NIC's MAC address?
There might be also single stations using my program... There's not always a network card in the workstation Michael PS: Answer only to the newsgroup you read (some people already complained) |
#5
|
|||
|
|||
"Michael Wittmann" wrote in message ... | What's wrong with the NIC's MAC address? | There might be also single stations using my program... There's not always a | network card in the workstation | Make them buy a NIC then. There are plenty of workstations were you cannot get a disk serial number. RAID and poor IDE drivers. |
#6
|
|||
|
|||
On Thu, 13 Nov 2003 13:38:13 +0100, "Michael Wittmann"
wrote:: Hi folks, I have to write a Visual Basic 6.0 Program and need to uniquely identify a computer in a network and the user mustn't be able to change that id while my program is running. So the Volume Serial Number of the HDD isn't a possibility, because you can set the Volume SN whatever you want and therefore it's not unique in a Network. I heard that there's a manufacturer's Serial Number on the HDD that can't be changed and that is unique (worldwide?). How can I get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? Thanks a lot in advance, Michael PS: Answer in German is ok. What about a software solution? As you're using VB, I guess it's for windows systems. Under normal operating conditions, windows will lock out file write access to all other apps if it's currently in use. While not efficient, and not terribly secure, it will hamper modification attempts so long as the program's running. Just code your app to open a filestream to the serial number file, and keep it open until the app closes. Just be sure to have clean up code in place, as leaving it up to the OS can cause problems -- especially when we're talking VB, which is flakey already. As for uniqueness, that would be up to you to generate a unique serial number for each installation. If you want a hardware solution, there's the suggested MAC address which was previously mentioned, or if you know how to do it, you could have the program refuse to run unless the CPU ID feature is enabled. Of course, your users would probably have issue with that. ---------------------------------------- Thanks, MCheu |
#7
|
|||
|
|||
@drian schrieb:
"Michael Wittmann" wrote HDD that can't be changed and that is unique (worldwide?). How can I get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? What's wrong with the NIC's MAC address? It can be changed by the User easily and is therefore neither Unique nor secure. |
#8
|
|||
|
|||
"Michael Stum" wrote in message
... @drian schrieb: "Michael Wittmann" wrote HDD that can't be changed and that is unique (worldwide?). How can I get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? What's wrong with the NIC's MAC address? It can be changed by the User easily and is therefore neither Unique nor secure. The MAC address? The MAC address is a fixed, unique number embedded in the NIC. So how do you change the MAC on your NIC card? I'm interested. @drian. |
#9
|
|||
|
|||
"@drian" wrote in message
... The MAC address? The MAC address is a fixed, unique number embedded in the NIC. So how do you change the MAC on your NIC card? I'm interested. I'm thinking of cable modem's that have the difficult to change MAC address. @drian. |
#10
|
|||
|
|||
It isn't clear to me if you need a unique session ID number, or a =
permanent and unique ID number identifying the computer, but in the case = of sessions, you can use the CoCreateGuid API function to create a 128 = bit number which is assured to a high degree of probability to be = completely unique accross the world for now and in the future weather = networked or not. Howard Henry Schlunder "Michael Wittmann" wrote in message = ... Hi folks, =20 I have to write a Visual Basic 6.0 Program and need to uniquely = identify a computer in a network and the user mustn't be able to change that id = while my program is running. So the Volume Serial Number of the HDD isn't a = possibility, because you can set the Volume SN whatever you want and therefore it's = not unique in a Network. I heard that there's a manufacturer's Serial = Number on the HDD that can't be changed and that is unique (worldwide?). How can I = get that SN with VB6? Or do you have any other ideas? Like a BIOS SN? =20 Thanks a lot in advance, =20 Michael PS: Answer in German is ok. |
|
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Modem and other on same serial, alternately? | Rick | General | 4 | October 25th 03 06:13 PM |
USB, Parallel Scanner, Serial Joystick | The Kid | General | 2 | September 1st 03 04:38 AM |
serial to parallel adapter | Old guy | General | 2 | July 30th 03 11:11 PM |
Adding ten or so serial ports? | Paul Hutchings | General | 4 | July 23rd 03 08:54 AM |
KVM Switch for Both PS/2 and AT Connectors | Alien Zord | General | 5 | July 9th 03 07:19 PM |