使用windows api解压zip文件(不依赖第三方工具和库)

news/2024/9/19 8:56:32/文章来源:https://www.cnblogs.com/rrbfd-xq/p/18416825

本人最近工作当中遇到了解压失败的问题,由于工作中使用C++语言,当前的解压方案是起一个进程去调用7z工具来解压,该方法有时会报错,具体原因尚未明确。于是我在想要不直接使用C++代码解压,先看了一下当前的解压第三方库,一个有名的是zlib,当看了一下解压到目录的实现,好家伙,2000行代码,吃不消,后来放弃这条路了。然后就一直在网上查找是否用简单的方式实现,最好不要依赖第三方库,那样还得引入开源备案及遵守开源协议等一些麻烦事。找了好久,终于找到了一篇博文,介绍了一个使用windows api直接解压到一个目录的代码,由于比较久远,原文链接有时间再补上。代码不多,我自己润色了一下(改了一些变量名并加了好多判断),最终实现了。
`#include <Windows.h>

include <Shldisp.h> ///Shldisp.idl

include <stdio.h>

include <locale.h>

define FreeResource(A) \

if (A != NULL) {    \A->Release();   \
}

bool UnZipFolder(wchar_t* zipFile, wchar_t* dstDir)
{
bool bReturn = false;
HRESULT hResult;
IShellDispatch* pISD = NULL;
Folder* pToFolder = NULL;
Folder* pFromFolder = NULL;
FolderItems* pFolderItems = NULL;
FolderItems* pToFolderItems = NULL;
BSTR bstrZipFile = NULL;
BSTR bstrDstDir = NULL;
IDispatch* pDispatch = NULL;
VARIANT vDstDir, vZipFile, vtDispatch, vOpt;
long fromFolderCount = 0;
long toFolderCount = 0;

hResult = CoInitialize(NULL);
if (FAILED(hResult)) 
{printf("%d failed", __LINE__);goto FINAL;
}hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pISD);
if (FAILED(hResult) || pISD == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}bstrZipFile = SysAllocString(zipFile);
if (bstrZipFile == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}bstrDstDir = SysAllocString(dstDir);
if (bstrDstDir == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}VariantInit(&vZipFile);
vZipFile.vt = VT_BSTR;
vZipFile.bstrVal = bstrZipFile;VariantInit(&vDstDir);
vDstDir.vt = VT_BSTR;
vDstDir.bstrVal = bstrDstDir;hResult = pISD->NameSpace(vZipFile, &pFromFolder);
if (FAILED(hResult) || pFromFolder == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}hResult = pISD->NameSpace(vDstDir, &pToFolder);
if (FAILED(hResult) || pToFolder == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}hResult = pFromFolder->Items(&pFolderItems);
if (FAILED(hResult) || pFolderItems == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}pFolderItems->get_Count(&fromFolderCount);
if (fromFolderCount < 1)
{printf("%d failed", __LINE__);goto FINAL;
}pFolderItems->QueryInterface(IID_IDispatch, (void**)&pDispatch);
if (FAILED(hResult) || pDispatch == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}VariantInit(&vtDispatch);
vtDispatch.vt = VT_DISPATCH;
vtDispatch.pdispVal = pDispatch;VariantInit(&vOpt);
vOpt.vt = VT_I4;
vOpt.lVal = 16 + 4; // Do not display a progress dialog box ~ This will not work properly!printf("Extracting files ...\n");
hResult = pToFolder->CopyHere(vtDispatch, vOpt);
if (FAILED(hResult))
{printf("%d failed", __LINE__);goto FINAL;
}hResult = pToFolder->Items(&pToFolderItems);
if (FAILED(hResult) || pToFolderItems == NULL)
{printf("%d failed", __LINE__);goto FINAL;
}// 等待10000秒,看是否会超时
for (int i = 0; i < 10000; i++)
{toFolderCount = pToFolderItems->get_Count(&toFolderCount);printf("target = %d, current = %d\n", fromFolderCount, toFolderCount);if (toFolderCount >= fromFolderCount){printf("unzip succes done at time %d\n", i);bReturn = true;goto FINAL;}Sleep(1);
}    
printf("unzip out time\n");

FINAL:
FreeResource(pISD);
FreeResource(pToFolder);
FreeResource(pFromFolder);
FreeResource(pFolderItems);
FreeResource(pToFolderItems);
FreeResource(pDispatch);
if (bstrZipFile) SysFreeString(bstrZipFile);
if (bstrDstDir) SysFreeString(bstrDstDir);
CoUninitialize();
return bReturn;
}

int wmain(int argc, wchar_t* argv[])
{

setlocale(LC_ALL, "");
wchar_t zip[260] = { 0 };
wchar_t dir[260] = { 0 };wcscpy(zip, L"E:\\test\\游戏.zip");
wcscpy(dir, L"E:\\test\\XXXX");
CreateDirectoryW(dir, 0);DWORD64 tk = GetTickCount64();
UnZipFolder(zip, dir);
printf("\r\nspend %llums\r\n", GetTickCount64() - tk);
system("pause");
return 0;

}`

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/798286.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Tauri2+Vue3搭建桌面端程序|tauri2+vite5多窗口|消息提醒|托盘闪烁

