# Friday, December 11, 2009

198 - Copy I received this question this morning from the Microsoft Online Concierge. We have a Concierge? Who knew?! Can you set me a wake-up time please, for 10AM? Oh, and a full breakfast would be excellent too.

The specific question was:
“I want to check the assembly residing in GAC, previously we use to check using gacutil, but now it is not a part of .net framework so is there any replacement for gacutil?”

I’ve seen this same question many times before, almost verbatim. Clearly, time to get something on the InterWebs to slow down the frequency of it.

The short answer is that gacutil is still your answer, but that it lives in the SDK (v2, v3.5, v3.5). It doesn’t ship with the redist product, and since gacutil is intended as a development time scenario only, that makes sense. End-users (the ones using your apps) shouldn’t be messing with the GAC.

From what I understand, Gacutil *did* end up on customer machines in a service pack of .NET 1.1. Apparently, the SP relied on gacutil.exe to do GACing, and did not delete the exe as part of its final cleanup. So, there were two mistakes there (in order): using a different set of tools/APIs than what we guide customers to use, and leaving behind turds on end-user machines. Bad, bad, bad. In any case, gacutil.exe was never intended to be part of the end-user install.

Gacutil also ships with most (maybe all) SKUs of VS. So, if you open the VS command-prompt, you just need to type “gacutil” you’ll see it print a bunch of command-line switch help.

To check if an assembly is in the GAC, you can type one of the following two forms:

  • gacutil /l [simple name]
  • gacutil /l [full strong name]

Here are two examples, using the .NET 4 gacutil:

C:\Users\rlander\Documents\Visual Studio 2010\Projects>gacutil /l System
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.21201.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro
cessorArchitecture=MSIL
  System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro
cessorArchitecture=MSIL

Number of items = 2

C:\Users\rlander\Documents\Visual Studio 2010\Projects>gacutil /l "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.21201.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro
cessorArchitecture=MSIL

Number of items = 1

C:\Users\rlander\Documents\Visual Studio 2010\Projects>

Notice that specifying “System” (simple name only) returns both the v4 and v2 version of the assembly, but specifying the “System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089” (full strong name) returns just the v4 version of the assembly. That makes sense, for a general query (the first one) and a specific query (the second one).

If I had passed in mscorlib, System.Web or System.Data, I would have seen 4 assemblies, as those assemblies are bit-specific, and require a different compiled assembly (using the platform switch) for each processor type (X86, X64). See:

C:\Users\rlander\Documents\Visual Studio 2010\Projects>gacutil /l System.Web
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.21201.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=AMD64
  System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=x86
  System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=AMD64
  System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=x86

Number of items = 4

If you do need to check whether assemblies are in the GAC on end-user machines, we do have a set of APIs for doing that. Being that they are APIs, you need to code to them, and they are native. A good question is whether a set of first-class managed APIs would be generally useful to developers. You can do searches for samples, which would likely help you.

MSI has support for installing and uninstalling assemblies. For that scenario, you should just rely on that support. That’s what Visual Studio does, for example. I should note that MSI supports installing .NET 4 assemblies; no updates are required for that.

Looking back at the history of this blog, it looks like I take a few moments out to answer this question every 2 years. It appears that I’m right on target again, in late 2009. See you again (on this topic) in late 2011! Hopefully not.

Friday, December 11, 2009 6:15:52 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, December 08, 2009

I posted an article on the CLR Team blog on a new scenario that we enabled for sharing assemblies between Silverlight and .NET. This is one of the features that I worked on in the .NET 4 cycle.

http://blogs.msdn.com/clrteam/archive/2009/12/01/sharing-silverlight-assemblies-with-net-apps.aspx

 

Tuesday, December 08, 2009 11:53:02 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

I'm doing a little project right now that requires me to know (among other things) the number of hardlinks for a given file. I have a tool that already will tell me the number of hard links for a given file, but I need to collect a bunch more information, and I really hate calling out to an exe and collecting and parsing its output, as part of a larger app. So, I set out to write that slightly larger app.

Having never written an app that cares about hardlinks, I didn't know whether or not the BCL had APIs that exposed this info. It doesn't. Whether it should expose this info is a whole other question. So, I resorted to p/invoke, which is fine. I did a few searches and found that there isn't too much info out there on doing this from .NET, hence my motivation for writing this post.

I started out with NtQueryInformationFile. I'm pretty sure that the p/invoke signature on p/invoke.net is wrong. I wasn't able to get this function working to my satisfaction, but can share where I ended up, in the hope that it might help someone:

        [DllImport("ntdll.dll", SetLastError=true)] 
        static extern Int32 NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, [MarshalAs(UnmanagedType.LPArray)] Byte[] arrayBuffer, uint length, FILE_INFORMATION_CLASS fileInformation); 

