如何在Windows中使用C创建密码保护的ZIP文件?

如何在Windows中使用C创建密码保护的ZIP文件?,c,winapi,zip,C,Winapi,Zip,我正在尝试用C在Windows文件中创建一个受保护的ZIP 基于这些答案,我创建了以下方法: 代码如下: #include <windows.h> #include <shldisp.h> #include <tlhelp32.h> #include <stdio.h> #include <shlobj.h> #include <shlwapi.h> #include <shellapi.h> #includ

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

基于这些答案,我创建了以下方法:

  • 代码如下:

    #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;
    
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    int main(int argc,TCHAR*argv[])
    {
    德沃德·斯特伦=0;
    char szFrom[]=“C:\\Users\\dist”,
    szTo[]=“C:\\Users\\harrison4\\Desktop\\example.zip”;
    HRESULT HRESULT;
    ISHELL*pISD;
    Folder*pToFolder=NULL;
    变量vDir、vFile、vOpt;
    BSTR strptr1,strptr2;
    文件*f;
    深圳福彭食品有限公司(“wb”);
    如果(!f)
    返回0;
    写入(“\x50\x4B\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00”,22,1,f);
    fclose(f);
    共初始化(空);
    hResult=CoCreateInstance(&CLSID_Shell,NULL,CLSCTX_INPROC_SERVER,&IID_IShellDispatch,(void**)和pISD);
    如果(成功(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=vtbstr;
    vDir.bstrVal=strptr1;
    hResult=pISD->名称空间(vDir和文件夹);
    如果(成功(hResult))
    {
    strlen=MultiByteToWideChar(CP_ACP,0,szFrom,-1,0,0);
    strpr2=SysAllocStringLen(0,strlen);
    MultiByteToWideChar(CP_ACP,0,szFrom,-1,strptr2,strlen);
    VariantInit(&vFile);
    vFile.vt=vt\u BSTR;
    vFile.bstrVal=strptr2;
    VariantInit(&vOpt);
    vOpt.vt=vt_I4;
    vOpt.lVal=4;//不显示进度对话框
    printf(“正在将%s复制到%s…\n”,szFrom,szTo);
    hResult=pToFolder->CopyHere(vFile,vOpt);//注意:即使出现错误,它也会始终返回S_OK
    /*
    *1)使用Thread32First/Thread32Next枚举进程中的当前线程
    *2)启动操作
    *3)再次枚举线程
    *4)使用WaitForMultipleObjects等待任何新线程
    *
    *当然,如果操作创建了任何不退出的新线程,那么您就有问题了。
    */
    如果(hResult==S_OK){
    //注意:硬编码用于测试-如果存在>5个线程,请确保不会使阵列溢出
    处理hThrd[5];
    HANDLE h=CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);//TH32CS_SNAPMODULE,0);
    DWORD NUM_线程数=0;
    if(h!=无效的\u句柄\u值){
    THREADENTRY32-te;
    te.dwSize=sizeof(te);
    if(螺纹32优先(h和te)){
    做{
    if(te.dwSize>=(字段_偏移量(THREADENTRY32,th32OwnerProcessID)+sizeof(te.th32OwnerProcessID))){
    //仅枚举此进程调用的线程,而不是主线程
    如果((te.th32OwnerProcessID==GetCurrentProcessId())&&(te.th32ThreadID!=GetCurrentThreadId()){
    //printf(“进程0x%04x线程0x%04x\n”,te.th32OwnerProcessID,te.th32ThreadID);
    hThrd[NUM_THREADS]=OpenThread(SYNCHRONIZE,FALSE,te.th32ThreadID);
    NUM_线程++;
    }
    }
    te.dwSize=sizeof(te);
    }while(Thread32Next(h,&te));
    }
    闭合手柄(h);
    printf(“等待所有线程退出…\n”);
    //等待所有线程退出
    WaitForMultipleObjects(NUM_线程,hThrd,TRUE,无限);
    //关闭所有手柄
    对于(DWORD i=0;i发布();
    }
    SysFreeString(strptr1);
    pISD->Release();
    }
    coninitialize();
    printf(“按ENTER键退出\n”);
    getchar();
    返回0;
    }
    
    它确实有效。但是,我找不到任何文档来设置文件的密码

    我还发现,它简化了ZIP创建,但不幸的是,它没有包含密码保护。

    您可以在Windows上使用库。它可以通过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;
    }
    
    #包括“mz.h”
    #包括“mz_os.h”
    #包括“mz_strm.h”
    #包括“mz_strm_buf.h”
    #包括“mz_strm_split.h”
    #包括“mz_zip.h”
    #包括“mz_zip_rw.h”
    #包括
    int main(){
    void*writer=NULL;
    int32_t err=MZ_OK;
    mz_zip_writer_创建(&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_文件(writer,“output.zip”,0,0);
    如果(错误!=MZ_正常){
    printf(“无法打开zip文件进行写入”);
    返回1;
    }
    err=mz_zip_writer_add_path(writer,“text1.txt”,NULL,0,0);
    如果(错误!=MZ_正常){
    printf(“未能将文件添加到存档。”);
    }
    mz_zip_writer_close(writer);
    mz_zip_writer_delete(&writer);
    返回0;
    }
    
    此代码将创建一个带有密码保护文件的
    output.zip
    文件
    text1.txt

    有关更多信息和用法,请参阅示例文件


    我希望它能帮上忙。

    如果你严格不想要.zip格式,可以使用外部文件
    system("aescrypt -e -p apples picture.jpg")