Query BIOS serial number
From NSIS Wiki
Jump to navigationJump to search
The following code demonstrates the usage of the Windows Management Instrumentation (WMI) only via the System plugin.
The sample code displays the BIOS serial number in a message box. The idea for this script stems from the example published on MSDN see links below.
The script makes use of features available in NSIS 3.0 or newer such as the Target directive and use of p for pointer in System::Call statements.
Script
; Licensed under the zlib/libpng license (same as NSIS) OutFile "bios_serial.exe" Target x86-unicode !include "LogicLib.nsh" !define CLSCTX_INPROC_SERVER 1 !define CLSID_WbemLocator {4590f811-1d3a-11d0-891f-00aa004b2e24} !define IID_IWbemLocator {dc12a687-737f-11cf-884d-00aa004b2e24} !define RPC_C_AUTHN_LEVEL_DEFAULT 0 !define RPC_C_IMP_LEVEL_IMPERSONATE 3 !define EOAC_NONE 0 !define WBEM_FLAG_FORWARD_ONLY 0x20 !define WBEM_FLAG_RETURN_IMMEDIATELY 0x10 !define WBEM_INFINITE 0xffffffff !define VT_BSTR 8 Function bios_serial ; Save registers Push $1 Push $2 Push $3 Push $4 Push $5 Push $6 Push $7 ; Initialization of COM is done via OleInitialize in NSIS installer code ; Set general COM security level System::Call "ole32::CoInitializeSecurity( \ p 0, i -1, p 0, p 0, i ${RPC_C_AUTHN_LEVEL_DEFAULT}, \ i ${RPC_C_IMP_LEVEL_IMPERSONATE}, p 0, i ${EOAC_NONE}, p 0) i.r1" ${If} $1 != 0 StrCpy $0 "failed to initialize security: $1" Goto bios_serial_end ${EndIf} ; Create IWbemLocator interface System::Call "ole32::CoCreateInstance( \ g '${CLSID_WbemLocator}', p 0, \ i ${CLSCTX_INPROC_SERVER}, \ g '${IID_IWbemLocator}', *p .r2) i.r1" ${If} $1 != 0 StrCpy $0 "failed to create IWebmLocator object: $1" Goto bios_serial_end ${EndIf} ; Call IWbemLocator->ConnectServer System::Call "$2->3(w 'ROOT\CIMV2', p 0, p 0, p 0, i 0, p 0, p 0, *p .r3) i.r1" ${If} $1 != 0 StrCpy $0 "failed to connect: $1" ${Else} ; Call IWbemServices->ExecQuery System::Call "$3->20(w 'WQL', w 'Select SerialNumber from Win32_BIOS', \ ${WBEM_FLAG_FORWARD_ONLY} | ${WBEM_FLAG_RETURN_IMMEDIATELY}, \ p 0, *p .r4) i.r1" ${If} $1 != 0 StrCpy $0 "failed to query: $1 $3" ${Else} ; Call IEnumWbemClassObject->Next System::Call "$4->4(i ${WBEM_INFINITE}, i 1, *p .r5, *i .r6) i.r1" ${If} $6 != 0 ; Variant ; (unsigned short vt, WORD wReserved1, WORD wReserved2, WORD wReserved3, BSTR bstrVal) System::Call "*(i 0, i 0, &i8 0) p.r7" ${If} $7 != 0 ; Call IWbemClassObject->Get System::Call "$5->4(w 'SerialNumber', i 0, p r7, p 0, p 0) i.r1" ${If} $1 != 0 StrCpy $0 "failed to get: $1" ${Else} ; Check type of variant System::Call "*$7(&i2 .r1)" ${If} $1 == ${VT_BSTR} ; Access bstrVal from Variant System::Call "*$7(i, i, w .r0)" ${Else} StrCpy $0 "failed to access data: wrong type [$1]" ${EndIf} System::Call "ole32::VariantClear(p r7)" ${EndIf} ; Deallocate memory of variant System::Free $7 ${Else} StrCpy $0 "failed to allocate memory for variant" ${EndIf} ; Call IWbemClassObject->Release System::Call "$5->2()" ${Else} StrCpy $0 "failed to iterate [$6] $1" ${EndIf} ; Call IEnumWbemClassObject->Release System::Call "$4->2()" ${EndIf} ; Call IWbemService->Release System::Call "$3->2()" ${EndIf} ; Call IWbemLocator->Release System::Call "$2->2()" bios_serial_end: ; Restore registers Pop $7 Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 FunctionEnd Function .onInit InitPluginsDir Call bios_serial MessageBox MB_OK "Bios Serial Number=$0" Quit FunctionEnd Section SectionEnd
Links
- This forum thread contains the original but due to PHP prettifying messed up version of this script.
- This MSDN link describes the Win32_BIOS WMI class used in this script.
- Example: Getting WMI Data from the Local Computer (MSDN)