Pregunta

Estoy buscando una forma de crear un archivo ZIP de una carpeta en Windows de C/C++ Api.No puedo encontrar la manera de hacer esto en VBScript mediante el Shell32.Aplicación CopyHere método, y he encontrado un tutorial que explica cómo hacerlo en C# también, pero nada de la API de C (C++ está muy bien también, el proyecto ya se utiliza MFC).

Yo estaría muy agradecido si alguien puede compartir algunos ejemplos de código C que puede crear correctamente un archivo zip en Windows XP/2003.En su defecto, si alguien puede encontrar sólidos docs o un tutorial que sería genial, ya que MSDN búsquedas no suba mucho.Estoy realmente esperando para evitar tener que enviar un tercero lib para esto, debido a que la funcionalidad es obviamente no, simplemente no puedo averiguar cómo acceder a ella.Las búsquedas de Google suba nada útil, sólo tentadora pedacitos de información.Aquí está la esperanza de que alguien de la comunidad ha ordenado esto y compartirlo para la posteridad!

¿Fue útil?

Solución

EDITAR:Esta respuesta es viejo, pero yo no se puede eliminar porque había aceptado.Ver el siguiente

https://stackoverflow.com/a/121720/3937

----- RESPUESTA ORIGINAL -----

No es el ejemplo de código para hacer eso aquí

[EDITAR:Enlace ahora está roto]

http://www.eggheadcafe.com/software/aspnet/31056644/using-shfileoperation-to.aspx

Asegúrese de leer acerca de cómo manejar la supervisión para que el hilo completo.

Editar:A partir de los comentarios, este código sólo funciona en archivo zip existente, pero @Simon siempre este código para crear un archivo zip en blanco

FILE* f = fopen("path", "wb");
fwrite("\x50\x4B\x05\x06\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 22, 1, f);
fclose(f);

Otros consejos

Como se señala en los comentarios, esto sólo funcionará en una ya creada en un archivo Zip.El contenido no debe existir en el archivo zip, o se mostrará un error.Aquí está la muestra de trabajo código fui capaz de crear basa en la aceptación de la respuesta.Es necesario vincular a shell32.lib y también kernel32.lib (para 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;

}

He decidido no ir a esta ruta a pesar de quedar semi-funcional de código, ya que después de la investigación adicional, aparece la Carpeta::CopyHere() método en realidad no respetar la vOptions pasado, lo que significa que no se puede forzar a sobrescribir archivos o no error en la visualización de los cuadros de diálogo para el usuario.

En vista de eso, he probado el XZip biblioteca mencionados por otro cartel así.Esta biblioteca de funciones de multa para la creación de un archivo Zip, pero tenga en cuenta que el ZipAdd() la función se llama con ZIP_FOLDER no es recursiva - simplemente crea una carpeta en el archivo.En fin recursivamente zip un archivo que usted necesita para usar el AddFolderContent() función.Por ejemplo, para crear un C:\Sample.zip y Añadir el C: emp carpeta, utilice el siguiente:

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

Nota importante:el AddFolderContent() la función no es funcional, como se incluyó en el XZip de la biblioteca.Es recurse en la estructura de directorios, pero no se puede agregar todos los archivos en el archivo zip, debido a un error en las rutas de acceso pasa a ZipAdd().Para poder utilizar esta función debes modificar la fuente y cambiar esta línea:

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

A la siguiente:

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)

Utilizamos XZip para este propósito.Es gratis, viene como código fuente de C++ y funciona muy bien.

http://www.codeproject.com/KB/cpp/xzipunzip.aspx

El código anterior para crear un vacío archivo zip roto, como los comentarios del estado, pero yo era capaz de conseguir que funcione.He abierto un vacío zip en un editor hexadecimal, y señaló algunas diferencias.Aquí está mi ejemplo modificado:

FILE* f = fopen("path", "wb"); 
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);

Esto funcionó para mí.Yo era capaz de, a continuación, abra la carpeta comprimida.No se probó con la 3 ª parte aplicaciones como winzip.

Una rápida búsqueda en Google se acercó con este sitio: http://www.example-code.com/vcpp/vcUnzip.asp que tiene un muy breve ejemplo para descomprimir un archivo mediante un descargable de la biblioteca.Hay un montón de otras bibliotecas disponibles.Otro ejemplo es disponibles en Código Proyecto titulado Zip y Descomprimir en el MFC manera que tiene todo un gui ejemplo.Si quieres hacerlo con .NET, entonces siempre hay las clases en el Sistema.La compresión.

También está el 7-Zip libarary http://www.7-zip.org/sdk.html.Esto incluye fuente para varios idiomas, y ejemplos.

No creo que MFC o el de Windows estándar de C/C++ Api proporcionan una interfaz para el construido en el zip de la funcionalidad.

Siempre se puede enlazar estáticamente para el freeware zip de la biblioteca si no desea enviar otra biblioteca...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top