Viewing GAC’d Assemblies in the Windows Azure OS
One of the main issues you can run into when deploying is that one of your dependent assemblies is not available in the cloud.
This will result in your cloud service never hitting the running state, instead it will cycle between the initializing, busy and stopping states.
(the other main reason is that a storage account, especially the one included in the default template, is pointing to development storage – see this post about running the app on the devfabric with devstorage turned off to weed that issue out)
To help you understand what assemblies are available in the cloud and which are not, this post goes through the steps of building a cloud service that will output the assemblies in the GAC – a view into the cloud, similar to my certificate viewing app. (Download the Source Code)
Here’s the final product showing the canonical example of how System.Web.Mvc is not a part of the .NET Framework 3.5 install and needs to be XCOPY deployed to Windows Azure as part of the service package:
Since the GAC APIs are all native, I figured the easiest way to do what I want and leverage a bunch of existing functionality is to simply include gacutil as part my cloud service, run it and show the output in a web page.
1. Create a new cloud service with a web role
2. Add gacutil.exe and gacutil.exe.config to the project. Right click on WebRole1 in Solution Explorer and select Add | Existing Item.
Navigate to C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64 and add both gacutil.exe and gacutil.exe.config to the web role project.
3. Right click on each of the gacutil files and double check that the build action is set to content. This will ensure the two files we added are included as part of the Service Package. (see this post on adding files to the service package for more info)
4. Add some UI to Default.aspx – a couple of TextBoxes and Buttons. I added the following to the <div/> tag.
<asp:TextBox runat="server" Width="200" ID="assemblyName" />
<asp:Button runat="server" OnClick="OnViewAssemblyButtonClick" ID="viewAssemblyButton" Text="Look up Assembly" />
<asp:Button runat="server" OnClick="OnViewAllButtonClick" ID="viewAllButton" Text="View all Assemblies"/>
<br />
<asp:TextBox runat="server" ID="ressultsBox" Width="600" Height="800" TextMode="MultiLine"/>
5. Add some event handlers for the buttons that will call gacutil. “View all Assemblies” simply calls gacutil with the “/l” parameter whereas the “Look up Assembly” button will append the assembly name to that parameter causing gacutil only to list the assemblies that match that assembly name (no ".dll").
protected void OnViewAllButtonClick(object sender, EventArgs e)
{
string path = MapPath("gacutil.exe");
string command = "/l";
ressultsBox.Text = RunCommandLineTool(path, command);
}
protected void OnViewAssemblyButtonClick(object sender, EventArgs e)
{
string path = MapPath("gacutil.exe");
string command = "/l " + assemblyName.Text;
ressultsBox.Text = RunCommandLineTool(path, command);
}
6. The meat of the call to gacutil is contained in a method called “RunCommandLineTool”:
private string RunCommandLineTool(string path, string parameters)
{
ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(path, parameters);
info.UseShellExecute = false;
info.ErrorDialog = false;
info.CreateNoWindow = true;
info.RedirectStandardOutput = true;
Process p = Process.Start(info);
StreamReader sr = p.StandardOutput;
string output = sr.ReadToEnd();
sr.Close();
return output;
}
The code is pretty straightforward, launches gacutil and redirects standard output to a stream which is eventually converted to a string and set on one of the TextBoxes in the UI.
And that’s about it, when you deploy and then run this application in the Windows Azure cloud, you’ll be able to see what assemblies are in the GAC! Note that this is useful as the actual assemblies can vary for different OS versions.
Here’s the listing for Windows Azure Guest OS 1.1 (Release 201001-01). (in reality, even though there are changes in different OS versions, what you need to deploy and what’s available really isn’t going to change)
Once you figure out you need to add some dependent assemblies to you service package you can see this post to help you, and this post to see what assemblies are in the service package.
One final tip – in a new Cloud Service, we add references to Microsoft.WindowsAzure.Diagnostics, Microsoft.WindowsAzure.ServiceRuntime and Microsoft.WindowsAzure.StorageClient.
The Copy Local property for Microsoft.WindowsAzure.Diagnostics and Microsoft.WindowsAzure.StorageClient should be set to True and for Microsoft.WindowsAzure.ServiceRuntime, it should be set to False. (important to not if you add the reference yoursefl)
The reason is that Microsoft.WindowsAzure.ServiceRuntime is a bit of a special assembly so we treat it a little differently.
Comments
Anonymous
March 22, 2010
> your cloud service never hitting the running state It would even nicer if the Fabric was able to troubleshoot (to some extend) such pathological behavior on its own; basically detecting identical exceptions throw several times in a row, less than 10s after VM restart.Anonymous
March 22, 2010
Totally agree Joannes. We're thinking about ways to improve some of these problems and make Windows Azure more diagnosable.Anonymous
April 12, 2010
You can propose and/or vote for proposed Azure features via http://www.mygreatwindowsazureidea.com/pages/34685-sql-azure-feature-voting Join the Microsoft Front Runner Program for Azure to access one-on-one technical support by phone or e-mail from our developer experts, who can help get your applications in the cloud. Once your application is compatible, you'll get a range of marketing benefits to help you let your customers know that you're a Front Runner. http://frontrunner.msdev.com/whyjoin/windowsazure.aspx