AnkhSVN 1.0 RC4 released

In the time since RC3, it became obvious from the error reports we received that renames and deletes were very buggy. Deleting a file and then committing it would often result in an error message saying "ProjectItem not available". It was obvious that we could not release it as 1.0 as it was, and another release candidate would be necessary. We also received several reports of other problems that turned out to be rather critical to some people, or so trivial to fix that we considered it worth the risk.

It took some time to rework the handling of deletes and renames to avoid this error (it’s a very tricky problem, I might write about it some day), thus the long delay in producing RC4. However, it is now available at http://ankhsvn.tigris.org/servlets/ProjectDocumentList?folderID=7315.

Problems that have been fixed include:

  • The very common "ProjectItem not available" error.
  • Templates for performing merge and diff using TortoiseMerge no longer has quotes.
  • Reporting Services (and other Business Intelligence projects) now work.
  • New icons (from DamienG).
  • Solution load timeout in VS 2005 is increased from ten seconds to fifteen minutes.
  • Various embarrassing NullReferenceExceptions.
  • New lines entered for the log message in the configuration dialog are now treated properly.
  • Handle an edge-case which prevented deletes from working with F# projects.
  • Work around a NotImplementedException thrown in certain cases by certain third party project types.
  • Various bug fixes in the support for database projects.
  • Message box now shown if one or more items could not be Locked (previously this information was shown only in the output pane, and easily missed).
  • Avoid a weird race condition in the repository explorer which might throw an exception in certain edge cases.
Posted in Uncategorized | 68 Comments

New wiki

I have now changed the Wiki software for the AnkhSVN wiki to the wiki engine everyone is blogging about, namely ScrewTurn. I was immediately impressed by just how slick ScrewTurn was; dead easy to install and configure.

I have imported all the history from the previous Flexwiki-based wiki, however, historical versions lack proper formatting.

Unlike the previous wiki, this one requires users to be signed up in order to edit pages. This should let us avoid the wiki spam that plagued the old wiki.

Of course, it’s still a bit lacking in content, but I’m sure this will pick up quickly – ScrewTurn is so much more fun to work with than FlexWiki.

Posted in AnkhSVN | 42 Comments

Damien Guard new AnkhSVN committer

Damien Guard, more known as DamienG, is a new committer on the AnkhSVN project. He’s done some very good work for us already on redesigning the command icon set, and we look forward to working with him on new features in the post-1.0 timeframe.

The new icons will be available in the upcoming RC4.

Posted in AnkhSVN | 26 Comments

Powershell MSBuild task

UPDATE: The source and installer for this task can now be found at Codeplex: 
http://powershellmsbuild.codeplex.com/ 

I have written an MSBuild task that hosts a Powershell runspace and allows you to embed Powershell scripts in your MSBuild build files. While MSBuild ships with a large number of useful tasks (and there are also a lot of third party tasks available), there is often something you want to do which doesn’t fit into the tasks provided. You can always write your own tasks to achieve what you want, but this can often become tedious to maintain since you will have to recompile and redeploy the custom task every time you need to make a little change. Having small snippets of script embedded in the MSBuild file itself can be a more easily maintainable solution, and what better language for this than Powershell?

As a custom task, the Powershell task needs to be loaded into your build file with the <UsingTask> element:

<UsingTask AssemblyFile="PowershellMSBuildTask.dll" TaskName ="Powershell"/>

Since tasks in MSBuild don’t have access to the contents of their tags, the scripts themselves need to be MSBuild properties, declared in a <PropertyGroup>:

<PropertyGroup> 
	<HelloWorldScript>Write-Host "Hello world"</HelloWorldScript> 
</PropertyGroup>

Now, to invoke this script, you will use the Powershell task and invoke it from within a target. You reference the script property the same way you reference any other MSBuild script property:

<Target Name="HelloWorld">
  <Powershell Script="$(HelloWorldScript)"/>
</Target>

The full MSBuild file will now be something like this:

<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="HelloWorld" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
	<UsingTask AssemblyFile="PowershellMSBuildTask.dll" TaskName ="Powershell"/>

	<PropertyGroup> 
		<HelloWorldScript>Write-Host "Hello world"</HelloWorldScript> 
	</PropertyGroup>

	<Target Name="HelloWorld">
		<Powershell Script="$(HelloWorldScript)"/>
	</Target>
</Project>

Save it as HelloWorld.proj, place PowershellMSBuildTask.dll in the same directory and run it like this:

msbuild HelloWorld.proj

The output should be as follows:

PS D:tmp> msbuild HelloWorld.proj
Microsoft (R) Build Engine Version 2.0.50727.42
[Microsoft .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation 2005. All rights reserved.
Build started 13.09.2006 19:02:21.
__________________________________________________
Project "D:tmpHelloWorld.proj" (default targets):
Target HelloWorld:
    Hello world
Build succeeded.
    0 Warning(s)
    0 Error(s)
Time Elapsed 00:00:05.09

Not horribly exciting, but it works.

Of course, such a task would have limited usefullness if there wasn’t a way to pass arguments from MSBuild into the custom script. The Powershell task has two ways of doing this.

The first way is an attribute ‘Arguments’. This takes in named arguments on the form ‘varname1=value1;varname2=value2′. varname1 and varname2 will then be available as string variables inside the script. For example:

    <PropertyGroup>
        <HelloArgumentsScript><![CDATA[
        Write-Host ("{0}" -f (([int]$value1) + ([int]$value2)))
        ]]></HelloArgumentsScript>
    </PropertyGroup>

    <Target Name="HelloArguments">
        <Powershell Script="$(HelloArgumentsScript)" Arguments="value1=40;value2=2"/>
    </Target>
 

The output is as expected:

Project "D:tmpHelloWorld.proj" (HelloArguments target(s)):
Target HelloArguments:
    42
Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:02.78
 

The other way is through the task attribute ‘TaskItems’. As the name implies, this takes in a set of taskitem objects. They are available in the Powershell script as a collection of ITaskItem objects named $TaskItems:  

<PropertyGroup>
    <TaskItemsScript> <![CDATA[ Write-Host ("The answer is {0}" -f (([int]$taskitems[0].ItemSpec) + ([int]$taskitems[1].ItemSpec))) ]]> </TaskItemsScript>
</PropertyGroup>
<PropertyGroup>
    <Argument1>12</Argument1>
    <Argument2>30</Argument2>
</PropertyGroup>
<Target Name="TaskItems">
    <Powershell Script="$(TaskItemsScript)" TaskItems="$(Argument1);$(Argument2)">
</Target>

It is also possible for a script to return values to the calling task. This happens through the Output taskparameter, and works like this:

<Powershell Script="$(ValueReturningScript)">
    <Output TaskParameter="Output" PropertyName="ScriptOutput"/>
</Powershell>

<Message Lines="$(ScriptOutput)"/>
 

The source code can be found in a Subversion repository here, and a downloadable zip including both source and the prebuilt task can be found here.



Posted in Powershell | 100 Comments

Losing faith

(Also posted as a reply to a post on our mailing list, users@ankhsvn.hm.hm)

Gah. I’m starting to lose my faith in my fellow programmers. A little background:

Ankh uses a couple of hash tables to map EnvDTE.Project and EnvDTE.ProjectItem objects (these are from the VS automation model) representing projects and (doh) their project items to our internal objects representing the same artifacts. These hash tables are used extensively when gathering SVN resources to determine whether commands should be enabled and to provide input to the execution of said commands. In other words, when a command is invoked, the hash tables are queried for our internal objects corresponding to the currently selected ProjectItem or Project.

So, if this mechanism fails, commands won’t be enabled in the first place, and if they were, they wouldn’t execute correctly since no resources had been harvested.

And this mechanism will obviously fail if the hash codes retrieved from the Project and ProjectItem objects are different each time they are retrieved using GetHashCode().

I’ll leave the rest of this horror story to the imagination of the reader. I will not reveal the particular type of project that is committing this atrocity; suffice it to say that the common name for it starts with an R and ends with -eport Server Project.

Posted in AnkhSVN | 57 Comments

Debugging more events

A couple of months ago, I posted a class that used the new DynamicMethod class in .NET to dynamically hook up events to all events declared on an object and display a string in VS’ output pane whenever that event is raised. While quite useful, it has some drawbacks; most importantly, if you are doing this to multiple objects of the same or similar type (think multiple controls, all of which share a large number of events), it’s very hard to see which particular object the event is coming from.

In some cases, you might also want to hook up only a particular event or set of events on a class, or exclude certain events. For example, all the Mouse-related events (MouseEnter, MouseMove, MouseLeave) can quickly clog up your output and hide the information you are looking for.

With this in mind, I decided to make a better version of this method. The new version is vastly improved:

  • It now supports a filter string which lets you specify a regex that has to match the name of the event(s) you are after
  • It now supports a custom format string which lets you output a lot of relevant information whenever the event is raised

The filter string can be used like this:

DebugUtils.DebugEvents(someControl, null, ".*Changed"); // only monitor the *Changed events on the control (think databinding events)

That’s pretty much all there is to the filter string, if you know your regular expressions. The format string is a little more involved, though. It supports the following special keywords (yeah, I stole some of these from the VS 2005 tracepoint syntax, so sue me…):

  • $EVENT – Replaced with the name of the event raised (you almost always want this one).
  • $TYPE – Replaced with the fully qualified type name of the object raising the event.
  • $TIMESTAMP – Replaced with the current time.
  • $CALLER – Replaced with the fully qualified method name (and possibly line number if symbols are available) of the method that raised the event.
  • $STACKTRACE – Replaced with a full stack trace of the code that eventually raised the event in question.

You probably don’t want to use the last one unless you also have some filtering on the events (or very few events on the object to begin with); it generates a lot of output. However, it can often be very useful if you need to see why a particular event is being raised. Line numbers and file names will be included if debug symbols are available.

In addition to the special keywords, it can also evaluate simple property and field expressions on the two arguments passed into the event. These are designated as "sender" and "e", respectively (as is the custom for naming event arguments in .NET). For example:

DebugUtils.DebugEvents(this.reportsListView, "$TIMESTAMP: $EVENT raised, e.InvalidRect is {e.Invalidrect}", "Invalidated");

Which prints the following output to VS’ Output Pane:

22:53:32.995125: Invalidated raised, e.InvalidRect is {X=0,Y=0,Width=627,Height=269}
22:53:33.010750: Invalidated raised, e.InvalidRect is {X=0,Y=0,Width=627,Height=269}
22:53:39.932625: Invalidated raised, e.InvalidRect is {X=0,Y=0,Width=627,Height=269}

(etc…)

The source for this file can be found in the SVN repository at http://ankhsvn.com/svn/Utils/trunk/Utils/Debugging/DebugUtils.cs, and unit tests: http://ankhsvn.com/svn/Utils/trunk/UtilsTest/Debugging/DebugUtilsTest.cs. To use it for yourself, either copy the file as is or check out the entire VS 2005 project from http://ankhsvn.com/svn/Utils/trunk/ and build it. The class is made available under a slightly modified MIT license (I removed the clause requiring derivatives to carry the notice).

UPDATE: I’ve removed the use of the ListUtils class so that people who want to copy the file in itself won’t need to also get the ListUtils class. I’ve also added XML doc comments to the various overloads.

Posted in .NET | 52 Comments

AnkhSVN 1.0 RC3 released

Following the release of Subversion 1.4 RC5, we have released a new release candidate of AnkhSVN linked against the Subversion 1.4 RC5 libraries. This Subversion release candidate fixes a bug in Subversion that was triggered by our "Add Solution To Subversion Repository" command and that caused Visual Studio to crash. Other than that, the only change to Ankh itself is support for VS 2005 web projects in the same command. Previously, they would not be detected and you would get the "The following projects are not under the solution root" message even if said web projects actually were under the solution root.

Download from http://ankhsvn.tigris.org/servlets/ProjectDocumentList?folderID=7315

Posted in Uncategorized | 45 Comments