2016年2月13日土曜日

IFileOperationのCopyItemsについて

こんにちは

最近、windows内で、ファイルをコピーするときに、SHFileOperationより、IFileOperationを利用したほうが良いと知りました。windows XP SP3以降はそうらしいです。

しかし、ネット上にIFileOperationの情報が少なくて、実装に大分時間がかかりました。。。それで、ネット上に備忘録も記載します。

参考になったサイトは以下で、そこを見れば、大体のことはわかると思います。

単体ファイルコピーのCopyItem関数についてはmsdnのサイト、そのままでいけました。その後、の複数ファイルをコピーするCopyItems関数の使い方を調べ出して、時間がかかりました。CopyItemをループで回してる人も多そうですね。もしかすると、そっちの方が、内部処理的に早いかもといまさら思いました 笑

CopyItemsを使う場合は以下のようにすれば、可能です。

int CFileManager::CopySelectedFileToSpecifiedFolder(list<CString>* listCopiedFilePath, CString csImportFolder)
{
if (listCopiedFilePath == NULL || listCopiedFilePath->empty() == true) {
return -1;
}

HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 
if (!SUCCEEDED(hr))
{
return -1;
}

PIDLIST_ABSOLUTE abSourcePidl = NULL;
SFGAOF attrs;

int srcFileNum = listCopiedFilePath->size();
PIDLIST_ABSOLUTE[] pPidlRawArray = new PIDLIST_ABSOLUTE[srcFileNum]);

int no = 0;
for (list<CString>::iterator it = listCopiedFilePath->begin(); it != listCopiedFilePath->end(); it++)
{
CString strSource = *listCopiedFilePath->begin();
hr = SHParseDisplayName(*it, NULL, &abSourcePidl, 0, &attrs);    
if (FAILED(hr))
{
return -1;
}
pPidlRawArray[no] = abSourcePidl;
no++;
}
    delete[] PIDLIST_ABSOLUTE;

CComPtr<IShellItemArray> pShellItemArr = NULL;
hr = SHCreateShellItemArrayFromIDLists(srcFileNum, (LPCITEMIDLIST*)pPidlRawArray.get(), &pShellItemArr);
if (FAILED(hr))
{
return -1;
}


PIDLIST_ABSOLUTE abDestPidl = NULL;

hr = SHParseDisplayName(csImportFolder, NULL, &abDestPidl, 0, &attrs);
if (FAILED(hr))
{
return -1;
}

CComPtr<IShellItem2> pDestShellItem;

hr = SHCreateItemFromIDList(abDestPidl, IID_IShellItem2, reinterpret_cast<LPVOID*>(&pDestShellItem));
if (FAILED(hr))
{
return -1;
}

CComPtr<IFileOperation> fileOp;
hr = fileOp.CoCreateInstance(CLSID_FileOperation);
if (FAILED(hr))
{
return -1;
}

hr = fileOp->CopyItems(pShellItemArr, pDestShellItem);
if (FAILED(hr))
{
return -1;
}

hr = fileOp->PerformOperations();
if (FAILED(hr))
{
return -1;
}

CoUninitialize();

return 0;
}

std::listを使ってたり、一部コード修正したので、コンパイルは未確認だったりしますが、ほぼ同じコードで動作確認しています。
ご参考までにご利用ください。

ではでは~ 

0 件のコメント:

コメントを投稿