FWIW, I allocated a byte[2048], and passed in (uint)array.Length as the length paramter. 2k was overkill for what I needed, but at least got me a bunch of bytes. I wasn't too sure what to do next, so decided to look for something easier. I was guessing that I needed to write a struct who fields mapped over that byte[], but I wasn't sure what the meaning of those fields was going to be. I couldn't find any docs that would have that easier, and didn't see any code samples either.

The good news is that I found another function -- GetFileInformationByHandle -- that is much easier to use, and that did work for me.

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);

You can see my app below. For now, it just contains calculates the hard-links, which is the part that I tackled first. I'll now move to writing the rest of my experiment.

using System;
using System.Runtime.InteropServices;
using System.IO;

namespace banff
{
    class Program
    {
        static void Main(string[] args)
        {

            if (args == null || args.Length == 0)
            {
                Console.WriteLine("Please specify a file to check");
                return;
            }
            else if (!File.Exists(args[0]))
            {
                Console.WriteLine("File doesn't exist");
            }

            

            FileStream fs = null;

            fs = new FileStream(args[0],FileMode.Open,FileAccess.Read);
            BY_HANDLE_FILE_INFORMATION fileInfo;

            Boolean result = GetFileInformationByHandle(fs.Handle, out fileInfo);

            Console.WriteLine(fileInfo.NumberOfLinks);

            fs.Close();

        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool GetFileInformationByHandle(IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation);


        struct BY_HANDLE_FILE_INFORMATION
        {
            public uint FileAttributes;
            public FILETIME CreationTime;
            public FILETIME LastAccessTime;
            public FILETIME LastWriteTime;
            public uint VolumeSerialNumber;
            public uint FileSizeHigh;
            public uint FileSizeLow;
            public uint NumberOfLinks;
            public uint FileIndexHigh;
            public uint FileIndexLow;
        }

    }
}

 

 

Tuesday, December 08, 2009 7:19:57 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, May 29, 2009

A few months ago, we started the CLR Team Blog. There are quite a number of posts there and we're getting quite a lot of traffic to the site. It has been a long time overdue, but I'm really excited that our team has a single face now. Please do pop by and take a look.

In addition, the team just completed a ton (a dozen or so) of Channel 9 videos. I've only watched the one with Vance so far, but I expect that they are all very good. If you are a propeller-head, like the rest of us, you'll likely get a kick out of these.

Now that we've shipped Beta 1 of the .NET 4, we should see quite a number of posts on .NET 4. Please do provide us with feedback on what we've built. We're very interesting in what you think.

Friday, May 29, 2009 5:45:12 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

Having installed Windows 7 RC, I decided to try Windows Virtual PC. I had heard a number of months ago that we were building a new version for Windows 7 that took advantage, actually required, hardware virtualization, but had never tried it. Anyway, I'm quite happy with the experience. I had to do some Vista --> Win7 upgrade testing over the weekend, and did a bunch of it in the new virtual PC. It was quite easy and pretty performant. It also didn't 0wn my machine (the host OS), in terms of performance. I actually kept a virtual machine of Win7 up (that I was testing) for a number of days, even through a number of sleeps (close laptop). It didn't seem to bother my laptop having the VPC up, even though I had a ton of other apps open, and I did fiddle with the Win7 VPC along the way. There just wasn't much of a motivation to close the session. Cool!

I first ran a tool to ensure that my chip (AMD or Intel) supported hardware virtualization. It takes just a few mins to run. It is a good thing to verify that you will have virtualization supported when you make your next PC/chip purchase. I certainly will. Fortunately, two of my work machines support it, and just one doesn't.

I briefly tried the XP mode. Seems to work! I can see using this for the one XP app that I have that doesn't (yet) work on Win7. Scott has a great post on how to use XP mode.

I also like how the management of the virtual machines is implemented via shell extentions (to the Windows Shell). It feels like (and is) a really light-weight experience. I've never really gotten into virtual machines before, and I think that this version will finally hook me!

Friday, May 29, 2009 5:15:04 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, October 23, 2008

20081014 028 I’m addressing the v2 question first. It is hard to know what to do in v1 if you don’t know where you want to end up when you go to build and deploy v2 (and later versions) of your product.

First, I'm going back to the three different product categories that I outlined earlier. I'm going to collapse the two different types of applications into just one category. Today's post is about applications. The next one will be about components.

Applications

For v2, you will want one of two situations:

