Click here to Skip to main content
Click here to Skip to main content

Iterate and Extract Cabinet File

By , 24 May 2004
 

Introduction

The .NET Framework doesn't provide us with Cabinet File functionality through the programming interface. However, the Setupapi.dll enables us to handle cabinet files except for compressing. This TCabinet class encapsulates some functions of the Setupapi.dll in order to iterate and extract a cabinet file.

Background

TCabinet class encapsulates the following functions in setupapi.dll:

[DllImport("SetupApi.dll", CharSet=CharSet.Auto)]
public static extern bool SetupIterateCabinet(string cabinetFile, 
                    uint reserved, PSP_FILE_CALLBACK callBack, uint context); 

public delegate uint PSP_FILE_CALLBACK(uint context, uint notification, 
                                       IntPtr param1, IntPtr param2);


private uint CallBack(uint context, uint notification, IntPtr param1, 
                     IntPtr param2)
{
    uint rtnValue = SetupApiWrapper.NO_ERROR;
    switch (notification)
    { 
        case SetupApiWrapper.SPFILENOTIFY_FILEINCABINET:
            rtnValue = OnFileFound(context, notification, param1, param2);
            break;
        case SetupApiWrapper.SPFILENOTIFY_FILEEXTRACTED:
            rtnValue = OnFileExtractComplete(param1);
            break;
        case SetupApiWrapper.SPFILENOTIFY_NEEDNEWCABINET:
            rtnValue = SetupApiWrapper.NO_ERROR;
        break;
    }
    return rtnValue;
}

History

  • 25th May, 2004: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

aplaxas

France France
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralThanks so much its working fine for me.membershahshi24-Aug-10 21:22 
But in c++ using simple extrac32.exe to extract cab file.
by using extrac32.exe is not possible to extract cab in c#.
if you know please reply for this.
GeneralThe system cannot find the file specifiedmembermikey22217-Oct-09 13:07 
This error occurs when the SetupIterateCabinet function is called, if there is more than one folder in the path.
 
(works) xxx.cab
(works) foldername\xxx.cab
(fails) foldername\foldername\xxx.cab
(fails) C:\\foldername\xxx.cab
 

I am using XP Pro/SP3 and VS 2008.
GeneralEssential!!!memberRakshun29-Aug-09 8:04 
Thanks a looot, you saved our lives! Wink | ;)
 
For anybody interested, here's the essence of the code (I needed only ExtractAll):
 
1) Keep APIWrapper.cs and TCabinetFile.cs _only_
 
2) Overwrite TCabinetFile.cs with this:
 
using System;
using System.Collections;
using System.ComponentModel;
 
using System.Runtime.InteropServices;
 
namespace CabinetFile
{
 
   public class TCabinetFile
   {
      /// <summary>
      /// The FileCallback callback function is used by a number of the setup functions. The PSP_FILE_CALLBACK type defines a pointer to this callback function. FileCallback is a placeholder for the application-defined function name.
      /// Platform SDK: Setup API
      /// </summary>
      private uint CallBack(uint context, uint notification, IntPtr param1, IntPtr param2)
      {
         uint rtnValue = SetupApiWrapper.NO_ERROR;
         switch (notification)
         {
            case SetupApiWrapper.SPFILENOTIFY_FILEINCABINET:
               rtnValue = OnFileFound(context, notification, param1, param2);
               break;
            case SetupApiWrapper.SPFILENOTIFY_FILEEXTRACTED:
               rtnValue = SetupApiWrapper.NO_ERROR; // OnFileExtractComplete(param1);
               break;
            case SetupApiWrapper.SPFILENOTIFY_NEEDNEWCABINET:
               rtnValue = SetupApiWrapper.NO_ERROR;
               break;
         }
         return rtnValue;
      }
 

      public TCabinetFile()
      {
 
      }
 
      /// <summary>
      /// output directory
      /// </summary>
      private string m_OutputDirectory = "";
      public string OutputDirectory
      {
         set
         {
            if (!System.IO.Directory.Exists(value))
               throw new System.Exception("The Output directory doesn't exist.");
 
            m_OutputDirectory = value;
         }
         get
         {
            if (m_OutputDirectory.Length <= 0)
               return System.IO.Directory.GetCurrentDirectory();
            return m_OutputDirectory;
         }
      }
 
      protected virtual uint OnFileFound(uint context, uint notification, IntPtr param1, IntPtr param2)
      {
         uint fileOperation = SetupApiWrapper.NO_ERROR;
         FILE_IN_CABINET_INFO fileInCabinetInfo = (FILE_IN_CABINET_INFO)Marshal.PtrToStructure(param1, typeof(FILE_IN_CABINET_INFO));
         
         //TFile file = new TFile(fileInCabinetInfo);

         switch (context)
         {
            case (uint)SetupIterateCabinetAction.Iterate:
               fileOperation = (uint)FILEOP.FILEOP_SKIP;
               break;
 
            case (uint)SetupIterateCabinetAction.Extract:
               fileOperation = (uint)FILEOP.FILEOP_DOIT;
 
               fileInCabinetInfo.FullTargetName = System.IO.Path.Combine(this.OutputDirectory, fileInCabinetInfo.NameInCabinet);
 
               Marshal.StructureToPtr(fileInCabinetInfo, param1, true);
 
               break;
         }
 
         return fileOperation;
      }
 
      public void ExtractAll(string cabinetFileName)
      {
         PSP_FILE_CALLBACK callback = new PSP_FILE_CALLBACK(this.CallBack);
 
         uint setupIterateCabinetAction = (uint)SetupIterateCabinetAction.Extract;
 
         if (!SetupApiWrapper.SetupIterateCabinet(cabinetFileName, 0, callback, setupIterateCabinetAction))
         {
            string errMsg = new Win32Exception((int)KernelApiWrapper.GetLastError()).Message;
            System.Windows.Forms.MessageBox.Show(errMsg);
         }
      } 
   }
}

GeneralSomething is wrong!It cannot open the 2nd cab file.memberwinxp8455-Jan-09 10:12 
Hi~
Thanks for your source, it helps me a lot. But it cannot work perfectly..The problem is that when I try to open the 2nd cab file, exception throws up..Why?
GeneralError opening second cabmemberXtravar24-Oct-08 7:53 
The first cab file lists fine. Then the second cab file errors out. It seems that SetupIterateCabinet cannot be called twice. Does anyone have a work-around for this?
 
Using Visual Studio 2008 with .Net Framework 2.0 (also tested 3.5).
QuestionSome Questions!memberlilish18-Dec-06 9:07 
Hi!
 
Thanks for your code. However, I want to know that how can I broke it!!!! I mean how we can broke the cab file? Does it return an exception or ...?
 

 
Thanks alot.
GeneralA little more work requiredmemberColin Angus Mackay25-May-04 9:55 
Your article is potentially quite interesting. Care to talk more about the API you use, how to use it in other applications and so on?
 

"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
 
The Second EuroCPian Event will be in Brussels on the 4th of September
 
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!


General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130619.1 | Last Updated 25 May 2004
Article Copyright 2004 by aplaxas
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid