カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

Visual C++ 2017でATLを利用してScripting.FileSystemObjectのインスタンスを作成する方法

概要

Visual C++ 2017でATLを利用してScripting.FileSystemObjectのインスタンスを作成する方法のサンプルコードです。この例では作成したインスタンスから現在のフォルダの名前を取得します。

ソースコード

#define STRICT
#include <Windows.h>
#include <atlbase.h>

using namespace::ATL;

CComBSTR GetCurrentFolderNameByFSO();

int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
	// COMの初期化
	HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
	if (FAILED(hr))
		return hr;

	auto currentFolderName = GetCurrentFolderNameByFSO();

	// COMの開放
	CoUninitialize();

	return hr;
}

CComBSTR GetCurrentFolderNameByFSO()
{
	CComPtr<IDispatch> pFSO;
	HRESULT hr = pFSO.CoCreateInstance(L"Scripting.FileSystemObject", nullptr);
	if (FAILED(hr))
		return nullptr;

	CComVariant vResult;
	hr = pFSO.Invoke1(L"GetFolder", &CComVariant(L"."), &vResult);
	if (FAILED(hr))
		return nullptr;

	CComQIPtr<IDispatch> pFolder(vResult.pdispVal);
	CComVariant vName;
	hr = pFolder.GetPropertyByName(L"Name", &vName);
	if (FAILED(hr) || vName.vt != VT_BSTR)
		return nullptr;
	return vName.bstrVal;
}

説明

using namespace::ATLによるATL::の省略

ATLのメンバーはATL名前空間(namespace ATL {...})に存在しており、例えばCComPtr<...>はATL::CComPtr<...>と書く必要があります。このソースコードはサンプル用のものであり、ATL名前空間のメンバーとの衝突を気にしないため、using namespace::ATLによりATL::の省略を許可しています。

CComPtr<...>::CoCreateInstanceメソッドによるProgIDからインスタンスの作成

ATLを使用しない場合、既知のProgIDからCOMクラスのインスタンスを作成する場合、(1)ProgIDからCLSIDの取得(CLSIDFromProgID関数)、(2)CLSIDからインスタンスの作成(CoCreateInstanceEx関数)の手順が必要となります。

ATLを使用する場合、CComPTRクラスの公開するProgIDを引数としたCoCreateInstanceメソッドを使用することでこれらの手順を省略することができます。また、CLSIDFromProgID関数の呼び出しやメモリ管理を省略することができます。

CComPtrによるDISPID取得の省略

ATLを使用しない場合、IDispatchインターフェイスを使用して名前と引数からメソッドやプロパティを呼び出すには名前からDISPIDの取得などが必要となります。

ATLを使用する場合、Invoke系メソッド(Invoke0、Invoke1、Invoke2、InvokeN)やGetPropertyByNameメソッド等を使用することでこれらの手順を省略することができます。