gpt4 book ai didi

c++ - 使用 C/C++ 在 Windows (XP/2003) 上创建 ZIP 文件

转载 作者:可可西里 更新时间:2023-11-01 14:53:51 25 4
gpt4 key购买 nike

我正在寻找一种从 Windows C/C++ API 中的文件夹创建 ZIP 文件的方法。我可以使用 Shell32.Application CopyHere 方法在 VBScript 中找到执行此操作的方法,我还找到了一个教程来解释如何在 C# 中执行此操作,但对于 C API 没有任何帮助(C++ 也很好,项目已经使用 MFC)。

如果有人能分享一些可以在 Windows XP/2003 上成功创建 zip 文件的示例 C 代码,我将不胜感激。如果做不到这一点,如果有人能找到可靠的文档或教程那就太好了,因为 MSDN 搜索结果并不多。我真的希望避免为此发布第三方库,因为功能显然存在,我只是不知道如何访问它。谷歌搜索没有找到任何有用的信息,只有一些诱人的信息。希望社区中有人解决了这个问题并可以与后代分享!

最佳答案

如评论中其他地方所述,这仅适用于已创建的 Zip 文件。该内容还必须不存在于 zip 文件中,否则将显示错误。这是我能够根据接受的答案创建的工作示例代码。您需要链接到 shell32.lib 和 kernel32.lib(用于 CreateToolhelp32Snapshot)。

#include <windows.h>
#include <shldisp.h>
#include <tlhelp32.h>
#include <stdio.h>

int main(int argc, TCHAR* argv[])
{
DWORD strlen = 0;
char szFrom[] = "C:\\Temp",
szTo[] = "C:\\Sample.zip";
HRESULT hResult;
IShellDispatch *pISD;
Folder *pToFolder = NULL;
VARIANT vDir, vFile, vOpt;
BSTR strptr1, strptr2;

CoInitialize(NULL);

hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pISD);

if (SUCCEEDED(hResult) && pISD != NULL)
{
strlen = MultiByteToWideChar(CP_ACP, 0, szTo, -1, 0, 0);
strptr1 = SysAllocStringLen(0, strlen);
MultiByteToWideChar(CP_ACP, 0, szTo, -1, strptr1, strlen);

VariantInit(&vDir);
vDir.vt = VT_BSTR;
vDir.bstrVal = strptr1;
hResult = pISD->NameSpace(vDir, &pToFolder);

if (SUCCEEDED(hResult))
{
strlen = MultiByteToWideChar(CP_ACP, 0, szFrom, -1, 0, 0);
strptr2 = SysAllocStringLen(0, strlen);
MultiByteToWideChar(CP_ACP, 0, szFrom, -1, strptr2, strlen);

VariantInit(&vFile);
vFile.vt = VT_BSTR;
vFile.bstrVal = strptr2;

VariantInit(&vOpt);
vOpt.vt = VT_I4;
vOpt.lVal = 4; // Do not display a progress dialog box

hResult = NULL;
printf("Copying %s to %s ...\n", szFrom, szTo);
hResult = pToFolder->CopyHere(vFile, vOpt); //NOTE: this appears to always return S_OK even on error
/*
* 1) Enumerate current threads in the process using Thread32First/Thread32Next
* 2) Start the operation
* 3) Enumerate the threads again
* 4) Wait for any new threads using WaitForMultipleObjects
*
* Of course, if the operation creates any new threads that don't exit, then you have a problem.
*/
if (hResult == S_OK) {
//NOTE: hard-coded for testing - be sure not to overflow the array if > 5 threads exist
HANDLE hThrd[5];
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL ,0); //TH32CS_SNAPMODULE, 0);
DWORD NUM_THREADS = 0;
if (h != INVALID_HANDLE_VALUE) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) ) {
//only enumerate threads that are called by this process and not the main thread
if((te.th32OwnerProcessID == GetCurrentProcessId()) && (te.th32ThreadID != GetCurrentThreadId()) ){
//printf("Process 0x%04x Thread 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
hThrd[NUM_THREADS] = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
NUM_THREADS++;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);

printf("waiting for all threads to exit...\n");
//Wait for all threads to exit
WaitForMultipleObjects(NUM_THREADS, hThrd , TRUE , INFINITE);

//Close All handles
for ( DWORD i = 0; i < NUM_THREADS ; i++ ){
CloseHandle( hThrd[i] );
}
} //if invalid handle
} //if CopyHere() hResult is S_OK

SysFreeString(strptr2);
pToFolder->Release();
}

SysFreeString(strptr1);
pISD->Release();
}

CoUninitialize();

printf ("Press ENTER to exit\n");
getchar();
return 0;

}

尽管获得了半功能代码,我还是决定不走这条路,因为经过进一步调查,似乎 Folder::CopyHere() 方法实际上并不尊重传递给它的 vOptions,这意味着你不能强制它覆盖文件或不向用户显示错误对话框。

鉴于此,我也尝试了另一位发帖者提到的 XZip 库。该库可以很好地创建 Zip 存档,但请注意,使用 ZIP_FOLDER 调用的 ZipAdd() 函数不是递归的——它只是在存档中创建一个文件夹。为了递归压缩文件,您需要使用 AddFolderContent() 函数。例如,要创建 C:\Sample.zip 并将 C:\Temp 文件夹添加到其中,请使用以下命令:

HZIP newZip = CreateZip("C:\\Sample.zip", NULL, ZIP_FILENAME);
BOOL retval = AddFolderContent(newZip, "C:", "temp");

重要提示:AddFolderContent() 函数并不像 XZip 库中包含的那样起作用。由于传递给 ZipAdd() 的路径中存在错误,它将递归到目录结构中但无法将任何文件添加到 zip 存档中。为了使用此功能,您需要编辑源代码并更改此行:

if (ZipAdd(hZip, RelativePathNewFileFound, RelativePathNewFileFound, 0, ZIP_FILENAME) != ZR_OK)

以下内容:

ZRESULT ret;
TCHAR real_path[MAX_PATH] = {0};
_tcscat(real_path, AbsolutePath);
_tcscat(real_path, RelativePathNewFileFound);
if (ZipAdd(hZip, RelativePathNewFileFound, real_path, 0, ZIP_FILENAME) != ZR_OK)

关于c++ - 使用 C/C++ 在 Windows (XP/2003) 上创建 ZIP 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/118547/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com