Click here to Skip to main content
15,896,348 members
Articles / Web Development / HTML

Cabinet File (*.CAB) Compression and Extraction

Rate me:
Please Sign up or sign in to vote.
4.93/5 (217 votes)
23 Mar 2012CPOL38 min read 3.2M   26.5K   573  
How to implement creation and extraction of Microsoft CAB files
using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Collections;
using System.Runtime.InteropServices;

namespace Demo
{
	class CabLibDemo
	{
		[DllImport("kernel32.dll", EntryPoint="GetWindowsDirectoryA", CharSet=CharSet.Ansi)]
		private static extern int GetWindowsDirectory(StringBuilder s_Text, int MaxCount); 

		[DllImport("kernel32.dll", EntryPoint="GetCurrentDirectoryA", CharSet=CharSet.Ansi)]
		private static extern int GetCurrentDirectory(int MaxCount, StringBuilder s_Text); 

		[STAThread]
		static void Main(string[] args)
		{
			// Change this to split the archive into multiple files (200000 --> CAB split size = 200kB)
			// ATTENTION: In this case Parameter 1 of CompressFile() MUST contain "%d"
			int s32_SplitSize = 0x7FFFFFFF;

			// Store filetimes as UTC in CAB files
			bool b_UtcTime = true;

			// You can specify your own key for CAB encryption here (the longer the more secure, up to 5000 characters)

			String s_EncryptionKey = ""; // to handle CAB files without encryption
//			String s_EncryptionKey = "AH%KJ/76?KJ�H�\\��dghf7(ZTbjasdf82iz<sx87qpc5ba&m;-@^l#";

			// ########################## Initialization ############################


			StringBuilder s_WinDir = new StringBuilder(500);
			GetWindowsDirectory(s_WinDir, 500);

			String s_Explorer = s_WinDir + "\\Explorer.exe";
			String s_Notepad  = s_WinDir + "\\Notepad.exe";

			StringBuilder s_WorkDir = new StringBuilder(500);
			GetCurrentDirectory(500, s_WorkDir);

			String s_CompressDir = s_WorkDir + "\\_Compressed";
			String s_DecryptDir  = s_WorkDir + "\\_Decrypted";
			String s_ResourceDir = s_WorkDir + "\\_ExtractResource";
			String s_StreamDir   = s_WorkDir + "\\_ExtractStream";

			String s_CompressFile = s_CompressDir + "\\Packed_%d.cab";

			CabLib.Compress i_Compress = new CabLib.Compress();
			CabLib.Extract  i_Extract  = new CabLib.Extract();

			i_Compress.SetEncryptionKey(s_EncryptionKey);
			i_Extract. SetDecryptionKey(s_EncryptionKey);

			// ########################## Compress demo ############################

			// This will pack Explorer.exe and Notepad.exe into a CAB file with subfolders

			Console.WriteLine("                      CAB FILE COMPRESSION\n");

			try
			{
				ArrayList i_Files = new ArrayList();
				i_Files.Add(new string[] { s_Explorer, @"FileManager\Explorer.exe" });
				i_Files.Add(new string[] { s_Notepad,  @"TextManager\Notepad.exe"  });

				i_Compress.CompressFileList(i_Files, s_CompressFile, b_UtcTime, s32_SplitSize);

				Console.WriteLine("SUCCESS: Compressed Explorer.exe and Notepad.exe into cabinet in\n" + s_CompressDir);
			}
			catch (Exception Ex)
			{
				Console.WriteLine(Ex.Message);
				goto _RESOURCE;
			}

			// ########################## Decrypt demo ############################

			// This will decrypt the CAB file which was encrypted above

			if (s_EncryptionKey.Length == 0) // Skip the following if the file was not encrypted 
				goto _RESOURCE;

			Console.WriteLine("----------------------------------------------------------------");
			Console.WriteLine("\n                   CAB FILE DECRYPTION\n");

			// "Packed_%d.cab" --> "Packed_1.cab"
			s_CompressFile = s_CompressFile.Replace("%d", "1");

			try
			{
				// Now extract into subdirectory "_Decrypted" and the corresponding subdirectories in the CAB file
				i_Extract.ExtractFile(s_CompressFile, s_DecryptDir);
			
				Console.WriteLine("SUCCESS: Decrypted all files from the above encrypted cabinet to\n" + s_DecryptDir);
			}
			catch (Exception Ex)
			{
				Console.WriteLine(Ex.Message);
			}

			// ########################## Extract Win32 resource demo ############################

			// This will extract the file "Test.cab" in the embedded Win32 CabLib.dll resources

			_RESOURCE:
			i_Extract.SetDecryptionKey(""); // not needed anymore for resource extraction
			
			Console.WriteLine("----------------------------------------------------------------");
			Console.WriteLine("\n                 WIN32 CAB RESOURCE EXTRACTION\n");

			try
			{
				// Extract only one file from the cabinet which must be in the root folder!!
//				i_Extract.SetSingleFile("Root.txt");

				// Now extract into subdirectory "_ExtractResource" and the corresponding subdirectories in the CAB file
				i_Extract.ExtractResource("CabLib.dll", 101, "CABFILE", s_ResourceDir);

				Console.WriteLine("SUCCESS: Extracted all files from Win32 resource Test.cab in CabLib.dll to\n" + s_ResourceDir);
			}
			catch (Exception Ex)
			{
				Console.WriteLine(Ex.Message);
			}

			// ########################## Extract Stream demo ############################

			// This will extract the file "Test.cab" in the embedded CabLibDemo.exe resources

			Console.WriteLine("----------------------------------------------------------------");
			Console.WriteLine("\n                 .NET CAB STREAM EXTRACTION\n");

			try
			{
				Assembly i_Ass  = Assembly.GetExecutingAssembly();
				Stream   i_Strm = i_Ass.GetManifestResourceStream("CabLibDemo.Resources.Test.cab");

				// Attach the event handler
//				CabLib.Extract.delBeforeCopyFile i_Delegate = new CabLib.Extract.delBeforeCopyFile(OnBeforeCopyFile);
//				i_Extract.evBeforeCopyFile += i_Delegate;

				// Now extract into subdirectory "_ExtractStream" and the corresponding subdirectories in the CAB file
				i_Extract.ExtractStream(i_Strm, s_StreamDir);

//				i_Extract.evBeforeCopyFile -= i_Delegate;

				Console.WriteLine("SUCCESS: Extracted all files from .NET resource Test.cab in CabLibDemo.exe to\n" + s_StreamDir);
			}
			catch (Exception Ex)
			{
				Console.WriteLine(Ex.Message);
			}

			// Under some cirumstances the DOS window disappears immediately, so you cannot read anything!
			Console.WriteLine("\nHit any key to exit");
			Console.Read();
		}

		/// <summary>
		/// This event handler is called for every extratced file before it is written to disk
		/// return false here if you want a file not to be extracted
		/// </summary>
		static private bool OnBeforeCopyFile(CabLib.Extract.kCabinetFileInfo k_Info)
		{
			Console.WriteLine("Extracting " + k_Info.s_SubFolder + k_Info.s_File);
			return true;
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Software Developer (Senior) ElmüSoft
Chile Chile
Software Engineer since 40 years.

Comments and Discussions