DocCompiler.cs :  » Installers-Generators » WiX » Microsoft » Tools » DocCompiler » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Installers Generators » WiX 
WiX » Microsoft » Tools » DocCompiler » DocCompiler.cs
//-------------------------------------------------------------------------------------------------
// <copyright file="DocCompiler.cs" company="Microsoft">
//    Copyright (c) Microsoft Corporation.  All rights reserved.
//    
//    The use and distribution terms for this software are covered by the
//    Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
//    which can be found in the file CPL.TXT at the root of this distribution.
//    By using this software in any fashion, you are agreeing to be bound by
//    the terms of this license.
//    
//    You must not remove this notice, or any other, from this software.
// </copyright>
// 
// <summary>
// Compiles various things into documentation.
// </summary>
//-------------------------------------------------------------------------------------------------

namespace Microsoft.Tools.DocCompiler{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Xml;
    using System.Xml.Schema;

    /// <summary>
    /// Compiles various things into documentation.
    /// </summary>
    public class DocCompiler
    {
        internal const string DocCompilerNamespace = "http://schemas.microsoft.com/wix/2005/DocCompiler";
        internal const string XhtmlNamespace = "http://www.w3.org/1999/xhtml";

        private string hhcFile;
        private XmlNamespaceManager namespaceManager;
        private string versionNumber;
        private string outputDir;
        private string outputFileName;
        private bool showHelp;
        private string tocFile;
        private bool chm = false;
        private bool web = false;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        /// <param name="args">The command line arguments.</param>
        /// <returns>The error code for the application.</returns>
        [STAThread]
        public static int Main(string[] args)
        {
            DocCompiler docCompiler = new DocCompiler();
            return docCompiler.Run(args);
        }

        /// <summary>
        /// Run the application.
        /// </summary>
        /// <param name="args">The command line arguments.</param>
        /// <returns>The error code for the application.</returns>
        private int Run(string[] args)
        {
            try
            {
                this.ParseCommandline(args);

                // get the assemblies
                Assembly docCompilerAssembly = this.GetType().Assembly;
                FileVersionInfo fv = FileVersionInfo.GetVersionInfo(docCompilerAssembly.Location);
                this.versionNumber = fv.FileVersion;

                if (this.showHelp)
                {
                    Console.WriteLine("Microsoft (R) Documentation Compiler version {0}", fv.FileVersion);
                    Console.WriteLine("Copyright (C) Microsoft Corporation. All rights reserved.");
                    Console.WriteLine();
                    Console.WriteLine(" usage: DocCompiler [-?] {-c:hhc.exe|-w} tableOfContents.xml outputChmOrDir");
                    Console.WriteLine();
                    Console.WriteLine("    c - path to HTML Help Compiler to create output CHM");
                    Console.WriteLine("    w - creates Web HTML Manual to output directory");

                    return 0;
                }

                // ensure the directory containing the html files exists
                Directory.CreateDirectory(Path.Combine(this.outputDir, "html"));

                // load the schema
                XmlReader schemaReader = null;
                XmlSchemaCollection schemas = null;
                try
                {
                    schemaReader = new XmlTextReader(docCompilerAssembly.GetManifestResourceStream("Microsoft.Tools.DocCompiler.Xsd.docCompiler.xsd"));
                    schemas = new XmlSchemaCollection();
                    schemas.Add(DocCompilerNamespace, schemaReader);
                }
                finally
                {
                    schemaReader.Close();
                }

                // load the table of contents
                XmlTextReader reader = null;
                try
                {
                    reader = new XmlTextReader(this.tocFile);
                    XmlValidatingReader validatingReader = new XmlValidatingReader(reader);
                    validatingReader.Schemas.Add(schemas);

                    // load the xml into a DOM
                    XmlDocument doc = new XmlDocument();
                    doc.Load(validatingReader);

                    // create a namespace manager
                    this.namespaceManager = new XmlNamespaceManager(doc.NameTable);
                    this.namespaceManager.AddNamespace("doc", DocCompilerNamespace);
                    this.namespaceManager.AddNamespace("xhtml", XhtmlNamespace);
                    this.namespaceManager.PushScope();

                    this.ProcessCopyDirectories(doc);
                    this.ProcessCopyFiles(doc);
                    this.ProcessTopics(doc);
                    this.ProcessSchemas(doc);

                    if (this.chm)
                    {
                        this.CompileChm(doc);
                    }
                    if (this.web)
                    {
                        this.BuildWeb(doc);
                    }
                }
                finally
                {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                }
            }
            catch (XmlException xe)
            {
                Console.WriteLine("{0}({1},{2}) : fatal error DCMP0002 : {3}", xe.SourceUri, xe.LineNumber, xe.LinePosition, xe.Message);
                Console.WriteLine();
                Console.WriteLine("Stack Trace:");
                Console.WriteLine(xe.StackTrace);
                return 2;
            }
            catch (Exception e)
            {
                Console.WriteLine("DocCompiler.exe : fatal error DCMP0001: {0}", e.Message);
                Console.WriteLine();
                Console.WriteLine("Stack Trace:");
                Console.WriteLine(e.StackTrace);

                if (e is NullReferenceException)
                {
                    throw;
                }

                return 1;
            }

            return 0;
        }

