Post

Leveraging Windows Vista's Windows System Assessment Tool (WinSAT) API in Visual Basic

Introduction

There are a lot of new features in Windows Vista. In this installment, we’ll explore the WinSAT (Windows System Assessment Tool) API. (The Windows Experience Index in the Vista UI is part of WinSAT.) The Vista SDK defines it as:

Windows System Assessment Tool (WinSAT) assesses the performance characteristics and capabilities of a computer. Developers can use this API to develop software that can access the performance and capability information of the computer to determine the optimal application settings based on that computer’s performance capabilities.

The capabilities also indicate what scenarios and applications will perform well on the computer. For example, if a software package contains a rating on its packaging, a user can use the rating on the software package and the computer’s capability rating to determine if the package will run well on the computer.

Here is a sample screen shot of this functionality exposed to the end user.

WinSAT 1

The numeric scores represent an overall performance characteristic for each system “component” in the machine. It’s import to understand that this value is artificially capped at 5.9 and does not necessarily mean raw performance, at least not totally; meaning that there are many factors that are considered for each component when determining the final number including “performance” characteristics. Breakdowns of what the numbers actually mean are as follows:

Base ScoreApplications & ScenariosDesktop & Laptop Types
1.0

Basic performance.

Productivity applications, IM, web, email, simple games like Solitaire, educational games.

Minimal specifications needed to run Windows Vista.

Types: Entry level PCs and laptops. Ultra small laptops.

2.0

Improved responsiveness.

Same applications as level 1.

PCs will run Windows Vista but in most cases will not be Aero capable.

Types: Lower end of mid-market desktops. Many slim & light laptops.

3.0Aero graphics, Media Center with standard definition TV, basic graphical games, basic performance while running high-end graphical games.

Minimum specification needed to run Windows Vista Premium features, including the new Aero user interface.

Types: Value end market desktops. Slim & light laptops + desktop replacement laptops.

4.0Snappy performance, high definition video, high resolution monitors, dual monitors.

Very good performing PCs.

Types: Desktop replacement laptops. High end desktops.

5.0Fast moving games with amazingly rich graphics, 3D modeling, high end multimedia and high performance applications.

Top end of the PC market.

Types: Top end desktops and laptops.

Microsoft plans on increasing this number over time (every 12-18 months) to include hardware performance and characteristics as new hardware is released.

Why is this important? Well, it enables several scenarios for the consumer, business management and to us, the developer such as:

  • When purchasing a new machine, you could use these numbers to determine if the extra $500 is worth it by comparing a “high-end” machine with another more “generic” machine.
  • As an end user, you could use these numbers to determine the bottlenecks in your existing machine and possible ways to improve performance through simple upgrades.
  • Packaged software could use these numbers (in addition to their other “minimum requirements”) to give you an idea of whether or not your machine was capable of running said software.
  • As a developer, you could dynamically adjust the characteristics of the software based on these numbers. If, for example, they had a low gaming graphics score, you could restrict 3D functionality and instead display a 2D counterpart.
  • As a support person, you could use these numbers to diagnose why someone is experiencing poor performance.

As a developer (and to some degree a consumer), it’s important to understand what these numbers mean. There is an excellent entry by Nick White on the Windows Vista Team Blog titled “Windows Experience Index: An In-Depth Look”. (The following is an overview of how the numbers are calculated. To read about how each component is calculated in depth, be sure go there and read the full entry.)

The following are detailed descriptions of each of the base score levels:

1.0

A base score of 1.0 is intended to reflect the minimum specification needed to run Windows Vista™. PCs that meet this level will run Windows Vista™ in a basic, but acceptable manner. This is a “catch all” level assigned to any machine that can realistically upgrade to Windows Vista™ but won’t meet Level 2 specifications.

2.0

A base score of 2.0 represents the mainstream Windows Vista upgrade target system. This level of PC may run Windows Aero but users may see noticeable performance issues from time to time, especially on PCs with scores less than 2.5 and/or 64MB of graphics memory. Performance issues may also be noticeable when opening many application windows at the same time or when using very large monitors.

3.0

This level represents the value end of machines that will ship at the end of 2006 and into 2007. This is the lowest capability Windows Premium Logo PC that will ship with Windows Vista™ pre-installed. Windows Vista will generally enable Aero automatically on level 3 machines. Aero will perform quite well on level 3 machines with single monitors. With dual monitors (especially larger than 1280x1024), users may see noticeable performance issues from time to time, especially on machines with scores less than 3.5 and/or 128MB of graphics memory.

