Update February 2016:If you just want to disable R#, like it is not installed, go to Tools → Options → ReSharper → Suspend/Resume

I've been using ReSharper (R#) for a long time now and I can tell you that if you are a Visual Studio C# developer and you are not using it, you are missing out. These guys must have the greatest job in the world: develop for developers. Or could it be the worst job, since doctors always make the worst patients? anyway...

I have been preaching about ReSharper for about 4 years now and the most common complaint from people new to it is that it makes things go slowly in certain situations. The thing is, R# is doing so much stuff in the background, that I find it amazing it moves so fast as it does. It is a valid complaint to want to have the same speed of typing and moving around that you have in the normal Visual Studio environment and still have the many features provided by ReSharper.

So, my solution was to have a command to "pause" the ReSharper analysis until I need it. The scenario would be:
  • Suspend analysis and regain swiftness of typing
  • Write your fingers off, since you already know what to type and even Intellisense feels like slowing you down
  • Resume the analysis and get all the R# goodness
In other words, something like writing your code in notepad and then copy pasting it all in the VS window.

Well, as most of the time, the R# have thought about it already! You have two possible options. One is using the commands ReSharper_Suspend, ReSharper_Resume and ReSharper_ToggleSuspended. You can either bind them in the Tools -> Options -> Environment -> Keyboard to whatever combination you desire, or go to Tools -> Options -> ReSharper -> General and use the Suspend button. This is equivalent to enabling/disabling the ReSharper addon. Since it is a very large addon and needs a lot of resources and hooks, this option is terribly slow. It does have the advantage of freeing all memory used by R#. The second option is more what I was having in mind: the command ReSharper_EnableDaemon. It sounds kind of like "Release the Kraken!" and it works in a similar way. What it does is suspend/enable code analysis on the current file! It is already bound as a global shortcut on Ctrl-Alt-Shift-8. It works almost instantly and enables the scenario I wanted.

Bottom line: Ctrl-Alt-Shift-8 to suspend/resume code analysis on the current file so you can type like your livelyhood depends on it. Again, thank you, JetBrains!

Update: It seems on older versions of ReSharper (not 5), the shortcut is Ctrl-8.

If you have a T4 Template .tt file that throws a weird Compiling transformation: Invalid token 'this' in class, struct, or interface member error that seems to come out of nowhere, try to delete extraneous spaces.

In my case, I has copied/pasted the .tt content from a web page and I was trying to understand why it wouldn't work. I right clicked on the source, went to Advanced, chose Convert all spaces to tabs, then back to Convert all tabs to spaces. Then it worked. I guess some white spaces where not really spaces or some other formatting issue.

If you don't have the options when you right click, it might be that they are features of the Tangible T4 Editor.

Update: Thanks to Tim Fischer from Tangible, I got to solve all the problems described in the post below using VolatileAssembly and macros like $(SolutionDir) or $(ProjectDir).

When T4 (Text Template Transformation Toolkit) appeared as a third party toolkit that you could install on Visual Studio 2008, I thought to myself that it is a cool concept, but I didn't get to actually use it. Now it is included in Visual Studio 2010 and I had the opportunity to use it in a project.

The idea is to automatically create code classes and other files directly in Visual Studio, integrated so that the files are generated when saving the template. All in all a wonderful idea... but it doesn't work. Well, I may be exagerating a bit, but my beginning experience has been offputting. I did manage to solve all the problems, though, and this is what this blog post is about.

First of all, there is the issue of intellisense. I am using ReSharper with my Visual Studio, so the expectations for the computer knowing what I am doing are pretty high. In the .tt (the default extension for T4) files you don't have any. The solution for this is to use the Tangible T4 editor (I think they were going for a fifth T here) that comes as a Visual Studio addon for VS2008 and VS2010. Fortunately, there is a free version. Unfortunately, it doesn't do intellisense on your own libraries unless you buy the priced one. Also, the intellisense is years behind the one provided by ReSharper or even the default Visual Studio one and the actions one can do automatically on code in a T4 template are pretty limited.

The second problem was when trying to link to an assembly using a relative path to the .tt file. The Assembly directive supports either the name of an assembly loaded in the GAC or a rooted path. Fortunately, the VS2010 version of the T4 engine supports macros like $(SolutionDir). I don't know if it supports all Visual Studio build macros in the link, but the path ones are certainly there.

Here is how you use it. Instead of

<#@ Assembly Name="Siderite.Contract.dll" #>
use

<#@ Assembly Name="$(SolutionDir)/Assemblies/Siderite.Contract.dll" #>


The third problem was that using an assembly directive locked the assembly used until you either reopened the solution or renamed the assembly file. That proved very limiting when using assemblies that needed compiling in the same solution.

This can be solved by installing the T4 Toolbox and using the VolatileAssembly directive. Actually, on the link above from Oleg Sych you can also find a bit advising using the T4 toolbox VolatileAssembly directive in the Assembly Locking section.

Here is how you use it. Instead of

<#@ Assembly Name="$(SolutionDir)/Assemblies/Siderite.Contract.dll" #>
use

<#@ VolatileAssembly
processor="T4Toolbox.VolatileAssemblyProcessor"
name="$(SolutionDir)/Assemblies/Siderite.Contract.dll" #>
As you can see you need to specify the processor (the VolatileAssemblyProcessor would have been installed by the T4 Toolbox) and you can use macros to get to a relative rooted path.

So thanks to the eforts of Oleg and Tim here, we can actually use T4. It would have been terribly akward to work with the solution in the obsolete section below. The Tangible guys have a learning T4 section on their site as well. I guess that using the resources there would have spared me from a day and a half wasted on this.

The following is obsolete due to the solutions described above, but it is still an informative read and may provide solutions for similar problems.

Click to expand.


Tips And Tricks:
Problem: the T4 generated file has some unexplained empty lines before the start of the text.
Solution: Remove any spaces from the end of lines. Amazingly so, some white space at the end of some of the lines were translated as empty lines in the resulting .tt.

Problem: The code is not aligned properly
Solution: Well, it should be obvious, but empty spaces before the T4 tags are translated as empty spaces in the resulting .tt file. In other words, stuff like <# ... should not be preceded by any indenting. It will make the template look a bit funny, but the resulting template will look ok. If you dislike the way the intending looks in the template, move the indent space in the tag, where it will be treated as empty space in the T4 code.

This post should have been titled Have your cake and eat it, too, but people need to find it in Google.

First of all, a bit of theory.

Web controls in ASP.Net can persist their properties in markup in two ways: attributes and nested tags. The problem with attributes is that the type of the property may be complex and iself have properties.

ASP.Net does have a mechanism for specifying subproperties by using a hyphen to separate properties and their subproperties. For example the BackColor property of a row of a GridView can be specified as both BackColor="Red" in the RowStyle tag or as RowStyle-BackColor="Red" in the GridView tag. However, that way is pretty unreadable and cumbersome that is why using inner tags is sometimes necessary (and implemented by decorating the properties with [PersistenceMode(PersistenceMode.InnerProperty)]).

But using inner tags is not always possible! Imagine a control like Panel. Its contents are interpreted as controls that are supposed to be rendered, so an inner tag would just be rendered to the page and not interpreted. There is no way of making such a control (decorated in its class declaration with [ParseChildren(false)]) have inner properties, but one can use something like an ITemplate property so that the controls can be placed in a tag of their own.

Also, consider controls like the DropDownList, in which ListItems are placed directly in the control tag and it is assumed automatically that they are children of the Items collection. That is because the Items collection is marked as [PersistenceMode(PersistenceMode.InnerDefaultProperty)] which means all the children of the control are considered elements in the property. Adding an inner tag would raise an error, as it would not be a ListItem object.

Yet, there is a way! And finding it was like discovering the holly grail. I have only tested it on a ListControl, but it should work on templated controls as well.

Let's start with a class that inherits from ListControl, therefore it has the Items collection in it and adding a complex property to it. I will create a special class called InnerTagClass that has a Text property. The control that inherits from ListControl and which I will call BaseClass will have an InnerTag property of type InnerTagClass. The code would look like this:

public class BaseClass:ListControl
{
private InnerTagClass mInnerTag;

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[NotifyParentProperty(true)]
public virtual InnerTagClass InnerTag
{
get
{
if (mInnerTag==null)
{
mInnerTag=new InnerTagClass();
}
return mInnerTag;
}
set
{
mInnerTag = value;
}
}
}
Now go into the designer and modify the Text property of InnerTag. You will notice that it will be saved as a hyphen attribute, while adding items to the Items collection would render the list items as children in the BaseClass tag:

<local:BaseClass ID="BaseClass1" runat=server InnerTag-Text="Test">
<asp:ListItem>Test</asp:ListItem>
</local:BaseClass>
Now, an InnerDefaultProperty is still an InnerProperty. You can put the ListItem inside an Items tag and it will still work, and also you can add an InnerTag tag with a Text attribute and it will work as well! However, if you go into the designer and you change the Text for the InnerTag property you get the changed property as an attribute and the previous InnerTag tag, with the old value. That is not acceptable.

However, you can inherit from the BaseClass, override the Items and the InnerTag properties and change their persistence mode to InnerTag! Here is the code:

public class InheritedClass : BaseClass
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public override System.Web.UI.WebControls.ListItemCollection Items
{
get
{
return base.Items;
}
}

[PersistenceMode(PersistenceMode.InnerProperty)]
public override InnerTagClass InnerTag
{
get
{
return base.InnerTag;
}
set
{
base.InnerTag = value;
}
}
}
Now editing in the designer will create the Items tag and add the list items to it and an InnerTag tag with a Text attribute! But when you type it in source view, you get intellisense for both the Items tag and the ListItem tag! Adding only list items to the control works just like an inner default property.

There is a catch, though, as adding list items as direct children of the InheritedClass tag will not allow you to change the values of Items or InnerTag from the designer. It will save the current items in an Items tag, create the InnerTag, but fail to remove the previous items and thus throw a designer error. Still, fixing that is as easy as switching to source view and removing the old items.

Another possible question would be if one could add both InnerDefaultProperty and InnerProperty as decoration to a property in a class, but the answer is no. An error of Duplicate 'PersistenceMode' attribute is thrown.

Also, it might be possible to be able to fix that via a specialised editor, but I think it would be too complicated by far.

So there you have it: a way to satisfy both the styles of source people (like myself) and designer people by using inheritance and persisting differently the base property and its override.

Well, there are a lot of reasons why you might get exceptions in the designer, but just in case you get one of these, that make no sense, and you open another Visual Studio with the same solution and you debug the other Visual Studio when entering design mode and you still don't get any meaningful result... shut down Visual Studio and restart it.

There are all these attributes that can be used to decorate properties and classes so that the Property Grid control knows to handle them. One of these attributes is PersistenceModeAttribute, which specifies how to persist the information in ASP.Net markup. More often than not, you need to persist a complex object with subproperties as an inner tag. In that case one uses [PersistenceMode(PersistenceMode.InnerProperty)]. For the possible values of the constructor parameter, just follow the link if interested.

The problem comes when you want to persist the properties as attributes, in the ASP.Net specific "flattened" syntax, using a hyphen to separate property from subproperty. (<Style Color="red"/> as an inner tag is the same as Style-Color="red" as an attribute). You want this because some controls interpret their inner content as controls to be placed in them, such as the Panel control. You cannot add a Style tag in it because it just gets rendered in the page. The solution is to not use PersistenceMode! Of course, you might say, that's obvious. But it is not when your property already has the PersistenceModeAttribute decorating it and you are desperately looking for a parameter that does what you want. There is no such parameter. Not decorating the property is a separate option and it is the default behavior.

I was working on a small ASP.Net control that inherited from Button, so nothing special. I went into Visual Studio in design mode and I noticed that the control did not display any resize handles so I could only move the control, not resize it using the mouse.

After intensive Googling, trying custom ControlDesigner classes with AllowResize set to true and all other kinds of strange things, I realised that in the Render method I would write a style tag while in DesignMode before rendering the button. The method was described in a previous blog entry to fix the problem with CSS files with WebResource entries inside and PerformSubstitution.

It appears that Visual Studio, by default, only resizes the controls that render an HTML element that has size. A style tag does not! The solution was to add a div around the control (and the style block) while in DesignMode. The only problem was that the div is a block element, while the input of type button is an inline element. That means that two div elements would place themselves one under the other, not next to the other like two buttons would. So I fixed the problem by also adding a float style attribute and setting it to left.

Here is a small code sample:

protected override void Render(HtmlTextWriter writer)
{
if (DesignMode)
{
writer.AddStyleAttribute("float", "left");
writer.RenderBeginTag("div");
// this renders an embedded CSS file as a style block
writer.Write(this.RenderDesignTimeCss("MyButton.css"));
}
base.Render(writer);
if (DesignMode)
{
writer.RenderEndTag();
}
}

I was trying to make a web control that would be completely styled by CSS rules. That was hard enough with the browsers all thinking differently about what I was saying, but then I had to also make it look decent in the Visual Studio 2008 designer.

You see, in order to use in the CSS rules (or in Javascript resources, for that matter) files that have been stored as embedded resources in the control assembly, a special construct that looks like <%=WebResource("complete.resource.name")%> is required.

The complete resource name is obtained by appending the path of the embedded resource inside the project to the namespace of the assembly. So if you have a namespace like MyNamespace.Controls and you have an image called image.gif in the Resources/Images folder in your project, the rule for a background image using it is background-image:url(<%=WebResource("MyNamespace.Controls.Resources.Images.Image.gif")%>);.

Also, in order to access the CSS file you need something like [assembly:
WebResource("MyNamespace.Controls.Resources.MyControl.css",
"text/css", PerformSubstitution = true)]
somewhere outside a class (I usually put them in AssemblyInfo.cs). Take notice of the PerformSubstitution = true part, that looks for WebResource constructs and interprets them.

Great! Only that PerformSubstitution is ignored in design mode in Visual Studio!!. The only solution to render the control correctly is to render the CSS file yourself and handle the WebResource tokens yourself. Here is a method to do just that:

private static readonly Regex sRegexWebResource =
new Regex(@"\<%\s*=\s*WebResource\(""(?<resourceName>.+?)""\)\s*%\>",
RegexOptions.ExplicitCapture | RegexOptions.Compiled);

public static string RenderDesignTimeCss2(Control control, string cssResource)
{
var type = control.GetType();
/*or a type in the assembly containing the CSS file*/


Assembly executingAssembly = type.Assembly;
var stream=executingAssembly.GetManifestResourceStream(cssResource);

string content;
using (stream)
{
StreamReader reader = new StreamReader(stream);
using (reader)
{
content = reader.ReadToEnd();
}
}
content = sRegexWebResource
.Replace(content,
new MatchEvaluator(m =>
{
return
control.GetWebResourceUrl(
m.Groups["resourceName"].Value);
}));
return string.Format("<style>{0}</style>", content);
}

All you have to do is then override the Render method of the control and add:

if (DesignMode) {
writer.Write(
RenderDesignTimeCss2(
this,"MyNamespace.Controls.Resources.MyControl.css"
);
}


Update:
It seems that rendering a style block before the control disables the resizing of the control in the Visual Studio designer. The problem and the solution are described here.

I have this ASP.Net web control that has a property that is persisted as an inner property and sets some custom style attributes. Then there is another control that inherits from the first one and overloads this custom style property with another having the same name and returning a different type. All this is done via the new operator

Now, while this is perfectly acceptable from the standpoint of Object Oriented Programming and it compiles without any issues, I get a compile error when I actually use the property and save it in the aspx code. That is a limitation of ASP.Net and I could find no way to circumventing other than changing the name of the property. This would also be the case if you have two public properties that have the same name only differently cased.

While this second situation I understand, the first is really stupid. I am specifying the type of the control so there should be no issues with an overloaded property. I guess it has something to do with the persistence mechanism, but still... Annoying.

I have been working on a class that has some properties of type Color?, a nullable Color. I noticed that, in Visual Studio 2008, when I go to edit the properties in question in the property grid I get a dropdown of possible colors whereas if I go to edit a color on a WebControl, something like BackColor, I get a nice dialog window with the title 'More Colors' with colored hexagons from which to choose a color. Researching on the net I found out that if you want to use the ColorEditor in the property grid control you should decorate the property with [Editor(typeof(ColorEditor), typeof(UITypeEditor))]. I did that and, indeed, the editor was changed. However, it was not the one for BackColor, with its hexagonal design.

Reflecting the WebControl class I noticed that it didn't use any Editor decoration, but rather [TypeConverter(typeof(WebColorConverter))], so I added that and removed the editor on my property. Now the only editing option for my property was a simple textbox. Using both TypeConverter with the Editor option didn't have any visible effect either, it just used the normal editor.

As a last test I changed the type of the property to Color and decorated it only with the TypeConverter attribute and there it was, the 'More colors' editor. My only conclusion is that the editor is chosen by the property grid itself on Color properties decorated with the WebColorConverter. It must be hardcoded and thus it will never work on other types. Just stick with the ColorEditor option for nullable values.

Needless to say, I spent quite a lot of time compiling, closing and opening the designer on a test page and so on, so I hope this helps other people with a similar problem.

Today I found out about a very cool attribute called DebuggerDisplayAttribute. What it does is tell the Visual Studio debugger how to display a certain class when making a break in the code. And it seems it is very powerful, using expressions in the string that is given as its parameter (ex: [DebuggerDisplay("x = {x} y = {y}")]). Check out the link on MSDN here.

The way the class is displayed can be further customized by using the DebuggerTypeProxyAttribute class, which actually uses a completely different class to be presented in the debugger windows. Read Using DebuggerTypeProxy Attribute for more details.

Whenever you build a more complex ASP.Net control you get to build templates. Stuff like collapsing panels, headered controls or custom repeaters are all usually working with templates, by having properties of the ITemplate type which then are instantiated into a simple control like a Placeholder or Panel. There are many tutorials on how to do this, so I won't linger on the subject.

What I find very difficult to achieve was to have a templated control that would just accept dropped controls and place them into a template, without having to enter in "template mode". First I will copy the entire code of a very simple control, then I will explain.

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;

namespace Web.Controls
{
[Designer(typeof (TestControlDesigner), typeof (IDesigner))]
[ParseChildren(true)]
[PersistChildren(false)]
public class TestControl : WebControl
{
#region Properties

[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[DefaultValue(typeof (ITemplate), "")]
[TemplateInstance(TemplateInstance.Single)]
public ITemplate MainTemplate
{
get;
set;
}

#endregion

#region Private Methods

protected override void CreateChildControls()
{
base.CreateChildControls();
if (MainTemplate != null)
{
MainTemplate.InstantiateIn(this);
}
}

#endregion
}

public class TestControlDesigner : ControlDesigner
{
#region Member data

private TestControl mTestControl;

#endregion

#region Public Methods

public override void Initialize(IComponent component)
{
base.Initialize(component);
SetViewFlags(ViewFlags.TemplateEditing, true);
mTestControl = (TestControl) component;
}

public override string GetDesignTimeHtml()
{
mTestControl.Attributes[DesignerRegion.DesignerRegionAttributeName] = "0";
return base.GetDesignTimeHtml();
}

public override string GetDesignTimeHtml(DesignerRegionCollection regions)
{
var region = new EditableDesignerRegion(this, "MainTemplate");
region.Properties[typeof (Control)] = mTestControl;
region.EnsureSize = true;
regions.Add(region);
string html = GetDesignTimeHtml();
return html;
}


public override string GetEditableDesignerRegionContent(
EditableDesignerRegion region)
{
if (region.Name == "MainTemplate")
{
var service = (IDesignerHost) Component.Site.GetService(typeof (IDesignerHost));
if (service != null)
{
ITemplate template = mTestControl.MainTemplate;
if (template != null)
{
return ControlPersister.PersistTemplate(template, service);
}
}
}
return string.Empty;
}


public override void SetEditableDesignerRegionContent(
EditableDesignerRegion region,string content)
{
if (region.Name == "MainTemplate")
{
if (string.IsNullOrEmpty(content))
{
mTestControl.MainTemplate = null;
}
else
{
var service = (IDesignerHost)
Component.Site.GetService(typeof (IDesignerHost));
if (service != null)
{
ITemplate template = ControlParser.ParseTemplate(service, content);
if (template != null)
{
mTestControl.MainTemplate = template;
}
}
}
}
}

#endregion

#region Properties

public override TemplateGroupCollection TemplateGroups
{
get
{
var collection = new TemplateGroupCollection();

var group = new TemplateGroup("MainTemplate");
var template = new TemplateDefinition(this,
"MainTemplate", mTestControl, "MainTemplate", true);
group.AddTemplateDefinition(template);
collection.Add(group);
return collection;
}
}

#endregion
}
}


The above code is a pretty common way of making a templated control. We have a Control (TestControl) with one or more ITemplate properties (MainTemplate) and a ControlDesigner (TestControlDesigner) that decorates the TestControl class via the Designer attribute. The trick for the drag and drop to work with this scenario is in the last two methods.

First look at the GetDesignTimeHtml() override. There I did a little hack in order to set for the target control an attribute with the name DesignerRegion.DesignerRegionAttributeName and with the value of "0". This actually declares the entire control in the Visual Studio designer as the first (and only) "editable region". The region is registered in the GetDesignTimeHtml(DesignerRegionCollection regions) override and named MainTemplate.

Secondly, look at the TemplateGroups property override. This is in order for the "Edit Templates" action to appear in design mode. Since drag and drop would work very nicely, technically we don't need it. However, I noticed that if one tries to drag a control out of the templated one, it doesn't really work :). We still need Template Editing mode, but only in unlikely scenarios. Even if the template group is called "MainTemplate" it has no connection with the editing region.

Thirdly, look at the lots of attributes decorating the TestControl class and the MainTemplate property. An important one is [TemplateInstance(TemplateInstance.Single)], which says that there will be only one instance of the template, in other words, the controls can be treated as in a Panel and accessible from the code as protected members.

Finally, let's look at the methods that actually permit the drag and drop operation: GetEditableDesignerRegionContent, which has a region as a parameter, and SetEditableDesignerRegionContent, which also has a region, but also a string content parameter.

The trick lies in the conversion from this unwieldy string variable to a control tree and viceversa. The string is necessary because it is the XML/HTML as interpreted by the Visual Studio designer.

As you can see, in the get method the static class ControlPersister is used to transform the control tree into a string, while in the set method the static ControlParser class is used to do the reverse.

Hope this helps someone.

I actually didn't know that a 32bit program could not use more than 2Gb of virtual memory by default. It makes sense, now that I think of it, but I just didn't make the connection. My office computer has 3Gb of memory and there is also the swap file, so having a program using more than 2GB of memory would be beneficial. And I am talking about Visual Studio here, especially since today I got an error I've never seen before: "Not enough storage is available to complete this operation".

So I've stumbled upon this article: Hacking Visual Studio to Use More Than 2Gigabytes of Memory which told me how to convince Visual Studio to use more than 2GB of memory. Also, since I am a ReSharper user, I found this little wrapper for Visual Studio that makes it use a different memory allocation method that reduces memory fragmentation: OutOfMemoryException Fix.


Short story shorter (for XP users with Visual Studio 2008 only - read the full articles for other configuration):
  1. Edit boot.ini to have the /3GB option
  2. Use editbin /LARGEADDRESSAWARE devenv.exe to change Visual Studio to have IMAGE_FILE_LARGE_ADDRESS_AWARE in the process header (editbin can be found in \Program Files\Microsoft Visual Studio 9.0\VC\bin\
  3. Download the Jetbrains devenv wrappers and change the signature of the Visual Studio shortcut to point to devenv2008_wrap.exe instead of devenv.exe
  4. (of course) Restart the computer


Update:
Thanks to the warnings from Lex Li, I went to study the /3G switch some more. The most important thing seems to be to also use the /USERVA switch to tune the /3G functionality.

More details here:
Memory Management - Demystifying /3GB
Summary of the recent spate of /3GB articles.

It is weird that this doesn't happen with all types of Visual Studio projects, but only with Web apps. You have all those annoying .MySCMServerInfo files that pop-up in your check-in window and then cause errors because SCM knows they should not be checked in.

Enter StackOverflow with a really good solution: Hidding source control files within Visual Studio’s solution tree. No need for me to copy paste, just remember you need to restart Visual Studio for this to work.

Short (but true) story: I was compiling this solution with a lot of projects in it. And one of these projects had some post-build events set to run which copied the resulting dll in an Assemblies folder. Only it failed.

On building the project I was getting an error: The command "[Complete command]" exited with code 1.

What was weird about it is that if I copied the command in a batch file and ran it, it would work perfectly. After trying a zillion things I've stumbled upon the condition of build events Run the post-build event: which was set to On successful build. I set it to Always and voila, it worked.

But I still needed to know what was going on, especially since it would make no sense to run the copy command if the build has failed. So I switched it back to On successful build. Surprize! It also worked.

Therefore, the silly solution for a problem that doesn't make much sense is to switch to always run the build events, build successfully, then switch back and build again. Fun!