//////////////////////////////////////////////////////////////////////////////////////// // // MSICLASS FUNCTION DEFINITIONS // // //////////////////////////////////////////////////////////////////////////////////////// public void Start(BackgroundWorker workerThread, int pStep, DoWorkEventArgs workEventArgs) { string msiName = "Codeword_Installer.msi"; int progress = 0; ArrayList FilesToAddToMsi = new ArrayList(); string tmpCabName = "tmp.cab"; //arguments passed in from GUI ArrayList args = (ArrayList)workEventArgs.Argument; bool skipDotNetFxAssembly = (bool)args[0]; ArrayList x509certs = (ArrayList)args[1]; ArrayList thirdPartyApps = (ArrayList)args[2]; //add any x509 certificates now if (x509certs.Count > 0) { foreach (string x in x509certs) { if (x != "") { FilesToAddToMsi.Add(x); } } } //add any third party apps we should run post-scan if (thirdPartyApps.Count > 0) { foreach (string filename in thirdPartyApps) { if (filename != "") { FilesToAddToMsi.Add(filename); } } } //******************************************************** // EXTRACT DOTNETFX //******************************************************** //while dotnetfx.exe (21mb) .NET 2.0 installer is included //in the Handler assembly itself, we do not always necessarily //write it to the generated MSI installer -- the only time //we DONT is when the user has checked the appropriate checkbox if (!skipDotNetFxAssembly) { try { CwUtilitiesHelperClass.ExtractInternalResource("CwHandler.Resources.dotnetfx.exe", "dotnetfx.exe"); } catch (Exception ex) { workEventArgs.Result = false; throw new Exception("The .NET 2.0 Framework installer file (dotnetfx.exe) was not found. If you do not want to deploy .NET, please select the appropriate checkbox on the Options tab.\n\nError text: '" + ex.Message); } FilesToAddToMsi.Add("dotnetfx.exe"); workerThread.ReportProgress(25); } //******************************************************** // EXTRACT TEMPLATE MSI //******************************************************** //rather than create an MSI from scratch, we will use and build //upon the MSI created in Visual Studio for our tool (CwInstaller.msi). //this MSI is stored in our own internal assembly (in memory) //It initially contains: // (1) CwAgent.exe - the actual program binary // (2) Ionic.Utils.Zip.dll - zipping library needed //We will add to it: // (1) CwAgentConfiguration.xml - the config file the admin just generated // (2) dotnetfx.exe - .NET installer that setup.exe expects to be in same folder // (3) any other files specified by the admin // this MSI will wrap all these files into an installer database msi file // which can be pushed out and executed on host systems using SMS or other distro system try { CwUtilitiesHelperClass.ExtractInternalResource("CwHandler.Resources.CwInstaller.msi", msiName); } catch (Exception ex) { workEventArgs.Result = false; throw new Exception(ex.Message); } workerThread.ReportProgress(25); //******************************************************** // SET MSI PROPERTIES //******************************************************** //setup projects are retarded. one example of this retardedness //is that the setup project will not install over older versions //unless the version number has changed (this is set in the Setup Project's properties in VS) //a hack , as described here http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework/2009-01/msg00161.html //is to set the REINSTALLMODE to "amus" ...? IntPtr hProduct = IntPtr.Zero; CwMsiWin32.MsiOpenPackage(msiName, hProduct); CwMsiWin32.MsiSetProperty(hProduct, "REINSTALLMODE", "amus"); //also, set the product code to a new version, so taht when the MSI is installed, //it removes the other version. See: http://msdn.microsoft.com/en-us/library/aafz9hx4(VS.80).aspx CwMsiWin32.MsiSetProperty(hProduct, "PRODUCTCODE", Guid.NewGuid().ToString().ToUpper()); CwMsiWin32.MsiCloseHandle(hProduct); //******************************************************** // EXTRACT CABARC UTILITY //******************************************************** try { CwUtilitiesHelperClass.ExtractInternalResource("CwHandler.Resources.CABARC.EXE", "CABARC.EXE"); } catch (Exception ex) { workEventArgs.Result = false; throw new Exception(ex.Message); } workerThread.ReportProgress(50); //manually add two files we know will exist at this point- // -CwAgentConfiguration.xml - agent config // -CwAgentSignatures.xml - signatures FilesToAddToMsi.Add("CwAgentConfiguration.xml"); FilesToAddToMsi.Add("CwAgentSignatures.xml"); progress = 50; int progressPerFile = progress / FilesToAddToMsi.Count; foreach (string filename in FilesToAddToMsi) { //process cancelation request? if (workerThread.CancellationPending) { workEventArgs.Cancel = true; } else { try { MsiAddFile(msiName, filename, tmpCabName); progress += progressPerFile; workerThread.ReportProgress(progress); } catch (Exception e) { MsiCleanUpOnFailure(tmpCabName); workEventArgs.Result = false; throw new Exception("Failed to add '" + filename + "' to the MSI database in '" + msiName + "'. This MSI is most likely corrupt now.\n\n" + e.Message); } } } return; }