Autor
|
Tema: Obtener número de serie de un disco físico (no volumen lógico) (Leído 5,538 veces)
|
bybaal
Desconectado
Mensajes: 52
|
Alguien me pudiera aclarar como se puede obtener el número de serie de un disco físico, también el modelo del disco.
OJO!!! Que sea usando la API de Windows y en VB
|
|
|
En línea
|
|
|
|
BlackZeroX
Wiki
Desconectado
Mensajes: 3.158
I'Love...!¡.
|
Alguien me pudiera aclarar como se puede obtener el número de serie de un disco físico, también el modelo del disco.
OJO!!! Que sea usando la API de Windows y en VB
GetVolumeInformationA function (fileapi.h) https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationaEncontré el uso en C/C++ solo tradúcelo y adáptalo a tus necesidades que tampoco creo en los foros se hagan encargos de codigo a modo. https://gist.github.com/micjabbour/a2fbe50160862e6abe439c0b0769c3fbLo modifique para listara los números de serie de todos los discos físicos instalados (es un asco como lo adapte, lo se jajajaja). #include <windows.h> #include <memory> #include <string> #include <iostream> #include <bitset> #include <vector> using namespace std; #define CTL_CODE(DeviceType, Function, Method, Access) \ (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) #define METHOD_BUFFERED 0 //returns the serial number of the first physical drive in a string or an empty string in case of failure //based on http://codexpert.ro/blog/2013/10/26/get-physical-drive-serial-number-part-1/ string getFirstHddSerialNumber(wchar_t *pDisk) { //get a handle to the first physical drive HANDLE h = CreateFileW(pDisk, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(h == INVALID_HANDLE_VALUE) return {}; //an unique_ptr is used to perform cleanup automatically when returning (i.e. to avoid code duplication) unique_ptr<remove_pointer<HANDLE>::type, void(*)(HANDLE)> hDevice{h, [](HANDLE handle){CloseHandle(handle);}}; //initialize a STORAGE_PROPERTY_QUERY data structure (to be used as input to DeviceIoControl) STORAGE_PROPERTY_QUERY storagePropertyQuery{}; storagePropertyQuery.PropertyId= StorageDeviceProperty; storagePropertyQuery.QueryType= PropertyStandardQuery; //initialize a STORAGE_DESCRIPTOR_HEADER data structure (to be used as output from DeviceIoControl) STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader{}; //the next call to DeviceIoControl retrieves necessary size (in order to allocate a suitable buffer) //call DeviceIoControl and return an empty string on failure DWORD dwBytesReturned= 0; if(!DeviceIoControl(hDevice.get(), IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL)) return {}; //allocate a suitable buffer const DWORD dwOutBufferSize= storageDescriptorHeader.Size; unique_ptr<BYTE[]> pOutBuffer{new BYTE[dwOutBufferSize]{}}; //call DeviceIoControl with the allocated buffer if(!DeviceIoControl(hDevice.get(), IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), pOutBuffer.get(), dwOutBufferSize, &dwBytesReturned, NULL)) return {}; //read and return the serial number out of the output buffer STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor= reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(pOutBuffer.get()); const DWORD dwSerialNumberOffset= pDeviceDescriptor->SerialNumberOffset; if(dwSerialNumberOffset==0) return {}; const char* serialNumber= reinterpret_cast<const char*>(pOutBuffer.get() + dwSerialNumberOffset); return serialNumber; } void printPhysicalDriversSerial() { bitset<32> drives(GetLogicalDrives()); vector<char> goodDrives; for (char c = 'A'; c <= 'Z'; ++c) { if (drives[c - 'A']) { //if (GetDriveType((c + string(":\\")).c_str()) == DRIVE_FIXED) { descomentar para solo obtener los Discos físicos internos. goodDrives.push_back(c); //} } } for (auto & drive : goodDrives) { string s = string("\\\\.\\") + drive + ":"; HANDLE h = CreateFileA( s.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS, NULL ); if (h == INVALID_HANDLE_VALUE) { cerr << "Drive " << drive << ":\\ cannot be opened" << endl; continue; } DWORD bytesReturned; VOLUME_DISK_EXTENTS vde; if (!DeviceIoControl( h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &bytesReturned, NULL )) { cerr << "Drive " << drive << ":\\ cannot be mapped into physical drive" << endl; continue; } for (int i = 0; i < vde.NumberOfDiskExtents; ++i) { wchar_t disk [MAX_PATH]; swprintf(disk, MAX_PATH, L"\\\\.\\PhysicalDrive%d", vde.Extents[i].DiskNumber); string serialNumber = getFirstHddSerialNumber(disk); fputws ( disk, stdout ); cout << endl; if(serialNumber.empty()) { cout << "failed to retrieve serial number" << endl; } else { cout << "serial number: " << serialNumber << endl; } } } } int main() { printPhysicalDriversSerial(); return 0; }
Para corroborar los datos pintados, ejecutar en CMD: wmic diskdrive get Name, Manufacturer, Model, InterfaceType, MediaType, SerialNumber Saludos.
|
|
« Última modificación: 3 Febrero 2021, 07:15 am por BlackZeroX (Astaroth) »
|
En línea
|
The Dark Shadow is my passion.
|
|
|
bybaal
Desconectado
Mensajes: 52
|
Buscando me he encontrado un código en vb6, pero me parece que no logró adaptarlo correctamente a vb.net, ya que me genera un error cuando se va a usar la api ZeroMemory Alguien que tenga alguna idea de que hay que corregir, ya que a mi no se me ocurre nada más Private Declare Auto Function CreateFile _ Lib "kernel32" Alias "CreateFileA" ( ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As Integer, ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As IntPtr ) As Integer Private Declare Auto Function CloseHandle _ Lib "kernel32" ( ByVal hObject As IntPtr ) As Integer Private Declare Auto Function DeviceIoControl _ Lib "kernel32" ( ByVal hDevice As IntPtr, ByVal dwIoControlCode As Integer, <MarshalAs(UnmanagedType.AsAny)> lpInBuffer As Object, ByVal nInBufferSize As Integer, <MarshalAs(UnmanagedType.AsAny)> lpOutBuffer As Object, ByVal nOutBufferSize As Integer, lpBytesReturned As Integer, ByVal lpOverlapped As Integer ) As Integer Private Declare Auto Sub ZeroMemory _ Lib "kernel32" Alias "RtlZeroMemory" ( <MarshalAs(UnmanagedType.AsAny)> dest As Object, ByVal numBytes As Integer) 'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Object, Source As Object, ByVal Length As Integer) Private Declare Auto Function GetLastError Lib "kernel32" () As Integer Private Const DFP_RECEIVE_DRIVE_DATA = &H7C088 Private Const FILE_SHARE_READ = &H1 Private Const FILE_SHARE_WRITE = &H2 Private Const GENERIC_READ = &H80000000 Private Const GENERIC_WRITE = &H40000000 Private Const OPEN_EXISTING = 3 Private Const CREATE_NEW = 1 Private Enum HDInfo HD_MODEL_NUMBER = 0 HD_SERIAL_NUMBER = 1 HD_FIRMWARE_REVISION = 2 End Enum Private Structure IDEREGS Public bFeaturesReg As Byte Public bSectorCountReg As Byte Public bSectorNumberReg As Byte Public bCylLowReg As Byte Public bCylHighReg As Byte Public bDriveHeadReg As Byte Public bCommandReg As Byte Public bReserved As Byte End Structure Private Structure SENDCMDINPARAMS Public cBufferSize As Integer Public irDriveRegs As IDEREGS Public bDriveNumber As Byte <VBFixedArray(1, 3)> Public bReserved() As Byte <VBFixedArray(1, 4)> Public dwReserved() As Integer End Structure Private Structure DRIVERSTATUS Public bDriveError As Byte Public bIDEStatus As Byte <VBFixedArray(1, 2)> Public bReserved() As Byte <VBFixedArray(1, 2)> Public dwReserved() As Integer End Structure Private Structure SENDCMDOUTPARAMS Public cBufferSize As Integer Public DStatus As DRIVERSTATUS <VBFixedArray(1, 512)> Public bBuffer() As Byte End Structure Private mvarCurrentDrive As Byte Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load MsgBox(GetHDDInfo(0, "serial")) End End Sub Public Function GetHDDInfo(ByVal Number As Byte, ByVal Cmd As String) As String mvarCurrentDrive = Number Select Case LCase(Cmd) Case "model" : GetHDDInfo = CmnGetHDData(HDInfo.HD_MODEL_NUMBER) Case "serial" : GetHDDInfo = CmnGetHDData(HDInfo.HD_SERIAL_NUMBER) Case "firmware" : GetHDDInfo = CmnGetHDData(HDInfo.HD_FIRMWARE_REVISION) Case Else : GetHDDInfo = "" End Select End Function Private Function CmnGetHDData(hdi As HDInfo) As String Dim Bin As SENDCMDINPARAMS Dim Bout As SENDCMDOUTPARAMS Dim hdh As Long Dim br As Long Dim Ix As Long Dim hddfr As Long Dim hddln As Long Dim S As String Select Case hdi Case HDInfo.HD_MODEL_NUMBER hddfr = 55 hddln = 40 Case HDInfo.HD_SERIAL_NUMBER hddfr = 21 hddln = 20 Case HDInfo.HD_FIRMWARE_REVISION hddfr = 47 hddln = 8 Case Else : Err. Raise(10001, "Illegal HD Data type") End Select hdh = CreateFile("\\.\PhysicalDrive" & mvarCurrentDrive, GENERIC_READ + GENERIC_WRITE, FILE_SHARE_READ + FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0) If hdh = 0 Then Err. Raise(10003, , "Error on CreateFile") ZeroMemory(Bin, Len(Bin)) ZeroMemory(Bout, Len(Bout)) With Bin .bDriveNumber = mvarCurrentDrive .cBufferSize = 512 With .irDriveRegs If (mvarCurrentDrive And 1) Then .bDriveHeadReg = &HB0 Else .bDriveHeadReg = &HA0 End If .bCommandReg = &HEC .bSectorCountReg = 1 .bSectorNumberReg = 1 End With End With DeviceIoControl(hdh, DFP_RECEIVE_DRIVE_DATA, Bin, Len(Bin), Bout, Len(Bout), br, 0) S = "" For Ix = hddfr To hddfr + hddln - 1 Step 2 If Bout.bBuffer(Ix + 1) = 0 Then Exit For S &= Chr(Bout.bBuffer(Ix + 1)) If Bout.bBuffer(Ix) = 0 Then Exit For S &= Chr(Bout.bBuffer(Ix)) Next Ix CloseHandle(hdh) CmnGetHDData = Trim(S) End Function
|
|
|
En línea
|
|
|
|
BlackZeroX
Wiki
Desconectado
Mensajes: 3.158
I'Love...!¡.
|
Puedes omitir el llamado de ZeroMemory* en VB .NET las variables ya se inicializan limpias* y no se ve que las uses entre la declaracion y la implementación de las mismas.
ZeroMemory La función ZeroMemory llena un bloque de memoria con ceros.
Sintaxis VOID ZeroMemory ( PVOID Destination, // puntero al bloque a llenar con ceros DWORD Length, // tamaño, en bytes, del bloque a llenar ); Parámetros Destination: puntero a la dirección de comienzo del bloque de memoria a llenar con ceros.
Length: especifica el tamaño, en bytes, del bloque de memoria a llenar con ceros.
Valor de retorno Esta función no tiene valor de retorno.
Saludos.
|
|
|
En línea
|
The Dark Shadow is my passion.
|
|
|
Serapis
|
Alguien me pudiera aclarar como se puede obtener el número de serie de un disco físico, también el modelo del disco.
OJO!!! Que sea usando la API de Windows y en VB
.NET es muy completo, no necesitas usar APIs... Si partes desde vb6, por ejemplo tiene sel objeto Scripting, que contiene la clase FilesystemObject, que a su vez contiene las clases Drives y Drive, para obtener datos de la unidad, si bien trae el SerialNumber (que los objetos Drive de .NET, no lo incorporan), tampoco trae el modelo de la unidad. Aquí una sopa de código para rescatar algunos datos desde diversas fuentes en .NET... Nota sin embargo que para usar el objeto Scripting tienes que agregar la referencia COM al proyecto, antes de instanciar y poder usarla... Al final, accedemos al registro, para rescatar los nombres de las unidades conectadas internamente, las conectadas externamente ('removibles') se acceden desde la clave 'UsbStor' (incluídas las unidades ópticas). El ejemplo te vale para profundizar y modificar a tu gusto... como el registro es una base de datos fuertemente jerarquizada es engorroso, para escribir código rápido pues debes recorrerlo iterativa o recursivamente si no te construyes alguna clase exprofeso para manejarlo con comodidad. Imports Microsoft.Win32 Public Class Form1 Private Enum DriveTypeScripting DRIVE_TYPE_DESCONOCIDO = 0 DRIVE_TYPE_DESCONECTABLE = 1 DRIVE_TYPE_DISCODURO = 2 DRIVE_TYPE_REMOTO = 3 DRIVE_TYPE_OPTICA = 4 DRIVE_TYPE_RAMDISK = 5 End Enum Private Function DriveTypeToString(ByVal DtS As DriveTypeScripting) As String Select Case DtS Case 0 : Return "Desconocido" Case 1 : Return "Desconectable" Case 2 : Return "Disco Duro" Case 3 : Return "Unida de Red" Case 4 : Return "Unidad óptica" Case 5 : Return "Unidad de Memoria" 'Case else End Select Return "" End Function Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim dev As Devices.Computer Dim info As String Dim key As RegistryKey, keyDrive As RegistryKey, keyIde As RegistryKey Dim hk As RegistryHive Dim rv As RegistryView ' Acceso desde el spacename IO For Each d As IO.DriveInfo In IO.DriveInfo.GetDrives With d info = (.Name & vbNewLine & .DriveType.ToString) If (.IsReady) Then info += (vbNewLine & .DriveFormat) MessageBox.Show(info) 'info. End With Next ' Acceso desde el namespace IO y/o Win32.Devices dev = New Devices.Computer For Each d As IO. DriveInfo In dev. FileSystem. Drives MessageBox.Show(d.Name) Next ' Acceso a los datos de las unidades mediante el objeto FileSystemObject de la referencia Scripcing (que debe agregar desde COM). Dim dtipo As Scripting.DriveTypeConst Dim volLabel As String For Each disk As Scripting. Drive In ds With disk dtipo = .DriveType If (dtipo = DriveTypeScripting.DRIVE_TYPE_DISCODURO) Then volLabel = .VolumeName & vbNewLine Else If .IsReady Then volLabel = .VolumeName & vbNewLine Else volLabel = "" End If End If info = (.DriveLetter & ":\" & vbNewLine & volLabel & DriveTypeToString(dtipo)) If .IsReady Then info += (vbNewLine & .SerialNumber) MessageBox.Show(info) End With Next ' Acceso al registro para rescatar el modelo de la unidad... Dim subkeys() As String hk = RegistryHive.LocalMachine rv = RegistryView.Registry32 key = RegistryKey.OpenBaseKey(hk, rv) Try key = key.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Enum").OpenSubKey("IDE") ' "UsbStor" subkeys = key.GetSubKeyNames For k As Integer = 1 To key.SubKeyCount keyIde = key.OpenSubKey(subkeys(k - 1)) keyDrive = keyIde.OpenSubKey(keyIde.GetSubKeyNames(0)) MsgBox(keyDrive.GetValue("FriendlyName")) keyDrive.Close() : keyIde.Close() Next Catch ex As Exception ' no tienes permiso, MessageBox.Show(ex.Message) Finally key.Close() End Try End Sub End Class
Y ya desde ahí compón lo precises...
|
|
|
En línea
|
|
|
|
BlackZeroX
Wiki
Desconectado
Mensajes: 3.158
I'Love...!¡.
|
Scripting.FileSystemObject... de hecho dicho objeto no parte de vb6 parte de vba, al final del día ya tiene varias formas de hacerlo API Win32 Objetos COM (vba) en vb .NET En cualquier caso según veo se debe ejecutar con privilegios de administrador, así que deberá agregar un MANIFEST para que escale permisos o que se ejecute con dicho permiso. El código posteado por serapis (Solo parte del COM) por lo que se ve lista volúmenes lógicos y no físicos que para lo que se requiere es similar a este (VBS) crear un archivo en escritorio y con extensión "vbs" como ejecutar.vbs y pegar este código y darle doble click: Dim fs, d, dc, s Set fs = CreateObject("Scripting.FileSystemObject") Set dc = fs.Drives For Each d in dc s = s & d.DriveLetter & " tipo " & d.DriveType & " serialNumber (Logico) " & d.SerialNumber & vbNewLine Next MsgBox s
Saludos.
|
|
« Última modificación: 4 Febrero 2021, 06:16 am por BlackZeroX (Astaroth) »
|
En línea
|
The Dark Shadow is my passion.
|
|
|
Mr. NoBody
Desconectado
Mensajes: 20
"You Take The Red Pill - You Stay In Wonderland"
|
Un tal ElektroStudios, programador enfocado en el desarrollo de aplicaciones de escritorio con VB.NET, publicó cierto programa / API open-source con fines educativos para demostrar cómo obtener todo tipo de información S.M.A.R.T de un disco, incluyendo por supuesto el número de serie y modelo: S.M.A.R.T. Demo: https://github.com/ElektroStudios/S.M.A.R.T.-Tool-for-.NETDicho esto, ten en cuenta que .NET Framework / VB.NET es en gran parte un gigantesco y optimizado wrapper de la API de Windows, así que en la mayoría de escenarios habituales de un programador con necesidades normales y corrientes no es necesario ni tampoco recomendable utilizar directamente la API de Windows, a menos que sea para escenarios y por motivos muy específicos, y siempre teniendo una base mínima de cococimiento sobre el uso de la librería de Windows y su implementación en .NET mediante Platform Invoke. El código fuente del programa S.M.A.R.T. Demo se apoya en las funcionalidades de la infrastructura WMI (que hace uso interno de la API de Windows) para obtener toda la información. Esto es lo más completo que vas a encontrar de forma open-source para .NET, la API es reutilizable así que es practicamente copiar y pegar código (todo el contenido de la carpeta 'DevCase') y ya estaría listo para darle uso en tu aplicación siguiendo y adaptando el ejemplo del programa... Imports DevCase.Core.IO For Each drive As HardDriveInfo In HardDriveInfo. GetDrives() Dim sb As New StringBuilder() sb.AppendLine($"{NameOf(drive.Name)}: {drive.Name}") sb.AppendLine($"{NameOf(drive.VolumeLabel)}: {drive.VolumeLabel}") sb.AppendLine($"{NameOf(drive.SerialNumber)}: {drive.SerialNumber}") Console.WriteLine(sb.ToString())
Name: C:\ VolumeLabel: Windows 10 SerialNumber: S4X6NJ0MC20670B Pero también te digo que es bien fácil buscar en Google un simple código de pocas lineas para obtener el número de serie de un disco mediante WMI, ya sea en VB.NET y en C# también, y así no te complicas la vida usando toda una extensa API para lograr el mismo objetivo. Saludos!
|
|
« Última modificación: 5 Febrero 2021, 12:19 pm por Mr. NoBody »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Obtener numero de serie del fabricante (usb)
Programación Visual Basic
|
Vampersy
|
1
|
15,516
|
21 Enero 2009, 13:00 pm
por Fabricio
|
|
|
Obtener el numero de serie de una impresora
Scripting
|
Hekaly
|
1
|
9,815
|
18 Septiembre 2012, 23:38 pm
por MCKSys Argentina
|
|
|
Obtener mayor número de una serie C++
Programación C/C++
|
Ingrid1997
|
1
|
2,146
|
19 Octubre 2015, 05:52 am
por Seyro97
|
|
|
Cambiar número serie disco ?
Hardware
|
Rnovatis
|
2
|
9,987
|
14 Octubre 2016, 20:05 pm
por Rnovatis
|
|
|
cambiar numero de serie de un disco duro.
Dudas Generales
|
julian@23
|
1
|
1,931
|
6 Julio 2023, 04:20 am
por Machacador
|
|