Announcing SevenZipCmdLine.MSBuild

This was a quick and dirty thing born out of necessity, and need to make zip files of PoshRunner so I could make its chocolatey package.

I made MSBuild tasks for creating 7zip and zip files out of the $(TargetDir) of an MSBuild project. There is a nuget package for it. Simply include it in your project via nuget and build it from the command line with the following command line:

%windir%\microsoft.net\framework\v4.0.30319\msbuild __PROJECT_FOLDER__\__PROJECT_FILE__ /t:SevenZipBin,ZipBin

This will create project.zip and project.7z in __PROJECT_FOLDER__\bin\Target. To see how to override some of the defaults, look at this msbuild file in PoshRunner.

Source code is available via a github repo, and patches are welcome!

PoshRunner now on SourceForge and Chocolatey

I’ve been periodically hacking away at PoshRunner. I have lots of plans for it. Some of these are rewriting some of it in C++, allowing you to log output to MongoDB and total world domination! However, today’s news is not as grand.

The first piece of news is I made a PoshRunner sourceforge project to distribute the binaries. To download the latest version, click here. Secondly, there is now a PoshRunner chocolatey package, so you can install it via chocolatey. Finally, there is not a lot of documentation on PoshRunner.exe, so here is the output of poshrunner -help.

Usage: poshrunner.exe [OPTION] [...]

Options:
   --appdomainname=NAME                                     Name to give the AppDomain the PowerShell script executes in.
   --config=CONFIGFILE                                      The name of the app.config file for the script. Default is scriptName.config
   -f SCRIPT, --script=SCRIPT                               Name of the script to run.
   -h, --help                                               Show help and exit
   --log4netconfig=LOG4NETCONFIGFILE                        Override the default config file for log4net.
   --log4netconfigtype=LOG4NETCONFIGTYPE                    The type of Log4Net configuration.
   --shadowcopy                                             Enable Assembly ShadowCopying.
   -v, --version                                            Show version info and exit

“Forking” a long running command to a new tab with ConEmu. The magic of -new_console:c

Here’s a quick tip I’d thought I’d share after being quite rightly told to RTFM by the author of ConEmu.

Suppose you are running FarManager from ConEmu and want to update all your chocolatey packages. You can do so with the command cup all. However, that will block your FarManager session until the cup all completes. You have four options to fix this:

  1. You can start a new tab in ConEmu with the menu. This is undesirable because you’re obviously a command line guy.
  2. You press Shift+Enter after the cup all command. This is undesirable because unless you configure ConEmu to intercept every new command window, a regular console window will appear. Also, the console will close automatically upon completion.
  3. You can type cup all & pause and hit Shift+Enter to allow the window to stay open. Or
  4. You can type cup all -new_console:c to open a new tab that will execute the command, and not close upon completion.

Obviously I recommend option 4.

How to reference the registry in MSBuild4.0 (Visual Studio 2010) and later on a 64 bit OS

In the past I’ve written about using the Windows Registry to reference  assembly paths in Visual Studio. In it I made reference to the seminal article New Registry syntax in MSBuild v3.5, which is the dialect Visual Studio 2008 speaks. That syntax has served me well until recently.

See fate lead me to writing a small C++/CLI program. In it I had to refer to some .NET assemblies that were not installed in the GAC. They were however installed as part of a software package that wrote its install path to the registry. So I figured out which value it wrote the install directory to and referenced it in the .vcxproj file using the $(Registry:HKEY_LOCAL_MACHINE\Software\Company\Product@TargetDir). Unfortunately, it didn’t work!

I did some troubleshooting and discovered it worked when I build the vcxproj from the command line with msbuild.exe. It seemed logical to blame it one the fact that I was using C++. Devenv.exe (the Visual Studio executable) must have been treating .vcxproj files differently than csproj and vbproj files. Then suddenly it dawned it me, the problem was I was running on a 64 bit version of Windows! This was a relief, because it meant that .vcxproj were not special or subject to unique bugs.