4.0

This level of machine represents a very good performing machine. In late 2006 and 2007 machines at this level will be considered high end. All Windows Vista features will run well with snappy performance. HD playback and recording of one HD stream will work well. 3D games and other high-end 3D applications will run acceptably on Level 4 machines. Multi-tasking will be quite good on these machines (when an application makes use of this capability). Many mid to high level 4 PCs will have dual core CPUs.

5.0

This level of machine represents the highest end of the PC market - gaming machines, high performance desktops, powerful media center systems and the like. Level 5 PCs will dramatically exceed the Windows Premium logo requirements. They will easily run Aero-Glass on multi-monitor systems at high resolution. First person shooters, multiple HD streams, video creation, high end multimedia applications are all characteristic scenarios of people who will be using Level 5 systems. As Level 6 machines are not defined yet, it is possible that the highest performance and capable Level 5 machines may be re-leveled as level 6 in the future (i.e. that may happen if the new hardware is evaluated before the index is updated with the new capabilities).

6.0 and beyond

Base scores of 6.0 and higher are not defined yet. They will be defined when the time comes and new innovations in hardware allow new capabilities. From past experience, it is expected this will happen at a rate of once every 12-18 months.

Accessing information programatically

So now that we have an understanding of what the numbers mean and how they are calculated, it’s possible that we could use this information to modify the behavior of our application.

First you need to know where to find the WinSAT API. It is located in the %windir%\system32 folder and is contained in the WinSATAPI.dll as a COM library. Documentation is available in the Windows SDK and online on MSDN. For now, we will limit our focus on the following interfaces:

  • IProvideWinSATResultsInfo - Retrieves information regarding the WinSAT assessment (the Windows Experience Index) such as the assessment state, assessment date and time, a friendly description and the base score. Using the GetAssessmentInfo, detailed information can be obtained, represented as an IProvideWinSATAssessmentInfo interface.
  • IProvideWinSATAssessmentInfo - Retrieves information such as description, score and title about an individual component assessment (e.g. CPU, memory, graphics, gaming and disk).
  • IProvideWinSATVisuals - Used to retrieve a Vista generated bitmap that represents a score graphically, as shown below. This is the same mechanism used in the Vista UI and you can leverage it to display the same information in your application in a consistent manner as will be done through software packaging, downloads, etc.

Launch Visual Studio 2005 and to create a Windows Application in VB, named WinSAT. Next we need to add a reference to the WinSAT COM library.

To add a reference, access the projects properties and select the “References” tab. Click the “Add” button which will display the “Add reference” dialog. At this point you can either use the “COM” or “Browse” tab to find the library to add. Using the “COM” tab, search through the list for the “Winsat 1.0 Type Library”, select it and press the “OK” button. Using the “Browse” tab, browse to the %windir%\system32\WinSATAPI.dll file accordingly.

Once you have the library added to your list of “References”, you can press the “X” button to close the project properties.

Open the code view for Form1.vb. Add the following two lines to the very top (outside of the Class):

1
2
3
4
5
Imports WINSATLib
Imports WINSATLib.WINSAT_ASSESSMENT_STATE
Imports WinSATLib.WINSAT_ASSESSMENT_TYPE
Imports WINSATLib.WINSAT_BITMAP_SIZE
Imports System.Runtime.InteropServices

The first four lines import the WinSAT library and enumerators to save us a bit of typing. The last line will be utilized when we interact with the library to pull the Vista generated graphic representing the base score.

At this point, you now have access to the WinSAT information in your Windows Application. Let’s just try something really simple. In the Form_Load event, add the following code:

1
2
3
4
Dim winSat As New CQueryWinSATClass()
MsgBox(winSat.Info.RatingStateDesc & vbCrLf & _
       winSat.Info.AssessmentDateTime.ToString & vbCrLf & _
       winSat.Info.SystemRating)

At this point, you can run the application and a message box will be displayed that looks like the following:

WinSAT 2

As you can see, it’s very simple to get the overall “base score” and when this score was determined. Now remember the base score (of which this method returns) represents the lowest score across all the components (with a variance allowance of .1) so if you wanted to adjust your software based on one of the individual component scores, we’d have to delve a little deeper. Let’s say that you wanted to adjust some drawing functionality based on the graphics score. Replace the code in the Form_Load event with the following:

1
2
3
4
5
6
Dim winSat As New CQueryWinSATClass()
Dim info As IProvideWinSATAssessmentInfo = _
  winSat.Info.GetAssessmentInfo(WINSAT_ASSESSMENT_GRAPHICS)
MsgBox(info.Title & vbCrLf & _
       info.Description & vbCrLf & _
       info.Score)

Execute the project and you should now see a message box similar to the following:

WinSAT 3

At this point, you can see that the score for my graphics card is a 5.9 and I have an NVIDIA GeForce 7800 GT utilizing the WDDM drivers from Microsoft Corporation. As you can see, it’s pretty simple to get the individual scores. Using the scores, you can modify your application to respond accordingly based on the end users machine characteristics.

Now let’s say that you’d like to display the Vista generated image that represents the base score to the end user in your applications “About” dialog. To do so, add a new item to your project (right click on the project and use the “Add->New item” context menu item). From the “Add new item” dialog, select the “About Box” item and press OK. You should now have an AboutBox1.vb file added to your project and Visual Studio 2005 has opened Windows Forms designer automatically upon adding the file. For simplicity sake, we’ll just be replacing the included graphic with the Vista generated base score image. Open the code view for AboutBox1.vb. Add the imports statements we added to Form1 to this file and in the Form_Load event, add the following code after all of the other code already included:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
' Get bitmap with assessment rating figure in WinSAT style.
Dim winSat As New CQueryWinSATClass()

' To hold the "real" Hbitmap value (Integer).
Dim bitmapPointerBuffer(3) As Byte
' Pin the buffer for interop usage.
Dim handle As GCHandle = GCHandle.Alloc(bitmapPointerBuffer, GCHandleType.Pinned)
' Retrieve the pointer to the pinned location.
Dim bitmapPointerPointer As IntPtr = handle.AddrOfPinnedObject()
' Create an instance of the class that will provide the image.
Dim v As New CProvideWinSATVisualsClass()
' Call the method to retrieve the pointer to the graphic.
v.get_Bitmap(WINSAT_BITMAP_SIZE_NORMAL, _
             winSat.Info.AssessmentState, _
             winSat.Info.SystemRating, _
             bitmapPointerPointer)
' Release the buffer from being "pinned".
handle.Free()

' Check to make sure that we actually have a value in the buffer.
If BitConverter.ToInt32(bitmapPointerBuffer, 0) <> 0 Then

  ' Convert the buffers value to an IntPtr and use it to get an 
  ' image from the Hbitmap (IntPtr).
  Dim bmp As Bitmap = Bitmap.FromHbitmap(_
    New IntPtr(BitConverter.ToInt32(bitmapPointerBuffer, 0)))

  ' Modify the default behavior of the AboutBox's LogoPictureBox 
  ' from StretchImage to Normal.
  LogoPictureBox.SizeMode = PictureBoxSizeMode.Normal

  ' Set the LogoPictureBox image to the Vista generated base score image.
  LogoPictureBox.Image = bmp

End If

In order to get the about box to show, replace the code in Form1.vb for the Form_Load event with the following code:

1
AboutBox1.ShowDialog()

Execute the application and you’ll see that the about box now looks similar to the following:

WinSAT 4

Let’s delve into the work that was necessary to retrieve the generated image. Obviously this COM library was designed to be utilized by Windows Vista. As such, it was not necessarily designed to be used from your application or from .NET directly (and I am a little disappointed since the party line I’ve been hearing has been “all new API’s would be .NET friendly”).

As such, we have to do a little work to get this information. If we were using C++, it’s a simple matter of dealing with pointers. If we were using C#, we could utilize “unsafe” code to, again, deal with pointers. (Personally, I think the utilization of “unsafe” if there is an alternative is a bad idea, but that is a personal opinion so digest accordingly.) So how do we pull off the same functionality in this case without the use of “pointers”? Well, a pointer is simply an address to a memory location that contains the information we are looking for. .NET does contain such a construct to hold these and it’s called System.IntPtr. However, we can’t just simply pass an IntPtr to the method since it’s actually a pointer to a pointer. So, what we need to do is pass to the method a pointer to a block of memory that we can then use to pull the written pointer that ultimately points to the dynamically generated image.

