#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;

}