概要

 シェルが提供するIShellDispatchを用いてZIPファイルを解凍します。
 IShellDispatchには、ファイル名を指定して実行(FileRun)や検索などがあります。
 Windows XPより標準でZIP圧縮機能が搭載されました。
 本プログラムでは、C:¥temp2¥sample.zipファイルをC:¥temp2¥sampleフォルダーに解凍します。
 C:¥temp2¥sampleフォルダーは予め作成しておく必要があります。

テスト環境

コンパイラ

Visual C++ 2013 Express 32/64bit Windows 7/10

プログラムソースの概要

_tmain関数

 Windowsから最初に_tmain関数が呼び出されます。
 COMインターフェースをCoInitializeExで初期化します。
 CoCreateInstanceによりIShellDispatchオブジェクトを取得します。
 ExtractZip関数を呼び出してZIPファイルを指定フォルダーへ解凍します。
 CoUninitializeでCOMインターフェースを解放します。

ExtractZip

 ZIPファイル中身(Items)のフォルダー型から解凍先のフォルダーのFolder型へコピーすることにより解凍することができます。圧縮と異なり実際に実行すると非同期動作はしていませんでしたので圧縮に比べると単純なプログラムとなります。  以下のような手順で処理します。
  1.  解凍先フォルダー名(TCHAR*型)からVARIANT型を作成しNameSpaceによりFolder型オブジェクトを作成します。
    VARIANT型は不要ですのでVariantClearにより解放します。
  2.  ZIPファイル名(TCHAR*型)からVARIANT型を作成しNameSpaceによりFolder型オブジェクトを作成します。
    VARIANT型は不要ですのでVariantClearにより解放します。
  3.  ZIPファイルのFolder型の中身をitemsで取得します。
  4.  解凍先のFolder型のCopyHere関数により解凍します。
  5.  各オブジェクトを解放して関数を終了します。

プログラムソース

// ZIPファイルの展開(Unicode専用)
// あらかじめ展開先フォルダーを作成する必要が有ります。
// Visual C++ 2013

#include <windows.h>
#include <shlobj.h>
#include <tlhelp32.h>
#include <locale.h>
#include <tchar.h>

// ZIPファイルの展開
BOOL ExtractZip(IShellDispatch *pShellDisp, TCHAR* ZipPath, TCHAR* OutPath);

void _tmain(void){
	HRESULT hr;
	IShellDispatch *pShellDisp;
	// UNICODE文字を標準出力に正しく表示させるためにロケールを設定
	_tsetlocale(LC_ALL, _TEXT(""));

	CoInitializeEx(0, COINIT_MULTITHREADED);
	hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pShellDisp));
	if (FAILED(hr)) {
		CoUninitialize();
		return;
	}
	//                               ZIPファイル                     展開先
	ExtractZip(pShellDisp, _TEXT("c:¥¥temp2¥¥sample.zip"), _TEXT("c:¥¥temp2¥¥sample"));
	CoUninitialize();
	return;
}

BOOL ExtractZip(IShellDispatch *pShellDisp, TCHAR* ZipPath, TCHAR* OutPath){
	HRESULT hr;
	VARIANT vDtcDir;
	Folder  *pOutDtc;
	// 展開先Folderオブジェクトを作成
	VariantInit(&vDtcDir);
	vDtcDir.vt = VT_BSTR;
	vDtcDir.bstrVal = SysAllocString(OutPath);
	hr = pShellDisp->NameSpace(vDtcDir, &pOutDtc);
	VariantClear(&vDtcDir);
	if (hr != S_OK){
		MessageBox(NULL, TEXT("展開先フォルダーが見つかりませんでした。"), NULL, MB_ICONWARNING);
		return FALSE;
	}
	// ZIPファイルのFolderオブジェクトを作成
	VARIANT varZip;
	Folder *pZipFile;
	VariantInit(&varZip);
	varZip.vt = VT_BSTR;
	varZip.bstrVal = SysAllocString(ZipPath);
	hr = pShellDisp->NameSpace(varZip, &pZipFile);
	VariantClear(&varZip);
	if (hr != S_OK) {
		pOutDtc->Release();
		MessageBox(NULL, TEXT("ZIPファイルが見つかりませんでした。"), NULL, MB_ICONWARNING);
		return FALSE;
	}
	// ZIPファイルの中身を取得
	FolderItems *pZipItems;
	hr = pZipFile->Items(&pZipItems);
	if (hr != S_OK) {
		pZipFile->Release();
		pOutDtc->Release();
		return FALSE;
	}
	VARIANT vDisp, vOpt;
	VariantInit(&vDisp);
	vDisp.vt = VT_DISPATCH;
	vDisp.pdispVal = pZipItems;
	VariantInit(&vOpt);
	vOpt.vt = VT_I4;
	vOpt.lVal = 0; //FOF_SILENTを指定すると処理中の経過が表示されなくなります
	// ZIPファイルの中身を展開先フォルダーにコピー
	hr = pOutDtc->CopyHere(vDisp, vOpt);
	if (hr != S_OK) {
		pZipItems->Release();
		pZipFile->Release();
		pOutDtc->Release();
		MessageBox(NULL, TEXT("展開に失敗しました。"), NULL, MB_ICONWARNING);
		return FALSE;
	}

	pZipItems->Release();
	pZipFile->Release();
	pOutDtc->Release();

	return TRUE;
}

ソースファイルと実行ファイルのダウンロード

ダウンロード zip_ext.zip(50.1kByte)
ZIPファイルに含まれるファイル
zip_ext.cpp
zip_ext.exe