This is where we take advantage of some of the Interop features with a little help from the garbage collector. We first create a four byte buffer to hold a signed integer value (the real pointer to the generated image). This buffer is then “pinned” using the garbage collector classes. By pinning the buffer, it will tell the garbage collector not to move it around during GC compaction. We can then get the address to this location using the AddrOfPinnedObject. This will act as our pointer to the pointer in the get_Bitmap call.

At this point we can now utilize the CProvideWinSATVisualsClass to get the generated image (get_Bitmap). We will pass in the address of the pinned object (bitmapPointerPointer in this case). Upon completion, the buffer that bitmapPointerPointer points to should contain an address pointing to the actual generated image. Now that the method has completed, we can “un-pin” the address so GC can do its normal job with the variable. This is done by using the .Free() method on the handle we created during the creation of the pinned object.

We can now utilize the BitConverter class to interrogate the buffer to see if it is a value that is greater or less than 0. (If it is 0, we didn’t get and address for some reason). Using this, we can then convert the contained four bytes to an IntPtr that can in turn be utilized by the Bitmap class to “convert” the bitmap to a BCL compatible one. This is done using the Bitmap.FromHbitmap method.

Now that you have a BCL compatible bitmap, you can do anything you could do normally as such. In this case we are just setting the Image property to the bitmap so it will be displayed on the form.

Up to this point, we’ve covered the basics of gathering the information and how to retrieve the Vista generated image. All of this was making the assumption that the WinSAT state was where it should be in order to gather the information. You should check the current state accordingly before calling any of the methods to verify that the numbers are indeed meaningful. This can be done simply by wrapping the code (after the initial declare statement for CQueryWinSATClass) with the following:

1
2
3
If winSat.Info.AssessmentState = WINSAT_ASSESSMENT_STATE_VALID OrElse _
  winSat.Info.AssessmentState = WINSAT_ASSESSMENT_STATE_INCOHERENT_WITH_HARDWARE Then
End If

The various states are contained within the WINSAT_ASSESSMENT_STATE enumeration and are defined as:

  • WINSAT_ASSESSMENT_STATE_MIN - Minimum enumeration value for this enumeration.
  • WINSAT_ASSESSMENT_STATE_UNKNOWN - The current state of the assessment is unknown.
  • WINSAT_ASSESSMENT_STATE_VALID - The current assessment data is valid for the current computer configuration.
  • WINSAT_ASSESSMENT_STATE_INCOHERENT_WITH_HARDWARE - The hardware has changed configuration since the last time a formal assessment was run but the data is still present and should be displayed.
  • WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE - No data is available because a formal WinSAT assessment has not been run on this computer.
  • WINSAT_ASSESSMENT_STATE_INVALID - The assessment data is not valid.
  • WINSAT_ASSESSMENT_STATE_MAX - Minimum enumeration value for this enumeration.

In our case, we are only interested in the VALID and INCOHERENT_WITH_HARDWARE states. All others, we assume that something is wrong and handle accordingly.

Taking it a step further

Now that we’ve run through the basics of access the information, let’s do something a little more interesting. We are going to build a “clone” of the Windows Experience Index display that is in Windows Vista. All the steps to create will be done in an overview fashion, so please download the sample to follow along.

So going back to our project we’ve created up to this point, we are going to remove the code contained within the Form_Load event. We’ll come back to this in a few moments.

Opening the Form1.vb file in the Windows Forms designer, we are going to make the form a little bit larger (566 by 265). We are going to add the following components:

  • Label that contains the text "Your computer has a Windows Experience Index base score of". (Name: IndexLabel, Location: 9, 13)
  • PictureBox that is sized to 30 x 24 pixels and has the SizeMode set to StretchImage. (Name: IndexPictureBox, Location: 315, 7)
  • Panel with its size set to 525 x 3 and the BackColor set to LightGray. (Name: BorderPanel1, Location: 525, 3)
  • Label that contains the text "Component" and the font modified to Bold. (Name: ComponentLabel, Location: 12, 53)
  • Label that contains the text "What is rated". (Name: WhatIsRatedLabel, Location: 148, 53)
  • Label that contains the text "Subscore". (Name: SubscoreLabel, Location: 362, 53)
  • Label that contains the text "Base score". (Name: BaseScoreHeaderLabel, Location: 437, 53)
  • Panel with its size set to 525 x 2 and the BackColor set to LightGray. (Name: BorderPanel2, Location: 12, 74)
  • Add five Panel controls with their size set to 408 x 23. (Name: ProcessorPanel, Location: 12, 76, MemoryPanel, Location: 12, 101, GraphicsPanel, Location: 12, 126, GamingPanel, Location: 12, 151 and HardDiskPanel, Location: 12, 176)
  • To each of the panels, add three Label controls. These will be organized into three columns across the five panels. The first column in each panel will have the label control modified to have the text bold. The third column will have the TextAlign modified to MiddleCenter, the height set to 21, the width set to 26 and top set to 0. The tops of the first two columns are set to 4 and the column offsets are 3, 136 and 380 accordingly. The names for each one follow a similar pattern. For example, the first row contains ProcessorNameLabel, ProcessorDescriptionLabel and ProcessorLabel. The other rows are similar and follow suite based on the Panel name they are contained within. The text for the first two columns matches the Windows Experience Index dialog, leaving the third column blank.
  • Panel with its size set to 118 x 123 and the BackColor set to Lavender. (Name: BaseScorePanel, Location: 420, 75)
  • To the BaseScorePanel, add a PictureBox control sized to 80, 80. (Name: BaseScorePictureBox, Location: 18, 6)
  • To the BaseScorePanel, add a Label. Set the AutoSize mode to False and size the label to 86, 32. (Name: BaseScoreLabel, Location: 17, 89)
  • Panel with its size set to 525 x 2 and the BackColor set to LightGray. (Name: BorderPanel3, Location: 12, 196)
  • Label that contains no text. Modify the AutoSize mode to false, the TextAlign to RightCenter, ForeColor to MenuHighlight and size to 409, 14. (Name: DateLabel, Location: 129, 204)

Now we are ready to add the code. In the Form_Load event, add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
Try

  ' Provides access to assessment state.
  Dim winSat As New CQueryWinSATClass()

  ' Check for valid state.
  If winSat.Info.AssessmentState = WINSAT_ASSESSMENT_STATE_VALID OrElse _
     winSat.Info.AssessmentState = WINSAT_ASSESSMENT_STATE_INCOHERENT_WITH_HARDWARE Then

    ' General rating information.
      DateLabel.Text = String.Format("{0} on {1}", winSat.Info.RatingStateDesc, winSat.Info.AssessmentDateTime)

    ' Get ratings for individual assessment types.

    For Each type As WINSAT_ASSESSMENT_TYPE In _
      [Enum].GetValues(GetType(WINSAT_ASSESSMENT_TYPE))
      Dim info As IProvideWinSATAssessmentInfo = winSat.Info.GetAssessmentInfo(type)
      Select Case type
        Case WINSAT_ASSESSMENT_CPU
          ProcessorLabel.Text = info.Score.ToString
          If info.Score = winSat.Info.SystemRating Then
            ProcessorLabel.BackColor = Color.Lavender
          End If
        Case WINSAT_ASSESSMENT_MEMORY
          MemoryLabel.Text = info.Score.ToString
          If info.Score = winSat.Info.SystemRating Then
            MemoryLabel.BackColor = Color.Lavender
          End If
        Case WINSAT_ASSESSMENT_GRAPHICS
          GraphicsLabel.Text = info.Score.ToString
          If info.Score = winSat.Info.SystemRating Then
            GraphicsLabel.BackColor = Color.Lavender
          End If
        Case WINSAT_ASSESSMENT_D3D
          GamingLabel.Text = info.Score.ToString
          If info.Score = winSat.Info.SystemRating Then
            GamingLabel.BackColor = Color.Lavender
          End If
        Case WINSAT_ASSESSMENT_DISK
          HardDiskLabel.Text = info.Score.ToString
          If info.Score = winSat.Info.SystemRating Then
            HardDiskLabel.BackColor = Color.Lavender
          End If
        Case Else
          Throw New InvalidOperationException("Unknown WinSAT Assessment Type")
      End Select
    Next

    ' Overall system base score.
    Me.Text = "WinSAT - Base score: " & winSat.Info.SystemRating

    ' Get bitmap with assessment rating figure in WinSAT style.

    ' To hold the "real" Hbitmap value (Integer).
    Dim bitmapPointerBuffer(3) As Byte
    ' Pin the buffer for interop usage.
    Dim handle As GCHandle = GCHandle.Alloc(bitmapPointerBuffer, GCHandleType.Pinned)
    ' Retrieve the pointer to the pinned location.
    Dim bitmapPointerPointer As IntPtr = handle.AddrOfPinnedObject()
    ' Create an instance of the class that will provide the image.
    Dim v As New CProvideWinSATVisualsClass() 
    v.get_Bitmap(WINSAT_BITMAP_SIZE_NORMAL, _
                 winSat.Info.AssessmentState, _
                 winSat.Info.SystemRating, _
                 bitmapPointerPointer)
    ' Release the buffer from being "pinned".
    handle.Free()

    ' Check to make sure that we actually have a value in the buffer.
    If BitConverter.ToInt32(bitmapPointerBuffer, 0) <> 0 Then

      ' Convert the buffers value to an IntPtr and use it to 
      ' get an image from the Hbitmap (IntPtr).
      Dim bmp As Bitmap = Bitmap.FromHbitmap( _
        New IntPtr(BitConverter.ToInt32(bitmapPointerBuffer, 0)))

      ' Turn the white into transparent.
      bmp.MakeTransparent(Color.White)

      ' Small image on white background.
      IndexPictureBox.Image = bmp

      ' Larger image on Lavendar background.
      BaseScorePictureBox.Image = bmp

    End If

  Else

    DateLabel.Text = "Error: Unexpected state."

  End If

