#import 쓰면 엄청 간단해지긴 한데. 해보니 컴파일러가 이름 충돌에 매개 변수 선언 ㅈㄹㅈㄹ거려서
해결하다가 짱나서 걍 IDIspatch 노가다로 함. ㅅㄱ
Visual Basic 6의 CreateObject 함수나 JScript의 new ActiveXObject가 내부적으로 쓰는 방법과 똑같은 방법임.
코드 디씨 게시판이라 짤릴 수 있으니 http://pastebin.com/pSUkxM05 에서 보기를 권장.
#include <cstdio>
#include <cstdlib>
#include <windows.h>
using namespace std;
int main(void) {
// 0단계: COM 초기화
CoInitialize(NULL);
// 1단계: ProgID → CLSID 변환 (CLSID를 직접 알고 있는 경우엔 생략)
CLSID clsid;
if(!SUCCEEDED(CLSIDFromProgID(L"WScript.Shell", &clsid)))
return EXIT_FAILURE;
// 1단계 성공
printf("[+] ProgID(Progmatic ID) \"WScript.Shell\"로부터 CLSID(Class ID)를 얻음!\\n");
// 2단계: Class Instance 생성 (인터페이스는 IDIspatch)
IDispatch *pDisp = NULL;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void **)&pDisp);
if(!SUCCEEDED(hr))
return EXIT_FAILURE;
printf("[+] 클래스 인스턴스 생성 성공!\\n");
// 3단계: WScript.Shell의 메서드 사용
DISPID dispId;
LPOLESTR rgszNames[] = {L"Run"};
hr = pDisp->GetIDsOfNames(IID_NULL, rgszNames, 1U, LOCALE_SYSTEM_DEFAULT, &dispId); // Run 메서드의 Dispatch ID를 구함
if(!SUCCEEDED(hr))
return EXIT_FAILURE;
printf("[+] WScript.Shell의 Run 메서드의 DIspatch ID를 얻어옴!\\n");
// 인자는 한 개. 인자에 대한 정보를 만듦
DISPPARAMS dispParams;
DISPID dispIdNamedArgs[] = {0}; // 첫번째 인자
VARIANTARG v[1];
dispParams.cArgs = dispParams.cNamedArgs = 1;
dispParams.rgdispidNamedArgs = dispIdNamedArgs;
dispParams.rgvarg = v;
v[0].vt = VT_BSTR; // BSTR(Basic String) 타입
v[0].bstrVal = SysAllocString(L"calc.exe");
VARIANT varResult;
UINT uArgErr;
hr = pDisp->Invoke(dispId, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispParams, &varResult, NULL, &uArgErr); // IDispatch::Invoke를 이용해 Run 메서드 호출
if(!SUCCEEDED(hr))
return EXIT_FAILURE;
printf("[+] WScript.Shell의 Run 메서드 호출 성공!\\n");
// 4단계: COM 정리
CoUninitialize();
return EXIT_SUCCESS;
}
https://download.kiwoom.com/web/openapi/kiwoom_openapi_plus_devguide_ver_1.1.pdf
음. 읽어 보니 꽤나 방대하네. 다 저 방법으로 호출해서 연동할 수 있기는 한데(이벤트도 IConnectionSink 인터페이스였나 이걸로 수동으로 연동 가능함) 사람 할 짓이 못 돼지. #import 쓰는 게 현명.