Created
December 6, 2023 11:04
-
-
Save kaimingguo/d2ebabbc6920f8e58ba48f1f0098e069 to your computer and use it in GitHub Desktop.
Automation OLE Display PowerPoint Version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <ole2.h> | |
#include <iostream> | |
#include <memory> | |
#include <sstream> | |
#include <vector> | |
template <class T> | |
void SafeRelease(T **ppT) { | |
if (*ppT) { | |
(*ppT)->Release(); | |
*ppT = nullptr; | |
} | |
} | |
HRESULT AutoWrap(int, VARIANT *, IDispatch *, LPOLESTR, int...); | |
int main(int argc, char *argv[]) { | |
HRESULT hr; | |
CLSID clsid; | |
IDispatch *app = nullptr; | |
std::wostringstream wss; | |
hr = CoInitialize(NULL); | |
if (FAILED(hr)) { | |
std::cerr << "Failed to initialize COM" << std::endl; | |
return EXIT_FAILURE; | |
} | |
hr = CLSIDFromProgID(_T("PowerPoint.Application"), &clsid); | |
if (FAILED(hr)) { | |
std::cerr << "CLSIDFromProgID() failed" << std::endl; | |
goto exit; | |
} | |
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, | |
reinterpret_cast<void **>(&app)); | |
if (FAILED(hr)) { | |
std::cerr << "PowerPoint not registered property" << std::endl; | |
goto exit; | |
} | |
{ | |
VARIANT result; | |
VariantInit(&result); | |
AutoWrap(DISPATCH_PROPERTYGET, &result, app, _T("Version"), 0); | |
std::wstring ws(result.bstrVal, SysStringLen(result.bstrVal)); | |
wss << _T("Microsoft PowerPoint v") << ws.c_str() << _T(" "); | |
VariantClear(&result); | |
} | |
{ | |
VARIANT result; | |
VariantInit(&result); | |
AutoWrap(DISPATCH_PROPERTYGET, &result, app, _T("Build"), 0); | |
std::wstring ws(result.bstrVal, SysStringLen(result.bstrVal)); | |
wss << _T("Build ") << ws.c_str() << _T(" "); | |
VariantClear(&result); | |
} | |
{ | |
VARIANT result; | |
VariantInit(&result); | |
AutoWrap(DISPATCH_PROPERTYGET, &result, app, _T("OperatingSystem"), 0); | |
std::wstring ws(result.bstrVal, SysStringLen(result.bstrVal)); | |
wss << _T("on ") << ws.c_str() << std::endl; | |
VariantClear(&result); | |
} | |
std::wcout << wss.str() << std::endl; | |
// Tell Excel to quit | |
AutoWrap(DISPATCH_METHOD, nullptr, app, _T("Quit"), 0); | |
exit: | |
SafeRelease(&app); | |
CoUninitialize(); | |
return 0; | |
} | |
HRESULT AutoWrap(int auto_type, VARIANT *result, IDispatch *disp, LPOLESTR name, | |
int args...) { | |
if (!disp) { | |
return E_INVALIDARG; | |
} | |
HRESULT hr; | |
DISPPARAMS dp = {0}; | |
DISPID dispid_named = DISPID_PROPERTYPUT; | |
DISPID dispid; | |
std::shared_ptr<EXCEPINFO> excep; | |
std::vector<VARIANT> arg_vec(args + 1); | |
va_list marker; | |
va_start(marker, args); | |
for (auto i = 0; i < args; i++) { | |
arg_vec[i] = va_arg(marker, VARIANT); | |
} | |
va_end(marker); | |
hr = disp->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid); | |
if (FAILED(hr)) { | |
_tprintf(_T("IDispatch::GetIDsOfName(\"%s\") failed w/err 0x%08lx"), name, hr); | |
return hr; | |
} | |
dp.cArgs = args; | |
dp.rgvarg = arg_vec.data(); | |
if (auto_type & DISPATCH_PROPERTYPUT) { | |
dp.cNamedArgs = 1; | |
dp.rgdispidNamedArgs = &dispid_named; | |
} | |
hr = disp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, auto_type, &dp, | |
result, excep.get(), nullptr); | |
if (FAILED(hr)) { | |
if (hr == DISP_E_EXCEPTION) { | |
_tprintf(_T("IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx"), name, dispid, excep->scode); | |
} else { | |
_tprintf(_T("IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx"), name, dispid, hr); | |
} | |
return hr; | |
} | |
arg_vec.clear(); | |
return S_OK; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment