SHFB error BE0065 after upgrading

Topics: User Forum
Jul 23, 2010 at 2:20 PM
Edited Jul 23, 2010 at 2:25 PM

I just upgraded our build help script and binaries to now use SHFB v1.9.1.0 with the last release of Sandcastle (v2.6) from SHFB v1.7.0.0 and Sandcastle v2.4. The build scrip is working correctly when invoke from command line (even when invoked on the build computer) , but failed each time when invoked by the build agent under the control of our build server, with the following error:

SHFB error BE0065: BUILD FAILED: Modifying the XML of an imported project file is not allowed. Open that project file directly.

Any idea ???

About out environment: the source come from a TFS 2010 server. But we do not relay on TFS build capabilities, but instead use TeamCity v5.1.3 as a build server. Our build script are done with NAnt 0.86 (Build 0.86.2898.0; beta1; 2007-12-08).

Here is the build log:

<?xml version="1.0" encoding="utf-8"?>

<shfbBuild product="Sandcastle Help File Builder Utilities" version="" projectFile="C:\TeamCityBuildAgent\work\89fb35eada6bb328\ISaGRAF\DocFull.shfbproj.teamcity.patch.tcprojx" started="23/07/2010 10:02:53 AM">

<buildStep step="Initializing">

Loading and initializing plug-ins...

Hierarchical Table of Contents Version

Copyright © 2006-2010, Eric Woodruff, All Rights Reserved


<buildStep step="FindingTools">

Finding tools...

Found Sandcastle tools in 'C:\TeamCityBuildAgent\work\89fb35eada6bb328\Tools\Sandcastle\'

Found HTML Help 1 compiler in 'C:\TeamCityBuildAgent\work\89fb35eada6bb328\Tools\Ms Help Compiler v1\'

Found MS Help 2 help compiler in 'C:\TeamCityBuildAgent\work\89fb35eada6bb328\Tools\Ms Help Compiler v2\'


<buildStep step="ValidatingDocumentationSources">

Validating and copying documentation source information

Last step completed in 00:00:00.0000


<buildStep step="Failed">

SHFB: Error BE0065: BUILD FAILED: Modifying the XML of an imported project file is not allowed. Open that project file directly.



Jul 23, 2010 at 7:16 PM

I don't know anything about Team City so I can't really say why it might be failing.  One thing I did notice is that the project filename in the build log is odd (DocFull.shfbproj.teamcity.patch.tcprojx).  Perhaps its getting modified or wrapped in another project file somehow with an import directive and that's what's causing the problem.



Jul 23, 2010 at 7:57 PM
Edited Jul 23, 2010 at 8:38 PM
You're right: it seem clearly related to TeamCity, as everything is all right if I called directly MsBuild instead of relaying on MsBuild nAnt task, which seem modified by TeamCity. I will deal with JetBrains for this issue, but do you know the reason this error rise ? I'ts because the .shfbproj is renamed ? Or because there is a write lock on it ? Any clue will certainly interest JetBrains.
Jul 24, 2010 at 2:08 AM

The error you're getting results from a project being referenced via an <import> element rather than being the actual project and somewhere an attempt is made to modify it.  So, either the SHFB project is being referenced via an import or one of the documentation sources is if you are using a solution or project as a documentation source.



Aug 4, 2010 at 10:26 PM

I, too, am using the latest versions of Sandcastle and SHFB and am getting the same error, though with a different notice.

My Documentation Source includes my solution.  Five of the projects in the solution use a custom target which pre-processes some XML files that are a part of the application to extract help information from them.  Those files are then <include>d into the triple-slash comments.  This process had been working until I modify the projects so that MSBuild could keep the files up to date all the time.  (Prior, I was using a pre-build step that invoked a command file.)

Now my help project does not build...  A clip from the build follows:

Source: C:\Projects\CoreSoftware\Inferno.sln
    Found project 'C:\Projects\CoreSoftware\..\Core\CUtilites\CUtilities.vbproj'
    Found project 'C:\Projects\CoreSoftware\..\Core\msgdialog\MsgDialog.vbproj'
    Found project 'C:\Projects\CoreSoftware\..\Core\registrywrangler\Registry.vbproj'
    Found project 'C:\Projects\CoreSoftware\..\Core\XMLReader\XMLReader.vbproj'
    Found project 'C:\Projects\CoreSoftware\loadunloadosd\LoadUnloadOSD.vbproj'
    Last step completed in 00:00:00.1875

SHFB: Error BE0065: BUILD FAILED: The imported project "C:\Projects\CoreSoftware\loadunloadosd\OSDhelp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.  C:\Projects\CoreSoftware\br_Inferno_1.0\Segue\loadunloadosd\LoadUnloadOSD.vbproj

 The LoadUnloadOSD project is the first to try to include the additional MSBuild content, shown below, and this fails.

<Project DefaultTargets="Build" xmlns="" ToolsVersion="3.5">
  <Import Project="$(SolutionDir)..\..\OSDhelp.targets" />

Is this simply disallowed, or is there something I can do about it?

Using the <Import>ed target, which keeps my help up to date, is preferable to doing it externally, and is simply for the other users of my libraries.

Aug 5, 2010 at 5:19 PM

It's not finding the noted .targets file in the indicated path.  Make sure it exists there and it should be able to find it and continue the build.



Aug 5, 2010 at 7:10 PM

I changed the path from    $(SolutionDir)..\..   to   ..\..\..   and this worked, but the location I want may move at a later time, to a location that may not be a simple relative path, but one relative to the solution file.  Since the .shfbproj and .sln are in the same folder, I assumed that $(SolutionDir) would work but it did not, as SHFB (or Sandcastle) apparently does not specify its own value for that property.

