Proxy problem with SHFB

Topics: Developer Forum
Jun 28, 2013 at 4:55 AM
Edited Jun 28, 2013 at 4:56 AM

I updated from SHFB to and have problems with my proxy server in this new version.
I uncomment the method 2 in the BuildAssembler.exe.config file as follow:
    <defaultProxy enabled="true" useDefaultCredentials="true">
        <proxy bypassonlocal="True" proxyaddress="http://proxy:8080" />
After this modification the build failes with following exception:

Building conceptual help topics...
BuildAssembler (v2.7.3.0)
Copyright c 2006-2013, Microsoft Corporation, All Rights Reserved.
Portions Copyright c 2006-2013, Eric Woodruff, All Rights Reserved.
Info: Loading configuration...

BUILDASSEMBLER : error : BuildAssembler: An error occured while initializing the build component 'SandcastleBuilder.Components.CodeBlockComponent' in the component assembly 'C:\Program Files (x86)\EWSoftware\Sandcastle Help File Builder\SandcastleBuilder.Components.dll'. The error message and stack trace follows: System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---> System.Configuration.ConfigurationErrorsException: Only one <configSections> element allowed per config file and if present must be the first child of the root <configuration> element. (C:\Program Files (x86)\Sandcastle\ProductionTools\BuildAssembler.exe.Config line 42) [D:\Projekte\Windows\Adi.NET SDK\Doc neu\Help\Working\BuildConceptualTopics.proj]
 at System.Configuration.ConfigurationSchemaErrors.ThrowIfErrors(Boolean ignoreLocal)
 at System.Configuration.BaseConfigurationRecord.ThrowIfParseErrors(ConfigurationSchemaErrors schemaErrors)
 at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
 --- End of inner exception stack trace ---
 at System.Configuration.ClientConfigurationSystem.EnsureInit(String configKey)
 at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
 at System.Configuration.ConfigurationManager.GetSection(String sectionName)
 at System.Xml.Xsl.XslCompiledTransform.Load(String stylesheetUri)
 at SandcastleBuilder.Components.CodeBlockComponent..ctor(BuildAssembler assembler, XPathNavigator configuration)
Last step completed in 00:00:00.5909
In consequence of this exception I put the <> element after the <configSections> element and everything works fine.

Is this an effect of the new version of SHFB or of a .NET update? Can you update the documentation and the sample BuildAssembler.exe.config file in the next version oft SHFB?


Jun 28, 2013 at 10:44 AM
AFAIK, the .NET Framework has always required that the configSections element be the first one if present. In SHFB v1.9.6.0, BuildAssembler.config did not include this element. It was added to Sandcastle\Source\BuildAssembler\BuildAssembler\app.config in changeset 101042 on Dec 30, 2012. I agree it would be better to move configSections above the commented-out sections.
Jun 29, 2013 at 2:51 AM
I've moved the configSections element to the start of the configuration file.

Jul 5, 2013 at 6:04 AM
Thank you for your support.

I have moved the configSection element on the first position of the config file and activated the proxy method 2. My XML code of method 2 is the same as in the config file of SHFB but this method doesn't work with SHFB
I traced the network traffic with Wireshark and there are no conections to the proxy address. There are only M-SEARCH HTTP/1.1 packets in the capture output.
It seems as the MSBuild.exe ignores the <> section in the configuration file.

<?xml version="1.0"?>

<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
  <section name="Microsoft.Ddue.Tools.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- If you get an HTTP status 407 or 417 error, try one of the following methods to configure BuildAssember
     to work with your proxy server so that it can contact the MSDN web service to resolve framework reference
         links. -->

<!-- Method 1 (this works most often so try it first) -->
    <defaultProxy useDefaultCredentials="true">
        <proxy usesystemdefault="true"/>

<!-- Method 2 (update the URL for your proxy) -->

    <defaultProxy enabled="true" useDefaultCredentials="true">
        <proxy bypassonlocal="True" proxyaddress="http://proxy:8080" />

<!-- Method 3 (update the URL for your proxy) -->
    <defaultProxy useDefaultCredentials="true">
        <proxy scriptLocation="" usesystemdefault="true" />

<!-- Add this element just after the defaultProxy element in the section above if you get an
         HTTP 417 error. -->
        <servicePointManager expect100Continue="false" />

        <setting name="BuildComponents_MtpsContentService_ContentService"

    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
Jul 5, 2013 at 1:52 PM
SHFB automatically caches MSDN data to disk files. If you have ever run the build in a network that does not require a proxy, then it may already have cached everything it needs, which would explain why it doesn't try to use your proxy. The cache files go in the {@LocalDataFolder}\Cache folder; see Special Folder Locations.

I tried renaming the Cache directory, editing BuildAssembler.exe.config to set proxyaddress="http://localhost:31313", running the Cygwin version of netcat at port 31313, and building an .shfbproj by starting MSBuild from Command Prompt. Netcat displayed a proxy HTTP POST request (which I aborted), and the generated HTML did not link to the MSDN Library, so I think the configuration change did take effect.
Jul 5, 2013 at 4:00 PM
Edited Jul 5, 2013 at 4:01 PM
The MSDN ID cache is build cumulatively. If it doesn't exist or is deleted, the first build will generate a varying amount of traffic depending on the project. Subsequent builds of the same project will use the cache entirely and generate no traffic. New projects may generate some traffic if they use new assemblies that don't exist in the cache (i.e. documenting a Windows Forms or WPF project for the first time).

As long as the links work in the generated help file, everything worked as expected.

Jul 8, 2013 at 5:52 AM
Thank you for your quick and detailed answers.
The problem on my PC was the cache. I deleted the MsdnContentId.cache file and now everything works fine.
Jul 8, 2013 at 12:30 PM
Perhaps Microsoft.Ddue.Tools.MsdnResolver should be smarter about which errors it saves in the cache. As of changeset 102391, it looks like GetMsdnUrl(string id) saves a null endpoint string to the cache if the SOAP request fails in any way. I think it should do that only if it gets a SoapException with the mtpsContentIdentifierNotFound error code. In particular, it should not alter the cache if it gets a WebException.
Jul 8, 2013 at 7:35 PM
It could be updated I suppose. The original component never made a distinction between error results either. About the only one that could conceivably happen is mtpsGeneralServerError though I don't think I've ever seen one. In the event of a web exception, the service is disposed of and is not used anymore so no cache updates will occur.

Jul 8, 2013 at 8:06 PM
To test this issue with SHFB, I renamed the Cache folder, disconnected the computer from the network, and built the same documentation project three times. On each build, the MsdnContentId.cache file grew a little. Using the Cygwin "strings" utility, I saw that the file then ended with three strings: "T:System.Runtime.Serialization.DataContractAttribute", "T:System.ArgumentException", and "T:System.Runtime.Serialization.DataContractSerializer". Next, I reconnected the computer to the network and built the documentation project once more. In the resulting HTML, most .NET Framework types had MSDN hyperlinks, but those three did not.

This experiment shows that, although MsdnResolver disables itself after the WebException, it regardless adds one null entry to the cache each time this happens, and these entries get saved to disk too -- even if MsdnResolver.IsDisabled starts returning true.