Catch ex As System.Runtime.InteropServices.COMException

  DateLabel.Text = "Error: " & ex.ToString

End Try

We can now execute the application to make sure everything is working as expected. I’ve commented the code, so I’m not going to go into too much detail as to what is going on except to say that we are utilizing the same techniques in order to display the information on the screen that we did at the beginning of the article. In addition, if / when the application is executed previous to Windows Vista machine, we handle the COM exception that will be generated (since the library doesn’t actually exist on pre-Vista machines).

You will notice though that the display doesn’t completely look like the Vista counterpart we are cloning. The Vista version has the component panels set as a gradient background. To handle this, modify all of the labels contained on the five panels so they are their background color is set to transparent. Now add the following code to the Form1 class to handle the Paint event for the panels.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Private Sub GradientPanel_Paint(ByVal sender As System.Object, _
                                ByVal e As System.Windows.Forms.PaintEventArgs) _
  Handles ProcessorPanel.Paint, _
          MemoryPanel.Paint, _
          GraphicsPanel.Paint, _
          GamingPanel.Paint, _
          HardDrivePanel.Paint

  If TypeOf sender Is Control Then 

    Dim rect As New Rectangle(0, 0, DirectCast(sender, Control).Width, DirectCast(sender, Control).Height)

    Using b As New Drawing2D.LinearGradientBrush(rect, _
                                                 Color.Lavender, _
                                                 Color.White, _
                                                 Drawing2D.LinearGradientMode.Horizontal)
      e.Graphics.FillRectangle(b, rect)
    End Using

  End If

End Sub

The above code will simply determine the panel being handled and create a linear gradient brush to fill the rectangle with. Since we set the labels contained on the panel to transparent backgrounds, it will be automatically handled by the WinForms engine in .NET 2.0 to “copy” the containers background that it overlaps as the background for the label before drawing the text. Now when you execute the application, you should end up with something that looks similar to the following:

WinSAT 5

Summary

And there you go. You’re now been able to retrieve the performance characteristics of a Windows Vista machine to use however you see fit. Along the way you’ve explored how to do a little bit of Interop and custom drawing to spruce up your application.

As always, if you have any questions, please feel free to send them my direction.

You can download the code from here.

Further Reading

This article was initially inspired by one written by Bart De Smet, Windows Vista - Exploring The Windows System Assessment Tool (WINSAT) API In C#. So if you’re interested in a how do to this using C# (or simply a different perspective), please feel free to bounce over to his article for a look see.

You can also view the complete WinSAT SDK reference online by browsing to the MSDN website under the MSDN Library -> Win32 and COM Development -> Security -> Windows System Assessment -> WinSAT Reference.

To read more about how the numbers are actually calculated and what they ultimately mean, be sure to read Nick White’s “Windows Experience Index: An In-Depth Look”.

UPDATE: Modified the gradient drawing to be a little cleaner and defensive. (Thanks to Michael for pointing out the obvious and setting me straight.)

UPDATE: Something was bothering me after I posted the article but wasn’t sure it was really necessary. Since I had to make changes anyway, I modified the source code to handle releasing the COM references as described here.

This post is licensed under CC BY 4.0 by the author.