        /// <summary>
        /// Process directories to copy.
        /// </summary>
        /// <param name="doc">The documentation compiler xml document.</param>
        private void ProcessCopyDirectories(XmlDocument doc)
        {
            XmlNodeList copyDirectoryNodes = doc.SelectNodes("//doc:CopyDirectory", this.namespaceManager);

            foreach (XmlElement copyDirectoryElement in copyDirectoryNodes)
            {
                DirectoryInfo sourceDirectory = new DirectoryInfo(copyDirectoryElement.GetAttribute("Source"));
                string destinationDirectory = copyDirectoryElement.GetAttribute("Destination");

                destinationDirectory = Path.Combine(this.outputDir, destinationDirectory);

                CopyDirectory(sourceDirectory, destinationDirectory);
            }
        }

        /// <summary>
        /// Recursively copy a directory.
        /// </summary>
        /// <param name="sourceDirectory">DirectoryInfo object representing the source directory.</param>
        /// <param name="destinationDirectory">String representing the fully qualified path to the
        /// destination directory.</param>
        private void CopyDirectory(DirectoryInfo sourceDirectory, string destinationDirectory)
        {
            // create the destination directory if it does not yet exist
            if (!Directory.Exists(destinationDirectory))
            {
                Directory.CreateDirectory(destinationDirectory);
            }

            // copy all files in the directory
            foreach (FileInfo fileToCopy in sourceDirectory.GetFiles())
            {
                string destinationFile = Path.Combine(destinationDirectory, fileToCopy.Name);
                fileToCopy.CopyTo(destinationFile, true);

                // remove the read-only attribute
                File.SetAttributes(destinationFile, File.GetAttributes(destinationFile) & ~FileAttributes.ReadOnly);
            }

            // recursively copy all sub-directories in the directory
            foreach (DirectoryInfo directoryToCopy in sourceDirectory.GetDirectories())
            {
                CopyDirectory(directoryToCopy, Path.Combine(destinationDirectory, directoryToCopy.Name));
            }
        }

        /// <summary>
        /// Process files to copy.
        /// </summary>
        /// <param name="doc">The documentation compiler xml document.</param>
        private void ProcessCopyFiles(XmlDocument doc)
        {
            XmlNodeList copyFileNodes = doc.SelectNodes("//doc:CopyFile", this.namespaceManager);

            foreach (XmlElement copyFileElement in copyFileNodes)
            {
                string sourceFile = copyFileElement.GetAttribute("Source");
                string destinationFile = copyFileElement.GetAttribute("Destination");

                destinationFile = Path.Combine(this.outputDir, destinationFile);

                File.Copy(sourceFile, destinationFile, true);

                // remove the read-only attribute
                File.SetAttributes(destinationFile, File.GetAttributes(destinationFile) & ~FileAttributes.ReadOnly);
            }
        }

        /// <summary>
        /// Process the xml schemas.
        /// </summary>
        /// <param name="doc">The documentation compiler xml document.</param>
        private void ProcessSchemas(XmlDocument doc)
        {
            XmlNodeList schemaNodes = doc.SelectNodes("//doc:XmlSchema", this.namespaceManager);

            XmlSchemaCompiler schemaCompiler = new XmlSchemaCompiler(this.outputDir, this.versionNumber);
            schemaCompiler.CompileSchemas(schemaNodes);
        }

