12,452,106 members (57,603 online)
alternative version

19.5K views
28 bookmarked
Posted

# Flexible Self Extracting Application in C# (ProjectSFX)

, 26 Mar 2012 CPOL
 Rate this:
This project presents a self extracting archive creator using Reflection and codeDOM

## Introduction

Self extracting archives have been extensively used from last couple of decades specially in windows. Most of the installers are self extracting archives which are executable files. These executable store files needed for installation in a centralized manner. In computer slang self extracting archives are also abbreviated as SFX.This project is developed in C# language as an open source project. The download-able content involves visual studio code, which can be manipulated according to custom need of deployment scenario. Presently in this application one can pack his or her data in a self extracting archive which will be a windows executable, running this executable stored data can be extracted as and when needed . Ultimate aim of this project was to replace commercial sfx installers for windows with a free .net based tool although at this time this is just a initial concept of a simple and flexible SFX. Let me explain, this is simple because it is not having many features of professional SFX (they are listed at end of code) and flexible because target SFX archive can be designed in a designer of visual studio though it will be compiled at runtime . An important thing to be noted at this time is that this ordinary open source tools relies on codeDOM and Reflection namespaces. One can learn concept of these with the code presented here. Before starting down the article ensure that reader is aware of basic concepts of adding resources in project. Just Google down you will find plethora of helpful articles over adding resources to ypur project.

## Background

I started this project because I wanted an Open Source setup application for IT community. Because of studies I was unable to further develop this project. Contribution to this code at http://sourceforge.net/projects/projectsfx/ is welcomed and highy appriciated.

## Software Usage

While running from code please run without debugging.  And also remember that some important files like codeFile1.cs, Form2.cs are in Resources folder of  VS (Visual Studio) solution.

when you run this code following form appears :

You can drag and drop files and folders for making SFX archive (Or you can use Add file/folder buttons). Next window shows status of application after clicking Finalize button. A save dialog box appears which should be provided with appropriate file name for SFX archive. A message of success appears after successful save of SFX as:

Now you can run the SFX archive which you have saved as by double clicking on it. It appears as:

If you keep the "Extract to same directory" check box checked this will extract the contents to same directory or else a save folder dialog will ask you the destination of extraction.

## Usability and Flexibility of code

I have taken utmost care so that code is reusable and easy to understand by commenting it everywhere. So that you folks can contribute to this code as well as use it for your own applications. An important feature of this code is that you can modify the final sfx in designer. For this just open the designer from solution pane of VS IDE as for CodeFile1.cs or Form2.cs. As shown :

All important functions to encapsulate folders and files are given in namespace SFX which is distributed in CodeFile1.cs as well (i.e some code of this namespace is also at CodeFile1.cs). Since code is sincerely long it would not be possible to discuss it here. Throughout the source, coding is properly commented for easy understanding and usage. While important code snippets are described below in following section.

## Working of Code

Project uses CodeDOM for compiling assembly at run time. Please see following code :

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)

{

SFXmaker.cp = new System.CodeDom.Compiler.CompilerParameters();

//FileStream f1 = new FileStream(@"C:\item_set11.xml", FileMode.Create);

FileStream f1 = new FileStream(Environment.GetEnvironmentVariable("TEMP")+"item_set11.xml", FileMode.Create);

string s1 = Environment.GetEnvironmentVariable("TEMP") + "Form2.cs";

File.WriteAllText(s1, SFX.Resource1.Form2);

string s2 = Environment.GetEnvironmentVariable("TEMP") + "Fd.cs";

File.WriteAllText(s2,

SFX.Resource1.Form2_Designer);

File.WriteAllText(Environment.GetEnvironmentVariable("TEMP") + "SFX1.cs",

SFX.Resource1.CodeFile1.ToString());

string[] itemstring = Summation.itemstostring(listView1.Items);

int nof = SFXmaker.countfilesonly(itemstring);

item_set[] iset = new item_set[nof];

iset.Initialize();

SFXmaker.lister(itemstring, ref iset);

XmlSerializer xs = new XmlSerializer(typeof(item_set[]));

xs.Serialize(f1,iset);

f1.Close();

foreach (item_set i in iset)

string[] sa = { (Environment.GetEnvironmentVariable("TEMP") + "SFX1.cs"), s1, s2 };

string err =

//SFXmaker.Compiler1(@"C:\SFX1.exe", @"E:\Icon1.ico", sa);

SFXmaker.Compiler1(savefilename, "", sa);//"" string for icon i.e. icon not defined

if (!(err == ""))

{

//textBox1.Text = err;

MessageBox.Show(err.ToString());

}

}

One can see in solution that SFX namespace is having numerous functions which are used through out this application. A function backgroundWorker1_DoWork() is executed asynchronously when finalize button of SFXmaker form is clicked. FileStream f1 creates and gets associated with a temporary file "item_set11.xml". We can see in last few lines of above code snippet that "xs.Serialize()" is using this stream to serialize iset. The string s1 buffers contents of Form2.cs from resources of this application and writes it to "Form2.cs file. Similarly designer file is saved in directory associated with "TEMP" enviornment variables of system. Most important File "CodeFile1.cs" is saved with its content with name "SFX1.cs". This files contains the code to be compiled with their designers. So you can edit these files as prototype for self extracting archive which is dynamically generated at runtime by our application. Last screenshot shows editing of Form contained in CodeFile1.cs in designer. Please note that Form2 that we have saved is startup screen for archive. Now comming to iset, it is nothing but an array instance of itemset. Where itemset is a structure shared by target application (archive) and Parent application (archive generator) under namespace Dist. To see it open CodeFile1.cs and go at end of file the following :

