/// <summary> /// Create an AAPKG file from a source directory /// </summary> /// <param name="SourceDirectory"></param> /// <param name="AAPKGFilename"></param> public void CreateAAPKG(string SourceDirectory, string AAPKGFilename, Microsoft.Deployment.Compression.CompressionLevel CompressionLevel = Microsoft.Deployment.Compression.CompressionLevel.Normal) { string file1Path; try { log.Debug(""); file1Path = Path.GetTempPath() + "file1.cab"; // Create the File1.cab file from the directory containing all of the source files CabInfo ci = new CabInfo(file1Path); ci.Pack(SourceDirectory, true, CompressionLevel, null); //Now create a string list of just the File1.cab file and compress this to the final aapkg file List <String> SourceFiles = new List <String>(); SourceFiles.Add(file1Path); CabInfo ciAAPKG = new CabInfo(AAPKGFilename); ciAAPKG.PackFiles(null, SourceFiles, null, CompressionLevel, null); } catch { throw; } }
private static string ExtractMediaStream(Database db) { string tempFileName = Path.GetTempFileName(); string tempFolder = FileHelper.GetTempFolder(tempFileName); string cabTempFileName = Path.ChangeExtension(tempFileName, ".cab"); var cabFileName = (string)db.ExecuteScalar("SELECT `Cabinet` FROM `Media` WHERE `DiskId` = {0}", new object[] { 1 }); using (View view = db.OpenView("SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = '{0}'", new object[] { cabFileName.Substring(1) })) { view.Execute(); Record record = view.Fetch(); if (record == null) { throw new InstallerException("Stream not found: " + cabFileName); } using (record) record.GetStream("Data", cabTempFileName); } var cabinetInfo = new CabInfo(cabTempFileName); cabinetInfo.Unpack(tempFolder); cabinetInfo.Delete(); return(tempFolder); }
public void CreateCabFile() { // // Determine whether we're adding JetCanvas.xml to the jetproj file for the first time // If so, make the necessary call to AddItem() // if (false == this.jetCavasXmlExists) { this.AddItem("JetCanvas.xml", this.ProjectLocation, ProjectItemType.CanvasXml); this.jetCavasXmlExists = true; } // Always generate a fresh JetCanvas.xml when building cab this.canvas.GenerateXML(); // // Pack all ProjectItems into the CAB file // CabInfo cabInfo = new CabInfo(this.ProjectLocation + "\\" + "JetPak.cab"); List <string> filesToPack = new List <string>(); foreach (ProjectItem projectItem in this.listProjectItems) { filesToPack.Add(this.ProjectLocation + "\\" + projectItem.ItemName); } cabInfo.PackFiles(null, filesToPack, null); }
public InstallReactOSWorker ExtractingFiles() { if (Edition.Edition != ROSInstallEdition.ROSEdition.Setup) { return(null); } var ReactosCabPath = Path.Combine(Edition.SystemPath, "reactos", "reactos.cab"); CabInfo archive = new CabInfo(ReactosCabPath); for (int i = 0; i < FileList.Count; i++) { var file = FileList[i]; this.Check(); Program.MainWnd.SetStatus($"Extracting {file.Local.Name} ({i + 1}/{FileList.Count})"); Program.MainWnd.SetProgressFromValues(i, FileList.Count); if (file.Local.Exists) { file.Local.Delete(); } archive.UnpackFile(file.InCab, file.Local.FullName); } return(null); }
public static void UnCab(string cabFile, string wspFolderToUse) { EnsureDirectoryExists(wspFolderToUse); CabInfo cabToUnpack = new CabInfo(cabFile); cabToUnpack.Unpack(wspFolderToUse); }
public override SignatureVerificationResult VerifySignature(string path, string parent, string virtualPath) { SignatureVerificationResult svr = base.VerifySignature(path, parent, virtualPath); if (VerifyRecursive) { // MSU is just a CAB file really Log.WriteMessage(LogVerbosity.Diagnostic, SignCheckResources.DiagExtractingFileContents, svr.TempPath); CabInfo cabInfo = new CabInfo(path); cabInfo.Unpack(svr.TempPath); foreach (string cabFile in Directory.EnumerateFiles(svr.TempPath)) { string cabFileFullName = Path.GetFullPath(cabFile); SignatureVerificationResult cabEntryResult = VerifyFile(cabFile, svr.Filename, Path.Combine(svr.VirtualPath, cabFile), cabFileFullName); // Tag the full path into the result detail cabEntryResult.AddDetail(DetailKeys.File, SignCheckResources.DetailFullName, cabFileFullName); svr.NestedResults.Add(cabEntryResult); } DeleteDirectory(svr.TempPath); } return(svr); }
/// <summary> /// Extracts cab files from the specified MSIDB and puts them in the specified outputdir. /// </summary> /// <param name="msidb"></param> /// <param name="outputDir"></param> /// <returns></returns> private static List <CabInfo> CabsFromMsiToDisk(Path msi, Database msidb, string outputDir) { const string query = "SELECT * FROM `Media`"; var localCabFiles = new List <CabInfo>(); using (View view = msidb.OpenExecuteView(query)) { Record record = null; try { while (view.Fetch(out record)) { const int MsiInterop_Media_Cabinet = 4; string cabSourceName = record[MsiInterop_Media_Cabinet]; if (string.IsNullOrEmpty(cabSourceName)) { Debug.Print("Empty Cabinet value in Media table. This happens, but it's rare and it's weird!");//Debug.Fail("Couldn't find media CAB file inside the MSI (bad media table?)."); continue; } if (!string.IsNullOrEmpty(cabSourceName)) { bool extract = false; if (cabSourceName.StartsWith("#")) { extract = true; cabSourceName = cabSourceName.Substring(1); } Path localCabFile = Path.Combine(outputDir, cabSourceName); if (extract) { // extract cabinet, then explode all of the files to a temp directory ExtractCabFromPackage(localCabFile, cabSourceName, msidb, msi); } else { Path originalCabFile = Path.Combine(msi.Parent, cabSourceName); FileSystem.Copy(originalCabFile, localCabFile); } /* http://code.google.com/p/lessmsi/issues/detail?id=1 * apparently in some cases a file spans multiple CABs (VBRuntime.msi) so due to that we have get all CAB files out of the MSI and then begin extraction. Then after we extract everything out of all CAbs we need to release the CAB extractors and delete temp files. * Thanks to Christopher Hamburg for explaining this! */ var c = new CabInfo(localCabFile.PathString, cabSourceName); localCabFiles.Add(c); } } } finally { if (record != null) { record.Close(); } } } return(localCabFiles); }
public static CabFileInfo[] GetCabinetFiles(string path) { var cab = new CabInfo(path); var result = cab.GetFiles(); return(result.Select(c => c).ToArray()); }
private static string GetTemplate(string folderPath) { string templateName = Path.Combine(folderPath, DateTime.Now.ToString("yyyymmDDHHmmss") + ".xsn"); CabInfo cab = new CabInfo(templateName); cab.Pack(folderPath); return(templateName); }
/// <summary> /// Packs the input files into a cab that is appended to the /// output SfxCA.dll. /// </summary> private static void PackInputFiles(string outputFile, IDictionary <string, string> fileMap) { log.WriteLine("Packaging files"); CabInfo cabInfo = new CabInfo(outputFile); cabInfo.PackFileSet(null, fileMap, CompressionLevel.Max, PackProgress); }
public string ExtractFromCabFile(string filePath, string destinationFolder) { CabInfo cab = new CabInfo(filePath); cab.Unpack(destinationFolder); var filepath = Directory.GetFiles(destinationFolder, "*.xml"); return(filepath[0]); }
public static InfoPathTemplate CreateTemplate(string path) { // Lazy Init CabInfo cabInfo = new CabInfo(path); InfoPathTemplate template = new InfoPathTemplate(); template.CabInfo = cabInfo; return(template); }
/*public void ExpandFiles(string OutputPath, ProgressCallback progressCallback) * { * int buffersize = 0x20000; * * int fileCount = Files.Count(); * * int fileCounter = 0; * foreach (var file in Files) * { * int progressOffset = (int)Math.Round((double)fileCounter / fileCount * 100); * int progressScale = (int)Math.Round((double)1 / fileCount * 100); * * var filedirectoryonly = file.Contains("\\") ? string.Join("\\", file.Split('\\').Reverse().Skip(1).Reverse()) : ""; * var targetDirectory = Path.Combine(OutputPath, filedirectoryonly); * var targetFile = Path.Combine(OutputPath, file); * if (!Directory.Exists(targetDirectory)) * Directory.CreateDirectory(targetDirectory); * * using (var inStream = OpenFile(file)) * using (var outStream = File.Create(targetFile)) * { * byte[] buffer = new byte[buffersize]; * for (int i = 0; i < inStream.Length; i += buffersize) * { * int read = inStream.Read(buffer, 0, buffersize); * outStream.Write(buffer, 0, read); * progressCallback.Invoke(progressOffset + (int)Math.Round((double)i / inStream.Length * progressScale), file); * } * } * fileCounter++; * } * }*/ public static void ExpandFiles(string CabinetPath, string OutputPath, ProgressCallback progressCallback) { CabInfo info = new CabInfo(CabinetPath); info.Unpack(OutputPath, (a, b) => { progressCallback.Invoke((int)Math.Round((double)b.CurrentArchiveBytesProcessed / b.CurrentArchiveTotalBytes * 100), b.CurrentFileName); }); }
/// <summary>Creates a new cabinet file from the specified folder. WILL OVERWRITE ANY EXISTING CABINET FILE</summary> /// <param name="Folder"></param> /// <param name="Cab"></param> public static void FolderToCab(string Folder, string Cab) { if (File.Exists(Cab)) { File.Delete(Cab); } CabInfo C = new CabInfo(Cab); C.Pack(Folder, true, CompressionLevel.None, ProgHandler); }
/// <summary> /// Allocates a decompressor for each cab and merges any cabs that need merged. /// </summary> /// <param name="cabinets"></param> /// <returns></returns> private static IEnumerable <MSCabinet> MergeCabs(IList <CabInfo> cabInfos) { /* Sometimes cab files are part of a set. We must merge those into their set before we leave here. * Otherwise extracting a file that extends beyond the bounds of one cab in the set will fail. This happens in VBRuntime.msi * * It can be determined if a cabinet has further parts to load by examining the mscabd_cabinet::flags field: * if (flags & MSCAB_HDR_PREVCAB) is non-zero, there is a predecessor cabinet to open() and prepend(). Its MS-DOS case-insensitive filename is mscabd_cabinet::prevname * if (flags & MSCAB_HDR_NEXTCAB) is non-zero, there is a successor cabinet to open() and append(). Its MS-DOS case-insensitive filename is mscabd_cabinet::nextname */ var decompressors = new List <MSCabinet>(); for (int i = 0; i < cabInfos.Count; i++) { CabInfo cab = cabInfos[i]; MSCabinet msCab = null; try { msCab = new MSCabinet(cab.LocalCabFile); // NOTE: Deliberately not disposing. Caller must cleanup. } catch (Exception) { // As seen in https://github.com/activescott/lessmsi/issues/104, sometimes bogus cabs are inside of a msi but they're not needed to extract any files from. So we should attempt to ignore this failure here: Debug.Fail( string.Format("Cab name \"{0}\" could not be read by cab reader. Will attempt to ignore...", cab.CabSourceName) ); continue; } if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_NEXTCAB) != 0) { Debug.Assert(!string.IsNullOrEmpty(msCab.NextName), "Header indcates next cab but new cab not found."); // load the cab found in NextName: // Append it to msCab Debug.Print("Found cabinet set. Nextname: " + msCab.NextName); var nextCab = FindCabAndRemoveFromList(cabInfos, msCab.NextName); var msCabNext = new MSCabinet(nextCab.LocalCabFile); msCab.Append(msCabNext); decompressors.Add(msCab); } else if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_PREVCAB) != 0) { Debug.Assert(!string.IsNullOrEmpty(msCab.PrevName), "Header indcates prev cab but new cab not found."); Debug.Print("Found cabinet set. PrevName: " + msCab.PrevName); var prevCabInfo = FindCabAndRemoveFromList(cabInfos, msCab.PrevName); var msCabPrev = new MSCabinet(prevCabInfo.LocalCabFile); msCabPrev.Append(msCab); decompressors.Add(msCabPrev); } else { // just a simple standalone cab decompressors.Add(msCab); } } return(decompressors); }
public override ArcFile TryOpen(ArcView file) { if (VFS.IsVirtual) { throw new NotSupportedException("Cabinet files inside archives not supported"); } var info = new CabInfo(file.Name); var dir = info.GetFiles().Select(f => new CabEntry(f) as Entry); return(new ArcFile(file, this, dir.ToList())); }
public void OpenFile(string path) { textBoxFilePath.Text = path; cab = new CabInfo(path); cabFiles = cab.GetFiles(); Files = new List <EFile>(); string xml; using (StreamReader streamreader = new StreamReader(cab.OpenRead("_setup.xml"), Encoding.UTF8)) { xml = streamreader.ReadToEnd(); } XmlDocument setupxml = new XmlDocument(); setupxml.LoadXml(xml); XmlNodeList xnList = setupxml.SelectNodes("/wap-provisioningdoc/characteristic/characteristic/characteristic"); foreach (XmlNode xn in xnList) { foreach (XmlNode cxn in xn.ChildNodes) { if (cxn.Attributes["type"].Value.ToString() == "Extract") { foreach (XmlNode xnFile in cxn.ChildNodes) { if (xnFile.Attributes["name"].Value.ToString() == "Source") { CabFileInfo cabfileinfo = cabFiles.Where(x => x.Name == xnFile.Attributes["value"].Value.ToString()).FirstOrDefault(); EFile file = new EFile(); file.Source = xnFile.Attributes["value"].Value.ToString(); file.FileName = xn.Attributes["type"].Value.ToString(); file.LastUpDate = cabfileinfo.LastWriteTime; file.Lenght = cabfileinfo.Length; file.FileIcon = FileIconLoader.GetFileIcon(file.FileName, false); Files.Add(file); } } } } } BindDataGrid(); buttonExtract.Enabled = true; buttonInsertFiles.Enabled = true; }
// In-box device drivers = drivers that are shipped with Windows public static void DisableInBoxDeviceDrivers(string setupDirectory, string architectureIdentifier, int minorOSVersion, int productType, string hardwareID) { Console.WriteLine(); Console.WriteLine("Looking for drivers for your device (" + hardwareID + ") in Windows setup directory (to disable them):"); var filePaths = Directory.GetFiles(setupDirectory, "*.in_"); foreach (var filePath in filePaths) { var packedFileName = FileSystemUtils.GetNameFromPath(filePath); var unpackedFileName = packedFileName.Substring(0, packedFileName.Length - 1) + "F"; // the filename inside the archive ends with .INF and not with .IN_ var cabInfo = new CabInfo(filePath); ArchiveFileInfo fileInfo = null; try { // some files do not contain an inf file // for instance, netmon.in_ contains netmon.ini fileInfo = cabInfo.GetFile(unpackedFileName); } catch (CabException ex) { // file is invalid / unsupported Console.WriteLine("Cannot examine file '{0}': {1}", packedFileName, ex.Message); } if (fileInfo != null) { var driverInf = new PNPDriverINFFile(unpackedFileName); try { driverInf.ReadPackedFromDirectory(setupDirectory); } catch (CabException ex) { // the archive is a cab and it contains the file we are looking for, but the file is corrupted Console.WriteLine("Cannot unpack file '{0}': {1}", driverInf.PackedFileName, ex.Message); continue; } // Windows will pick up it's own signed drivers even if the added driver also match the SUBSYS, // so we have to disable in-box drivers regardless of the presence of &SUBSYS var found = driverInf.DisableMatchingHardwareID(hardwareID, architectureIdentifier, minorOSVersion, productType); if (found) { Console.WriteLine("Device driver for '{0}' found in file '{1}'.", hardwareID, packedFileName); driverInf.SavePackedToDirectory(setupDirectory); } } } Console.WriteLine("Finished looking for drivers for your device in Windows setup directory."); }
public static string Compress(string folderPath, string fileNamePath) { try { var cab = new CabInfo(fileNamePath); cab.Pack(folderPath, true, Microsoft.Deployment.Compression.CompressionLevel.Max, null); return(cab.FullName); } catch { return(String.Empty); } }
public void givenListOfRides_WhenCalculated_ShouldReturnInvoiceInformation() { rideList = new List <Ride> { new Ride(5, 20), new Ride(3, 15), new Ride(2, 10) }; double expectedFare = 145; int expectedRides = 3; double expectedAverage = expectedFare / expectedRides; CabInfo info = invoiceGenerator.GetInvoiceSummary(rideList); Assert.IsTrue(info.numberOfRides == expectedRides && info.totalFare == expectedFare && info.averageFare == expectedAverage); }
public static bool Decompress(string filePath, string extractFolder) { try { var cab = new CabInfo(filePath); cab.Unpack(extractFolder); return(true); } catch { return(false); } }
private SummaryXmlBinary GetSummaryXmlBinary() { var cabInfo = new CabInfo(_scenarioCabFile.FullName); var summaryXmlFiles = GetSummaryXmlFiles(cabInfo); if (!summaryXmlFiles.Any()) { throw new FileNotFoundException("Summary.xml file not found"); } var summaryFile = summaryXmlFiles.ElementAt(0); return(new SummaryXmlBinary(GetXmlText(summaryFile), GetSummaryMetaData(summaryFile))); }
public void givenUserId_WhenCheckedIfPresent_ShouldReturnInvoiceInfo() { rideList = new List <Ride> { new Ride(5, 20), new Ride(3, 15), new Ride(2, 10) }; double expectedFare = 145; int expectedRides = 3; double expectedAverage = expectedFare / expectedRides; invoiceGenerator.AddRides(1, rideList); CabInfo info = invoiceGenerator.GetUserInvoice(1); Assert.IsTrue(info.numberOfRides == expectedRides && info.totalFare == expectedFare && info.averageFare == expectedAverage); }
public static string GetKeyedWsp(string wspFile, string company, string servers, DateTime expiry) { Guid transGuid = new Guid(); //hax: config me string baseDir = @"D:\Hosting\5709750\html\sprockettools\d\"; string source = baseDir + @"original\" + transGuid.ToString() + @"\"; string dest = baseDir + @"modified\"; //load the cab and unpack it to the temporary directory used for this transaction CabInfo cab = new CabInfo(baseDir + wspFile); cab.Unpack(source); //get xml file string keyXmlFile = source + @"Layouts\SprocketValidator\key.xml"; XmlDocument xd = new XmlDocument(); xd.Load(keyXmlFile); //update XML file and write back to disk XmlNode n = xd.SelectSingleNode(@"/key"); n.InnerText = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(company + "|" + servers + "|" + DateTime.Today.AddDays(14).ToShortDateString())); using (XmlWriter xw = XmlWriter.Create(keyXmlFile)) { xd.WriteTo(xw); xw.Flush(); } //create a list with files and add them to a cab file string newFile = (dest + DateTime.Now.ToString("yyyyMMdd") + "_" + company + "_" + wspFile).Replace(" ", ""); CabInfo newCab = new CabInfo(newFile); List <string> paths = new List <string>(); //put files into list to be packed foreach (string compFile in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) { paths.Add(compFile.Replace(source, "")); } newCab.PackFiles(source, paths, paths); //delete the transaction directory Directory.Delete(source, true); return(newFile); }
static void Main(string[] args) { try { const string CabFile = @"E:\Gits\sample code\TestQML.cab"; const string CabFolder = @"E:\Gits\sample code\TestQML"; var cabInfo = new CabInfo(CabFile); cabInfo.Pack(CabFolder, true, Microsoft.Deployment.Compression.CompressionLevel.Max, Hanler); } catch (Exception ex) { throw; } }
public static bool ExpandCabFile(string cabFile, string destDir) { if (!Directory.Exists(destDir)) { DirectoryInfo dir = Directory.CreateDirectory(destDir); } if (!Directory.Exists(destDir)) { return(false); } CabInfo cab = new CabInfo(cabFile); cab.Unpack(destDir); return(true); }
private void InitializeManifest() { if (_infoPathManifest != null) { return; } // get the files named manifest.xsf (there should be one) IList <CabFileInfo> cbInfos = CabInfo.GetFiles("manifest.xsf"); if (cbInfos.Count != 1) { throw new ArgumentException("Invalid InfoPath xsn"); } _infoPathManifest = InfoPathManifest.Create(cbInfos[0]); }
private SummaryWsmBinary GetSummaryWsmBinary() { var cabInfo = new CabInfo(_scenarioCabFile.FullName); var summaryWsmFiles = cabInfo.GetFiles() .Where(e => e.Name.Equals("Summary.wsm")) .OrderBy(e => e.FullName); if (!summaryWsmFiles.Any()) { throw new FileNotFoundException("Summary.wsm file not found"); } var summaryFile = summaryWsmFiles.ElementAt(0); return(new SummaryWsmBinary(GetBinaryData(summaryFile), GetSummaryMetaData(summaryFile))); }
public List <byte[]> UnpackFile(byte[] data) { List <byte[]> list = new List <byte[]>(); if (data == null) { list.Add(data); return(list); } if (data.LongLength < 4) { list.Add(data); return(list); } //MSCF if (!(data[0] == 77 && data[1] == 83 && data[2] == 67 && data[3] == 70)) { list.Add(data); return(list); } var fileName = $"{ExtractorPath}{ExtractorFile}"; File.WriteAllBytes(fileName, data); CabInfo cab = new CabInfo(fileName); try { cab.Unpack(ExtractorDataPath); DirectoryInfo d = new DirectoryInfo(ExtractorDataPath); var files = d.GetFiles("*.*"); foreach (var file in files) { list.Add(File.ReadAllBytes($@"{ExtractorDataPath}\{file.Name}")); File.Delete($@"{ExtractorDataPath}\{file.Name}"); } File.Delete(fileName); } catch (Exception e) { throw e; } return(list); }
/// <summary> /// Extracts cab files from the specified MSIDB and puts them in the specified outputdir. /// </summary> /// <param name="msidb"></param> /// <param name="outputDir"></param> /// <returns></returns> private static List <CabInfo> CabsFromMsiToDisk(FileInfo msi, Database msidb, DirectoryInfo outputDir) { const string query = "SELECT * FROM `Media`"; var localCabFiles = new List <CabInfo>(); using (View view = msidb.OpenExecuteView(query)) { Record record; while (view.Fetch(out record)) { const int MsiInterop_Media_Cabinet = 4; string cabSourceName = record[MsiInterop_Media_Cabinet]; if (string.IsNullOrEmpty(cabSourceName)) { throw new IOException("Couldn't find media CAB file inside the MSI (bad media table?)."); } if (!string.IsNullOrEmpty(cabSourceName)) { bool extract = false; if (cabSourceName.StartsWith("#")) { extract = true; cabSourceName = cabSourceName.Substring(1); } string localCabFile = Path.Combine(outputDir.FullName, cabSourceName); if (extract) { // extract cabinet, then explode all of the files to a temp directory ExtractCabFromPackage(localCabFile, cabSourceName, msidb); } else { string originalCabFile = Path.Combine(msi.DirectoryName, cabSourceName); File.Copy(originalCabFile, localCabFile); } /* http://code.google.com/p/lessmsi/issues/detail?id=1 * apparently in some cases a file spans multiple CABs (VBRuntime.msi) so due to that we have get all CAB files out of the MSI and then begin extraction. Then after we extract everything out of all CAbs we need to release the CAB extractors and delete temp files. * Thanks to Christopher Hamburg for explaining this! */ var c = new CabInfo(localCabFile, cabSourceName); localCabFiles.Add(c); } } } return(localCabFiles); }
/// <summary> /// Finds packages given a locally-accessible filename /// Package information must be returned using <c>request.YieldPackage(...)</c> function. /// </summary> /// <param name="file">the full path to the file to determine if it is a package</param> /// <param name="id"> /// if this is greater than zero (and the number should have been generated using <c>StartFind(...)</c>, /// the core is calling this multiple times to do a batch search request. The operation can be delayed until /// <c>CompleteFind(...)</c> is called /// </param> /// <param name="request"> /// An object passed in from the CORE that contains functions that can be used to interact with /// the CORE and HOST /// </param> public void FindPackageByFile(string file, int id, Request request) { if( request == null ) { throw new ArgumentNullException("request"); } if( string.IsNullOrWhiteSpace(file) ) { throw new ArgumentNullException("file"); } // Nice-to-have put a debug message in that tells what's going on. request.Debug("Calling '{0}::FindPackageByFile' '{1}','{2}'", ProviderName, file, id); if (file.FileExists()) { var info = new CabInfo(file); request.YieldSoftwareIdentity(file, info.Name, null, null, null, null, null, file, info.Name); var files = info.GetFiles(); foreach (var i in files) { // read the properties file if (i.FullNameExtension == ".txt") { request.Debug("Reading properties file {0}", i.FullName); using (var reader = i.OpenText()) { var contents = reader.ReadToEnd(); Dictionary<string, string> keyValuePairs = contents.Split('\n').Select(line => line.Split('=')).Where(v => v.Count() == 2).ToDictionary(pair => pair[0], pair => pair[1]); foreach (var pair in keyValuePairs) { request.AddMetadata(pair.Key.Replace(' ', '_'), pair.Value.Replace("\"", "").Replace("\r", "")); } } } } } }
/// <summary> /// Extracts cab files from the specified MSIDB and puts them in the specified outputdir. /// </summary> /// <param name="msidb"></param> /// <param name="outputDir"></param> /// <returns></returns> private static List<CabInfo> CabsFromMsiToDisk(Database msidb, DirectoryInfo outputDir) { const string query = "SELECT * FROM `Media`"; var localCabFiles = new List<CabInfo>(); using (View view = msidb.OpenExecuteView(query)) { Record record; while (view.Fetch(out record)) { const int MsiInterop_Media_Cabinet = 4; string cabSourceName = record[MsiInterop_Media_Cabinet]; if (string.IsNullOrEmpty(cabSourceName)) throw new IOException("Couldn't find media CAB file inside the MSI (bad media table?)."); if (!string.IsNullOrEmpty(cabSourceName)) { if (cabSourceName.StartsWith("#")) { cabSourceName = cabSourceName.Substring(1); // extract cabinet, then explode all of the files to a temp directory string localCabFile = Path.Combine(outputDir.FullName, cabSourceName); ExtractCabFromPackage(localCabFile, cabSourceName, msidb); /* http://code.google.com/p/lessmsi/issues/detail?id=1 * apparently in some cases a file spans multiple CABs (VBRuntime.msi) so due to that we have get all CAB files out of the MSI and then begin extraction. Then after we extract everything out of all CAbs we need to release the CAB extractors and delete temp files. * Thanks to Christopher Hamburg for explaining this! */ var c = new CabInfo(localCabFile, cabSourceName); localCabFiles.Add(c); } } } } return localCabFiles; }
private void UpdateFilesOnOneMediaDisk(string mediaCab, InstallPathMap compressedFileMap, InstallPathMap uncompressedFileMap) { if(compressedFileMap.Count > 0) { string cabFile = null; bool cabFileIsTemp = false; if(mediaCab.StartsWith("#", StringComparison.Ordinal)) { cabFileIsTemp = true; mediaCab = mediaCab.Substring(1); using(View streamView = this.OpenView("SELECT `Name`, `Data` FROM `_Streams` " + "WHERE `Name` = '{0}'", mediaCab)) { streamView.Execute(); Record streamRec = streamView.Fetch(); if(streamRec == null) { this.LogMessage("Stream not found: {0}", mediaCab); throw new InstallerException("Stream not found: " + mediaCab); } using(streamRec) { this.LogMessage("extract cab {0}", mediaCab); Directory.CreateDirectory(this.TempDirectory); cabFile = Path.Combine(this.TempDirectory, Path.GetFileNameWithoutExtension(mediaCab) + ".cab"); streamRec.GetStream("Data", cabFile); } } } else { cabFile = Path.Combine(this.SourceDirectory, mediaCab); } CabInfo cab = new CabInfo(cabFile); ArrayList fileKeyList = new ArrayList(); foreach (CabFileInfo fileInCab in cab.GetFiles()) { string fileKey = fileInCab.Name; if(this.Files[fileKey] != null) { fileKeyList.Add(fileKey); } } string[] fileKeys = (string[]) fileKeyList.ToArray(typeof(string)); Directory.CreateDirectory(this.TempDirectory); ArrayList remainingFileKeys = new ArrayList(fileKeys); foreach(string fileKey in fileKeys) { InstallPath fileInstallPath = compressedFileMap[fileKey]; if(fileInstallPath != null) { UpdateFileStats(fileKey, fileInstallPath); string filePath = Path.Combine(this.WorkingDirectory, fileInstallPath.SourcePath); this.LogMessage("copy {0} {1}", filePath, fileKey); File.Copy(filePath, Path.Combine(this.TempDirectory, fileKey), true); remainingFileKeys.Remove(fileKey); } } if(remainingFileKeys.Count > 0) { this.cabName = mediaCab; this.cabMsg = "extract {0}\\{1}"; string[] remainingFileKeysArray = (string[]) remainingFileKeys.ToArray(typeof(string)); cab.UnpackFiles(remainingFileKeysArray, this.TempDirectory, remainingFileKeysArray, this.CabinetProgress); } ClearReadOnlyAttribute(this.TempDirectory, fileKeys); if(!cabFileIsTemp) { cab = new CabInfo(Path.Combine(this.WorkingDirectory, mediaCab)); } this.cabName = mediaCab; this.cabMsg = "compress {0}\\{1}"; cab.PackFiles(this.TempDirectory, fileKeys, fileKeys, this.CompressionLevel, this.CabinetProgress); if(cabFileIsTemp) { Record streamRec = new Record(1); streamRec.SetStream(1, cabFile); this.Execute(String.Format( "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = '{0}'", mediaCab), streamRec); } } foreach (KeyValuePair<string, InstallPath> entry in uncompressedFileMap) { UpdateFileStats((string) entry.Key, (InstallPath) entry.Value); } }
/// <summary> /// Extracts cab files from the specified MSIDB and puts them in the specified outputdir. /// </summary> /// <param name="msidb"></param> /// <param name="outputDir"></param> /// <returns></returns> private static List<CabInfo> CabsFromMsiToDisk(Path msi, Database msidb, string outputDir) { const string query = "SELECT * FROM `Media`"; var localCabFiles = new List<CabInfo>(); using (View view = msidb.OpenExecuteView(query)) { Record record; while (view.Fetch(out record)) { const int MsiInterop_Media_Cabinet = 4; string cabSourceName = record[MsiInterop_Media_Cabinet]; if (string.IsNullOrEmpty(cabSourceName)) { Debug.Print("Empty Cabinet value in Media table. This happens, but it's rare and it's weird!");//Debug.Fail("Couldn't find media CAB file inside the MSI (bad media table?)."); continue; } if (!string.IsNullOrEmpty(cabSourceName)) { bool extract = false; if (cabSourceName.StartsWith("#")) { extract = true; cabSourceName = cabSourceName.Substring(1); } Path localCabFile = Path.Combine(outputDir, cabSourceName); if (extract) { // extract cabinet, then explode all of the files to a temp directory ExtractCabFromPackage(localCabFile, cabSourceName, msidb); } else { Path originalCabFile = Path.Combine(msi.Parent, cabSourceName); FileSystem.Copy(originalCabFile, localCabFile); } /* http://code.google.com/p/lessmsi/issues/detail?id=1 * apparently in some cases a file spans multiple CABs (VBRuntime.msi) so due to that we have get all CAB files out of the MSI and then begin extraction. Then after we extract everything out of all CAbs we need to release the CAB extractors and delete temp files. * Thanks to Christopher Hamburg for explaining this! */ var c = new CabInfo(localCabFile.PathString, cabSourceName); localCabFiles.Add(c); } } } return localCabFiles; }