C++でのCreateObject
2006年1月19日
前の記事の続き。IDispatchの取得方法。
C++で"WScript.Shell"オブジェクトを作成し、Invokeで"CurrentDirectory"プロパティを取得してみた。
実行結果
C++で"WScript.Shell"オブジェクトを作成し、Invokeで"CurrentDirectory"プロパティを取得してみた。
#include <windows.h> UINT HexToByte(LPSTR hex,int pos){ UINT b1,b2; static const LPSTR ZeroToF="0123456789ABCDEFabcdef"; for (b1=0;hex[pos]!=ZeroToF[b1];b1++); if (15<b1) b1=b1-6; for (b2=0;hex[pos+1]!=ZeroToF[b2];b2++); if (15<b2) b2=b2-6; return (b1<<4)+b2; } IDispatch* CreateObject(LPSTR ComName){ int i,j; char ANSI[MAX_PATH]; //Resolve DLL file name HKEY key; CLSID clsid; for (i=0;ANSI[i]=ComName[i];i++); for (j=0;ANSI[i]="\\CLSID"[j++];i++); if (ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CLASSES_ROOT,ANSI,0,KEY_READ,&key)) return 0; for (i=0;ANSI[i]="CLSID\\"[i];i++); i=MAX_PATH-6; if (ERROR_SUCCESS!=RegQueryValueEx(key,NULL,0,NULL,(LPBYTE)(ANSI+6),(LPDWORD)&i)) return 0; RegCloseKey(key); for (i=0;ANSI[i];i++); for (j=0;ANSI[i]="\\InProcServer32"[j++];i++); if (ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CLASSES_ROOT,ANSI,0,KEY_READ,&key)) return 0; clsid.Data1=(((((HexToByte(ANSI,7)<<8)+HexToByte(ANSI,9))<<8)+HexToByte(ANSI,11))<<8)+HexToByte(ANSI,13); clsid.Data2=(HexToByte(ANSI,16)<<8)+HexToByte(ANSI,18); clsid.Data3=(HexToByte(ANSI,21)<<8)+HexToByte(ANSI,23); for (i=0;i<2;i++) clsid.Data4[i]=HexToByte(ANSI,26+i*2); for (i=2;i<8;i++) clsid.Data4[i]=HexToByte(ANSI,27+i*2); i=MAX_PATH; if (ERROR_SUCCESS!=RegQueryValueEx(key,NULL,0,NULL,(LPBYTE)ANSI,(LPDWORD)&i)) return 0; RegCloseKey(key); //Load DLL & check DllGetClassObject HINSTANCE hDLL; void* Address; if (!(hDLL=LoadLibrary(ANSI))) return 0; if (!(Address=GetProcAddress(hDLL,"DllGetClassObject"))) return 0; //DllGetClassObject(&clsid,IID_IClassFactory,(LPVOID*)&ppv); IClassFactory* ppv=0; void *Stack1,*Stack2,*Stack3; Stack3=&ppv; Stack2=(void*)&IID_IClassFactory; Stack1=&clsid; _asm push Stack3; _asm push Stack2; _asm push Stack1; _asm call Address; _asm mov i,eax; if (i!=S_OK || !ppv) return 0; IDispatch* ppvObject=0; if (S_OK!=ppv->QueryInterface(IID_IClassFactory, (void**) &ppv)) return 0; ppv->Release(); if (S_OK!=ppv->CreateInstance(NULL,IID_IUnknown,(void**)&ppvObject)) return 0; ppv->Release(); if (!ppvObject) return 0; if (S_OK!=ppvObject->QueryInterface(IID_IDispatch,(void**)&ppvObject)) return 0; ppvObject->Release(); return ppvObject; } WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int intShowCmd) { IDispatch* pDisp=CreateObject("WScript.Shell"); if (!pDisp) return 1; LPOLESTR* rgszNames; rgszNames=new LPOLESTR; DISPID* rgDispId; rgDispId=new DISPID; rgszNames[0]=L"CurrentDirectory"; int ret=pDisp->GetIDsOfNames(GUID_NULL, rgszNames,1, NULL, rgDispId); if (ret!=S_OK) return ret; DISPPARAMS* pDispParams; VARIANT* pVarResult; pDispParams=new DISPPARAMS; pVarResult=new VARIANT; pDispParams->rgdispidNamedArgs = NULL; pDispParams->cNamedArgs = 0; pDispParams->cArgs=0; pDispParams->rgvarg=NULL; ret=pDisp->Invoke(rgDispId[0], GUID_NULL, NULL,DISPATCH_PROPERTYGET,pDispParams, pVarResult,NULL, NULL); if (ret!=S_OK) return ret; if (pVarResult->vt!=VT_BSTR) return 1; MessageBoxW(0,pVarResult->bstrVal,L"CurrentDirectory",0); return 0; }
実行結果
コメント
Kat (2008年7月6日 16:11:33)
このコードでは問題ないが、利用するCOMオブジェクトによっては、
OleInitialize(NULL);
を最初に実行しておかないと、うまく働かないことがある。msscript.ocx(ScriptControl)などがそれ。
参考:
http://msdn.microsoft.com/en-us/library/ms690134(VS.85).aspx
OleInitialize(NULL);
を最初に実行しておかないと、うまく働かないことがある。msscript.ocx(ScriptControl)などがそれ。
参考:
http://msdn.microsoft.com/en-us/library/ms690134(VS.85).aspx