Coding Nightmare
Oh. I'm not relishing trying to get my head around this...
TeamCity, MSBuild 4.0, a 64bit Server, and Could Not Load File or Assembly
I've been spending some time recently setting up TeamCity for continuous integration and stumbled upon an annoying issue that had me stumped for a while.
Following a simple update to a build script where I changed the way paths were resolved my build started failing. The error message was (cut down):
default.build(83,5): error MSB4062:The "xxx" task could not be loaded from the assembly C:\Program Files%28x86%29\ ... \xxx.dll. Could not load file or assembly. The systemcannot find the file specified.
After some serious head scratching and a lot of Google time it turns out that this is a bug with MSBuild 4.0. Basically MSBuild 4.0 can't handle paths with parentheses in certain situations. As the path on the server to the build files was under c:\Program Files (x86)\ it was just falling over with a file not found exception. The work around suggested by Microsoft is to compensate by decoding the path reference in your build script. In my case this meant changing from this:
<UsingTask AssemblyFile="$(BuildFolder)\xxx.dll" TaskName="xxx"/>
to this:
<UsingTask AssemblyFile="$([MSBuild]::Unescape('$(BuildFolder)'))\xxx.dll" TaskName="xxx"/>
So there we go. There is a connect issue for this bug here but I just thought I'd put this out there because it frustrated me no end until I found out what the issue was. Coincidentally, and for those that are interested, it was build #69 that contained the fix.
Stored Procedures vs. ORM
I was recently asked to give an explanation of my preference toward use of stored procedures vs. an ORM solution which happens to be a question that I have considered several times during development myself so I thought I’d throw in my 10 cents, so to speak.
Listing each of their respective benefits is not something I intend to do as there’s plenty out there in the developer community doing just that. Looking about you can find a couple of detailed post on StackOverflow.com (here and here) that describe some of the advantages and disadvantages of each solution. There was a response on one of those threads from an individual who came from a database background who was leaning toward ORM generally for reasons around the simplicity of certain operations and the reduced time in writing them. As for me, I have a tendency to lean a little the other way – whilst I agree with the reduced development time associated with an ORM solution I like the enforced separation of concerns imposed by accessing the database just through stored procedures (although I appreciate that if you’re implementing the repository pattern then there is a separation imposed there).
Knowing also that stored procedures can do much more than perform CRUD operations and queries plays a part in my opinion. Enterprise applications can benefit from stored procedures performing operations that ORM was never designed to replace like distributed transactions, message queuing etc. and remember: stored procedures can be changed\tweaked without requiring a re-release of compiled code.
In my opinion then, the factors that come in to play are speed of development vs. ease of update - and I’d go with ease of update FTW. That means if you’ve got a database team I suggest you use them.
My Recent Agency Experience
I got a call a week ago regarding a role that sounded right up my street in terms of skillset and ability. The agent on the end of the line was fairly thorough in terms of his scoping me out for the role and following the conversation I was left under the impression that I was going to be sent across contact details which I could respond to with evidence that may support my application (references, credential certificates etc). Anyway, I waited and… nothing. That was it: I had no contact details for this guy, and - although he had introduced himself at the start of the conversation - his name had gone in one of my ears and out the other. I didn’t even know who he worked for. At this point you may be able to tell but I’d kind of been banking on that email arriving.
So, I get another call towards the end of the week regarding what most likely is the same role from an agent who emails me across a job spec, I and say “Yeah, submit my CV”. After all, I want the job!
It turns out that the agency who had initially called me for whom I have no contact information had gone ahead and submitted my CV. Great. Now what? I can’t contact them! I explain to the other agent my predicament but there’s not much he can do. It looks bad on me; it probably looks bad on the agencies. I’m surprised that the company to whom I’m applying hasn’t dismissed my CV as a matter of course.
Anyway a day or two pass and the first agent gets in touch asking what the score is – I’m not surprised considering they’ve got nothing but a telephone call to go on.
Well, that’s it. The agency that I first spoke to submitted my CV in first so as far as I’m concerned they’re my representative. I felt I should put this out there – maybe someone will take notice and it’ll save them the frustration of being in the same situation as I am now. I’m not sure what I put it down to really; foolishness on my part? I’d appreciate your comments.
InvalidOperationException: Dynamic operations can only be performed in homogenous AppDomain
Aaaah. Right. I didn't expect that.
To set the scene, I'm writing a .NET 4.0 unit test in Visual Studio 2010 and using Microsoft Moles to test code that's impossible to test (or something like that). My simplified unit test code can be found below.
using System.IO;
using System.IO.Moles;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public classFileWrapperTest
{
[TestMethod, HostType("Moles")]
publicvoid TestMethod1()
{
// arrange
var fileWrapper = new FileWrapper();
MFile.ExistsString = path => false;
// act
dynamic exists = fileWrapper.DoesExist(@"C:\temp\test.txt");
// assert
Assert.IsFalse(exists);
}
public classFileWrapper
{
public bool DoesExist(string path)
{
return File.Exists(path);
}
}
}
I've added a Moles assembly for mscorlib to the project and the following to AssemblyInfo.cs:
using Microsoft.Moles.Framework;
[assembly: MoledType(typeof(System.IO.File))]
I run the test and bang, InvalidOperationException: Dynamic operations can only be performed in homogenous AppDomain. Now - because of the lack of complexity in the simplified code - you may have spotted the cause. Why, you will be asking, has the boolean "exists" been declared as dynamic? Well... simply in order to illustrate the point (the test would work otherwise)! The DLR bombs if you attempt a dynamic operatioon, specifically System.Runtime.CompilerServices.CallSiteBinder.BindCore(CallSite site, Object[] args) with (thanks to Reflector) this little gem:
if (!AppDomain.CurrentDomain.IsHomogenous)
{
throw Error.HomogenousAppDomainRequired();
}
Now, I know that the AppDomain should be homogenous when running in Full Trust following the overhall to CAS has had in .NET 4.0 (more here) and as that's what I'm coding in why isn't it? Well, it turns out that when you host an MS Test inside a Moles test host that the AppDomain that is created for the test is not homogenous. And that's it. I'm not sure what to do next? I've posted in the forums and sent an email to Microsoft but not had a real reponse yet. I guess I'll just need to be aware that I can't use the DLR inside of a Moles test host.
UPDATE: There is now a solution to this issue which is documented here.
How Lotus Notes is the Worst Piece of Software Ever
I don't have the time or knowledge to go into details but anyone who has had the misfortune to use Lotus Notes (any version) will no doubt concur that it is the worst piece of software ever. There are some in the industry that have documented it's many, many pitfalls, details of which can be found here: http://homepage.mac.com/bradster/iarchitect/lotus.htm.
"The great thing about Lotus Notes is, that given that it is working in a Windows environment and that the ubiquitous keystroke in that I use to refresh in any other program is F5, whereas Lotus Notes has deemed it necessary to override this functionality to log you out thereby doing pretty much the exact opposite of refreshing (or somewhere in that ballpark)." - Paul Anderson
Tackling Code Reviews using Automation
I'm currently undertaking a QA exercise on outsourced code as it gets delivered. In order to increase the productivity of the review process by reducing the defects raised and number of iterative fix cycles, I have been involved in writing tools that can be used by the external developers for them to check for compliance with specific coding standards and techniques demanded by the business.
The tools I am using for this automation are StyleCop and FxCop, Microsoft's free code styling and managed code analysis tool. A great number of the standards we have defined are covered by the default rules that ship with these tools but there have been exceptions. For instance, we do not expect any TODO comments in code that has been delivered.
There are several detailed tutorials covering how to write these rules so I'm not going to repeat what's already out there (links below).
http://scottwhite.blogspot.com/2008/11/creating-custom-stylecop-rules-in-c.html
http://www.lovethedot.net/2008/05/creating-custom-rules-for-microsoft.html (3 parts)
The code for my TODO rule is below. You simply need to call this method from one of the visitor callbacks mentioned in the above posts.
private static void FlagViolationForToDoComment(
SourceAnalyzer analyzer,
CsElement element)
{
var todoComments = element.ElementTokens
.Where(e => e.CsTokenType == CsTokenType.SingleLineComment ||
e.CsTokenType == CsTokenType.MultiLineComment)
.Where(c => c.Text.Substring(0, c.Text.Length >= 10 ? 10 : c.Text.Length)
.Contains("TODO"));
if (todoComments.Any())
{
foreach (var comment in todoComments)
{
analyzer.AddViolation(
comment.FindParentElement(),
comment.LineNumber,
CustomRules.ToDoCommentsShouldBeActionedThenRemoved);
}
}
}
}
One of the things to watch for is that if you install StyleCop with the MSBuild plugin that StyleCop may reside in more than one folder with one instance being registered with Visual Studio, and the other with the Explorer shell. In order to update the rules for use with both you will need to copy your rules library into each installation folder; in my case:
C:\Program Files\Microsoft StyleCop 4.4.0.14
C:\Program Files\MSBuild\Microsoft\StyleCop\v4.4
There's also a StyleCop contrib project that provides a test-runner allowing unit testing of your StyleCop rules. I can't recommend this enough - in my mind the only way to write StyleCop rules is to use TDD.
Use the ActionName Attribute, Already
You heard.
I've done a bit of MVC in my time but Neville (who knows more than I do about Oracle but less than I do about MVC) just told me about the ActionName attribute. Here's the lowdown: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx.
That is all.
TF255440: The following account has a SQL Server login, but the login was denied access
I just got this error when trying to add an Administration Console User to TFS 2010 installed on Windows 7 using a SQL Server database on a different server:
TF255440: The following account has a SQL Server login, but the login was denied access: TEST\cameron.fletcher. The server selected to host the databases for Team Foundation Server is: SQL. The SQL Server login associated with the user account must be granted access to the SQL Server instance on that server.
It turns out that although I have a login specifically assigned to me on the SQL box because I am also a member of a SQL administrators group there appears to be some issue with the TFS logic when verifying the connection. The solution? I simply deleted the login and it worked for me.
File Transfer via Clipboard Text
I have recently been involved in some work that requires me to program on a Remote Desktop (via RDP over an SSL connection) so there is no development software installed locally. One of the downsides is that due to the restricted nature of the connection only text based copy and paste works, so it is not possible to transfer files onto the development environment. Not only this, but although the local machine has access to the internet, the development environment has none.
The solution? I wrote a console based application called MemCopy to copy files to and from the clipboard as text. It does this by either encoding the file as Base64 then saving it as text on the clipboard, or decoding it from the clipboard.
I'd only written this in one of the environments, so I had to decode it in the other before I could use it - a bit chicken and egg, if you ask me. Anyway, I have attached a link to the encoded text here (you didn't think I was going to give you the solution on a plate did you?)
The code below is all that was required to decode it. I placed the encoding into the resources as a file.
byte[] buffer = Convert.FromBase64String(Resources.Encoding);
FileStream stream = new FileStream("memcopy.zip", FileMode.Create,FileAccess.ReadWrite);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(buffer);
writer.Close();
For those of you without the technical acumen to decode the above source, I have attached a working copy MemCopy as a zip file here. Simply download and extract MemCopy to a folder of your choosing, copy the contents of the encoded text (above) into memory, then execute MemCopy from the extracted location using the following command:
MemCopy /decode MemCopy.zip
The result? Awesomeness.