How do I get the computer’s serial number? Consuming Windows Runtime classes in desktop apps, part 4: C#


Continuing our series on getting the computer's serial number in desktop apps in various languages, we look at C#.

From Visual Studio, create a new C# Console Application that goes like this:

class Program
{
  static public void Main()
  {
    var serialNumber = Windows.System.Profile.SystemManufacturers.
                       SmbiosInformation.SerialNumber;
    System.Console.WriteLine($"Serial number = {serialNumber}");
  }
}

Before building, you'll have to prepare the project, and the preparation is particularly ugly.

  • Close the solution in Visual Studio and open the *.csproj file in a text editor.

  • Add

        <TargetPlatformVersion>8.0</TargetPlatformVersion>
    

    to the main PropertyGroup. This requirement is obscurely documented on MSDN. Scott Hanselman tipped me off.

  • Reopen the project, right click the References node and select Add Reference.

  • The magic XML you added to the *.csproj enables a new node in the dialog box called Windows. Expand it, click on Core, and then check Windows.System because we are using Windows.System.BlahBlah. In general, check each second-level namespace your program uses.

Adding a reference from Core will access the information from your development machine, so it assumes that your development machine is running the same or greater version of Windows than your target. If you are doing cross-targeting, then instead of referencing the Windows.Blah namespaces under Core, go to the Browse option and browse to C:\Program Files (x86)\Windows Kits\10\References\CONTRACT\VERSION\CONTRACT.winmd.

In our case, Windows.System.Profile.SystemManufacturers.SmbiosInformation is in the Windows.System.Profile.System­Manufacturers.System­Manufacturers­Contract contract. I got this information from the documentation for the Smbios­Information class: Look under API contract.

That documentation also says that the Smbios­Information class was introduced in v1, so the minimum version I need is 1.0.0.0. The full path is therefore

C:\Program Files (x86)\
  Windows Kits\
    10\
      References\
        Windows.System.Profile.SystemManufacturers.SystemManufacturersContract\
          1.0.0.0\
            Windows.System.Profile.SystemManufacturers.SystemManufacturersContract.winmd

Repeat for each contract your program requires. Most classes are in the Windows.Foundation.Universal­Api­Contract contract.

The last bit is another obscure piece of information on MSDN: Adding a reference to System.Runtime. If you use a Windows Runtime class that projects as an IDictionary or some other fancy type, then you will get the error message "The type 'IDictionary`2' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'." But when you go to the Add Reference dialog, you won't see it! It's telling me to add a reference to an assembly that doesn't exist!

That's because it's hidden away somewhere that Visual Studio doesn't show you. Go to the Browse tab, click the Browse button, and then go to %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework.NETFramework\v4.5\Facades\System.Runtime.dll, substituting the version of the .NET Framework that applies to your project.

Okay, now that you got all the references set up, you can build and run the program.

It takes some work to set up, but personally I find C# to be the most convenient way of consuming Windows Runtime classes.

Next up is PowerShell. Just warning you ahead of time: You're going to be underwhelmed.

Comments (8)
  1. xcomcmdr says:

    Why is it so ugly ? Will the VS GUI be updated so it can become more discoverable ?

    1. Florian S. says:

      I guess you are not really supposed to consume those APIs from “traditional” Windows application, UWP is preferred, that’s why it is kind of a hidden feature.

      1. Someone says:

        In which way is a C# application not an UWP app? Does MS really expect C# to go away? That will fail just the same as Windows 8 & Windows Phone.

        1. Wear says:

          A C# application is not a UWP app if it’s not a UWP app?

          I suspect they are less worried about .NET developers switching to UWP since there’s less of a change. So while C++ folks get stepping stones to entice them into UWP C# folks are expected to just jump in. There’s the option to mix the two worlds if you want to but it’s not the main path they expect people to go down so there’s no great push to polish it up.

          1. Someone says:

            If so many years after introducation of the Windows store, C# as *the* Number 1 language for Windows apps still has not real easy-to-use connection to this UWP thing, MS can just scrap UWP entirely. It makes development complicated beyond believe, for no positive result, not for the developer and not for the user.
            .Net programs need to be “UWP” by the existing .Net framework. Anything else will just fail.

        2. I don’t quite understand the question. C# is a language. You can write a UWP app in that language (for which Visual Studio has some templates pre-made for you). Or you can write a desktop app in that language (for which Visual Studio also has templates pre-made for you). The UWP C# template is all ready to consume Windows Runtime classes. The desktop C# templates are not.

    2. Voo says:

      The people who want to use an exceedingly rare scenario are expected to do a bit of legwork themselves. This really shouldn’t come as a surprise, the same is true for almost everything.

      If you want a really easy to use way to invoke winrt then use c# in a UWP app, it’ll go just out of the box there.

  2. CMDBob says:

    I just looked up the Powershell version myself, and it’s exactly as underwhelming as you said. It’s literally one line of code underwhelming. The C# solution preparation seems a bit obtuse, hopefully (in VS2018 or whatever) it’ll be made simpler.

    One quick question, more just to make sure I understand something; the System.Runtime facade DLL “redirects” (for lack of a better term that I can think of right now) the object that the Windows Runtime uses back to the ones in the core .net framework? So instead of going “oh, I don’t have IDictionary right now” it goes “it’s located in the core framework, use that version”?

Comments are closed.

Skip to main content