Switching to .asp file names

Topics: User Forum
Aug 31, 2009 at 6:35 PM

Thanks for a most useful extenstion to Sandcastle - I couldn't use that product without your fine wrapper.

I want to change the file suffix for all Website output files, *.asp.

I would then need to ensure that all referenced links also had their file names change to .asp.

In addition I want to inject a bit of <%%> code into all pages - security check.

I've examined the VS2005.config and altered the tag:

 

        <component type="Microsoft.Ddue.Tools.SaveComponent" assembly="{@SandcastlePath}ProductionTools\BuildComponents.dll">
            <save base="Output\html" path="concat(/html/head/meta[@name='file']/@content,'.asp')" indent="{@IndentHtml}" omit-xml-declaration="true" />
        </component>

        <component type="Microsoft.Ddue.Tools.SaveComponent" assembly="{@SandcastlePath}ProductionTools\BuildComponents.dll">

            <save base="Output\html" path="concat(/html/head/meta[@name='file']/@content,'.asp')" indent="{@IndentHtml}" omit-xml-declaration="true" />

        </component>

However,  I can't seem to find the XSL which specifies the file suffix. 

Any clues would be greatly appreciated.

AM

 

Aug 31, 2009 at 7:51 PM

And if this request is not possible then perhaps knowing the name of the XSL or config or what-have-you file that is the template for the output of .htm files when one builds a Website type output. 

I can use WinGrep to do a global search and replace - but only if I can get rid of the unicode characters embedded in the very beginning of every file generated. But I can't seem to identify this template file and so I can't get rid of these characters. WinGrep won't replace in a "binary" file (or so it says).

Thanks again.

AM

Coordinator
Aug 31, 2009 at 8:15 PM

You'd have to search the Sandcastle presentation style transformations for ".htm" to see where to change the extensions.  However, this has other side-effects that may cause problems.  The most obvious is the table of content.  This would also break Help 1 and Help 2 builds.  Your best bet is probably to create a plug-in for SHFB that only runs in a website build that renames the output files, updates href attributes in each file, inserts your extra ASP code, and modifies the website TOC file to use the new names.

Eric

 

Aug 31, 2009 at 9:52 PM

I've replaced every .htm in every XSL, Config, XML, proj, etc. - no joy.

I've tried to replace every "encoding="UTF-8"" with encoding="ansi" in every XSL and .config file I could fine (trying to get all the html files out of UTF-8 format so I can do a search/replace). No joy there either.

Doxygen let's me do this - but it looks like Sandcastle is gonna stump me.  That whole build a plug-in suggestion - yeah, that's too much work for this effort. Doxygen is done and working. Thanks for the thoughts though.

AM

 

Sep 11, 2009 at 5:25 PM

What is Microsoft.DDue?

Where can I get it?

Coordinator
Sep 11, 2009 at 7:16 PM

It's a namespace in the Sandcastle assemblies.  You can find them in C:\Program Files\Sandcastle\ProductionTools.

Eric

 

Sep 11, 2009 at 11:51 PM

Thanks. Found them.

I went ahead and fetch both projects source code and stuffed it all into a single solution.

I'm getting some strange message about the XslTransformer ???

 

 Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'CommandLine, Version=2.4.10520.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

  File name: 'CommandLine, Version=2.4.10520.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
     at Microsoft.Ddue.Tools.XslTransformer.Main(String[] args)

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'CommandLine, Version=2.4.10520.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

  File name: 'CommandLine, Version=2.4.10520.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

     at Microsoft.Ddue.Tools.XslTransformer.Main(String[] args)

And I can't find a Ddue.Tools.XslTransformer anywhere in the project list...
Clues?
Any idea what Ddue stands for? 

 

Sep 12, 2009 at 12:04 AM

Ah, Nevermind. I found the XslTransformer project - added it and built - I'm off to the next problem...

M:\Help\Working\BuildReferenceTopics.proj(27,5): error MSB6004: The specified task executable location &quot;M:\Program Files\Sandcastle\ProductionTools\BuildAssembler.exe&quot; is invalid.

 

Sep 12, 2009 at 1:46 AM

And, I've fixed that error too. Had to recompile the BuildAssembler.exe

I'll tell ya, I don't know of any other rig like this - what are there a dozen EXEs that get called to get this simple job of reflection and document creation? Well, maybe not that many.

Anyway, I was able to mod the whole set to my liking and it now produces .ASP files with my custom header content in them.

It's much easier with all of the projects in one solution. I yanked all the snk's too; strong names for what/why?

And all that post compile copying - yeah, did a way with that - I shoved all the config into one instead of what 20? (just kidding).

There was just too much sprawl here. Got to do the "One ring to rule them all" dance and well, none of this code will ever be used outside of this one project - so why separate it all into tiny pieces? Bah, I shoved it all into a single project, at least the libraries that is. All those console EXEs - nuts to that.

However,

I would like to thank you for all of your hard work here. I too contribute to open sauce code and often it's a thankless activity. Your efforts have given my code base a great looking doc set now.

Much gratitude.

AM

Sep 16, 2009 at 11:55 PM

Sorry to keep chiming in here, but...

If you could tell me the name or the list of file names that are used to drive the Prototype output with regards to the templates. I have

main_conceptual.xsl
main_schema.xsl
utlities_reference.xsl

What I'm trying to accomplish is to put a very simple set of ASP tags at the very top of every HTML file that is produced. And I have tried EVERYTHING I can think of. I've modified every XSL in the sandcastle directory, every xml file, every config file and every csharp file. I've replaced all the encoding with ASCII so as to get rid of the utf-8 encoding on the files (this so that I might be able to do a simple search and replace). I just can't seem to find the right combination. Every time I re-run the build, I always get the same header in the HTML files. I've gotten the Index.html to work just fine. I added a {@serverscriptinjection} type variable to the top of some page I found (don't remember which one now) and it that worked.

But the army of html files that are built I can in no way influence. I think I'm starting to lose my grip on reality here...

They all have this:

<html xmlns:MSHelp="http://msdn.microsoft.com/mshelp"><head>

I need to get rid of the Unicode prefix Or be able to inject some script at the beginning of the file <% asp code here %> <!-- #include file here src="xx" -->

Any clue would be most appreciated.

Thanks again,,

AM

 

 

 

 

Coordinator
Sep 17, 2009 at 7:46 PM

Those are the only three that I'm aware of.  main_conceptual.xsl is for conceptual content (MAML topic files), main_schema.xsl is for XSL schemas and isn't applicable, and utilities_reference.xsl is for the API topics.

Eric

Oct 23, 2009 at 9:11 PM

Eric,

I finally found the problem.

The encoding for all output files for a Website are in UTF-8. I didn't want that. But I could not for the life of me find where that was set or where to change it.

I found it.

SandCastle BuildComponents project, SaveComponent.cs SaveComponent method - has the settings.Encoding set to UTF8. I changed this to ASCII and bingo - I'm good.

In addition, I wanted to write some VBS script to the top of every page. The SaveComponent.cs was also the spot for this. In the Apply method:

 

 

                    using (XmlWriter writer = XmlWriter.Create(path, settings)) {
                        writer.WriteRaw("<%Auth=AUTH_DEV%>");
                        writer.WriteRaw("<!--#include virtual=\"/doc0/classes/cUser.asp\"-->");
                        document.Save(writer);
                    }

                    using (XmlWriter writer = XmlWriter.Create(path, settings)) {

                        writer.WriteRaw("<%Auth=AUTH_DEV%>");

                        writer.WriteRaw("<!--#include virtual=\"/doc0/classes/cUser.asp\"-->");

                        document.Save(writer);

                    }

Thanks again for your efforts and the selfless release of your code.
Toodles,
Anonymole

 

 

Dec 31, 2012 at 11:07 PM

With having to update to the lastest version of SandCastle and the help file builder I've gone ahead and taken your advice Eric and create a post process exe that renames all .HTM to .ASP (or ASPX)

Here's the code if anyone wants to do the same. It's simple file replace and file move - but built for the sandcastle output.

Build and copy to the /Help/ directory and run after a help file build.

 

        static void Main(string[] args) {

            int fileCounter = 0;
            string targetPath = Environment.CurrentDirectory;
            string targetFileSuffix = ".htm";
            string resultFileSuffix = ".asp";
            string targetPrefix = @"<!--#include virtual=""/SecurityClassHere.asp""-->" + Environment.NewLine;
            string[] targetFileReplaceInternalList = new string[] { "index.html""index.aspx""WebTOC.xml""WebKI.xml""TOC.js""SearchHelp.aspx""LoadIndexKeywords.aspx""FillNode.aspx" };
            string[] targetFileAppendInternalList = new string[] { "index.html" };
            string[] targetFileReplaceInternalSuffixList = new string[] { ".json" };
            string[] targetDirectories = new string[] { "html""fti" };

            if (args.Length > 0) {
                // TODO: set the above variables based on the commandline arguments.
            }

            // Replace in the current directory first
            Console.WriteLine(string.Format("Processing root directory files..."));
            foreach (string fileName in targetFileReplaceInternalList) {
                string[] targetFileNames = Directory.GetFiles(targetPath, fileName);
                foreach (string targetFileName in targetFileNames) {
                    FileUtility.ReplaceWithinFile(targetFileName, targetFileSuffix + @"""", resultFileSuffix + @"""");
                    fileCounter++;
                    if (fileCounter % 100 == 0)
                        Console.Write(string.Format("Processing file #:{0}", fileCounter));
                }
            }

            foreach (string fileName in targetFileAppendInternalList) {
                string[] targetFileNames = Directory.GetFiles(targetPath, fileName);
                foreach (string targetFileName in targetFileNames) {
                    FileUtility.AddToFile(targetFileName, targetPrefix, true);
                    fileCounter++;
                    if (fileCounter % 100 == 0)
                        Console.Write(string.Format("Processing file #:{0}", fileCounter));
                }
            }

            string[] filenames;

            // Rename and replace in each sub directory named last
            foreach (string directoryName in targetDirectories) {
                Console.WriteLine(string.Format(@"Processing child directory files \{0}...", directoryName));

                // Replace internal content only for these types of files ".json ( .htm -> .asp)"
                foreach (string targetFileSuffixName in targetFileReplaceInternalSuffixList) {
                    filenames = Directory.GetFiles(Path.Combine(targetPath, directoryName), "*" + targetFileSuffixName);
                    foreach (string fileName in filenames) {
                        FileUtility.ReplaceWithinFile(fileName, targetFileSuffix + @"\", resultFileSuffix + @"\"); //.htm\
                        fileCounter++;
                        if (fileCounter % 100 == 0)
                            Console.Write(string.Format("Processing file #:{0}", fileCounter));
                    }
                }

                // Replace everything for these types of files ".htm -> .asp"
                filenames = Directory.GetFiles(Path.Combine(targetPath, directoryName), "*" + targetFileSuffix);
                foreach (string fileName in filenames) {
                    FileUtility.ReplaceWithinFile(fileName, targetFileSuffix + @"""", resultFileSuffix + @"""");
                    FileUtility.AddToFile(fileName, targetPrefix, true);
                    FileUtility.RetypeFile(fileName, targetFileSuffix, resultFileSuffix);
                    fileCounter++;
                    if (fileCounter % 100 == 0)
                        Console.WriteLine(string.Format("Processing file #:{0,6}", fileCounter));
                }
            }

            Console.WriteLine("Done!");
            Console.WriteLine("Press any key to close window.");
            Console.ReadKey();

        }
    }

    public class FileUtility {

        public static void RetypeFile(string fileName, string oldType, string newType) {
            try {
                string newFileName = fileName.Replace(oldType, newType);
                File.Move(fileName, newFileName);
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
        }

        public static void ReplaceWithinFile(string fileName, string outgoing, string incoming) {
            try {
                string[] fileLines = File.ReadAllLines(fileName);
                List<string> newFileLines = new List<string>();
                foreach (string line in fileLines)
                    newFileLines.Add(line.Replace(outgoing, incoming));
                File.WriteAllLines(fileName, newFileLines.ToArray());
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }

        }

        public static void AddToFile(string fileName, string addThis, bool isPrefix) {
            try {
                string currentContent = string.Empty;
                if (File.Exists(fileName)) {
                    currentContent = File.ReadAllText(fileName);
                }
                if (isPrefix)
                    File.WriteAllText(fileName, addThis + currentContent);
                else
                    File.WriteAllText(fileName, currentContent + addThis);
            } catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
        }
    }