        /// <summary>
        /// Process the topics.
        /// </summary>
        /// <param name="doc">The documentation compiler xml document.</param>
        private void ProcessTopics(XmlDocument doc)
        {
            XmlNodeList topicNodes = doc.SelectNodes("//doc:Topic", this.namespaceManager);

            foreach (XmlElement topicElement in topicNodes)
            {
                string sourceFile = topicElement.GetAttribute("SourceFile");

                if (sourceFile.Length > 0)
                {
                    string htmlDir = Path.Combine(this.outputDir, "html");
                    string destinationFile = Path.Combine(htmlDir, Path.GetFileName(sourceFile));

                    // save the relative path to the destination file
                    string relDestinationFile = Path.Combine("html", Path.GetFileName(sourceFile));
                    topicElement.SetAttribute("DestinationFile", relDestinationFile);

                    File.Copy(sourceFile, destinationFile, true);

                    // remove the read-only attribute
                    File.SetAttributes(destinationFile, File.GetAttributes(destinationFile) & ~FileAttributes.ReadOnly);

                    // copy the relative destination file path to the child Index nodes
                    XmlNodeList indexNodes = topicElement.SelectNodes("doc:Index", this.namespaceManager);
                    foreach (XmlElement indexElement in indexNodes)
                    {
                        indexElement.SetAttribute("DestinationFile", relDestinationFile);
                    }
                }
            }
        }