I wonder: is there a way to specify SolutionDir in the help project, so that the help build can use it just as the compile build of the solution does?  Or perhaps there is another property that will be common between the two?  Can the help project even accept and work around custom modifications by the user?   I just want the solution and help to be able to find the same folder paths.

Aug 5, 2010 at 7:15 PM
Edited Aug 5, 2010 at 7:44 PM

I think you made a mistake: "$(SolutionDir)" is a property manage by VS, not MsBuild. And the new SHFB is an MsBuild project, so such property will never been set. There is certainly another way provided directly by MsBuild to get the path you need. Unfortunately, I know how to do it with NAnt, but not with MsBuild.

Aug 5, 2010 at 7:36 PM

I realize that SolutionDir is defined by VS.  However, I thought that since SHFB can accept a solution file as a documentation source, and because it only accepts one such, and because the solution file itself would likely depend on SolutionDir being defined correctly, that SHFB would define it as the folder in which the solution file was found.  My case is a simple example: the sub-project wants something from the solution, which it can easily get.  SHFB might have anticipated such a request, and defined the same value.  There are not so many defined properties that SHFB could not define them just as VS does, ensuring that things work when parsing a solution.

The MSBuildProjectDirectory reserved property will find the location of the help project, and I could use that if I am allowed to defined properties in the help project: I could use that value to define SolutionDir.  But I cannot leave SolutionDir undefined, because the sub-project file refers to it, and the sub-project (LoadUnloadOSD.vbproj) is NOT in the same folder as the solution, nor even a subfolder of it.

The solution refers to projects, which refer back to the solution using the property SolutionDir.  If I cannot do the same, I can only assume that the .shfbproj is in the same folder as the solution; this may not be true, which requires that I find a solution that always works based on the knowledge that SHFB has of solutions.

Aug 5, 2010 at 10:04 PM

The $(SolutionDir) variable will be set by SHFB after it loads the project.  Since <import> is interpretted when the project is loaded, it won't equate to the path you want.  There may be a way to set it beforehand but it won't work as you want it to in the current build engine.  Setting it as an environment variable may work around the issue.



Aug 6, 2010 at 4:58 PM

After much thought, this is still not clear to me.  The SHFB project is unmodified, and has no mention of $(SolutionDir).  However, it loads the solution as a Documentation Source, which in turn loads each of the projects.  One of those projects wants to refer back to the $(SolutionDir) but cannot.  If you mean that $(SolutionDir) will not be defined until after this entire process is complete, then what good can it do anyone?  What process would need it after that point?  But if you mean that it will be defined after the help project is loaded, but before the solution is, then why does it not that not the right place to define it after all?

Two questions about the process: Is it allowed to modify the help project (will SHFB preserve user changes...), and would it work to say:


so that SolutionDir is defined, and the same folder as the help project itself?  That is an acceptable constraint, that the .shfbproj and .sln be in the same folder.

Second, will using an environment variable or defining SolutionDir early not perturb the build process due to the value that SHFB sets later?

Using an environment variable is a tolerable workaround.

Aug 7, 2010 at 8:05 PM
Edited Aug 7, 2010 at 8:19 PM

The Solution* macros are something specific to Visual Studio and they are not part of MSBuild.  You'd run into a similar issue if building your Visual Studio projects from the command line with MSBuild.  My guess is that Visual Studio defines them as global variables and sets them prior to loading the solution.  This isn't something SHFB can do since it may be dealing with multiple solution files in different locations as documentation sources so it sets them as local variables in the projects once they are loaded.  Typically, the Solution* macros are used in pre and post build events or in other project properties such as the output assembly name, etc.  In these cases, nothing is done with the values when the project is loaded so there are no issues within SHFB.  However, using them in an element such as <import> which MSBuild does evaluate and utilize when a project is loaded will require that they are defined prior to the project being loaded.  As such, it's your responsibility to ensure that they are defined with a default value much as you would have to do if building your solution from the command line with MSBuild.  You may be able to add a user defined property to the SHFB project that defines the solution folder or you may have to add it to your Visual Studio projects much as you would have to do if building them from the command line.  In either case, I'd make them conditional so that they are only evaluated if needed:

        <SolutionDir Condition=" '$(SolutionDir)' == '' ">$(MSBuildProjectDirectory)</SolutionDir>



Aug 9, 2010 at 2:58 PM

A good answer.  Thank you very much!

Aug 9, 2010 at 4:32 PM

Actually, I was a bit hasty.  What you said is technically correct, and using it the project builds correctly using VS, which already defines SolutionDir.  It now builds with MSBuild from the command line, because SolutionDir is correctly defined in my project file.  However, it still does not work from SHFB.  From the MSBuild documentation online, I learned that a property defined in the project file overrides an environment variable, and a property defined as a passed-in value overrides the project file.  From testing I find that the SolutionDir property is NOT undefined.  It is simply defined wrongly for what I need, and I cannot override it because it is defined from the outside and therefore overrides my setting.  Instead of SolutionDir pointing to the folder which contains the .sln file, it points to the folder that contains the .csproj or .vbproj file, which in my case is usually, but not always, a subfolder of the solution location.  This is the wrong location for the value, so the SHFB build error I get is always that the <Import>ed file is not found, because the folder in which SHFB looks for it is incorrect.  ProjectDir should point to that location, not SolutionDir.  I thought that there could only be one .sln file loaded, found in $(SolutionDir), though multiple project files found in individually defined $(ProjectDir) folders, and that therefore the solution folder would be unambiguous, but from your comments above this is not the case.  Because usually SolutionDir is not needed, few people have an issue with the current definition, but it doesn't work for me.

I do have an acceptable workaround right now, and will just go with that until such time as this works like I would expect, if ever.  Thank you for your help.