2008-09-23 36 views
11

में विंडोज (एक्सपी/2003) पर एक ज़िप फ़ाइल बनाना, मैं विंडोज सी/सी ++ एपीआई में किसी फ़ोल्डर से ज़िप फ़ाइल बनाने का एक तरीका ढूंढ रहा हूं। मैं Shell32.Aplication CopyHere विधि का उपयोग करके वीबीस्क्रिप्ट में ऐसा करने का तरीका ढूंढ सकता हूं, और मुझे यह पता चलता है कि सी # में यह कैसे करना है, लेकिन सी एपीआई के लिए कुछ भी नहीं है (सी ++ ठीक है, प्रोजेक्ट पहले ही एमएफसी का उपयोग करता है)।सी/सी ++

यदि कोई कुछ नमूना सी कोड साझा कर सकता है तो मैं वास्तव में आभारी रहूंगा जो विंडोज XP/2003 पर सफलतापूर्वक ज़िप फ़ाइल बना सकता है। यह विफल होने पर, अगर कोई ठोस दस्तावेज़ या ट्यूटोरियल ढूंढ सकता है जो बहुत अच्छा होगा, क्योंकि एमएसडीएन की खोज बहुत अधिक नहीं होती है। मैं वास्तव में इस के लिए एक थर्ड-पार्टी lib को जहाज से बचने की उम्मीद कर रहा हूं, क्योंकि कार्यक्षमता स्पष्ट रूप से वहां है, मैं बस यह नहीं समझ सकता कि इसे कैसे पहुंचाया जाए। Google खोजों में कुछ भी उपयोगी नहीं होता है, केवल बिट्स और जानकारी के टुकड़े tantalizing। यहां उम्मीद है कि समुदाय में किसी ने इसे हल किया है और इसे जन्म के लिए साझा कर सकता है!

+1

Win32 API का उपयोग कर Windows में संपीड़ित फ़ोल्डर कैसे बनाएं: http://ixmx.wordpress.com/2009/09/16/how-to-create-a-compress-folder-in-windows-using-win32 -पीआई/ – anno

+0

आप सी या सी ++ से Shell32.CopyHere का उपयोग कर सकते हैं, COM ऑब्जेक्ट को तुरंत चालू करने के लिए केवल आवश्यक Win32 API को कॉल करें। – Motes

उत्तर

4

संपादित करें: यह उत्तर पुराना है, लेकिन मैं इसे हटा नहीं सकता क्योंकि इसे स्वीकार किया गया था। [: लिंक अब टूट गया है संपादित करें]

अगले एक

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

----- मूल उत्तर ----- देखें

है कि यहाँ

लिए नमूना कोड नहीं है

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

सुनिश्चित करें कि आप कैसे धागा पूरा करने के लिए निगरानी संभाल करने के बारे में पढ़ा करें।

संपादित करें: टिप्पणी से, इस कोड को केवल मौजूदा ज़िप फ़ाइल पर काम करता है, लेकिन @Simon एक खाली ज़िप फ़ाइल

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

मुझे उस नमूना कोड को पहले मिला था, लेकिन यह वास्तव में काम करने के लिए प्रतीत नहीं होता है। अंत में मैंने इसे कुछ ट्विकिंग और कामों के प्रकार के बाद संकलित और चलाने के लिए प्राप्त किया, बशर्ते ज़िप फ़ाइल पहले से मौजूद है। यदि कोई और अधिक पूर्ण उत्तर के साथ आता है तो मैं इसे स्वीकार करूंगा। – Jay

+1

रिक्त ज़िप बनाएं: FILE * f = fopen ("path", "wb"); fwrite ("\ x80 \ x75 \ x05 \ x06 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0", 22, 1, एफ); fclose (एफ); –

+1