        /// <summary>
        /// Compile the documentation into a chm file.
        /// </summary>
        /// <param name="doc">The documentation compiler xml document.</param>
        private void CompileChm(XmlDocument doc)
        {
            XmlElement defaultTopicNode = (XmlElement)doc.SelectSingleNode("//doc:Topic", this.namespaceManager);
            string defaultTopicFile = defaultTopicNode.GetAttribute("DestinationFile");
            string defaultTopicTitle = defaultTopicNode.GetAttribute("Title");

            // create the project file
            string projectFile = Path.Combine(this.outputDir, "project.hhp");
            using (StreamWriter sw = File.CreateText(projectFile))
            {
                sw.WriteLine("[OPTIONS]");
                sw.WriteLine("Compatibility=1.1 or later");
                sw.WriteLine(String.Format("Compiled file={0}", this.outputFileName));
                sw.WriteLine("Contents file=toc.hhc");
                sw.WriteLine("Index file=idx.hhk");
                sw.WriteLine("Default Window=Main");
                sw.WriteLine(String.Format("Default topic={0}", defaultTopicFile));
                sw.WriteLine("Display compile progress=No");
                sw.WriteLine("Error log file=log.txt");
                sw.WriteLine("Full-text search=Yes");
                sw.WriteLine("Language=0x409 English (United States)");
                sw.WriteLine(String.Format("Title={0}", defaultTopicTitle));
                sw.WriteLine("");
                sw.WriteLine("[WINDOWS]");
                sw.WriteLine("Main=,\"toc.hhc\",\"idx.hhk\",\"{0}\",\"{0}\",,,,,0x63520,,0x384e,,,,,,,,0", defaultTopicFile);
            }

            // create the index file
            string indexFile = Path.Combine(this.outputDir, "idx.hhk");
            using (StreamWriter sw = File.CreateText(indexFile))
            {
                sw.WriteLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
                sw.WriteLine("<HTML>");
                sw.WriteLine("<HEAD>");
                sw.WriteLine("<META NAME=\"GENERATOR\" CONTENT=\"A tool\">");
                sw.WriteLine("</HEAD>");
                sw.WriteLine("<BODY>");
                sw.WriteLine("<OBJECT TYPE=\"text/site properties\">");
                sw.WriteLine("  <PARAM NAME=\"FrameName\" VALUE=\"TEXT\">");
                sw.WriteLine("</OBJECT>");
                sw.WriteLine("<UL>");

                XmlNodeList topicNodes = doc.SelectNodes("//doc:Topic|//doc:Index", this.namespaceManager);
                foreach (XmlElement topicElement in topicNodes)
                {
                    string title = topicElement.GetAttribute("Title");
                    string destinationFile = topicElement.GetAttribute("DestinationFile");

                    if (destinationFile.Length > 0)
                    {
                        sw.WriteLine("\t<LI> <OBJECT type=\"text/sitemap\">");
                        sw.WriteLine(String.Format("\t\t<param name=\"Keyword\" value=\"{0}\">", title));
                        sw.WriteLine(String.Format("\t\t<param name=\"Name\" value=\"{0}\">", title));
                        sw.WriteLine(String.Format("\t\t<param name=\"Local\" value=\"{0}\">", destinationFile));
                        sw.WriteLine("\t\t</OBJECT>");
                    }
                }

                sw.WriteLine("</UL>");
                sw.WriteLine("</BODY>");
                sw.WriteLine("</HTML>");
            }

            // create the table of contents file
            string tocFile = Path.Combine(this.outputDir, "toc.hhc");
            using (StreamWriter sw = File.CreateText(tocFile))
            {
                sw.WriteLine("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">");
                sw.WriteLine("<HTML>");
                sw.WriteLine("<HEAD>");
                sw.WriteLine("<meta name=\"GENERATOR\" content=\"Microsoft&reg; HTML Help Workshop 4.1\">");
                sw.WriteLine("<!-- Sitemap 1.0 -->");
                sw.WriteLine("</HEAD><BODY>");
                sw.WriteLine("<OBJECT type=\"text/site properties\">");
                sw.WriteLine("\t<param name=\"ImageType\" value=\"Folder\">");
                sw.WriteLine("</OBJECT>");
                sw.WriteLine("<UL>");

                XmlNodeList topicNodes = doc.SelectNodes("//doc:TableOfContents/doc:Topic", this.namespaceManager);
                foreach (XmlNode topicNode in topicNodes)
                {
                    this.WriteTopic((XmlElement)topicNode, sw);
                }

                sw.WriteLine("</UL>");
                sw.WriteLine("</BODY></HTML>");
            }

            // call the help compiler
            Process hhcProcess = new Process();
            hhcProcess.StartInfo.FileName = this.hhcFile;
            hhcProcess.StartInfo.Arguments = String.Concat("\"", projectFile, "\"");
            hhcProcess.StartInfo.CreateNoWindow = true;
            hhcProcess.StartInfo.UseShellExecute = false;
            hhcProcess.StartInfo.RedirectStandardOutput = true;
            hhcProcess.Start();

            // wait for the process to terminate
            hhcProcess.WaitForExit();

            // check for errors
            if (hhcProcess.ExitCode != 1)
            {
                throw new InvalidOperationException("The help compiler failed.");
            }
        }

        /// <summary>
        /// Write a single topic and its children to the HTMLHelp table of contents file.
        /// </summary>
        /// <param name="topicElement">The topic element to write.</param>
        /// <param name="sw">Writer for the table of contents.</param>
        private void WriteTopic(XmlElement topicElement, StreamWriter sw)
        {
            string destinationFile = topicElement.GetAttribute("DestinationFile");
            string title = topicElement.GetAttribute("Title");

            sw.WriteLine("\t<LI> <OBJECT type=\"text/sitemap\">");
            sw.WriteLine(String.Format("\t\t<param name=\"Name\" value=\"{0}\">", title));
            if (destinationFile.Length > 0)
            {
                sw.WriteLine(String.Format("\t\t<param name=\"Local\" value=\"{0}\">", destinationFile));
            }
            sw.WriteLine("\t\t</OBJECT>");

            XmlNodeList topicNodes = topicElement.SelectNodes("doc:Topic", this.namespaceManager);
            if (topicNodes.Count > 0)
            {
                sw.WriteLine("<UL>");
            }

            foreach (XmlNode topicNode in topicNodes)
            {
                this.WriteTopic((XmlElement)topicNode, sw);
            }

            if (topicNodes.Count > 0)
            {
                sw.WriteLine("</UL>");
            }
        }

        /// <summary>
        /// Build web manual pages.
        /// </summary>
        /// <param name="doc">The documentation compiler xml document.</param>
        private void BuildWeb(XmlDocument doc)
        {
            XmlNodeList topicNodes = doc.SelectNodes("//doc:TableOfContents/doc:Topic", this.namespaceManager);

            List<XmlNode> parentTopics = new List<XmlNode>();

            foreach (XmlNode topicNode in topicNodes)
            {
                this.WriteWebTopic((XmlElement)topicNode, parentTopics);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="topicElement">The topic element to write.</param>
        /// <param name="parentTopics"></param>
        private void WriteWebTopic(XmlElement topicElement, List<XmlNode> parentTopics)
        {
            string file = Path.Combine(this.outputDir, topicElement.GetAttribute("DestinationFile"));
            string title = topicElement.GetAttribute("Title");

            if (String.IsNullOrEmpty(file))
                return;

            string outputFile = Path.Combine(this.outputDir, Path.ChangeExtension(file, ".xml"));
            XmlTextWriter w = new XmlTextWriter(outputFile, Encoding.UTF8);

            w.WriteStartElement("ManualPage");
            w.WriteAttributeString("File", Path.GetFullPath(file));
            w.WriteAttributeString("Title", title);

            IEnumerator<XmlNode> parentTopicEnumerator = parentTopics.GetEnumerator();
            if (parentTopicEnumerator.MoveNext())
            {
                w.WriteStartElement("ParentTopics");
                this.WriteWebParentTopic(parentTopicEnumerator, w);
                w.WriteEndElement();
            }

            w.WriteEndElement();
            w.Close();

            XmlNodeList topicNodes = topicElement.SelectNodes("doc:Topic", this.namespaceManager);
            if (topicNodes.Count > 0)
            {
                parentTopics.Add(topicElement);

                foreach (XmlNode topicNode in topicNodes)
                {
                    this.WriteWebTopic((XmlElement)topicNode, parentTopics);
                }

                parentTopics.RemoveAt(parentTopics.Count - 1);
            }
        }

        /// <summary>
        /// Writes "breadcrumb" trail of links to parent topic elements.
        /// </summary>
        /// <param name="topicEnumerator"></param>
        /// <param name="w"></param>
        private void WriteWebParentTopic(IEnumerator<XmlNode> topicEnumerator, XmlWriter w)
        {
            XmlElement topicElement = (XmlElement)topicEnumerator.Current;

            string destinationFile = Path.GetFileName(topicElement.GetAttribute("DestinationFile"));
            string title = topicElement.GetAttribute("Title");

            w.WriteStartElement("Topic");
            w.WriteAttributeString("File", destinationFile);
            w.WriteAttributeString("Title", title);

            if (topicEnumerator.MoveNext())
            {
                WriteWebParentTopic(topicEnumerator, w);
            }

            w.WriteEndElement();
        }

        /// Parse the command line arguments.
        /// </summary>
        /// <param name="args">Command line arguments.</param>
        private void ParseCommandline(string[] args)
        {
            foreach (string arg in args)
            {
                if (arg.StartsWith("-") || arg.StartsWith("/"))
                {
                    if (arg.Length > 1)
                    {
                        switch (arg[1])
                        {
                            case '?':
                                this.showHelp = true;
                                break;
                            case 'c':
                                this.hhcFile = arg.Substring(3);
                                this.chm = true;
                                break;
                            case 'w':
                                this.web = true;
                                break;
                            default:
                                throw new ArgumentException(String.Format("Unrecognized commandline parameter '{0}'.", arg));
                        }
                    }
                    else
                    {
                        throw new ArgumentException(String.Format("Unrecognized commandline parameter '{0}'.", arg));
                    }
                }
                else if (this.tocFile == null)
                {
                    this.tocFile = arg;
                }
                else if (this.outputFileName == null)
                {
                    if (this.chm)
                    {
                        this.outputFileName = Path.GetFileName(arg);
                        this.outputDir = Path.GetDirectoryName(arg);
                    }
                    if (this.web)
                    {
                        this.outputDir = arg;
                    }
                }
                else
                {
                    throw new ArgumentException(String.Format("Unrecognized argument '{0}'.", arg));
                }
            }

            // check for missing mandatory arguments
            if (!this.showHelp && (this.outputDir == null || (!this.chm && !this.web) || (this.chm && this.hhcFile == null)))
            {
                throw new ArgumentException("Missing mandatory argument.");
            }
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.