To make a long story short, Visual Studio is a 32 bit application, and by default when a 32 bit process interacts with the registry on a 64 bit version of Windows, HKEY_LOCAL_MACHINE\Software gets redirected to HKEY_LOCAL_MACHINE\Software\Wow6432Node. This MSDN article explains the gory details.

At first it seemed the only workaround was a custom MSBuild task line the MSBuild Extension Pack. I complained on twitter to Scott Hanselman (blog|twitter).  He replied with this article talking about how the page faults, addressable memory space, etc was not an issue. That article made some good points. However, it didn’t address my (at the time) very real and legitimate concern. Scott said he’d ask around internally if I filed a connect bug and got David Kean (blog|twitter) involved in the conversation.  I filed a connect bug. Then David pointed out a link to the MSBuild 4.0 key GetRegistryValueFromView.

Here is a comparison of the old and new syntax using msbuild <Message/> msbuild tasks, the printf() of msbuild.

<Target Name="BeforeBuild">
	<!-- Read the registry using the native MSBUILD 3.5 method: http://blogs.msdn.com/b/msbuild/archive/2007/05/04/new-registry-syntax-in-msbuild-v3-5.aspx -->
	<PropertyGroup>
		<MsBuildNativeProductId>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion@ProductId)</MsBuildNativeProductId>
		<MsBuildNativeProductName>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion@ProductName)</MsBuildNativeProductName>
		<MsBuild4NativeProductId>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'ProductId', null, RegistryView.Registry64))</MsBuild4NativeProductId>
		<MsBuild4NativeProductName>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'ProductName', null, RegistryView.Registry64))</MsBuild4NativeProductName>
	</PropertyGroup>
	<!-- Lets use the MSBuild Extension Pack (still no joy) http://www.msbuildextensionpack.com/help/4.0.5.0/html/9c8ecf24-3d8d-2b2d-e986-3e026dda95fe.htm -->
	<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Value="ProductId">
		<Output PropertyName="MsBuildExtProductId" TaskParameter="Data" />
	</MSBuild.ExtensionPack.Computer.Registry>
	<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Value="ProductName">
		<Output PropertyName="MsBuildExtProductName" TaskParameter="Data" />
	</MSBuild.ExtensionPack.Computer.Registry>
	<!-- And now RegistryView: http://msdn.microsoft.com/en-us/library/microsoft.win32.registryview.aspx -->
	<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Value="ProductId" RegistryView="Registry64">
		<Output PropertyName="MsBuildExt64ProductId" TaskParameter="Data" />
	</MSBuild.ExtensionPack.Computer.Registry>
	<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\Windows NT\CurrentVersion" Value="ProductName" RegistryView="Registry64">
		<Output PropertyName="MsBuildExt64ProductName" TaskParameter="Data" />
	</MSBuild.ExtensionPack.Computer.Registry>
	<!-- All messages are of high importance so Visual Studio will display them by default. See: http://stackoverflow.com/questions/7557562/how-do-i-get-the-message-msbuild-task-that-shows-up-in-the-visual-studio-proje -->
	<Message Importance="High" Text="Using Msbuild Native: ProductId: $(MsBuildNativeProductId) ProductName: $(MsBuildNativeProductName)" />
	<Message Importance="High" Text="Using Msbuild v4  Native: ProductId: $(MsBuild4NativeProductId) ProductName: $(MsBuild4NativeProductName)" />
	<Message Importance="High" Text="Using Msbuild Extension Pack: ProductId: $(MsBuildExtProductId) ProductName: $(MsBuildExtProductName)" />
	<Message Importance="High" Text="Using Msbuild Extension Pack: ProductId: $(MsBuildExt64ProductId) ProductName: $(MsBuildExt64ProductName)" />
</Target>

That MSBuild code has been tested via this github project on two machines running Visual Studio 2010 SP1. One has Windows XP3 32 bit and the other runs Windows 8 64 bit. I’ve verified that $([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\whatever', 'value', null, RegistryView.Registry64)) will give you the same value as you see in regedit.exe

Yes MSBuild 4.0, and therefore Visual Studio 2010 solved this problem and I simply didn’t google hard enough for the answer. However, I googled pretty hard, and I’m pretty good at googling. I didn’t think I was particularly rash in “pulling the Hanselman card.” The best I can do is write this blog post, comment on other blogs and answer questions on StackOverflow to fill the internet with references to the MSBuild syntax.

Trouble purchasing an MSDN subscription

Recently I’ve decided to purchase a Visual Studio 2012 Professional  MSDN subscription. There are several reasons for this. First of all, my Visual Studio 2012 30 day trial ran out and I absolutely need the non-express edition of it for a side project. Secondly, I’d like to be able to test poshrunner in older versions of Windows. Thirdly, Having access to checked builds of Windows would allow me to lean more in my Windows Internals study group.

I started my journey to an MSDN subscription on Saturday December 8th 2012. I was able to access my benefits Thursday December 12th. The four day journey was not pleasant.

On Saturday I sat down credit card in hand and placed my order. I didn’t save the receipt (stupid I know). I got no confirmation email, and I did not see an authorization on my credit card. I waited. On Sunday I got notification that my order was pending. Perhaps they wanted to verify I wasn’t a software pirate. It seemed annoying that this wasn’t an instant process, but I remained patient and understanding. Then Tuesday I woke up to an email stating that my order was canceled.

MSDN customer support hours are from 5:30PST to 17:30PST. I am on EST so I had to wait until 8:30 to call. I was already in the office at that time. I was told the bank did not accept my charge, but that if I placed the order again in 48 hours, the security check would be overridden and I would be able to download the software instantaneously  I tried buying the MSDN license again. It failed, but instantaneously.  I called my bank. I was told both authorizations were successful on their end. So I called Microsoft again. They claimed a system glitch prevented them from accepting the payment. The specific phrase “system glitch” was used consistently by several MSDN customer support representatives over several phone calls to describe instances when my bank authorized a charge but Microsoft rejected it. I never uttered that phrase once. I’m suspicious this is a common enough occurrence that there are procedures and guidelines in place documenting the “system glitch”.

At this point they asked if I placed the second order from a computer on the same network as the first. I said no. The first order was placed at home and the second order was placed in the office. I was told to try again from the same network. I don’t have remote access to my home computer (take away my geek card) so I had to wait till I got home. I asked what would happen if it didn’t work when I tried again. I was told the only other option was to place the order over the phone, and that phone orders take three business days to process. I didn’t get home until after midnight so I didn’t try Tuesday night.

Wednesday

Wednesday I awoke and attempted to place the order. It failed. I went into the office,  called customer support and attempted a phone order. It failed, because my bank decided three identical charges for $1,305.41 (Microsoft collects sales tax in NY on top of the $1199 base price) seemed suspicious. Luckily I am able to fix that by responding to a text message CitiBank sent me. A chat session and a call later and the purchase seems to have been resolved. I would have my subscription on Monday.

Thursday

Thursday I got a call saying my order was canceled. However, T-Mobile dropped the call before I could deal with it. When I had some free time I called CitiBank. The first operator gave me some free airline miles and transfered me to Ashley, the fraud department specialist. Ashley ensured me Microsoft could bang my credit card as often and as many times as they wanted to. I then called MSDN support and talked to Chris.

I summarized the situation for Chris. I told him I didn’t want to wait another three days for a phone order. He said he had no power to deal with that. He determined my order from Wednesday was still going through. After putting me on hold a few times, he said he would get me a welcome email that would let me download my MSDN products in 30 minutes. I got his name and a case number and he did just that.  I got a call back to ensure I was able to access my download, and everything worked just fine. I’m a little curious as to why his tune changed and he was able to get me my subscription number in thirty minutes though.

Conclusion

First of all I have to thank CitiBank for their actions. At no point did they do anything wrong or fail to do anything. Secondly, the customer service staff at MSDN were very professional and understanding, despite my growing irateness. However, the fact is they were never able to tell me why my order was canceled. If they at some point explained that I was flagged as a pirate, or something else, I’d be a bit more understanding. Thirdly, why does the process take so long? I was able to buy a new car in about an hour. It took a few days for delivery because the package I wanted wasn’t on the lot. However, it took less than four days for the car to be driver off the lot (by someone else because it was the car I learned stick on).

The MSDN subscription sales model seems to make sense for businesses purchasing volumne licenses. They take checks, you can talk to a real person. Its not at all optimized for the person that wants to buy one MSDN license “right now”. People like me are on the lower end of the income bracket for Microsoft, but we are also the ones that are either really passionate hobbyists, entrepreneurs, or the people on the fence. While I’m still going to develop on the Microsoft stack for years, this experience has left a bad taste in my mouth for their purchase process, compared with for example JetBrains or RedGate.

In the end the real issue was the lack of transparency. Its generally safe to assume that when you are buying software for online delivery, you will have it within an hour. If Microsoft made it clear its not as simple for them, first time subscribers like me would be a little more understanding.

Announcing ILRepack-BuildTasks

ILMerge is a great tool for creating a single executable out of multiple .NET assemblies. However, it has two limitations. The first is that its not open source, and you’re not supposed to include a copy in your public source code repos. The second is its an executable and therefore needs to be called from the MSBuild post build event as opposed to a proper MSBuild task. Each problem had its own mutually exclusive solution.

For the first problem, Francois Valdy (blog|twitter) wrote IL-Repack, an open source clone of ILMerge. So now I could have an exe that could be included in github repos.  This allowed my projects (specifically poshrunner.exe) to have a merge step in the postbuild. ALthough this was still a clunky batch file embedded in the csproj, it just worked.

For the second problem, Marcus Griep (blog|twitter) created ILMerge Tasks. Since the merging APIs in ILMerge are all exposed as public members, you can simply reference the exe as a dll. He did this in an MSBuild DLL. However, this dll still requires ILMerge.exe.

These solutions are no longer mutually exclusive. I’ve forked ILMerge-tasks (and contacted Marcus to see if he wants to incorporate my changes). I had it reference ILRepack. The new project is called ILRepack-BuildTasks on github. Enjoy!

A misleading SQL Error Message Error: 18456, Severity: 14, State: 38

On Friday I had to help a client out with an error that kept appearing in their event logs:

Login failed for user ‘domain\user’. Reason: Failed to open the explicitly specified database. [CLIENT: 192.168.0.25]

It took me a while to troubleshoot the error. The client’s internal system administrator (who was quite sharp) only had to call me in in the first place because the error was a little misleading. See the first thing I did when I saw that was audit login failures. In the trace, the database was listed as master. The user had full access to master. However, I later learned that the user was switching from master to a non-existent database, which was triggering this error. I figured this out thanks to Sadequl Hussain‘s article, SQL Server Error 18456: Finding the Missing Databases.

Sadequl explains in detail the how and the why. However, the take home is you need to trace for User Error Message to get the message that tells you what database you are connecting to.

This took me about an hour to solve. Honestly, it was a bit humbling of an experience. It took me an hour to figure out something a full time senior DBA would probably be able to solve in 15 minutes. However, I’ll probably be able to solve this error in 15 minutes myself go forward. Finally, the fact that it took me a while to find this one blog article that explained what the issue actually was proves how dependent I’ve become upon google.

The #MongoHelp twitter manifesto

What is #mongohelp?

#mongohelp is a hashtag on twitter that members of the mongo community use for support.

What’s appropiate to tag #mongohelp?

In order for something to be appropiate for appending the #mongohelp hash tag to one of the following two criteria must be met

  1. You are asking a question related to MongoDb
  2. You are @replying to a question #mongohelp with an answer or a request for clarification

Those are the rules. You can reply with a recommendation for a commercial product or service, but please disclose if you work for partner with or own the product. You can’t make unsolicited promotions with this hash tag. You can’t post a link to your latest blog article to the tag, unless you are answering a question.

Any other guidelines?

Twitter is about instant gratification, so if you ask a question on #mongohelp, its expected you will be sticking around for 10-15 minutes for an answer. Also, if you have a long question to ask on #mongohelp, you should ask it in one of these forums, and link to the question.

This seems awfully familar

Your absolutely right! I borrowed the idea from Aaron Nelson’s (blog|twitter) proposal that was documented by Brent Ozar (blog|twitter) of creating the #sqlhelp hashtag. I’ve spent the last year speaking about MongoDb at SQL Saturdays and after observing both communities. Both communities are very self organized, and provide a lot of free help. The one thing I saw missing from the MongoDB community was a grassroots support tag to connect with others.

Announcing poshrunner.exe so MyScript.ps1 can use MyScript.ps1.config instead of powershell.exe.config

I have a tendency to do odd things with technology so that things don’t just work. When I point out the obscure edge cases I find, most people tell me, “well don’t do that.” I usually ignore them and dream of tilting windmills. Well today a windmill has been tilted, and this is the epic tale.

I’m a developer that fell in love with PowerShell. As such I often call .NET API functions from powershell scripts. This usually just works. However, it kind of falls apart when you have to use settings in the app.config file. This means its basically impossible call functions from a DLL that use NHibernate, Entity Framework or WCF Service references. (However, WCF Services can be called direcctly from PowerShell quite easily)

The solution is to run the PowerShell script in a new PowerShell Runspace in a second AppDomain that uses its own app.config. However, things quickly fall apart because you need to write three classes that inherit from PSHostRawUserInterface, PSHostUserInterface and PSHost respectively or else Write-Host will throw an exception.

Now all this is a lot scarier than it sounds. However, it stops two important groups of people from ever using PowerShell to call DLLs that absolutely require you to manipulate your app.config:

  • People scared off by the word AppDomain
  • People that realize they have better things to do than everything I described above

Lucky for these two groups of people, I wasted my time so they didn’t have to! The project is currently called AppDomainPoshRunner, and I ILMerge it (via IL-Repack) into poshrunner.exe. Right now poshrunner takes one command line argument, the path to a script. If the script exists it will run it in an AppDomain whose config file is scriptname.config. Log4net configuration is read from a file called ADPR.log4net.config in the same directory as poshrunner.config.

The full background is to long and convoluted for this post. This was all born out of a problem with calling New-WebServiceProxy twice in the same PowerShell console. I use log4net to write the console messages so this has the potential to be quite extendable. Then Stan needed to run PowerShell scripts from msbuild and was complaining to me about it over twitter. He didn’t like the hacky solution I had then. Eventually I realized this was the way to simplify my previous solution.

So download the zip file. Try it out. Complain to me when you find bugs!

TLDR; Unlike powershell.exe -file foo.ps1, which uses the shared powershell.exe.config, poshrunner.exe foo.ps1 uses foo.ps1.config, for great justice. Download it now!

Visual Studio 2010 and VisualStudio.com TFS Hosting

Yesterday, Stan, the founder of this blog, gave me a link to a project host on the Team Foundation Service (visual studio.com). I tried to connect to it with Visual Studio 2010. it simply refused to work.

Visual Studio Add TFS Server Error

After much annoyance, he asked me to try adding the TFS server to Visual Studio 2012 and it worked (Why didn’t I think of that?). Eventually I figured out that I needed to install the Visual Studio 2010 SP1 Team Foundation Server 2012 Compatibility GDR (KB2662296). Then I was able to add the solution to Visual Studio 2010. It seems there are several updates for Visual Studio 2010 SP1, some specifically dealing with Windows 8 compatibility. Unfortunately Windows update does not prompt me to install them. I will search for and install these tonight to prevent future issues.