Skip to content

Instantly share code, notes, and snippets.

@lxfly2000
Created October 7, 2017 05:13
Show Gist options
  • Save lxfly2000/24c7c3984128578e080e17eb0365d627 to your computer and use it in GitHub Desktop.
Save lxfly2000/24c7c3984128578e080e17eb0365d627 to your computer and use it in GitHub Desktop.
使用Windows自带的API解压zip文件。
#include<Windows.h>
#include<ShObjIdl.h>
#include<ShlObj.h>
#include<fstream>
LPWSTR TrimQuote(LPWSTR str)
{
int ifrom = 0, ito = 0;
while (str[ifrom])
{
if (str[ifrom] != '\"')
{
str[ito] = str[ifrom];
ito++;
}
ifrom++;
}
return str;
}
//http://blog.csdn.net/xhhjin/article/details/6550467
//释放使用 CoTaskMemFree
LPITEMIDLIST GetItemIDListFromFilePath(LPCTSTR strFilePath)
{
if (!strFilePath)
{
return NULL;
}
// 得到桌面的目录
LPSHELLFOLDER pDesktopFolder = NULL;
HRESULT hr = SHGetDesktopFolder(&pDesktopFolder);
if (FAILED(hr))
{
return NULL;
}
// 得到文件路径对应的ItemIDList
LPITEMIDLIST pItemIDList = NULL;
TCHAR strbuf[MAX_PATH];
lstrcpy(strbuf, strFilePath);
hr = pDesktopFolder->ParseDisplayName(NULL, NULL, strbuf, NULL, &pItemIDList, NULL);
pDesktopFolder->Release();
if (FAILED(hr))
{
return NULL;
}
return pItemIDList;
}
BOOL ChooseDirectory(HWND hWndParent, TCHAR *fullPath, PCTSTR pcszDefaultPath, PCTSTR pcszTitle)
{
IFileDialog *pf;
CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pf));
FILEOPENDIALOGOPTIONS odo;
pf->GetOptions(&odo);
pf->SetOptions(FOS_PICKFOLDERS | odo);
pf->SetTitle(pcszTitle);
IShellItem *psi;
if (pcszDefaultPath)
{
LPITEMIDLIST pi = GetItemIDListFromFilePath(pcszDefaultPath);
SHCreateShellItem(NULL, NULL, pi, &psi);
CoTaskMemFree(pi);
pf->SetFolder(psi);
psi->Release();
}
if (pf->Show(hWndParent) == HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
pf->Release();
return FALSE;
}
TCHAR *compath;
pf->GetResult(&psi);
psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &compath);
lstrcpy(fullPath, compath);
CoTaskMemFree(compath);
psi->Release();
pf->Release();
return TRUE;
}
BOOL ChooseFile(HWND hWndParent, TCHAR *filepath, TCHAR *filename, PCTSTR pcszFiletype, PCTSTR pcszTitle)
{
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof OPENFILENAME;
ofn.hwndOwner = hWndParent;
ofn.hInstance = nullptr;
ofn.lpstrFilter = pcszFiletype;
ofn.lpstrFile = filepath;
ofn.lpstrTitle = pcszTitle;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = filename;
ofn.nMaxFileTitle = MAX_PATH;
ofn.Flags = OFN_HIDEREADONLY;
return GetOpenFileName(&ofn);
}
//https://vcpptips.wordpress.com/tag/copyhere/
int NewZipFile(const wchar_t *strFilePath)
{
std::fstream fnzip;
fnzip.open(strFilePath, std::ios::in | std::ios::binary);
if (fnzip)
{
fnzip.close();
return -1;
}
char startBuffer[22] = { 80,75,5,6 };
fnzip.open(strFilePath, std::ios::out | std::ios::binary);
if (!fnzip)return -2;
fnzip.write(startBuffer, std::size(startBuffer));
fnzip.close();
return 0;
}
__declspec(deprecated("该函数目前无法使用。"))int ZipFile(LPWSTR strSrc, LPWSTR strZipFile)
{
if (NewZipFile(strZipFile))return -1;
IShellDispatch *ps;
Folder *ptof;
VARIANT vDir, vFile, vOpt;
CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&ps);
VariantInit(&vDir);
vDir.vt = VT_BSTR;
vDir.bstrVal = strZipFile;
ps->NameSpace(vDir, &ptof);
VariantInit(&vFile);
vFile.vt = VT_BSTR;
vFile.bstrVal = strSrc;
VariantInit(&vOpt);
vOpt.vt = VT_I4;
vOpt.lVal = NULL;// FOF_NO_UI;
if (FAILED(ptof->CopyHere(vFile, vOpt)))return -2;
ptof->Release();
ps->Release();
return 0;
}
//COM 函数
int UnzipFile(LPWSTR strSrc, LPWSTR strFolder)
{
IShellDispatch *ps;
Folder *pfromf, *ptof;
VARIANT vToDir, vFileFrom, vOpt;//OLE 类型
CoCreateInstance(CLSID_Shell, nullptr, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&ps);
VariantInit(&vToDir);
vToDir.vt = VT_BSTR;
vToDir.bstrVal = strFolder;
ps->NameSpace(vToDir, &ptof);
VariantInit(&vFileFrom);
vFileFrom.vt = VT_BSTR;
vFileFrom.bstrVal = strSrc;
ps->NameSpace(vFileFrom, &pfromf);
FolderItems *pfis;
pfromf->Items(&pfis);
VariantInit(&vOpt);
vOpt.vt = VT_I4;
vOpt.lVal = NULL;// FOF_NO_UI;
VARIANT vNew;
VariantInit(&vNew);
vNew.vt = VT_DISPATCH;
vNew.pdispVal = pfis;
if (FAILED(ptof->CopyHere(vNew, vOpt)))
return -1;
pfromf->Release();
ptof->Release();
ps->Release();
return 0;
}
int wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
WCHAR zipfile[MAX_PATH] = L"", topath[MAX_PATH] = L".\\";
bool cancelled = false;
if (FAILED(CoInitialize(NULL)))return -1;
if (__argc == 3)
{
lstrcpy(zipfile, __wargv[1]);
TrimQuote(zipfile);
lstrcpy(topath, __wargv[2]);
TrimQuote(topath);
}
else
{
if (!ChooseFile(NULL, zipfile, NULL, L"压缩文件(ZIP)\0*.zip\0所有文件\0*\0\0", NULL) ||
!ChooseDirectory(NULL, topath, NULL, NULL))
cancelled = true;
}
//解压文件
if (!cancelled&&UnzipFile(zipfile, topath))return -2;
CoUninitialize();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment