Updating Visual Studio Extensions

Today I wanted to do some overdue updating of Visual Studio extensions. Among others there where an update of NuGet from version 1.6 to 1.7 and for the Visual Studio Achievements from Version 1.6 to 2.0.

But unfortunatly the updated didn’t work as expected. For the Visual Studio Achievements I got an error, that the digital signature did not match and therefore the update could not be installed. For NuGet the message was different, but with the same result. I just got a message, that the update could not be installed.

Doing some quick google research revealt for NuGet, that problemes during updates are somewhat expected. The recommended solution is to uninstall NuGet and to reinstall the new version of NuGet.

I found however a hotfix for Visual Studio, which is supposed to resolve the update problem with the not matching signatures I encountered with the Visual Studio Achievements. This hotfix actually did resolve the problem for the NuGet update as well 🙂

Populating sharepoint discussion boards using code

I recently was tasked to import a legacy discussion board into SharePoint 2010. So I wrote a small application, that could dump the old discussions to XML and then import them into SharePoint 2010 using the SharePoint Object model. Nothing more easy than this. A discussion-board is just some kind of list after all.

Well, kinda. If you look closely, you will notice, that discussion-boards differ in some details from regular lists. For one: a discussion-board has threads and replies. The replies can be shown threaded, so I have to maintain which post is a reply to what other post.

SharePoint does some strange stuff to manage this. Each discussion thread is a folder. With this knowledge one might expect to find all replies in this folder, which sound total reasonable to me. But that’s not the SharePoint way. Instead all replies are siblings. Folders are just the SharePoint-way to distinguish threads from replies. I don’t really know how SharePoint manages the reply-hierarchy, but it does work – somehow.

Well, after these discoveries, let’s write some code. I assume the new discussion board already exists and all there is to do is to import the existing posts from the old forum. First I have to create a new thread like this:

var newThread = SPUtility.CreateNewDiscussion(discussionBoard.Items, oldPost.Title);
newThread[SPBuiltInFieldId.Body] = oldPost.Text;
newThread[SPBuiltInFieldId.Created] = FormatDate(oldPost.Date);
string author = CheckUser(oldPost.Creator, web);
newThread[SPBuiltInFieldId.Author] = author;
newThread[SPBuiltInFieldId.Editor] = author;
newThread.Update();

Then I check the oldPost for replies and append them to my newly created thread.

foreach (var oldReply in oldPost.Replies)
{
    var newReply = SPUtility.CreateNewDiscussionReply(newThread);
    string replyAuthor = CheckUser(oldReply.Creator, web);
    newReply[SPBuiltInFieldId.Body] = oldReply.Text;
    newReply[SPBuiltInFieldId.Created] = FormatDate(oldReply.Date);
    newReply[SPBuiltInFieldId.Author] = replyAuthor ;
    newReply[SPBuiltInFieldId.Editor] = replyAuthor ;
    newReply[SPBuiltInFieldId.Title] = oldReply.Title;
    newReply.Update();
    newThread.Update();
}

The replies can be created recursively for replies to replies as well.

This is actually all that is needed. So with some little magic of the SPUtility namespace I was able to import a couple of thousand messages in no time.

Logging from multiple processes

When logging with log4net to a file (using the FileAppender), the FileAppender is holding an exclusive lock on the file. This doesn’t cause any problems, not even when the application is running with multiple threads, because log4net should be thread-safe.

This does change however when working with multiple processes, that all share a common log4net configuration and thus all will utilize the same FileAppender. In this case there should not be an exclusive lock by any process. Fortunately log4net has an appropriate configuration-setting.

<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

But acquiring and release locks is quite costly and thus will slow down the overall performance of the application.

An alternative would be to create an individual log per processes. Luckily log4net supports the expansion of variables to generate log-filenames, so we can add the process-id to the filename-pattern.

<appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net">
    <file type="log4net.Util.PatternString" value="Log[%processid]" />
[...]
</appender>

Exponention in c#

To compute 10 to the power 2 shouldn’t be any problem

int result = 10 ^ 2;

As if! Visual Studio strongly believes that the result of this computation should be 8. Damn! ^ is a reserved symbol in c# for bitwise exclusive or (XOR). The correct way to computer this would be

int result = Math.Pow(10, 2);

Logging in NHibernat 3.0

