Click here to Skip to main content
15,891,567 members
Articles / Programming Languages / C#
Article

Iterate and Extract Cabinet File

Rate me:
Please Sign up or sign in to vote.
2.95/5 (14 votes)
24 May 2004CPOL 78.8K   2.1K   12   7
Iterate and extract Cabinet File

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:

C#
[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)


Written By
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralThanks so much its working fine for me. Pin
shahshi24-Aug-10 21:22
shahshi24-Aug-10 21:22 
GeneralThe system cannot find the file specified Pin
mikey22217-Oct-09 13:07
mikey22217-Oct-09 13:07 
GeneralEssential!!! Pin
Rakshun29-Aug-09 8:04
Rakshun29-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. Pin
winxp8455-Jan-09 10:12
winxp8455-Jan-09 10:12 
GeneralError opening second cab Pin
Xtravar24-Oct-08 7:53
Xtravar24-Oct-08 7:53 
QuestionSome Questions! Pin
lilish18-Dec-06 9:07
lilish18-Dec-06 9:07 
GeneralA little more work required Pin
Colin Angus Mackay25-May-04 9:55
Colin Angus Mackay25-May-04 9:55 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.