Page 1 of 2

WMI

Posted: Tue Feb 09, 2016 11:45 pm
by nco2k
i needed wmi to return some system internal data, so i wrote this little function from scratch. it works in ascii-, unicode-, 32bit- and 64bit-mode and supports the proper "SELECT X FROM Y WHERE Z" syntax. you can write "SELECT A, B, C FROM X" to list only the properties you need or you can write "SELECT * FROM X" to list them all.

the function supports almost every type. only one dimensional safe-arrays are supported though. i couldnt find any data that uses multi dimensional safe-arrays, so i didnt have the chance to figure out how they work. i wanted to add support for the #VT_DECIMAL type as well, but also couldnt find any data to play with.

each property entry is separated by #CRLF$:
WMI("SELECT Caption, OSArchitecture FROM Win32_OperatingSystem") returns for example: "Caption=Microsoft Windows 7 Home Premium"+#CRLF$+"OSArchitecture=64-Bit"+#CRLF$

each array entry is separated by #US$:
WMI("SELECT BiosCharacteristics FROM Win32_BIOS") returns for example: "BiosCharacteristics=1"+#US$+"2"+#US$+"3"+#US$+"4"+#US$+"5"+#US$+#CRLF$

have fun!

Code: Select all

;WMI by nco2k for PureBasic 5.41 LTS

EnableExplicit

#RPC_C_AUTHN_WINNT = 10
#RPC_C_AUTHN_LEVEL_CALL = 3
#RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6
#RPC_C_AUTHZ_NONE = 0
#RPC_C_IMP_LEVEL_IMPERSONATE = 3
#RPC_E_CHANGED_MODE = $80010106
#EOAC_NONE = 0
#CLSCTX_INPROC_SERVER = $1
#WBEM_FLAG_ALWAYS = 0
#WBEM_FLAG_RETURN_IMMEDIATELY = 16
#WBEM_FLAG_FORWARD_ONLY = 32
#WBEM_FLAG_NONSYSTEM_ONLY = 64
#WBEM_INFINITE = -1

Structure DECIMAL2
  wReserved.w
  scale.b
  sign.b
  Hi32.l
  Lo64.q
EndStructure

Structure VARIANT2
  vt.w
  wReserved1.w
  wReserved2.w
  wReserved3.w
  StructureUnion
    llVal.q
    lVal.l
    bVal.b
    iVal.w
    fltVal.f
    dblVal.d
    boolVal.w
    bool.w
    scode.l
    cyVal.q
    date.d
    bstrVal.i
    *punkVal.IUnknown
    *pdispVal.IDispatch
    *parray
    *pbVal.BYTE
    *piVal.WORD
    *plVal.LONG
    *pllVal.QUAD
    *pfltVal.FLOAT
    *pdblVal.DOUBLE
    *pboolVal.WORD
    *pbool.WORD
    *pscode.LONG
    *pcyVal.QUAD
    *pdate.DOUBLE
    *pbstrVal.INTEGER
    *ppunkVal.INTEGER
    *ppdispVal.INTEGER
    *pparray.INTEGER
    *pvarVal.VARIANT2
    *byref
    cVal.b
    uiVal.w
    ulVal.l
    ullVal.q
    intVal.l
    uintVal.l
    *pdecVal.DECIMAL2
    *pcVal.BYTE
    *puiVal.WORD
    *pulVal.LONG
    *pullVal.QUAD
    *pintVal.LONG
    *puintVal.LONG
    brecord.VARIANT_BRECORD
    decVal.DECIMAL2
  EndStructureUnion
EndStructure

Import "OleAut32.lib"
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    SysAllocString2_(String.p-unicode) As "_SysAllocString"
    SysFreeString2_(*String) As "_SysFreeString"
  CompilerElse
    SysAllocString2_(String.p-unicode) As "SysAllocString"
    SysFreeString2_(*String) As "SysFreeString"
  CompilerEndIf
EndImport

