Frage

Ich bin auf der Suche nach einer Möglichkeit, eine ZIP-Datei von einem Ordner in Windows C / C ++ APIs zu erstellen. Ich kann den Weg finden, dies in VBScript zu tun, um die Shell32.Application Copyhere-Methode, und ich fand ein Tutorial erklärt, wie man es in C # zu tun, auch, aber nichts für den C-API (C ++ ist zu fein, Projekt bereits verwendet MFC).

Ich wäre wirklich dankbar, wenn jemand einige Beispiel-C-Code gemeinsam nutzen können, die erfolgreich eine Zip-Datei unter Windows XP / 2003 erstellen können. Gelingt das nicht, wenn jemand feste docs oder ein Tutorial finden können, die groß sein würde, da MSDN sucht viel nicht erscheinen. Ich hoffe wirklich zu vermeiden, dass ein Drittanbieter-lib für diese zu versenden hat, weil die Funktionalität offensichtlich ist, kann ich einfach nicht herausfinden, wie es zuzugreifen. Google-Suchanfrage auftauchen nichts brauchbar, nur Stücke von Informationen quälend. Hier hofft, dass jemand in der Gemeinschaft, um diese aussortiert hat und es für die Nachwelt teilen!

War es hilfreich?

Lösung

EDIT: Diese Antwort ist alt, aber ich kann es nicht gelöscht werden, da es angenommen wurde. Siehe die nächsten

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

----- ----- ORIGINAL ANTWORT

Es gibt Codebeispiel, das hier zu tun

[EDIT: Link ist nun gebrochen]

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

Stellen Sie sicher, lesen Sie, wie die Überwachung zu handhaben für den Thread zu beenden.

Edit: Aus den Kommentaren dieser Code funktioniert nur auf vorhandene Zip-Datei, aber @ Simon diesen Code zur Verfügung gestellt erstellen eine leere Zip-Datei

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);

Andere Tipps

Wie an anderer Stelle in den Kommentaren erwähnt, wird dies nur funktionieren, auf eine bereits erstellten Zip-Datei. Der Inhalt muss auch nicht bereits in der Zip-Datei vorhanden ist, oder wenn ein Fehler angezeigt wird. Hier ist der Arbeitsbeispielcode ich in der Lage war, auf der Grundlage der akzeptierten Antwort zu erstellen. Sie müssen eine Verknüpfung shell32.lib und kernel32.lib auch (für 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;

}

Ich habe beschlossen, nicht diesen Weg zu gehen, trotz immer halb-Funktionscode, da nach einer weiteren Untersuchung scheint es, den Ordner :: Copyhere () -Methode nicht respektiert tatsächlich die VOptions an sie übergeben, was bedeutet, dass Sie es nicht zwingen kann, zu Überschreiben von Dateien oder nicht Fehlerdialoge für den Benutzer angezeigt werden.

Im Lichte habe ich versucht, die xzip Bibliothek von einem anderen Poster erwähnt auch. Diese Bibliothek funktioniert gut für ein Zip-Archiv erstellen, aber beachten Sie, dass die ZipAdd () Funktion mit ZIP_FOLDER genannt nicht rekursiv ist - es lediglich einen Ordner in dem Archiv erstellt. Um zip rekursiv ein Archiv Sie die AddFolderContent () Funktion verwenden müssen. Um zum Beispiel einen C zu erstellen: \ Sample.zip und Fügen Sie den C: \ Temp-Ordner, um es verwenden wie folgt vor:

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

Wichtiger Hinweis: die AddFolderContent () Funktion nicht funktionsfähig ist, wie in der xzip Bibliothek enthalten. Es wird in die Verzeichnisstruktur rekursiv aber nicht alle Dateien in das Zip-Archiv hinzufügen, aufgrund eines Fehlers in der zu ZipAdd geben Pfade (). Um diese Funktion zu nutzen müssen Sie die Quelle bearbeiten und diese Zeile ändern:

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

Um die folgenden Möglichkeiten:

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)

Wir verwenden xzip für diesen Zweck. Es ist kostenlos, kommt als C ++ Quellcode und funktioniert gut.

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

Der obige Code eine leere Zip-Datei wird gebrochen, als die Kommentare Staat zu schaffen, aber ich konnte es an der Arbeit. Ich öffnete eine leere zip in einem Hex-Editor, und stellte fest, ein paar Unterschiede. Hier ist mein modifiziertes Beispiel:

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);

Das funktionierte für mich. Ich konnte dann die komprimierten Ordner öffnen. Nicht getestet mit 3rd-Party-Anwendungen wie Winzip.

Eine schnelle Google-Suche kam mit dieser Seite nach oben: http: //www.example -code.com/vcpp/vcUnzip.asp , die ein sehr kurzes Beispiel hat eine Datei mit einer herunterladbaren Bibliothek entpacken. Es gibt viele andere Bibliotheken zur Verfügung. Ein weiteres Beispiel ist availaible auf Code Project berechtigt Zip und entpacken Sie in dem MFC-Weg , die ein ganzes gui Beispiel hat. Wenn Sie es mit .NET tun wollen, dann gibt es immer die Klassen unter System.Compression.

Es gibt auch die 7-Zip libarary http://www.7-zip.org /sdk.html . Dazu gehören Quelle für mehrere Sprachen und Beispiele.

Ich glaube nicht, dass MFC oder die Windows-Standard-C / C ++ APIs eine Schnittstelle zu dem in Zip-Funktionalität gebaut bieten.

Sie können immer verknüpfen statisch auf die Freeware zip Bibliothek wenn Sie wollen eine andere Bibliothek versenden nicht ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top