public class item_set

{
public details_of_item detail;
public int actual_index;
public string Name;
public string folder;
public item_set()
{
detail = new details_of_item();
actual_index = 0;
Name = "";
folder = "";
}

}

As seen it contains different fields viz. actual_index, Name, folder. These fields are actually properties of it items we drop in drag-drop window (listView1) in form "Summation.cs". itemset is associated with listView1 with function SFXmaker.lister() , for which itemset is passed with reference. So modification of itemset by this function are directly in effect.

After this SFXmaker.ADD1() is called two times to push these files (files to be extracted by archive  ) over runtime compiled assembly. This is accomplished using following function of CodeDOM namespace.

CompilerParameters.EmbeddedResources.Add() The following code snippet presents the defination of Compiler1 in SFXmaker.
public static string Compiler1(string savepath, string pathtoicon, string[] compilefrom)

{

StringBuilder sb = new StringBuilder();

//output type and path to icon

if(pathtoicon!="")

cp.CompilerOptions ="/target:winexe"+" "+"/win32icon:"+"\""+pathtoicon+"\"";

else

cp.CompilerOptions = "/target:winexe";

//gen exe

cp.GenerateExecutable = true;

cp.IncludeDebugInformation = false;

cp.OutputAssembly = savepath;

//wastage of memory

cp.GenerateInMemory = false;

//dont treat warings as errors

cp.TreatWarningsAsErrors = false;

pr = new CSharpCodeProvider();

CompilerResults cr = pr.CompileAssemblyFromFile(cp,compilefrom);

if (cr.Errors.HasErrors)

{

for (int i = 0; i < cr.Errors.Count; i++)

{

sb.Append("\n" + ((i + 1).ToString()) +

". Error in compiling:"

+ cr.Errors[i].ToString());

}

}

return (sb.ToString());

}

Above code shows the configuration of codeDOM compiler while compiling the target assembly at runtime. In this way one can compile a run time target and programmer can edit that target in designer before running parent application in visual studios. Finally arriving to an important part of this project i.e Reflection of run time assembly. In order make the SFX self aware about its own content, functions provided under Reflection have been very useful following code snippet demonstrates it.

private void Extract_ALL(string rootp)

{

string[] a = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();

int i = 0;

StringBuilder sb = new StringBuilder();

foreach (string s in a)

{

if (s != a[0])

{

sb.Append(rootp + iset[i].folder + iset[i].Name + "\n");

// label2.Text = " Extracting:" + a1;

Stream theResource = System.Reflection.Assembly.GetExecutingAssembly()

.GetManifestResourceStream(s);

Directory.CreateDirectory(rootp + iset[i].folder);

FileStream fs = new FileStream(rootp + iset[i].folder + iset[i].Name, FileMode.Create);

BinaryWriter bw = new BinaryWriter(fs);

byte[] bt = new byte[theResource.Length];

bw.Write(bt);

br.Close();

bw.Close();

fs.Close();

//this.label1.Text = "Nakulite SFX";

//label3.Text ="Click extract to extract" ;

i++;

}

}

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames() enlists all the resource names that are contained in running assembly. Remaining code is just for copy & paste of these resources (embedded files) to destination locations.

## Applications of this Code for Community

1. As an application this project could be used to package any kind of computer contents (files and folders). For this purpose just download the SFX.exe as console run it (you need .NET 2.0 framework installed), extract setup files in some directory. Run setup , as such "Nakulite Summation" will get installed. This is an easy GUI program which could be used to make Self extracting executable archive.
2. You can use this code to test various compression and encryption algorithms which work on single file but you want to test them on directories. For this modify the following in SFXmaker.cs in VS source with your algorithm as
public static void FSI(string[] fileitems)

{ ..............

else

{ ..................

// Algorithm over file with "name = sitem"

..................

fn[count].realfilename = sitem; count += 1;

}

..........

}

To decode at archive side modify CodeFile.cs accordingly.

## Code modifications needed

Modifications are needed in code as well as documentation. Following enhancements are needed:

1. Code is to be provided for registering components programmatically (To make this application professional enough to be used as a setup application).
2. GUI of SFX needs to be more appealing and professional.
3. A kind of Registry editor needs to be incorporated as all professional one have them.

Filnally the source code of archive is compiled at runtime with " SFXmaker.Compiler1(savefilename, "", sa);".

## Share

 Student India

I am specialized with Embedded Systems, my areas of interest are Real time Programming , RTOS, Intelligent Sensors and Actuators, Low level firmware. My projects uploaded on CodeProject are very old and I did them at time of my first year of Bachelors degree.
Further I am not in India, I have now moved to Stuttgart, Germany.

## You may also be interested in...

 Pro Pro

 First Prev Next
 i couldn't build the project because the pfx files doesn't imported, what is the password for the pfx files? ysrc264-Dec-14 0:16 ysrc26 4-Dec-14 0:16
 regarding decompressing SFX CAB archives pintokeith5-Jun-12 11:25 pintokeith 5-Jun-12 11:25
 Re: regarding decompressing SFX CAB archives Nakul Vyas10-Jun-12 20:07 Nakul Vyas 10-Jun-12 20:07
 Last Visit: 31-Dec-99 18:00     Last Update: 28-Aug-16 11:28 Refresh 1