With the release of NHibernate 3.0 the way NHibernate handles logging is changed. Up to 2.1.2 NHibernate used log4net exclusive for logging. The usage of log4net was directly tied into each class of NHibernate.

Now this has been decoupled. NHibernate 3.0 introduces a LoggingProvider. So instead of

private static readonly ILog log = LogManager.GetLogger(typeof (Loader));

a new logger is created using

private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof (Loader));

Even though this might not seem like a big deal, there is more to the LoggingProvider. The logging provider currently only supports log4net (well, and a NoLoggingLoggerFactory). In order to determine whether log4net is available for logging, the LoggingProvider looks in the current SearchPath of BaseDirectory of the AppDomain like this:

// look for log4net.dll
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
string relativeSearchPath = AppDomain.CurrentDomain.RelativeSearchPath;
string binPath = relativeSearchPath == null ? baseDir : Path.Combine(baseDir, relativeSearchPath);
var log4NetDllPath = Path.Combine(binPath, "log4net.dll");

What go me started was the fact, the my log4net configuration wasn’t creating any log-output, and I was extremely puzzled on why. I checked my config a dozen times without any error. This was working perfectly fine when working with NHibernate 2.1.2.

After looking at the LoggingProvider and the way logging is initialized it struck me: my log4net assembly is located in the GAC – the the lookup for log4net isn’t detecting my log4net assembly! Changing the properties of the reference to log4net to Copy Local resolved this issue.

Supressing Messages from FXCop

In a recent project I rellay nailed the code using FXCop. The goal was to eliminate all messages of FXCop.

After a short periode of time I already figure: no way! There are just a couple of cases, where I have to irgnore the messages of FXCop. Luckily there is an easy way to supress the messages of FXCop. Just open the context menu of the message and copy the message as SupresseMessage to the clipboard.

suppress_messages

Next you can insert that at the appropriate position within your code, most likely as a method-attribute.

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]

OK, so now your’re good to go. The next run of FXCop should present you a lot less messages.

And if not? Something went wrong. Some little, very well hidden comment in the documentations says:

The ConditionalAttribute is applied to this class, specifying the preprocessing symbol “CODE_ANALYSIS” as the conditional symbol that determines whether the attribute call is included or omitted. If the symbol is defined, the attribute call is included; otherwise, the call is omitted.

OK. So opening up the project properties and adding the symbol CODE_ANALYSIS helped a lot in getting the number of FXCop messages down.

Errors that actually help to solve something

Well, suddenly it just happens – a YSOD. Just happened in my recent SharePoint dev-project.

Typical for SharePoint, this error is not obvious. Instead of the YSOD you’ll get a SharePoint specific page, telling you that something went wrong. No hint what happened or where the error actually occurred.

OK, so let’s head to the web.config and stop this hide-and-seek behaviors. I wanna know what’s happening. So we have to enable to show the actual CallStack and disable the use of CustomErrors.

<SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" TotalFileDependencies="50" AllowPageLevelTrace="false">
<customeErrors mode="off">

OK, so now we’re talking. I have some sort of Null-Reference-Exception in my code. But this code just worked perfect on my dev-machine, so why is it failing on the test-machine? And why is something null anyway? The StackTrace tells me, that this happened in a property-getter.

private SPGridView _mySpGrid;
public void CreateChildControls()
{
    _mySpGrid = new SPGridView();
}
public bool HasRows
{
    get { return _mySpGrid.Rows.Count > 0; }
}

How can this be null? CreateChildControls is always being called, so the grid always exists. This cannot be the reason why.

OK, let’s try something totally irrational:

public bool HatWerte
{
    get { return _mySpGrid == null ? 0 : _mySpGrid.Rows.Count > 0; }
}

This could should actually not be necessary … except when this modification makes the Null-Reference-Exception to disappear. But just to make room for the next Exception. And now everything is making sense (and I could revert the above modification).

The next exception states:

Could not load file or assembly ‘System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’ or one of its dependencies. The system cannot find the file specified.

D’oh!

My application was build against .Net 3.5 and I didn’t install that on my test-machine. Since the test-machine is a Windows 2003 Server running SharePoint 2007 there was no need to install .Net 3.5 – yet!

But .Net could have told me so from the beginning on – I would have understood this. But instead it was hiding behind some Null-Reference-Exception, just like a coward!