下面的代碼在exe中執行,能正確的用wmi讀取到硬體資訊,但是放到dll中就不行了,請高手們指點,如果分數不夠,還可以加。
//--------------------------------------------------------------------------
#include <comdef.h>
#include <wbemidl.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
char *AllWmiClasses[] =
{
"Win32_1394Controller" ,
"Win32_BaseBoard" ,
"Win32_Battery" ,
"Win32_BIOS" ,
"Win32_Bus" ,
"Win32_CacheMemory" ,
"Win32_CDROMDrive" ,
"Win32_CurrentProbe" ,
"Win32_DesktopMonitor" ,
"Win32_DeviceMemoryAddress" ,
"Win32_DiskDrive" ,
"Win32_DisplayConfiguration" ,
"Win32_DisplayControllerConfiguration",
"Win32_DMAChannel" ,
"Win32_Fan" ,
"Win32_FloppyController" ,
"Win32_FloppyDrive" ,
"Win32_HeatPipe" ,
"Win32_IDEController" ,
"Win32_InfraredDevice" ,
"Win32_IRQResource" ,
"Win32_Keyboard" ,
"Win32_MemoryArray" ,
"Win32_MemoryDevice" ,
"Win32_MotherboardDevice" ,
"Win32_NetworkAdapter" ,
"Win32_NetworkAdapterConfiguration" ,
"Win32_OnBoardDevice" ,
"Win32_ParallelPort" ,
"Win32_PCMCIAController" ,
"Win32_PhysicalMemory" ,
"Win32_PhysicalMemoryArray" ,
"Win32_PnPEntity" ,
"Win32_PointingDevice" ,
"Win32_PortableBattery" ,
"Win32_PortConnector" ,
"Win32_PortResource" ,
"Win32_POTSModem" ,
"Win32_PowerManagementEvent" ,
"Win32_Printer" ,
"Win32_PrinterConfiguration" ,
"Win32_PrintJob" ,
"Win32_Processor" ,
"Win32_Refrigeration" ,
"Win32_SerialPort" ,
"Win32_SerialPortConfiguration" ,
"Win32_SMBIOSMemory" ,
"Win32_SoundDevice" ,
"Win32_SystemEnclosure" ,
"Win32_SystemMemoryResource" ,
"Win32_SystemSlot" ,
"Win32_TapeDrive" ,
"Win32_TemperatureProbe" ,
"Win32_UninterruptiblePowerSupply" ,
"Win32_USBController" ,
"Win32_VideoConfiguration" ,
"Win32_VideoController" ,
"Win32_VoltageProbe" ,
NULL
};
void GetWmiInfo(TStrings *lpList, WideString wsClass)
{
IWbemLocator *pWbemLocator = NULL;
if(CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pWbemLocator) == S_OK)
{
IWbemServices *pWbemServices = NULL;
UnicodeString wsNamespace = (L"root\\cimv2");
if(pWbemLocator->ConnectServer(wsNamespace.c_str(), NULL, NULL, NULL, 0, NULL, NULL, &pWbemServices) == S_OK)
{
IEnumWbemClassObject *pEnumClassObject = NULL;
UnicodeString wsWQL=L"WQL", wsQuery=WideString(L"Select * from ")+wsClass;
if(pWbemServices->ExecQuery(wsWQL.c_str(), wsQuery.c_str(), WBEM_FLAG_RETURN_IMMEDIATELY,NULL, &pEnumClassObject) == S_OK)
{
IWbemClassObject *pClassObject = NULL;
ULONG uCount = 1, uReturned;
if(pEnumClassObject->Reset() == S_OK)
{ //MessageBox(NULL,L"enter1",L"aabb",MB_OK);
int iEnumIdx = 0;
while(pEnumClassObject->Next(WBEM_INFINITE, uCount, &pClassObject, &uReturned) == S_OK)
{
lpList->Add("---------------- ["+IntToStr(iEnumIdx)+"] -----------------");
//MessageBox(NULL,L"enter2",L"aab",MB_OK);
SAFEARRAY *pvNames = NULL;
if(pClassObject->GetNames(NULL, WBEM_FLAG_ALWAYS | WBEM_MASK_CONDITION_ORIGIN, NULL, &pvNames) == S_OK)
{
long vbl, vbu;
SafeArrayGetLBound(pvNames, 1, &vbl);
SafeArrayGetUBound(pvNames, 1, &vbu);
for(long idx=vbl; idx<=vbu; idx++)
{
long aidx = idx;
wchar_t *wsName = 0;
VARIANT vValue;
VariantInit(&vValue);
SafeArrayGetElement(pvNames, &aidx, &wsName);
BSTR bs = SysAllocString(wsName);
HRESULT hRes = pClassObject->Get(bs, 0, &vValue, NULL, 0);
SysFreeString(bs);
if(hRes == S_OK)
{
AnsiString s;
Variant v = *(Variant*)&vValue;
if(v.IsArray())
{
for(int i=v.ArrayLowBound(); i<=v.ArrayHighBound(); i++)
{
Variant a = v.GetElement(i);
if(!s.IsEmpty())
s+=", ";
s+=VarToStr(a);
}
}
else
{
s = VarToStr(v);
}
lpList->Add(AnsiString(wsName)+"="+s);
}
VariantClear(&vValue);
SysFreeString(wsName);
}
}
if(pvNames)SafeArrayDestroy(pvNames);
iEnumIdx++;
}
} else MessageBox(NULL,L"err4",L"aa",MB_OK);
if(pClassObject)pClassObject->Release();
} else MessageBox(NULL,L"err3",L"aa",MB_OK);
if(pEnumClassObject)pEnumClassObject->Release();
} else MessageBox(NULL,L"err2",L"aa",MB_OK);
if(pWbemServices)pWbemServices->Release();
}else MessageBox(NULL,L"err1",L"aa",MB_OK);
if(pWbemLocator)pWbemLocator->Release();
}
UnicodeString __fastcall Pub_getHD0(String id,bool toMD5) {
CoInitialize(NULL);
HRESULT hr=CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);
if (hr!= S_OK && hr!=RPC_E_TOO_LATE) {
//ShowMessage("無法獲取權限!"); Application->Terminate();
//gPermission=1;//只能讀取1次,否則會出錯
CoUninitialize(); return "NoPermission";
}
TStringList*st1=new TStringList;
GetWmiInfo(st1, "Win32_DiskDrive"); //"Win32_PhysicalMedia");//
CoUninitialize();
str=st1->Text; MessageBox(NULL,String(str).c_str(),L"aa",MB_OK);
return str;
}
uj5u.com熱心網友回復:
請問怎么呼叫的?uj5u.com熱心網友回復:
您好,是在外匯軟體的指標腳本中呼叫的;這個dll的封裝介面如下:
#include <vcl.h>
//#include "Descrypt.h"
//#include <windows.h>
#pragma hdrstop
#pragma argsused
#define MT4_EXPFUNC __declspec(dllexport)
extern "C" MT4_EXPFUNC wchar_t* __stdcall myGetHD();
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) {
return 1;
}
String mHD="";
MT4_EXPFUNC wchar_t* __stdcall myGetHD() {
mHD=Pub_getHD0("",false);
return mHD.c_str();
}
uj5u.com熱心網友回復:
首先str這個字串沒有宣告,看能不能通過uj5u.com熱心網友回復:
您好,請越過基本語法,謝謝uj5u.com熱心網友回復:
呼叫是成功的,可以得到dll中的彈窗,只是彈窗是空的。uj5u.com熱心網友回復:
看看你的作業系統是不是64位的,如果是,改用64位平臺試試uj5u.com熱心網友回復:
這有關系嗎? 代碼在exe中執行,能正確的用wmi讀取到硬體資訊,只是放到dll中就不行了uj5u.com熱心網友回復:
不能沉了,我頂uj5u.com熱心網友回復:
你既然用到了CoCreateInstance,但沒看你在DLL初始化時呼叫CoInitInstance來初始化COM環境啊,當然這個動作放在主調的exe程式中也行。uj5u.com熱心網友回復:
其實感覺用Wmi又費事又磨嘰,還不如直接自己去訪問磁盤設備來的簡潔、方便。uj5u.com熱心網友回復:
您好,上面的代碼中有用到CoInitialize(NULL);,不知道您所說的“CoInitInstance”是不是一回事,請指教,謝謝了; 感覺用wmi的通用性多好,直接訪問設備,好像有些硬碟會讀不出來,或者需要管理員權限。uj5u.com熱心網友回復:
myGetHD 函式中不要直接回傳 UnicodeString 物件的 .c_str() 資料,自己定義一個WCHAR的陣列,將結果復制到這個緩沖里,再回傳試試。uj5u.com熱心網友回復:
您好,和這個沒關系,我MessageBox(NULL,String(str).c_str(),L"aa",MB_OK); 的值都是空的,根本沒取到值。uj5u.com熱心網友回復:
哦,抱歉我沒看到下面的,確實呼叫了CoInitialize和CoInitializeSecurity并判斷了回傳狀態。這個估計你要單步或log輸出一下,上面GetWmiInfo中每步呼叫的回傳資訊才能判斷哪里出現問題了。
uj5u.com熱心網友回復:
您好,代碼是沒問題的,因為在.exe中執行這段代碼是正確的; 問題就在于,為什么在dll中不行,是不是dll中不支持wmi?uj5u.com熱心網友回復:
我沒說你的代碼有問題啊,問題是程式運行存在各種各樣的環境。所以有兼容性之說,你的代碼在DLL環境下不回傳預期值,必定是某一步或多步呼叫失敗了。你不除錯怎莫能知道那?
uj5u.com熱心網友回復:
“是在外匯軟體的指標腳本中呼叫的”有可能是用戶權限的問題,運行腳本的用戶很可能是一個內置的低權限帳戶,你自己寫個exe呼叫此dll看是否成功。uj5u.com熱心網友回復:
CoInitialize(NULL);//初始化COM套件CoUninitialize();//釋放COM套件
使用com組件前后需要呼叫com組件初始化和釋放;嘗試在動態庫中加入這兩個函式試試
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/71213.html