Procedure$ WMI(WQL$)
  Protected Result$, QuerySelect$, QuerySelectIndex, PropertyList$, PropertyListIndex, PropertyListSize, PropertyListElement$, *PropertyArray, PropertyArrayIndex, PropertyArrayOffset.l, PropertyArraySize.l, PropertyArrayDimensions, PropertyArrayElement$, BufferArrayIndex, BufferArrayOffset.l, BufferArraySize.l, BufferArrayDimensions, BufferArrayElement$
  Protected CoInit, *SysRoot, *SysLanguage, *SysQuery, *SysArray, *SysList, ClassObjectSize, iwbemlocator.IWbemLocator, iwbemservices.IWbemServices, ienumwbemclassobject.IEnumWbemClassObject, iwbemclassobject.IWbemClassObject, variant.VARIANT2, VarByte.b, VarWord.w, VarLong.l, VarQuad.q, VarFloat.f, VarDouble.d, *VarString, *VarArray
  If UCase(Left(WQL$, 7)) = "SELECT "
    QuerySelectIndex = FindString(WQL$, " FROM ", 9, #PB_String_NoCase)
    If QuerySelectIndex
      QuerySelect$ = Trim(Mid(WQL$, 8, QuerySelectIndex - 8))
    EndIf
  EndIf
  If QuerySelect$
    CoInit = CoInitializeEx_(0, #COINIT_APARTMENTTHREADED | #COINIT_DISABLE_OLE1DDE)
    If CoInit = #S_OK Or CoInit = #S_FALSE Or CoInit = #RPC_E_CHANGED_MODE
      If CoInitializeSecurity_(0, -1, 0, 0, #RPC_C_AUTHN_LEVEL_PKT_PRIVACY, #RPC_C_IMP_LEVEL_IMPERSONATE, 0, #EOAC_NONE, 0) = #ERROR_SUCCESS And CoCreateInstance_(?CLSID_WbemLocator, 0, #CLSCTX_INPROC_SERVER, ?IID_IWbemLocator, @iwbemlocator) = #ERROR_SUCCESS
        *SysRoot = SysAllocString2_("ROOT\CIMV2")
        If *SysRoot
          If iwbemlocator\ConnectServer(*SysRoot, 0, 0, 0, 0, 0, 0, @iwbemservices) = #ERROR_SUCCESS
            If CoSetProxyBlanket_(iwbemservices, #RPC_C_AUTHN_WINNT, #RPC_C_AUTHZ_NONE, 0, #RPC_C_AUTHN_LEVEL_CALL, #RPC_C_IMP_LEVEL_IMPERSONATE, 0, #EOAC_NONE) = #ERROR_SUCCESS
              *SysLanguage = SysAllocString2_("WQL")
              If *SysLanguage
                *SysQuery = SysAllocString2_(WQL$)
                If *SysQuery
                  If iwbemservices\ExecQuery(*SysLanguage, *SysQuery, #WBEM_FLAG_FORWARD_ONLY | #WBEM_FLAG_RETURN_IMMEDIATELY, 0, @ienumwbemclassobject) = #ERROR_SUCCESS
                    While ienumwbemclassobject\Next(#WBEM_INFINITE, 1, @iwbemclassobject, @ClassObjectSize) = #ERROR_SUCCESS And ClassObjectSize = 1
                      If QuerySelect$ <> "*"
                        PropertyList$ = QuerySelect$+","
                      Else
                        PropertyList$ = ""
                        *PropertyArray = #False
                        If iwbemclassobject\GetNames(0, #WBEM_FLAG_ALWAYS | #WBEM_FLAG_NONSYSTEM_ONLY, 0, @*PropertyArray) = #ERROR_SUCCESS And *PropertyArray
                          PropertyArrayDimensions = SafeArrayGetDim_(*PropertyArray)
                          If PropertyArrayDimensions = 1 And SafeArrayGetLBound_(*PropertyArray, PropertyArrayDimensions, @PropertyArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*PropertyArray, PropertyArrayDimensions, @PropertyArraySize) = #ERROR_SUCCESS
                            For PropertyArrayIndex = PropertyArrayOffset To PropertyArraySize
                              If SafeArrayGetElement_(*PropertyArray, @PropertyArrayIndex, @*SysArray) = #ERROR_SUCCESS And *SysArray
                                PropertyArrayElement$ = PeekS(*SysArray, -1, #PB_Unicode)
                                If PropertyArrayElement$
                                  PropertyList$+PropertyArrayElement$+","
                                EndIf
                                SysFreeString2_(*SysArray)
                              EndIf
                            Next
                          EndIf
                          SafeArrayDestroy_(*PropertyArray)
                        EndIf
                      EndIf
                      If PropertyList$
                        PropertyListSize = CountString(PropertyList$, ",")
                        For PropertyListIndex = 1 To PropertyListSize
                          PropertyListElement$ = Trim(StringField(PropertyList$, PropertyListIndex, ","))
                          If PropertyListElement$
                            *SysList = SysAllocString2_(PropertyListElement$)
                            If *SysList
                              If iwbemclassobject\Get(*SysList, 0, @variant, 0, 0) = #ERROR_SUCCESS
                                Select variant\vt
                                  Case #VT_EMPTY, #VT_NULL, #VT_VOID, #VT_BYREF | #VT_EMPTY, #VT_BYREF | #VT_NULL, #VT_BYREF | #VT_VOID
                                    Result$+PropertyListElement$+"="+#CRLF$
                                  Case #VT_BOOL, #VT_BYREF | #VT_BOOL
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarWord = variant\boolVal
                                    Else
                                      VarWord = variant\pboolVal\w
                                    EndIf
                                    If VarWord
                                      Result$+PropertyListElement$+"=1"+#CRLF$
                                    Else
                                      Result$+PropertyListElement$+"=0"+#CRLF$
                                    EndIf
                                  Case #VT_I1, #VT_BYREF | #VT_I1
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarByte = variant\cVal
                                    Else
                                      VarByte = variant\pcVal\b
                                    EndIf
                                    Result$+PropertyListElement$+"="+Str(VarByte)+#CRLF$
                                  Case #VT_UI1, #VT_BYREF | #VT_UI1
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarByte = variant\bVal
                                    Else
                                      VarByte = variant\pbVal\b
                                    EndIf
                                    Result$+PropertyListElement$+"="+StrU(VarByte, #PB_Byte)+#CRLF$
                                  Case #VT_I2, #VT_BYREF | #VT_I2
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarWord = variant\iVal
                                    Else
                                      VarWord = variant\piVal\w
                                    EndIf
                                    Result$+PropertyListElement$+"="+Str(VarWord)+#CRLF$
                                  Case #VT_UI2, #VT_BYREF | #VT_UI2
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarWord = variant\uiVal
                                    Else
                                      VarWord = variant\puiVal\w
                                    EndIf
                                    Result$+PropertyListElement$+"="+StrU(VarWord, #PB_Word)+#CRLF$
                                  Case #VT_I4, #VT_INT, #VT_BYREF | #VT_I4, #VT_BYREF | #VT_INT
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarLong = variant\lVal
                                    Else
                                      VarLong = variant\plVal\l
                                    EndIf
                                    Result$+PropertyListElement$+"="+Str(VarLong)+#CRLF$
                                  Case #VT_UI4, #VT_UINT, #VT_ERROR, #VT_BYREF | #VT_UI4, #VT_BYREF | #VT_UINT, #VT_BYREF | #VT_ERROR
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarLong = variant\ulVal
                                    Else
                                      VarLong = variant\pulVal\l
                                    EndIf
                                    Result$+PropertyListElement$+"="+StrU(VarLong, #PB_Long)+#CRLF$
                                  Case #VT_I8, #VT_CY, #VT_BYREF | #VT_I8, #VT_BYREF | #VT_CY
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarQuad = variant\llVal
                                    Else
                                      VarQuad = variant\pllVal\q
                                    EndIf
                                    Result$+PropertyListElement$+"="+Str(VarQuad)+#CRLF$
                                  Case #VT_UI8, #VT_BYREF | #VT_UI8
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarQuad = variant\ullVal
                                    Else
                                      VarQuad = variant\pullVal\q
                                    EndIf
                                    Result$+PropertyListElement$+"="+StrU(VarQuad, #PB_Quad)+#CRLF$
                                  Case #VT_R4, #VT_BYREF | #VT_R4
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarFloat = variant\fltVal
                                    Else
                                      VarFloat = variant\pfltVal\f
                                    EndIf
                                    Result$+PropertyListElement$+"="+StrF(VarFloat)+#CRLF$
                                  Case #VT_R8, #VT_DATE, #VT_BYREF | #VT_R8, #VT_BYREF | #VT_DATE
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      VarDouble = variant\dblVal
                                    Else
                                      VarDouble = variant\pdblVal\d
                                    EndIf
                                    Result$+PropertyListElement$+"="+StrD(VarDouble)+#CRLF$
                                  Case #VT_LPSTR, #VT_BYREF | #VT_LPSTR
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarString = variant\bstrVal
                                    Else
                                      *VarString = variant\pbstrVal\i
                                    EndIf
                                    If *VarString
                                      Result$+PropertyListElement$+"="+PeekS(*VarString, -1, #PB_Ascii)+#CRLF$
                                    Else
                                      Result$+PropertyListElement$+"="+#CRLF$
                                    EndIf
                                  Case #VT_LPWSTR, #VT_BSTR, #VT_BYREF | #VT_LPWSTR, #VT_BYREF | #VT_BSTR
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarString = variant\bstrVal
                                    Else
                                      *VarString = variant\pbstrVal\i
                                    EndIf
                                    If *VarString
                                      Result$+PropertyListElement$+"="+PeekS(*VarString, -1, #PB_Unicode)+#CRLF$
                                    Else
                                      Result$+PropertyListElement$+"="+#CRLF$
                                    EndIf
                                  Case #VT_ARRAY | #VT_EMPTY, #VT_ARRAY | #VT_NULL, #VT_ARRAY | #VT_VOID, #VT_BYREF | #VT_ARRAY | #VT_EMPTY, #VT_BYREF | #VT_ARRAY | #VT_NULL, #VT_BYREF | #VT_ARRAY | #VT_VOID
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          BufferArrayElement$+#US$
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_BOOL, #VT_BYREF | #VT_ARRAY | #VT_BOOL
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarWord) = #ERROR_SUCCESS
                                            If VarWord
                                              BufferArrayElement$+"1"+#US$
                                            Else
                                              BufferArrayElement$+"0"+#US$
                                            EndIf
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_I1, #VT_BYREF | #VT_ARRAY | #VT_I1
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarByte) = #ERROR_SUCCESS
                                            BufferArrayElement$+Str(VarByte)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_UI1, #VT_BYREF | #VT_ARRAY | #VT_UI1
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarByte) = #ERROR_SUCCESS
                                            BufferArrayElement$+StrU(VarByte, #PB_Byte)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_I2, #VT_BYREF | #VT_ARRAY | #VT_I2
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarWord) = #ERROR_SUCCESS
                                            BufferArrayElement$+Str(VarWord)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_UI2, #VT_BYREF | #VT_ARRAY | #VT_UI2
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarWord) = #ERROR_SUCCESS
                                            BufferArrayElement$+StrU(VarWord, #PB_Word)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_I4, #VT_ARRAY | #VT_INT, #VT_BYREF | #VT_ARRAY | #VT_I4, #VT_BYREF | #VT_ARRAY | #VT_INT
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarLong) = #ERROR_SUCCESS
                                            BufferArrayElement$+Str(VarLong)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_UI4, #VT_ARRAY | #VT_UINT, #VT_ARRAY | #VT_ERROR, #VT_BYREF | #VT_ARRAY | #VT_UI4, #VT_BYREF | #VT_ARRAY | #VT_UINT, #VT_BYREF | #VT_ARRAY | #VT_ERROR
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarLong) = #ERROR_SUCCESS
                                            BufferArrayElement$+StrU(VarLong, #PB_Local)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_I8, #VT_ARRAY | #VT_CY, #VT_BYREF | #VT_ARRAY | #VT_I8, #VT_BYREF | #VT_ARRAY | #VT_CY
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarQuad) = #ERROR_SUCCESS
                                            BufferArrayElement$+Str(VarQuad)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_UI8, #VT_BYREF | #VT_ARRAY | #VT_UI8
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarQuad) = #ERROR_SUCCESS
                                            BufferArrayElement$+StrU(VarQuad, #PB_Quad)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_R4, #VT_BYREF | #VT_ARRAY | #VT_R4
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarFloat) = #ERROR_SUCCESS
                                            BufferArrayElement$+StrF(VarFloat)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_R8, #VT_ARRAY | #VT_DATE, #VT_BYREF | #VT_ARRAY | #VT_R8, #VT_BYREF | #VT_ARRAY | #VT_DATE
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @VarDouble) = #ERROR_SUCCESS
                                            BufferArrayElement$+StrD(VarDouble)+#US$
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_LPSTR, #VT_BYREF | #VT_ARRAY | #VT_LPSTR
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @*VarString) = #ERROR_SUCCESS
                                            If *VarString
                                              BufferArrayElement$+PeekS(*VarString, -1, #PB_Ascii)+#US$
                                              SysFreeString2_(*VarString)
                                            Else
                                              BufferArrayElement$+#US$
                                            EndIf
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                  Case #VT_ARRAY | #VT_LPWSTR, #VT_ARRAY | #VT_BSTR, #VT_BYREF | #VT_ARRAY | #VT_LPWSTR, #VT_BYREF | #VT_ARRAY | #VT_BSTR
                                    If variant\vt & #VT_BYREF <> #VT_BYREF
                                      *VarArray = variant\parray
                                    Else
                                      *VarArray = variant\pparray\i
                                    EndIf
                                    If *VarArray
                                      BufferArrayDimensions = SafeArrayGetDim_(*VarArray)
                                      If BufferArrayDimensions = 1 And SafeArrayGetLBound_(*VarArray, BufferArrayDimensions, @BufferArrayOffset) = #ERROR_SUCCESS And SafeArrayGetUBound_(*VarArray, BufferArrayDimensions, @BufferArraySize) = #ERROR_SUCCESS
                                        BufferArrayElement$ = ""
                                        For BufferArrayIndex = BufferArrayOffset To BufferArraySize
                                          If SafeArrayGetElement_(*VarArray, @BufferArrayIndex, @*VarString) = #ERROR_SUCCESS
                                            If *VarString
                                              BufferArrayElement$+PeekS(*VarString, -1, #PB_Unicode)+#US$
                                              SysFreeString2_(*VarString)
                                            Else
                                              BufferArrayElement$+#US$
                                            EndIf
                                          EndIf
                                        Next
                                        Result$+PropertyListElement$+"="+BufferArrayElement$+#CRLF$
                                      EndIf
                                    EndIf
                                EndSelect
                                VariantClear_(variant)
                              EndIf
                              SysFreeString2_(*SysList)
                            EndIf
                          EndIf
                        Next
                      EndIf
                    Wend
                    ienumwbemclassobject\Release()
                  EndIf
                  SysFreeString2_(*SysQuery)
                EndIf
                SysFreeString2_(*SysLanguage)
              EndIf
            EndIf
            iwbemservices\Release()
          EndIf
          SysFreeString2_(*SysRoot)
        EndIf
        iwbemlocator\Release()
      EndIf
      If CoInit <> #RPC_E_CHANGED_MODE
        CoUninitialize_()
      EndIf
    EndIf
  EndIf
  ProcedureReturn Result$
  DataSection 
    CLSID_WbemLocator:
      Data.l $4590F811
      Data.w $1D3A, $11D0
      Data.b $89, $1F, $00, $AA, $00, $4B, $2E, $24
    IID_IWbemLocator:
      Data.l $DC12A687
      Data.w $737F, $11CF
      Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
  EndDataSection
EndProcedure

;List only the "Caption" and "OSArchitecture" Properties from the "Win32_OperatingSystem" Class
Debug WMI("SELECT Caption, OSArchitecture FROM Win32_OperatingSystem")

;List all Properties (*) from the "Win32_OperatingSystem" Class
Debug WMI("Select * FROM Win32_OperatingSystem")
ps: yes i know i could make it shorter, but i wanted to keep everything in place.

c ya,
nco2k

Re: WMI

Posted: Wed Feb 10, 2016 10:07 am
by RSBasic
Wow, very good, thank you for your code! Image

Re: WMI

Posted: Wed Feb 10, 2016 7:18 pm
by smacker
Nice, very nice, thanks for posting it :)

Just tried it though and doesn't want to work with some of the newer classes like, for example, MSFT_NetAdapter.

Re: WMI

Posted: Wed Feb 10, 2016 9:35 pm
by nco2k
weird. even if you change "Root\Cimv2" to "Root\StandardCimv2" and tweak some parameters, ienumwbemclassobject\Next() keeps failing with #WBEM_E_INVALID_QUERY. no idea how to make those work, sorry. microsoft really likes breaking things. :?

edit: so weird. i restarted my vm and now it works?! :?

simply change line 106 from:

Code: Select all

*SysRoot = SysAllocString2_("Root\Cimv2")
to:

Code: Select all

*SysRoot = SysAllocString2_("Root\StandardCimv2")
if you need data from MSFT_NetAdapter and probably other MSFT_* classes as well.

c ya,
nco2k

Re: WMI

Posted: Thu Feb 11, 2016 2:27 pm
by Kwai chang caine
Works great on W7 and v5.23
Thanks for sharing 8)

Re: WMI

Posted: Tue Jan 10, 2017 7:48 am
by kinglestat
Thanks, a life saver

Re: WMI

Posted: Tue Jan 10, 2017 9:53 am
by infratec
Hi,

nice work!

A feature request (but makes it incompatible :mrgreen: )

Add a string Map() as parameter
and add elements with the PropertyListElement$ as key
and the value as value.
Maybe the number of elements as return value.

Then you can easily access each element from the result.
And for listing you can use ForEach.

Bernd

Re: WMI

Posted: Tue Jan 10, 2017 11:21 am
by infratec
:oops: :oops: :oops:

A Map() is impossible because of duplicated keys/properties depending on the select.
And I don't know if a List() with 2 fields makes really sense.

Bernd

Re: WMI

Posted: Sat Jan 14, 2017 12:06 pm
by doctorized
Once upon a time, back in 2011 I had made a similar app. Find it here: http://kc2000labs.shadowtavern.com/pb/z ... r_4.41.zip

Re: WMI

Posted: Tue Oct 03, 2017 1:42 am
by Steving
Thanks so much! You are a steely-eyed programming MASTER! :D

Re: WMI

Posted: Fri Sep 21, 2018 5:28 pm
by skywalk
Very nice 8)
I have no luck attempting remote PC queries?
I verified my query works with a WMIC command line.

Code: Select all

        *SysRoot = SysAllocString2_("\\MyRemotePC\ROOT\CIMV2")
          *SysUserName = SysAllocString2_("MyAdmin")
          *SysPSWD     = SysAllocString2_("MyAdminPSWD")
          If iwbemlocator\ConnectServer(*SysRoot, *SysUserName, *SysPSWD, 0, 0, 0, 0, @iwbemservices) = #ERROR_SUCCESS
;; I connect OK, but ExecQuery fails?
                  If iwbemservices\ExecQuery(*SysLanguage, *SysQuery, #WBEM_FLAG_FORWARD_ONLY | #WBEM_FLAG_RETURN_IMMEDIATELY, 0, @ienumwbemclassobject) = #ERROR_SUCCESS
;; So, I tried to get the error info but not sure how?
                  Else
                    Protected IErrinfo.IErrorInfo
                    ;GetErrorInfo_(0, @IErrinfo)
                    ;Debug IErrinfo\GetDescription(*SysQuery)
                  EndIf

Re: WMI

Posted: Fri Sep 21, 2018 6:12 pm
by nco2k
try adding #CLSCTX_REMOTE_SERVER or simply use #CLSCTX_ALL.

edit: btw you are not using GetDescription() correctly: Retrieving Error Information.
also check if they are doing anything differently: Getting WMI Data from a Remote Computer.

c ya,
nco2k

Re: WMI

Posted: Fri Sep 21, 2018 6:47 pm
by skywalk
Yes, but where do I set those flags?
The ConnectServer() was ok.
No mention of these flags in the ExecQuery() docs?

Ok, tried...

Code: Select all

      If CoInitializeSecurity_(0, -1, 0, 0, #RPC_C_AUTHN_LEVEL_PKT_PRIVACY, #RPC_C_IMP_LEVEL_IMPERSONATE, 0, #EOAC_NONE, 0) = #ERROR_SUCCESS And CoCreateInstance_(?CLSID_WbemLocator, 0, #CLSCTX_INPROC_SERVER|#CLSCTX_REMOTE_SERVER, ?IID_IWbemLocator, @iwbemlocator) = #ERROR_SUCCESS
And same result. Fails on iwbemservices\ExecQuery()

Re: WMI

Posted: Wed Nov 06, 2019 10:36 am
by tatanas
I just read this topic and I'm also interested in remote connection with credentials.
I can't find the right parameters to use with all those functions and there is no example in PB.
I'm stucked.

Any idea ?

Thanks for your time.

(Oh, and I'm new in PB, it's my first post. I'm coming from Autoit)

Re: WMI

Posted: Wed Nov 06, 2019 1:59 pm
by Bitblazer
tatanas wrote:I just read this topic and I'm also interested in remote connection with credentials.
I can't find the right parameters to use with all those functions and there is no example in PB.
I'm stucked.

Any idea ?

Thanks for your time.

(Oh, and I'm new in PB, it's my first post. I'm coming from Autoit)
Welcome to PureBasic!

You may also want to look here.