基于tauri2+vite5+vue3封装多窗口实践|自定义消息提醒|托盘右键菜单及图标闪烁 这段时间一直在捣鼓最新版Tauri2.x整合Vite5搭建桌面端多开窗体应用实践。tauri2.0相较于1.0版本api有了比较多的更改,而且tauri2支持创建android/ios应用。至于具体的api变更,大家可以去官网查阅…

[CTFshow] 命令执行 29-77,118-124

web29 简单过滤 error_reporting(0); if(isset($_GET[c])){$c = $_GET[c];if(!preg_match("/flag/i", $c)){eval($c);}}else{highlight_file(__FILE__); }?c=system(tac fla*); web30 error_reporting(0); if(isset($_GET[c])){$c = $_GET[c];if(!preg_match("…

ComfyUI 基础教程(五) —— 应用 IP-Adapter 实现图像风格迁移

来吧,理解 IP-Adapter。中秋假期,又可以玩玩 AI 了。前面介绍了 ComfyUI 的 Lora 模型以及 ControlNet,本文介绍另一个非常重要且使用的节点,IP-Adapter。 一、 IP-Adapter 概念 1.1 IPAdapter 的介绍 IP-Adapter 的是腾讯 ailab 实验室发布的一个 Stable Diffusion 的适配…

创建一个虚拟机

需要一个iso文件(镜像)

白云龙期货投资-第四讲

趋势线波浪理论总结: 1.一般行情完成一次阶段性的上涨或者下跌都会通过三波来完成; 2.这三波上涨和下跌的时间空间,经常同等 3.可以利用波浪理论以上两个特性来判断和预测,还会有几次的上涨或者下跌行情,以及每次大概运行的时间及空间 三种常用实用突破法 1.早盘30mins突破…

中秋 -2024/9/16

今天是中秋假期的第二天,已经过了2/3了,怎么俺滴中秋这么快就没了 今天学习了SQL语句种的查询聚合函数进行查询和Java种的集合 TreeSet,HashSet,LinkedHashSet DQL-聚合函数介绍:将一列数据作为一个整体,进行纵向计算 常见聚合函数count - 统计数量 max - 最大值 min - 最小值 …

李尚杰的第一次作业

这次作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc这个作业的目标 熟悉博客的建立,向老师/助教介绍自己并阐述对课程的期待姓名-学号 李尚杰-2022329301146一、个人简介 (一)基本介绍我叫李尚杰,来自22自动化1班,浙江杭州人。我爱好摄影、旅游、看电影、健身…

数木莫系且的旭酱买水问题

dut开区用,在别的情况下该博客无效数木莫系且的旭酱买水问题 创中的招新又双叒叕开始了,“数木莫系且”要开始出招新题了,“数木莫系且”的36位老东西为了想招新题整天废寝忘食、绞尽脑汁、抓耳挠腮、呕心沥血,甚至连水都忘记喝了。“数木莫系且“的不时用日语小声发癫的旭…

字符编码发展史1 — ASCII和EASCII

1. 字符集与字符编码1.1. 字符集 1.2. 字符编码 1.3. 两者的关系2. 字符编码的发展历史2.1. 第一个阶段 ASCII编码2.1.1. ASCII 2.1.2. EASCII1. 字符集与字符编码 1.1. 字符集 字符集(Charcater Set或Charset): 是一个系统支持的所有抽象字符的集合,也就是一系列字符的集合…

[JVM]对象创建过程

Java 对象的创建过程 Java对象创建的过程主要分为五个步骤,下面我将详细介绍这五个步骤。 Step1:类加载检查 虚拟机遇到一条new指令时,首先会去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且会检查这个符号引用所指向的类是否已经完成加载、连接和初始化,…