【问题标题】:How to create a password protected ZIP file in Windows using C?如何使用 C 在 Windows 中创建受密码保护的 ZIP 文件?
【发布时间】:2020-03-09 23:45:28
【问题描述】:

我正在尝试用 C 语言在 Windows 文件中创建一个受保护的 ZIP。

我根据这些答案创建了以下方法:

  1. Creating a ZIP file on Windows (XP/2003) in C/C++ #1
  2. Creating a ZIP file on Windows (XP/2003) in C/C++ #2

代码如下:

#include <windows.h>
#include <shldisp.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <shellapi.h>
#include <stdlib.h>
#include <objbase.h>

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

    FILE* f;
    fopen_s(&f, szTo, "wb");
    if (!f)
        return 0;

    fwrite("\x50\x4B\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 22, 1, f);
    fclose(f);

    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

            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(SYNCHRONIZE, 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;

}

确实有效。但是,我找不到任何文档来设置文件的密码。

我还找到了the zip C library,它可以简化 ZIP 的创建,但不幸的是,它没有包含密码保护。

【问题讨论】:

  • 我不确定 Windows API 是否包含加密的 zip 功能。您可以获得执行 AES 加密 zip 所需的点点滴滴,但可能一个完整的工具/库更容易。 7-zip 有一些选项,但可能对您的需要来说有点大,并且不确定构建仅包含所需存档/压缩/加密的 DLL 是否容易。
  • 你能分享一下这样做的目的吗?在您提供的代码中,您可以创建一个空的 zip 文件,但这不能压缩现有文件。对于受保护的 zip 文件,我没有找到这样的 API。您可能需要使用第三方库。请参考this link
  • @StriveSun-MSFT 我发现this resource of minzip lib 也有一个更清晰的例子。我会及时通知你的。谢谢!
  • 也许你应该自己写答案!可能很整洁。
  • 赏金有点无意义。答案是使用第三方库,但推荐问题不在此处。

标签: c winapi zip


【解决方案1】:

您可以在 Windows 上使用 minizip 库。可以通过 CMake 编译。

这是您可以使用它来创建受密码保护的 zip 文件的方法:

#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_buf.h"
#include "mz_strm_split.h"
#include "mz_zip.h"
#include "mz_zip_rw.h"
#include <stdio.h>

int main() {
    void *writer = NULL;
    int32_t err = MZ_OK;

    mz_zip_writer_create(&writer);
    mz_zip_writer_set_password(writer, "mypassword");
    mz_zip_writer_set_compress_method(writer, MZ_COMPRESS_METHOD_DEFLATE);
    mz_zip_writer_set_compress_level(writer, MZ_COMPRESS_LEVEL_DEFAULT);
    err = mz_zip_writer_open_file(writer, "output.zip", 0, 0);
    if (err != MZ_OK) {
        printf("Could not open zip file for writing.");
        return 1;
    }
    err = mz_zip_writer_add_path(writer, "text1.txt", NULL, 0, 0);
    if (err != MZ_OK) {
        printf("Failed to add file to the archive.");
    }
    mz_zip_writer_close(writer);
    mz_zip_writer_delete(&writer);
    return 0;
}

此代码将创建一个带有密码保护文件text1.txt 的output.zip 文件。

有关更多信息和用途,请参阅minizip.c 示例文件。

希望对你有帮助。

【讨论】:

    【解决方案2】:

    如果您严格不想要 .zip 格式并且可以使用外部工具,这里有一个简单的方法:-

    您可以使用https://www.aescrypt.com/等外部软件。 下载它,将可执行文件放在与你的 c 程序相同的文件夹中,然后每当你想加密文件时,使用

    进行系统调用
    system("aescrypt -e -p apples picture.jpg") 
    

    (来自官方文档的代码):https://www.aescrypt.com/documentation/

    【讨论】:

      猜你喜欢
      • 2011-06-13
      • 1970-01-01
      • 2022-08-10
      • 1970-01-01
      • 2010-10-18
      • 2010-11-09
      • 2011-01-01
      • 1970-01-01
      • 2010-12-11
      相关资源
      最近更新 更多