So I have a very simple job to do: decompress a zip file. Thought I'd find a simple solution withing 5 seconds online but I'm still struggling.
I've obviously read these posts:
But the answers suggest to make use of zlib and libzip or miniz.
I'm sure these approaches works just fine. However it seems that it is not straightforward trying to apply this approach in existing VS2013 solution.
Then I came across this simple solution, ref1, ref2, that make use of IShellDispatch object
I rushed to implement it:
bool DecompressZIP(_In_ const wpath& pathFile, _In_ const wpath& pathDstDir)
{
BSTR source = _bstr_t(pathFile.string().c_str());
BSTR dest = _bstr_t(pathDstDir.string().c_str());
HRESULT hResult = S_FALSE;
IShellDispatch *pIShellDispatch = NULL;
Folder *pToFolder = NULL;
VARIANT variantDir, variantFile, variantOpt;
CoInitialize(NULL);
hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
IID_IShellDispatch, (void **)&pIShellDispatch);
if (SUCCEEDED(hResult) && NULL != pIShellDispatch)
{
VariantInit(&variantDir);
variantDir.vt = VT_BSTR;
variantDir.bstrVal = dest;
hResult = pIShellDispatch->NameSpace(variantDir, &pToFolder);
if (SUCCEEDED(hResult) && NULL != pToFolder)
{
Folder *pFromFolder = NULL;
VariantInit(&variantFile);
variantFile.vt = VT_BSTR;
variantFile.bstrVal = source;
hResult = pIShellDispatch->NameSpace(variantFile, &pFromFolder);
if (SUCCEEDED(hResult) && NULL != pFromFolder)
{
FolderItems *fi = NULL;
pFromFolder->Items(&fi);
VariantInit(&variantOpt);
variantOpt.vt = VT_I4;
variantOpt.lVal = FOF_NO_UI;
VARIANT newV;
VariantInit(&newV);
newV.vt = VT_DISPATCH;
newV.pdispVal = fi;
hResult = pToFolder->CopyHere(newV, variantOpt);
Sleep(1000);
pFromFolder->Release();
pToFolder->Release();
}
}
pIShellDispatch->Release();
}
CoUninitialize();
return true;
}
BUT IT DOES NOT WORK !
line:
hResult = pIShellDispatch->NameSpace(variantFile, &pFromFolder);
always result in pFromFolder == NULL
hResult is S_FALSESUCCEEDED(hResult) is trueGetLastError is 0what am I doing wrong?
bool CUnZip::Unzip2Folder(BSTR lpZipFile, BSTR lpFolder)
{
IShellDispatch *pISD;
Folder *pZippedFile = 0L;
Folder *pDestination = 0L;
long FilesCount = 0;
IDispatch* pItem = 0L;
FolderItems *pFilesInside = 0L;
VARIANT Options, OutFolder, InZipFile, Item;
CoInitialize(NULL);
__try{
if (CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pISD) != S_OK)
return 1;
InZipFile.vt = VT_BSTR;
InZipFile.bstrVal = lpZipFile;
pISD->NameSpace(InZipFile, &pZippedFile);
if (!pZippedFile)
{
pISD->Release();
return 1;
}
OutFolder.vt = VT_BSTR;
OutFolder.bstrVal = lpFolder;
pISD->NameSpace(OutFolder, &pDestination);
if (!pDestination)
{
pZippedFile->Release();
pISD->Release();
return 1;
}
pZippedFile->Items(&pFilesInside);
if (!pFilesInside)
{
pDestination->Release();
pZippedFile->Release();
pISD->Release();
return 1;
}
pFilesInside->get_Count(&FilesCount);
if (FilesCount < 1)
{
pFilesInside->Release();
pDestination->Release();
pZippedFile->Release();
pISD->Release();
return 0;
}
pFilesInside->QueryInterface(IID_IDispatch, (void**)&pItem);
Item.vt = VT_DISPATCH;
Item.pdispVal = pItem;
Options.vt = VT_I4;
Options.lVal = 1024 | 512 | 16 | 4;//http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
bool retval = pDestination->CopyHere(Item, Options) == S_OK;
pItem->Release(); pItem = 0L;
pFilesInside->Release(); pFilesInside = 0L;
pDestination->Release(); pDestination = 0L;
pZippedFile->Release(); pZippedFile = 0L;
pISD->Release(); pISD = 0L;
return retval;
}
__finally
{
CoUninitialize();
}
}
Source: https://social.msdn.microsoft.com/Forums/vstudio/en-US/45668d18-2840-4887-87e1-4085201f4103/visual-c-to-unzip-a-zip-file-to-a-specific-directory?forum=vclanguage
In the main, you call:
CUnZip * Z = new CUnZip();
BSTR bstrFile = strFileName.AllocSysString();
BSTR bstrPath = m_strPathName.AllocSysString();
Z->Unzip2Folder(bstrFile, bstrPath);
delete Z;
Z = NULL;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With