سؤال

أنا أبحث عن طريقة إنشاء ملف مضغوط من مجلد في ويندوز C/C++ برمجة التطبيقات.لا يمكن العثور على طريقة للقيام بذلك في VBScript باستخدام Shell32.تطبيق CopyHere الطريقة ، لقد وجدت البرنامج التعليمي يشرح كيفية القيام بذلك في C# أيضا ، ولكن ليس بالنسبة C API (C++ هو جيد جدا, المشروع بالفعل يستخدم MFC).

وسأكون ممتنا حقا إذا كان أي شخص يمكن مشاركة بعض نموذج التعليمات البرمجية C التي يمكن بنجاح إنشاء ملف مضغوط على Windows XP/2003.إذا تعذر ذلك, إذا كان شخص ما يمكن أن تجد الصلبة مستندات أو تعليمي من شأنها أن تكون كبيرة منذ MSDN البحث لا يظهر كثيرا.أنا آمل حقا لتجنب الاضطرار إلى السفينة طرف ثالث lib هذا ، لأن وظيفة ومن الواضح أن هناك, أنا فقط لا يمكن معرفة كيفية الوصول إليه.عمليات البحث جوجل يحضر شيئا مفيدا فقط محيرة اجزاء وقطع من المعلومات.هنا تأمل شخص ما في المجتمع وقد بينت هذا الأمر و يمكن تقاسمها للأجيال القادمة!

هل كانت مفيدة؟

المحلول

تحرير:هذا الجواب هو قديم ولكن أنا لا يمكن حذفه لأنه كان يقبلها.انظر التالي

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

----- الأصل في الإجابة -----

هناك نموذج التعليمات البرمجية للقيام بذلك هنا

[تحرير:الرابط هو الآن مكسورة]

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

تأكد من قراءة حول كيفية التعامل مع رصد الخيط لإكمال.

تحرير:من التعليقات ، هذا الكود يعمل فقط على القائمة ملف مضغوط ، ولكن @سيمون قدمت هذه التعليمة البرمجية لإنشاء ملف مضغوط فارغ

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

نصائح أخرى

كما لوحظ في أماكن أخرى في التعليقات, هذا سوف تعمل فقط على إنشاؤها بالفعل ملف مضغوط.المحتوى أيضا يجب أن لا تكون موجودة في ملف مضغوط أو خطأ سيتم عرضها.هنا هو العامل نموذج التعليمات البرمجية كنت قادرا على خلق بناء على الجواب المقبول.تحتاج إلى رابط shell32.lib و أيضا kernel32.ليب (على 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;

}

لقد قررت أن لا تذهب في هذا الطريق على الرغم من الحصول على شبه الوظيفية ، بما بعد مزيد من التحقيق ، يبدو المجلد::CopyHere() الأسلوب لا في الحقيقة احترام vOptions مرت عليه, مما يعني أنك لا يمكن النفاذ إلى الكتابة فوق الملفات أو لا يتم عرض خطأ مربعات حوار للمستخدم.

في ضوء ذلك حاولت XZip مكتبة ذكرها ملصق آخر كذلك.هذه المكتبة وظائف بخير إنشاء أرشيف Zip, ولكن لاحظ أن ZipAdd() وظيفة تسمى مع ZIP_FOLDER ليست متكررة - انها مجرد بإنشاء مجلد في الأرشيف.من أجل متكرر الرمز البريدي الأرشيف سوف تحتاج إلى استخدام AddFolderContent() وظيفة.على سبيل المثال ، إنشاء C:\Sample.zip وإضافة C: emp المجلد إلى ذلك ، استخدم ما يلي:

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

ملاحظة هامة:على AddFolderContent() وظيفة ليست الوظيفية كما وردت في XZip المكتبة.وسوف recurse في بنية الدليل ولكن فشل في إضافة أي ملفات أرشيف مضغوط ، وذلك بسبب الخلل في مسارات تمريرها إلى ZipAdd().من أجل استخدام هذه الوظيفة سوف تحتاج إلى تحرير مصدر تغيير هذا السطر:

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

إلى ما يلي:

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)

نحن نستخدم XZip لهذا الغرض.انها حرة, يأتي مع التعليمات البرمجية المصدر C++ و يعمل بشكل جيد.

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

رمز أعلاه لإنشاء فارغة ملف مضغوط مكسورة ، التعليقات الدولة ، ولكن كنت قادرا على الحصول على عمل.فتحت فارغة الرمز البريدي في محرر عرافة ، وأشار إلى بعض الاختلافات.هنا هو بلدي تعديل على سبيل المثال:

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

هذا عملت بالنسبة لي.تمكنت ثم فتح المجلد المضغوط.لم تختبر مع تطبيقات الطرف 3rd مثل برنامج لضغط الملفات.

جوجل للبحث سريع جاء مع هذا الموقع: http://www.example-code.com/vcpp/vcUnzip.asp والتي لديها قصيرة جدا مثلا فك ضغط الملف باستخدام للتحميل المكتبة.هناك الكثير من المكتبات الأخرى المتاحة.مثال آخر هو availaible على رمز المشروع بعنوان الرمز البريدي وبفك في MFC الطريقة التي لديها كامل واجهة المستخدم الرسومية سبيل المثال.إذا كنت تريد أن تفعل ذلك مع .صافي ثم هناك دائما فئات بموجب النظام.ضغط.

وهناك أيضا 7-Zip libarary http://www.7-zip.org/sdk.html.ويشمل هذا المصدر لعدة لغات, و الأمثلة.

لا أعتقد أن MFC أو ويندوز القياسية C/C++ برمجة التطبيقات توفر واجهة المضمنة في الرمز البريدي وظائف.

يمكنك دائما ثابت رابط مجانية الرمز البريدي المكتبة إذا كنت لا تريد أن السفينة مكتبة أخرى...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top