  • my v2 application completely replaces my v1 version entirely, or
  • my v2 application installs side-by-side with v1 and the two versions do not affect or interact with one another

In most cases, I suspect that folks want the former. As an example, almost no one expects or wants to continue to use Office 2003 after installing Office 2007 on their machine. Something like TurboTax is the example that breaks that rule.

If you opt to install your application side-by-side with the older version of your application, then you might need to consider the safety of side-by-side versions of the various libraries that you depend on. The specific scenario that I’m imagining is that v2 of your application might be perfectly side-by-side with the v1 version, but the newer version of the MathLib library that you depend on might not be properly designed for a side-by-side install. Let's assume that you purchased MathLib from MathCorp, and that the versioning/servicing scheme of MathLib is different (naturally) than what you employ for the libraries that you build for your own application.

There are (at least) two obvious gotchas that I can imagine:

  • MathLib doesn’t install side-by-side, but always overwrites older library versions with newer versions, and the MathLib developers made a breaking change this release (oops!), or
  • MathLib reads mathematic constants from a file at a particular location, and the format of the file changed, but the location did not (oops!), which will break the old version

And to the other option, if you opt to replace the earlier version of your application, you don't risk breaking the earlier version of your app (since it is now gone), but you still have the risk that you might affect another app on the machine that relies on MathLib in the same ways described above.

What I’ve just described is essentially the well-known “dll hell” problem. I’d hope that most developers are familiar with this problem and have enough information to avoid it. However, it is sometimes non-obvious that you are about to walk off that cliff. This post is really intended to get folks to think a little more about that cliff.

This whole scenario assumes that MathLib is installed in some global fashion, either to the GAC, or to a global directory, such as "C:\Program Files\MathCorp\MathLib". If MathLib is installed with the application, in the application directory, then this whole problem goes away. At that point, you really are back to the monolithic application that I discussed earlier where the entirety of the application is installed and serviced uniformly, in time and location.

To be clear, I'm not trying to push developers toward private installs. There are downsides to approach that too. The meta-message is that you need to understand the potential impact of deploying your v2, and align your v2 goals around avoiding those impacts.

What's with the picture in the post? I recently purchased a digital SLR and am getting into photography as a hobby of sorts. The pic is just to add something extra to the post. I like this particular picture since there is a lot to look at visually, and because the focus is pretty narrow and well off center. It is also fun to see a child’s toy as an artifact to study.

Thursday, October 23, 2008 6:40:49 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [9]  | 
# Friday, September 26, 2008

I posted last year about the home network that I had built. It was actually a fair bit of work and somewhat expensive to get the base network and the initial set of drops setup. It also required a fair bit of thinking and up-front design to get the network structured in such a way that it would work for my up-front needs, and then would scale for new scenarios that I could imagine. It may seem like the task is really simple, and it kind of is on the face of it.

The difficulty is that you need to think through how many CAT5e/6 cables that you string between major areas of your house. For example, my cable modem and HDHR devices are in my garage (where my cable comes into the house), my gigE switch, a bunch of machines and my VOIP box are in my basement, and my wifi AP is in my attic. That may sound horribly bizarre, but each device is really in the best location for its purpose, and I needed to ensure that I had enough cable going between locations to handle the neccessary connectivity.

That also doesn't count that I am running voice (voice originating from my VOIP box) throughout the house over some of these lines, which means that I have to add another line for analog voice between the major areas of house beyond what I need for the IP network.

My point in this post is that after nearly a year, I decided to add three more drops on the top floor of the house. Other than the requirement to crawl into the corners of my attic for one of the drops, it was really, really easy to tie into the base network that I'd setup months ago. It was very clear what I needed to do to tie into the network, and it all worked the first time.

In addition, I decided to hook up all three of the new drops for data for now, but it will take me just a few mins to 'downgrade' one of them to voice should I want to. It is really nice to have that degree of freedom w/o having to re-wire or otherwise re-do any of the work that I've done. 

Friday, September 26, 2008 10:48:51 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 

Lately, I’ve been thinking about the overall .NET deployment and servicing story. There are a number of aspects of deployment that one can consider. The particular issues that are salient for your product depend a lot on the kind of code you deploy onto end-user machines.

First, let’s look at the different kinds of products that developers might build, and need to deploy:

-          Monolithic applications

o   A single exe that is not dependent on any libraries, other than the .NET Framework itself, or

o   Solely dependent on libraries that are serviced/upgraded with the application

-          Aggregate applications

o   Dependent (at least partially) on libraries (or controls or components) that are installed/serviced/upgraded separately (in ‘time’ and/or ‘location’) from the application

o   These libraries are likely sourced from a 3rd party

-          Components, controls or class libraries

o   You build assemblies that other developers reference in their applications (both ‘Monolithic’ and ‘Aggregate’ applications as described above) or other libraries

While we’re thinking broadly, one is left wondering what the critical questions are to think about for each of the deployment cases above. There are a lot of questions that one can imagine looking into. They range from .NET Framework and application deployment, to servicing multiple versions of your applications out in the wild, to safely deploying a new version of your API (class libraries) onto end-user machines w/o any adverse impact.

The first one that I’d like to look at is: “Am I building my product correctly for the future?” This question, though, really boils down into two important questions:

-          What do I need to think about when shipping v1 of my product?

-          What do I need to do to safely, correctly and seamlessly ship v2 of my product?

Those questions seem very simple, and they are on the surface. The answers are not overly complicated, but do require some up-front thought to ensure that you end up where you want to.

We have had folks come to us after a successful v1, not quite sure what to do for v2. You may be wondering what the crux of this is … you just hit ‘go’ on csc/vbc another time and you’re done, right? Maybe. It all depends on how you want your code to behave when you ship your second version.

Note that I call out v2 specifically (and not v3 and v4) since v2 is the first version after your initial one, and will be the time when you need to address any issues that come up with shipping again. Once you’ve got a plan in place, you’ll be able to rinse and repeat for each subsequent version (provided that you have a good plan).

In my next posts, I’ll answer this question for each of the product types listed at the top of the post.

Friday, September 26, 2008 5:57:56 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, December 04, 2007

I finally decided that it was time to get a real network setup in my house. I had some one-off network segments around the house for particular purposes, but not a real whole-house network w/a set of primary interconnect points, in addition to CAT5e drops around the house.

This project really started this summer when we had the house painted. I ripped off (imagine a violent action) all the coax and phone cords off the side of the house prior to the painting, both to ensure that the paint got under the wires, and to remove them permanently. I bought an HDHR at the same time to enable a new cable connection to my TV, over one of the network segments that I mentioned earlier. That worked out nicely. Still, I wanted to be able to use my HDHR on any PC in the house, and that's kinda difficult to reliably over 'g' wireless. Others may argue the fact, but try viewing HD content, and you'll see that 'g' falls on its face for that application, particularly if you have multiple streams going at once. I could have gone 'n' and will, but I really wanted to get a gigE network up and running, since it is fast and reliable.

I also should note that my existing phone network had already proven to be pretty bad. So, I already had an existing need to fix that.

Off to Home Depot, which is pretty much the answer to all issues relating to the home. Come back with 1000ft of riser CAT5e, 50 RJ45 connectors, a Ideal crimper and and Ideal LinkMaster CAT5 line tester. I also bought 8 large pieces of drywall, wood, some insulation and a whole ton of other odds and sods, but that is indeed another project.

I'm finding that cutting (to length) and crimping CAT5 is something of a challenge. It is conceptually simple, but I appear to be still mastering this task. I've made a bunch of mistakes, such as not following a wiring standard at first (even though I've used them before for my earlier network segments), mistaking the pin order of the connectors, and then incorrectly ordering the pins once I'd chosen T568A as the standard to use. The test tool is kinda neat since it tells you exactly where and how you've messed up. This is pretty useful if you've got a 50ft segment from your basement to your attic that isn't able to create a connection.

When I'm done, I'll have both a new phone network (over CAT5) and data network. The phone network actually only uses 1/4 of a CAT5 line, but that's OK. The 'backbone' is two CAT5 (one data, one phone) lines and one additional CAT5 line that I may need later for some unknown reason. Every drop (phone or data) connects to this backbone at one of three interconnect points (garage, attic and wiring closet in the basement). This allows me to easily add machines, NAS, APs and pretty much any other kinda IP appliance (like the HDHR) at any point in the network.

My neighbor, who is in his 70s, keeps making references to me being able to "run Microsoft on this network". It is pretty funny to hear that viewpoint. I'm sure that there is more XBox Live traffic during the day on the internal MSFT network than my wee network would ever be able to handle, except maybe on Christmas day ;)

Tuesday, December 04, 2007 7:20:53 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, September 11, 2007

More Silverlight exploration.

 

I want to create a user control that has the concept of children that I can add (this.Children.Add()). I see that Panel adds this concept, but that Control is missing it. At the same time, Control provides the InitializeFromXaml helper, which seems to be pretty integral to user controls. Panel and Control are completely disjoint (in terms of inheritance chain), so you cannot nicely merge these two.

 

What are folks expected to do in this situation? Good question. The team is aware of this, and working on a solution. In the meantime, you (and me) will will need to do some hacking to get the control children outcome.

Tuesday, September 11, 2007 10:01:58 PM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  |