Example #1
0
 private void LoadStreams()
 {
     using (var stg = new OleStorageFile(new LessIO.Path(SelectedMsiFile.FullName)))
     {
         var streamViews = stg.GetStreams().Select(s => StreamInfoView.FromStream(s));
         View.SetStreamSelectorSource(streamViews);
     }
 }
Example #2
0
        /// <summary>
        /// Called by the view to notify of a change in the selection of the SelectedStreamInfo.
        /// </summary>
        public void OnSelectedStreamChanged()
        {
            if (View.SelectedStreamInfo != null && this.SelectedMsiFile != null)
            {
                // 1: find the right stream containing the cab bits:
                using (var oleFile = new OleStorageFile(new LessIO.Path(this.SelectedMsiFile.FullName)))
                {
                    var foundStream = oleFile.GetStreams().FirstOrDefault(s => string.Equals(View.SelectedStreamInfo.Name, s.Name, StringComparison.InvariantCulture));
                    if (foundStream == null)
                    {
                        View.ShowUserError("Could not find stream for CAB '{0}'", View.SelectedStreamInfo.Name);
                        return;
                    }
                    // if the file is a cab, we'll list the files in it (if it isn't clear the view):
                    IEnumerable <CabContainedFileView> streamFiles = new CabContainedFileView[] {};
                    if (View.SelectedStreamInfo.IsCabStream)
                    {
                        var tempFileName = System.IO.Path.GetTempFileName();
                        using (var cabBits = foundStream.GetStream(FileMode.Open, FileAccess.Read))
                            using (var writer = new BinaryWriter(File.Create(tempFileName)))
                            {
                                var buffer = new byte[1024 * 1024];
                                int bytesRead;
                                do
                                {
                                    bytesRead = cabBits.Read(buffer, 0, buffer.Length);
                                    writer.Write(buffer, 0, bytesRead);
                                } while (bytesRead > 0);
                            }
                        // 2: enumerate files in the cab and set them to the view's

                        using (var cab = new LibMSPackN.MSCabinet(tempFileName))
                        {
                            // ToList to force it to enumerate now.
                            streamFiles = cab.GetFiles().Select(f => new CabContainedFileView(f.Filename)).ToList();
                        }
                        Debug.Assert(streamFiles != null && streamFiles.Any());
                    }
                    View.SetCabContainedFileListSource(streamFiles);
                }
            }
        }
Example #3
0
        public static void ExtractCabFromPackage(Path destCabPath, string cabName, Database inputDatabase, LessIO.Path msiPath)
        {
            //NOTE: checking inputDatabase.TableExists("_Streams") here is not accurate. It reports that it doesn't exist at times when it is perfectly queryable. So we actually try it and look for a specific exception:
            //NOTE: we do want to tryStreams. It is more reliable when available and AFAICT it always /should/ be there according to the docs but isn't.
            const bool tryStreams = true;

            if (tryStreams)
            {
                try
                {
                    ExtractCabFromPackageTraditionalWay(destCabPath, cabName, inputDatabase);
                    // as long as TraditionalWay didn't throw, we'll leave it at that...
                    return;
                }
                catch (Exception e)
                {
                    Debug.WriteLine("ExtractCabFromPackageTraditionalWay Exception: {0}", e);
                    // According to issue #78 (https://github.com/activescott/lessmsi/issues/78), WIX installers sometimes (always?)
                    // don't have _Streams table yet they still install. Since it appears that msi files generally (BUT NOT ALWAYS - see X86 Debuggers And Tools-x86_en-us.msi) will have only one cab file, we'll try to just find it in the sterams and use it instead:
                    Trace.WriteLine("MSI File has no _Streams table. Attempting alternate cab file extraction process...");
                }
            }

            using (var stg = new OleStorageFile(msiPath))
            {
                // MSIs do exist with >1. If we use the ExtractCabFromPackageTraditionalWay (via _Streams table) then it handles that. If we are using this fallback approach, multiple cabs is a bad sign!
                Debug.Assert(CountCabs(stg) == 1, string.Format("Expected 1 cab, but found {0}.", CountCabs(stg)));
                foreach (var strm in stg.GetStreams())
                {
                    using (var bits = strm.GetStream(FileMode.Open, FileAccess.Read))
                    {
                        if (OleStorageFile.IsCabStream(bits))
                        {
                            Trace.WriteLine(String.Format("Found CAB bits in stream. Assuming it is for cab {0}.", destCabPath));
                            Func <byte[], int> streamReader = destBuffer => bits.Read(destBuffer, 0, destBuffer.Length);
                            CopyStreamToFile(streamReader, destCabPath);
                        }
                    }
                }
            }
        }
Example #4
0
 private static int CountCabs(OleStorageFile stg)
 {
     return(stg.GetStreams().Count(strm => OleStorageFile.IsCabStream((StreamInfo)strm)));
 }