Như đã đề cập ở những nơi khác trong các ý kiến, điều này chỉ sẽ làm việc trên một tập tin Zip đã tạo. Nội dung cũng phải không tồn tại trong tệp zip hoặc lỗi sẽ được hiển thị. Đây là mã mẫu làm việc mà tôi có thể tạo dựa trên câu trả lời được chấp nhận. Bạn cần liên kết đến shell32.lib và cũng là kernel32.lib (cho 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;
}
tôi đã quyết định không đi tuyến đường này mặc dù nhận được mã bán chức năng, kể từ sau khi tiếp tục điều tra, nó xuất hiện Folder :: phương pháp CopyHere() không thực sự tôn trọng vOptions truyền cho nó, có nghĩa là bạn không thể ép buộc ghi đè lên các tệp hoặc không hiển thị hộp thoại lỗi cho người dùng.
Do đó, tôi đã thử thư viện XZip được đề cập bởi một người đăng khác. Thư viện này hoạt động tốt để tạo một kho lưu trữ Zip, nhưng lưu ý rằng hàm ZipAdd() được gọi với ZIP_FOLDER không đệ quy - nó chỉ tạo một thư mục trong kho lưu trữ. Để đệ quy nén một kho lưu trữ, bạn sẽ cần sử dụng hàm AddFolderContent(). Ví dụ, để tạo một C: \ Sample.zip và Thêm thư mục C: \ Temp đến nó, sử dụng như sau:
HZIP newZip = CreateZip("C:\\Sample.zip", NULL, ZIP_FILENAME);
BOOL retval = AddFolderContent(newZip, "C:", "temp");
Lưu ý quan trọng: các AddFolderContent() chức năng không phải là chức năng như bao gồm trong XZip thư viện. Nó sẽ recurse vào cấu trúc thư mục nhưng không thêm bất kỳ tập tin vào kho lưu trữ zip, do một lỗi trong đường dẫn được chuyển đến ZipAdd(). Để sử dụng chức năng này, bạn sẽ cần phải chỉnh sửa mã nguồn và thay đổi dòng này:
if (ZipAdd(hZip, RelativePathNewFileFound, RelativePathNewFileFound, 0, ZIP_FILENAME) != ZR_OK)
Để sau:
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ách tạo thư mục nén trong Windows bằng Win32 API: http://ixmx.wordpress.com/2009/09/16/how-to-create-a-compress-folder-in-windows-using-win32 -api/ – anno
Bạn có thể sử dụng Shell32.CopyHere từ C hoặc C++, chỉ cần gọi các API win32 cần thiết để khởi tạo đối tượng COM. – Motes