Today I start a new small project on extracting file from .msi file. The reason I start this project is that sometimes I just want to run a program only once but it needs to install on my machine. I do not like that. For example, I would like to check if my computer is suitable for Windows 7 so I downloaded Windows 7 Upgrade Advisor and run it to test. After finising with download, I realized that it is a .msi file. That means I must install if I would like to use. So I search around to find an unpacker for MSI file but after some searching I decide to write my own one. I guess it is not so difficult to write a program to extract all files in .msi file.
In my first step, I searched for MSI file format specification but after hard searching in 30 minutes, I could not find any documenation about msi file format. I really hate Microsoft in some cases. Microsoft did not publish any documentation of some important file formats and protocols which they use in Windows. Before I have problem with MMS protocol and now with MSI, always no specification for them. :(. I thought I could not start my project because it is not easy to reverse a file format of a complex structure. Luckily Wikipedia leads me to a WIX.
The Windows Installer XML toolset, is a free software toolset that builds Windows Installer (MSI) packages from an XML document. It supports a command-line environment that developers may integrate into their build processes to build MSI and MSM setup packages. WiX was the first software released by Microsoft under an open-source license called Common Public License.
For more details, you can find at homepage of Wix. I just post below a small code snippet to access info from msi file.
string strFileMsi = "D:\\w7ua.msi"; string strFileMsiNameOnly = Path.GetFileNameWithoutExtension(strFileMsi); string strDirectory = Path.GetDirectoryName(strFileMsi); Database dbMsiFile = new Database(strFileMsi, OpenDatabase.ReadOnly); View viewTemp = dbMsiFile.OpenExecuteView("SELECT * FROM Media"); Record rcTemp = viewTemp.Fetch(); string strCabsName = rcTemp[CNST_MEDIA_CABINET]; Console.WriteLine(strCabsName); strCabsName = strCabsName.Substring(1); viewTemp = dbMsiFile.OpenExecuteView("SELECT * FROM `_Streams` WHERE `Name` = '" + strCabsName + "'"); rcTemp = viewTemp.Fetch();
To view all available tables from msi file you can use Orca tool which is shipped with Windows Installer 4.5 SDK as figure below.