Showing posts with label VisualStudio. Show all posts
Showing posts with label VisualStudio. Show all posts

Wednesday, October 31, 2012

Sandcastle Help File Builder and error MSB4062 on Team 2008 build agents

I recently had to add a Sandcastle Help File Builder task to our automated build process. Our product consists of both .Net 3.5 projects and native C++ projects. It compiles under Visual Studio 2008 with Team 2008 build agents.

The latest version of Sandcastle is built against .Net 4.0, so, as part of its installation, I also installed the .Net 4.0 runtime. Everything worked fine in the GUI but when the build agent tried to run, it failed with:
error MSB4062: The "SandcastleBuilder.Utils.MSBuild.BuildHelp" task could not be loaded from the assembly C:\Program Files\EWSoftware\Sandcastle Help File Builder\\SandcastleBuilder.Utils.dll. Could not load file or assembly 'file:///C:\Program Files\EWSoftware\Sandcastle Help File Builder\SandcastleBuilder.Utils.dll' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded. Confirm that the <UsingTask> declaration is correct, and that the assembly and all its dependencies are available.

The UsingTask declaration appeared correct and all the dependencies seemed to be in order. I searched for quite a while and found several places purporting to have answers, but none of them worked. As I expanded my search, I finally happened upon an InfoSupport article about building VS2010 solutions with the 2008 build agent. This article described a means to fix a problem with a similar error message and, even though it wasn't related to Sandcastle, I decided to give it a try.

Short answer: it worked!!

The fix feels more like a hacky workaround than a good solution, but absent anything better, and given the fact that it allows the build to actually function properly, it currently stands.

The solution is to change a setting in a .Net configuration file.
  1. Edit %Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssemblies\TFSBuildService.exe.config.
  2. Find the line that assigns a value to the key MSBuildPath.
  3. Change the value from an empty string to the directory of the .Net runtime that should be used, e.g. %WINDOWS%\Microsoft.NET\ Framework\v4.0.30319.
  4. Save the file.
  5. Either stop/stop the TFS build agent service or reboot the machine.

I hope that helps someone else.

Tuesday, June 15, 2010

Message Compiler errors and how I solved them

As part of my day job, for the last several weeks I have written a Windows Service in .Net 3.5. Today I did some clean-up of messages written to the EventLog. Because internally there are several parts to this service, I wanted to separate the messages using the Category field. After some searching of the web, it seems this isn't drop dead trivial. But, as it didn't seem terribly complex either, I decided to dive into the task.

One of the requirements is that the text for the categories are in a resource DLL. Unfortunately, these aren't natively supported by the .Net framework. You have to manually create the files, compile them with two compilers and then link it into the DLL. Even though it consisted of several steps, it still seemed pretty straight forward based on the details on MSDN. Following the instructions, I created a simple .mc file and tried compiling it with mc.

The Message Compiler emitted a bunch of errors:
  • invalid character (0x29)
  • invalid character (0x57)
  • invalid character (0x10)
  • Invalid message file token
Obviously something was wrong. Another web search revealed nothing. I tried to make minor changes to the file, reduced things to the bare minimum, but continued to get these errors. It seemed I had some odd characters in the file that none of the the editors I used revealed. Finally I used the command line "type" command and there they were: the Byte Order Marks. Arg. After some head scratching, I used the old text mode "edit" command and it revealed the characters. I easily deleted them and tried to compile. It worked! No errors!

Of course I really wanted to edit the file in Visual Studio and so made a change to the newly edited file and saved it. VS kindly put the BOM right back in. It can be so annoyingly helpful. Yet more searching for a means of eliminating the BOM didn't reveal anything that I wanted to use. I found a script or two that I could install in the IDE, but I didn't want to force the rest of the team to have to do this. The more environmental things that have to be configured and maintained, the harder it is to setup a new development machine. After a bit of pouring through VS's Tool | Options, I found Text Editor | File Extensions. This allows you to define which editor to use for a given file type. I added the .mc extension and told it to use the User Control Editor. Sure enough, this editor didn't put the BOM in the file. While not ideal for the team environment, it is better than a script.

So, these were some of the lessons I learned today working with Message Text Files and the Message Compiler. I hope it helps someone else.

Wednesday, August 20, 2008

Never write software that fails silently!!

One of the tenets of software development is to fail early. The earlier something fails the less costly it is since you don't have as much invested as if it failed later. Visual Studio needs to learn this lesson.

I just spent the better part of an hour trying to figure out why a DeploymentItem attribute on a test didn't work. I had created some new files for the test, added them to the project and created an attribute that should have copied them over. The test didn't fail in the expected manner, because the code hadn't been updated to handle multiple files, but rather because there were no files at all. Setting a break point indicated that in fact the files were not being copied even though the were right there in the project.

After much frustration, I found through cygwin's grep the missing element: the files themselves needed to have their Copy to Output Directory property changed from Never to Every time. Why couldn't anything in the five steps leading up to the test execution have told me there might be a problem?

(And why did Explorer's Search fail to find the files that grep did?!?)