एक खाली ज़िप फ़ाइल बनाने के लिए प्रदान किया गया कोड वैध फ़ाइल नहीं बनाता है (यह किसी भी ज़िप सॉफ़्टवेयर द्वारा खोला जा सकता है जिसमें Winzip, Windows अंतर्निहित ज़िप, ओएस एक्स पर BOMArchiver, या कमांड लाइन पर अनजिप है। – Jay

1

मुझे नहीं लगता कि एमएफसी या विंडोज मानक सी/सी ++ एपीआई अंतर्निहित ज़िप कार्यक्षमता के लिए एक इंटरफेस प्रदान करते हैं।

0

तुम हमेशा स्थिर अगर आप फ्रीवेयर ज़िप पुस्तकालय के लिए लिंक कर सकते हैं बनाने के लिए इस कोड प्रदान की एक और पुस्तकालय जहाज नहीं भेजना चाहते हैं ...

2

एक त्वरित Google खोज इस साइट के साथ आया: http://www.example-code.com/vcpp/vcUnzip.asp जिसमें एक डाउनलोड करने योग्य लाइब्रेरी का उपयोग कर फ़ाइल को अनजिप करने के लिए बहुत छोटा उदाहरण है। कई अन्य पुस्तकालय उपलब्ध हैं। कोड प्रोजेक्ट पर Zip and Unzip in the MFC way नामक एक और उदाहरण उपलब्ध है जिसमें एक संपूर्ण गुई उदाहरण है। यदि आप इसे .NET के साथ करना चाहते हैं तो हमेशा सिस्टम.कंप्रेशन के अंतर्गत कक्षाएं होती हैं।

7-ज़िप लिबररी http://www.7-zip.org/sdk.html भी है। इसमें कई भाषाओं और उदाहरणों के लिए स्रोत शामिल है।

6

हम इस उद्देश्य के लिए XZip का उपयोग करते हैं। यह मुफ़्त है, सी ++ स्रोत कोड के रूप में आता है और अच्छी तरह से काम करता है।

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

13

के रूप में टिप्पणी में कहीं उल्लेख किया, यह केवल एक पहले से ही बनाया ज़िप फ़ाइल पर काम करेंगे। सामग्री को ज़िप फ़ाइल में पहले से मौजूद नहीं होना चाहिए, या एक त्रुटि प्रदर्शित की जाएगी। यहां काम करने वाला नमूना कोड है जिसे मैं स्वीकार किए गए उत्तर के आधार पर बनाने में सक्षम था। आपको shell32.lib और kernel32.lib (CreateToolhelp32 स्नैपशॉट के लिए) से लिंक करने की आवश्यकता है।

#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 लाइब्रेरी की भी कोशिश की। यह लाइब्रेरी ज़िप संग्रह बनाने के लिए ठीक काम करती है, लेकिन ध्यान दें कि ज़िप_फॉल्डर के साथ बुलाया गया ZipAdd() फ़ंक्शन रिकर्सिव नहीं है - यह केवल संग्रह में एक फ़ोल्डर बनाता है। एक संग्रह को दोबारा ज़िप करने के लिए आपको AddFolderContent() फ़ंक्शन का उपयोग करने की आवश्यकता होगी। उदाहरण के लिए, एक सी बनाने के लिए: \ Sample.zip और सी जोड़ें:

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

महत्वपूर्ण नोट:: यह करने के लिए \ अस्थायी फ़ोल्डर, निम्न का उपयोग XZip में शामिल के रूप में AddFolderContent() फ़ंक्शन कार्यात्मक नहीं है पुस्तकालय। यह निर्देशिका संरचना में पुन: कार्य करेगा लेकिन 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) 
+0

क्या अभी भी एक काम करने वाले खोल का पता लगाने का कोई अच्छा तरीका नहीं है? [एच ttps: //msdn.microsoft.com/en-us//library/windows/desktop/gg537733 (v = vs.85) .aspx] (IShellDispatch.Windows) स्वयं परिभाषित अंतराल में खुली खोल विंडो की जांच करने के लिए f.e.? – Youka

+0

यह कोड काम करता है लेकिन फ़ंक्शन 'WaitForMultipleObjects' इस पंक्ति से पहले एक थ्रेड समाप्त होने पर अनंतता प्रतीक्षा करें। msdn दस्तावेज़ीकरण => [WaitForMultipleObjects] के अनुसार (https://msdn.microsoft।com/en-us/library/windows/desktop/ms687025 (v = vs.85) .aspx) यह कहता है, 'अगर प्रतीक्षा में अभी भी लंबित है, तो इन हैंडल में से एक बंद है, तो फ़ंक्शन का व्यवहार अपरिभाषित है।' इससे बचें, हैंडल में केवल सही ध्वज का सिंचन पहुंच होना चाहिए। तो 'THREAD_ALL_ACCESS' को' ओपन थ्रेड (THREAD_ALL_ACCESS, FALSE, te.th32ThreadID) में बदलें; '' SYNCHRONIZE 'द्वारा और यह ठीक काम करता है! –

3

एक खाली ज़िप फ़ाइल बनाने में उपरोक्त कोड टूट गया है, के रूप में इस फ़ंक्शन का उपयोग करने के लिए आपको स्रोत को संपादित करें और इस लाइन को बदलना होगा टिप्पणी राज्य, लेकिन मैं इसे काम करने में सक्षम था। मैंने एक हेक्स संपादक में एक खाली ज़िप खोला, और कुछ मतभेदों को नोट किया। यहां मेरा संशोधित उदाहरण दिया गया है:

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

यह मेरे लिए काम करता है। मैं संपीड़ित फ़ोल्डर खोलने में सक्षम था। Winzip जैसे तृतीय पक्ष ऐप्स के साथ परीक्षण नहीं किया गया।

+0

अच्छा, यह काम करता है। धन्यवाद –

संबंधित मुद्दे