Using Sensors in You Application – Managed Part 1

So far we covered the Windows 7 Sensor and Location Platform architecture (I Can Feel You – Using the Windows 7 Sensor Platform), and Using Sensors in Your Application – Native Part 1. This post introduces the managed API for using sensors. In future posts I’ll continue with the native API.

So far, you have seen C++ and COM examples of the Sensor and Location platform. Now let’s take a look at how managed code developers can use the platform, using the Windows API Code Pack for the .NET Framework, to discover and work with sensors.

Discovering Sensors Using Managed Code

Follow the same guidelines in managed code as you would in native code: first discover sensors, next check their state and request permissions if needed, and then read data from the sensor. Let’s start by discovering sensors.

The main namespace for sensors in the Windows API Code Pack is Microsoft.WindowsAPICodePack.Sensors as implemented in the Microsoft.WindowsAPICodePack.Sensors.dll assembly. This namespace contains the SensorManager class that manages the sensor devices that are connected to the PC. This class exposes a set of methods that are similar to those of the native ISensorManager interface. These methods include GetSensorsByCategoryId, GetSensorsByTypeId, and GetSensorsBySensorId, the last of which receives as an input parameter a GUID that either represents a sensor category, type, or single sensor ID. In addition, you can also find the GetAllSensors method, which returns all the sensors that are connected to the system regardless of type or category, as shown by the following code snippet.

private void PrintAllSensors()
{
    SensorList<Sensor> sensorList =  SensorManager.GetAllSensors();
    foreach (var sensor in sensorList)
    {
        StringBuilder sb = new  StringBuilder();
        sb.Append("Sensor Information:");
        sb.Append(Environment.NewLine);
        sb.Append(sensor.FriendlyName);
        sb.Append(Environment.NewLine);
        sb.Append(sensor.CategoryId);
        sb.Append(Environment.NewLine);
        sb.Append(sensor.State);
        sb.Append(Environment.NewLine);
 
        Console.WriteLine(sb.ToString());
    }
}

Running the above code snippet on my local dev machine yields the following output, showing the sensors installed on my local machine. Note that only the virtual light is Ready and the rest are showing AccessDenied indicating that they are not enabled.

Sensor Information:
Legacy GPS Driver
bfa794e4-f964-4fdb-90f6-51056bfe4b44
AccessDenied
 
Sensor Information:
Skyhook Wireless XPS Location Sensor
bfa794e4-f964-4fdb-90f6-51056bfe4b44
AccessDenied
 
Sensor Information:
Ambient Light Sensor
17a665c0-9063-4216-b202-5c7a255e18ce
Ready

 

Since the Windows API Code Pack includes the strongly typed sensor class Sensor, it is easy to get a list of sensors and print their various properties. The native API has a Sensor interface through which you work with sensors, but anything beyond that ISensor Interface requires you to use GUIDs. The Windows API Code Pack provides a list of all the GUIDs that are available in Sensors.h. The SensorPropertyKeys and SensorCategories classes contain the public read-only property of GUID objects that correspond to the same values in the Sensors.h file. However, this is not the usual or preferred programming model that .NET developers are accustomed to, mainly because the native sensor objects are not strongly typed and you have to use the more generic GUID system to access a sensor’s data. This doesn’t allow you to use all the great features .NET offers, such as data binding, type safety, and properties. Therefore, the Microsoft.WindowsAPICodePack.Sensors namespace, described in the image to the right, includes several strongly typed sensor classes that allow you to bind to their properties. For example, you can find AmbientLightSensor, which has one public property, CurrentLuminousIntensity, which represents the current amount of light (luminosity) detected by the sensors. The namespace also includes the interop layer that wraps the native interface, all the metadata information, and the object model that developers work with.

 

Codepack_Sensor

Please note that the Microsoft.WindowsAPICodePack.Sensors namespace offers an extensibility model that allows you to create any strongly typed sensor. When this is combined with the extensibility offered by the native API, you can create any type of sensor you want with any data values. You can read more about the Sensor and Location platform extensibility module at the Sensor and Location Platform Web site: http://www.microsoft.com/whdc/device/sensors/.

With a strongly typed sensor class, the Windows API Code pack can define a .NET Generics version of the Get methods. For example, GetSensorsByTypeId<S>, where S is a type derived from the Sensor base class. The prototype looks like this:

public static SensorList<S> GetSensorsByTypeId<S>( ) where S: Sensor

When using this function, you need to predefine a specific SensorList<> of the desired sensor type, (AmbientLightSensor, in our example), and then call the method requesting the sensor’s manager to return only AmbientLightSensor sensors. The following code snippet illustrates this process:

// Strongly typed SensorList of type AmbientLightSensor
SensorList<AmbientLightSensor> alsList = null;
try
{
    alsList = SensorManager.GetSensorsByTypeId<AmbientLightSensor>();
}
catch (SensorPlatformException) 
{
    //handle error when no sensor device is accessible 
}

The SensorManager class contains one event called SensorChanged, which is equivalent to the native ISensorManager::OnSensorEnter event. The one main difference between the native and managed code implementations is that the managed code implementation, in addition to receiving an event when a new sensor device is connected to the PC, also generates an event when a sensor gets disconnected. Therefore, SensorsChangedEventArgs, the arguments passed to the SensorManager.SensorChanged event handler, includes a SensorAvailabilityChange member that defines the type of change for each sensor, which can be Addition for new sensor devices and Removal when sensors are disconnected from the PC.

SensorManager_SensorsChanged is the function that handles the SensorsChanged event in our application, and it looks like this:

void SensorManager_SensorsChanged( SensorsChangedEventArgs change )
{
    // The SensorsChanged event comes in on a non-UI thread. 
    // Whip up an anonymous delegate to handle the UI update.
    BeginInvoke( new MethodInvoker( delegate
    {
        PopulatePanel( );
    } ) );
}
The SensorsChanged event is dispatched on a different thread than the application’s main form (UI) thread. Windows Forms does not allow you to update the UI of the application from a non-UI thread. Therefore, for any Windows application with a window-based UI, we highly recommend that you use a different thread than the main UI thread to execute long computations or any I/O-bound communication (as we do in our example of how to synchronously read sensor data). Therefore, to properly handle non-UI-thread UI updates, you should use BeginInvoke to execute the specified delegate asynchronously on the thread upon which the form’s underlying handle was created. This is also true for any WPF application. The PopulatePanel method iterates through all the ambient light sensors and updates the application UI as it verifies the sensor state and reads its data. We'll cover this in future posts.


Using Sensors in Your Application – Native Implementation, Part 1

After a quick overview of the Sensor and Location Platform - I Can Feel You – Using the Windows 7 Sensor Platform, it is time to start digging into the API. We’ll start with an overview of the Win32 API to understand the data flow and then will review the managed API via the Windows API Code Pack for the .NET Framework.

The Sensor and Location platform has two components, the sensor piece and, built on top of that, the location piece. We’ll cover the sensor piece in great detail to make sure that when the time comes to speak about location, we understand the foundation upon which it is built.

The Sensor API (as well as the Location API) is COM-based. You will find all the required API and GUID definitions in the Sensorsapi.h and Sensors.h files found in your local Windows 7 SDK install. The Sensors.h file contains a ton of GUIDs that define all the different aspects of a sensor’s categories, types, and data. The API and interface are found in the Sensorsapi.h file. A closer look at the Sensorsapi.h file reveals three main COM Interfaces that you should be aware of when working with Sensors:

  • ISensorManager is your main interface to all the sensors that are connected to the platform. The sensor manager allows you to enumerate through the sensors list, request permissions from the user to access the sensor data, and receive events upon new sensor arrivals.
  • ISensor is the actual sensor object you want to work with. Through this interface you will be able to set and get properties, get data reports and register for a range of events that happen during the life of the sensor.
  • ISensorDataReport is the one interface that you will learn to love and hate, as this is the one and only way to read actual data from the sensor; but it is a generic form of a generic data report that needs to span

You will need to work with these three interfaces to integrate sensors into your application.

Integrating Sensors into Your Application

When integrating sensors into your application, you need to follow three basic steps:

  1. Discover sensors – Before you can obtain a sensor, you need to discover which sensors are connected to the system. Use the ISensorManager interface to enumerate through the list of sensor devices that are connected to the platform and register to events that notify you when new sensor devices arrive.
  2. Acquire a sensor and request sensor permissions – Once you discover and choose the sensor with which you wish to work, you need to make sure you have permission to access it. If you don’t have permission to access the sensor’s data (use it…), you need to ask the user for permission in order for your application to access the sensor’s data.
  3. Interact with the sensor –Now that you have obtained a sensor whose data you have permission to access, you can start interacting with it, reading and setting properties, and registering for events.

Discovering Sensors

The first step you need to take for each application for which you want to use sensors is to discover which sensors are connected to the platform and then get access to one. To enable your application to do this, you need to use the ISensorManager COM Interface. The sensor manager maintains the list of available sensors. Since it is a COM interface, you need to initialize it using CoCreateInstance. You can think of this interface as the root interface for the sensor API. The following code snippet creates an instance of the sensor manager:

// Declare a smart pointer to receive the sensor manager interface pointer.
// Originally, this smart pointer is defined in the class prototype definition
// CAmbientLightAwareSensorManagerEvents
CComPtr<ISensorManager> m_spISensorManager;
HRESULT hr;
// Create the sensor manager
hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager);

The ISensorManager interface provides a set of methods for discovering and retrieving available sensors. It also exposes an event that is used for receiving notifications when a new sensor becomes available. You may ask yourself where to register for the event where a sensor “leaves” the system. Well, this can be found within the sensor itself. With an ISensorManager pointer at hand, you can start searching for sensors. ISensorManager has three methods that help you search for connected sensors:

  • GetSensorsByID – The first method returns a specific sensor by its ID, which is just a GUID. This is not the most useful function, since the sensor GUID is automatically generated when the sensor is first connected to the system to support multiple sensors of the same make and model.
  • GetSensorsByCategory – This function returns a collection of sensors that share the same category. For example, I could have several location sensors, including GPS and Wi-Fi triangulation, connected to the platform and you don’t want to exclude any.
  • GetSensorsByType – This function returns a collection of sensors that share the same type.

As you noticed, all function names reflect that there are multiple sensors connected at the same time to the computer. It is possible that several sensors of the same category are connected to the same PC. For example, on my machine, I have one light sensor built into the PC enclosure and another one as part of my Sensor Development Kit. It makes sense to use the light sensor built in to the enclosure because it provides the most accurate lighting condition reading from the PC. For an application, the best way to discover sensors is to use the Sensor Manager interface's type and category functions and then choose the sensor you need to work with from the list.

Through this series of posts, we’ll use a very simple Microsoft Foundation Classes (MFC) light-aware application that is part of the Windows 7 SDK. The following code is taken from the Initialize method of the CAmbientLightAwareSensorManagerEvents class. This class implements the ISensorManagerEvents interface notifications from the platform upon arrival of a new sensor.

The Initialize method is called during the initialization process of the main dialog (we have only one):

HRESULT CAmbientLightAwareSensorManagerEvents::Initialize()
{
    HRESULT hr;
    // Create the sensor manager
    hr = m_spISensorManager.CoCreateInstance(CLSID_SensorManager);
    if (SUCCEEDED(hr))
    {
        hr = m_spISensorManager->SetEventSink(this);
        if (SUCCEEDED(hr))
        {
            // Find all Ambient Light Sensors
            CComPtr<ISensorCollection> spSensors;
            hr = m_spISensorManager->GetSensorsByType
                        (SENSOR_TYPE_AMBIENT_LIGHT, &spSensors);
            if (SUCCEEDED(hr) && NULL != spSensors)
            {
                ULONG ulCount = 0;
                hr = spSensors->GetCount(&ulCount);
                if (SUCCEEDED(hr))
                {
                    for(ULONG i=0; i < ulCount; i++)
                    {
                        CComPtr<ISensor> spSensor;
                        hr = spSensors->GetAt(i, &spSensor);
                        if (SUCCEEDED(hr))
                        {
                            // Helper function that sets up event sinking 
                            // for a specific sensor
                            hr = AddSensor(spSensor);
                            if (SUCCEEDED(hr))
                            {
                                // Check the current sensor state.
                                SensorState state = SENSOR_STATE_READY;
                                hr = spSensor->GetState(&state);
                                if(SUCCEEDED(hr))
                                {
                                      if(state == SENSOR_STATE_READY)
                                     {
                                        // Read the sensor data and update the 
                                        // application's UI
                                        hr = m_pSensorEvents->GetSensorData
                                                                (spSensor);
                                     }
                            }
                        }
                    }
                }
            }
        }
    }
    return hr;
}

Here you can see how, after successfully obtaining an ISensorManager interface, you call ISensorManager::GetSensorsByType, passing SENSOR_TYPE_AMBIENT_LIGHT and a pointer to an ISensorCollection collection, spSensors. The SENSOR_TYPE_AMBIENT_LIGHT indicates that we want to receive only ambient light sensors (ALS). At the same time, you could ask for all sensors of the type SENSOR_TYPE_VOLTAGE from the electrical category, or SENSOR_TYPE_ACCELEROMETER_3D from the motion category.

If successful, the GetSensorsByType function fills ISensorCollection with a list of ALS. Next, you iterate through the sensor collection and call the AddSensor helper function for each sensor. This sets up event sinking (a delegate) by registering the sensor to m_pSensorEvents, which is a SensorEvents implementation class used for event sinking that I’ll explain later. Finally, you call another helper method, GetSensorData, to read data from the sensor and to update the LUX value in the application’s UI. We’ll address the actual reading of sensor data in future posts.

During an application's runtime, new light sensors might get connected to the PC, so you need a mechanism for notifying applications when new sensor devices are connected. The ISensorManager interface contains a SetEventSink method to set an event sinking implementation class – that is, a delegate that handles the events. This function receives an ISensorManagerEvents callback interface that receives the event notifications when a new sensor device is connected. This event sink acts as a listener that handles OnSensorEnter, the only event the ISensorManagerEvents interface has.

If you take a look at the above sample, you will see that you call SetEventSink right after the successful creation of the ISensorManager interface and pass thisas the input parameter, and then the local class CAmbientLightAwareSensorManagerEvents implements the ISensorManagerEvents interface.

Therefore, in this class you can find the implementation for the ISensorManager::OnSensorEnter event, which looks like the following code snippet:

HRESULT CAmbientLightAwareSensorManagerEvents::OnSensorEnter
                                    (ISensor* pSensor, SensorState state)
{
    HRESULT hr = S_OK;
 
    if (NULL != pSensor)
    {
        SENSOR_TYPE_ID idType = GUID_NULL;
        hr = pSensor->GetType(&idType);
        if (SUCCEEDED(hr))
        {
            // we are interested only in light sensors
            if (IsEqualIID(idType, SENSOR_TYPE_AMBIENT_LIGHT))
            {
                hr = AddSensor(pSensor);
                if (SUCCEEDED(hr))
                {
                    if (SENSOR_STATE_READY == state)
                    {
                        hr = m_pSensorEvents->GetSensorData(pSensor);
                    }
                }
            }
        }
    }
    else
    {
        hr = E_POINTER;
    }
 
    return hr;
}

In this code you can see that the OnSensorEnter method receives a pointer to the newly connected sensor device and the state status of the sensor. If the sensor pointer is valid (not null), you first read the sensor’s type by calling the GetType method on the ISensor interface. Because we are in a light-aware application and are interested only in light sensors, we’ll check if the newly connected sensor device is a light sensor by checking its type. Remember that ISensorManager receives notification of any type of sensor devices that are connected to the PC. Assuming the sensor is a light sensor, you then call the same AddSensor helper function that you used in the Initialize method to set up event sinking for specific sensors. (Don’t get confused with the ISensorManager event sinking.) The last thing you do is check whether the sensor is in a ready state. If it is, you read the sensor’s data and update the application’s UI.

But we'll save reading sensor data for our next posts.

You can find more Windows 7 Sensor and Location training at the Channel 9 Learning Center.


I Can Feel You – Using the Windows 7 Sensor Platform

Well, we are back. After a very long suspension, it is once again time to write about the cool new APIs that Windows 7 provides you for differentiating your application with compelling user experiences. I still owe you two more posts on Windows 7 Taskbar to complete the series, but the Sensor platform is way too cool to leave behind.

Before we dive into the API, I should explain the rational that went into the thinking process of the product team while building the Windows 7 Sensor and Location Platform. (I’ll talk about location in future posts.)

Why Sensors?

Lately we are witnessing the increasing role that sensors play in some very exciting scenarios. For example a mobile device that automatically changes its screen orientation from portrait to landscape based on its relative position to the earth (center of gravitation pull), or computers that automatically control their screen brightness when the lighting conditions change to facilitate a better reading experience. However, I think the best example is the automatic time zone change of a mobile device - when you travel, one of the first things you do once your plane lands is turn on your mobile device, which magically shows you the correct time, even if you crossed a few time zones.

Besides the obvious functional reasons, another good reason to have a “platform” is that it unifies the API and lowers the API and entry costs for developers. In the past, using sensors tended to be a very vertical solution. There was no specific definition of what a sensor was, what its data fields were, or how to access those fields. Lack of standardization made programming for sensors an arduous task. When using a sensor, like a GPS location sensor, you had to choose hardware from a wide range of vendors, each of whom had a specific set of drivers and APIs you had to learn about in order to work with that piece of hardware. If you wanted to change your hardware or vendor, you often had to learn new APIs to access similar information.

In Windows 7, we set out to solve this problem from the ground up (as we usually do). We addressed these problems by providing out-of-the-box support for sensors. The Windows 7 Sensor and Location platform provides a set of standard interfaces that free developers from the need to become familiar with specific vendor devices and, instead, focus on their application logic, treating sensors as just another “standard” input device. By providing these standard interfaces, the Windows 7 Sensor and Location platform offers a win-win-win situation, wherein it’s easier for developers to discover, access, and receive information from sensors, thus creating room for more developers to optimize their applications to environmental changes. In return, this creates a greater demand for sensor hardware and, if you are a hardware provider, you have a standardized way to target one set of APIs to integrate with Windows. And most importantly, end users get to experience applications that take into account the environments they are working in.

The location piece of the puzzle adds an abstraction layer on top of the Sensor platform with the sole purpose of providing an easy way to retrieve data about a geographic location while protecting user privacy.

Sensors Under the Hood

To better understand the Sensor Platform API, I want to take you through a quick overview of the platform architecture, explaining the role of the main components in the platform. The following figure illustrates the main components in the system. Note that this figure is doesn’t outline the entire platform, as it misses the location piece, but it will most certainly do for now.

sensor_Arch1

The first component in the platform is the actual sensor device – shown as number 1. Usually, this is a real physical device that measures physical phenomena such as the amount of light, temperature, humidity, relative gravity force, and so on. However, a sensor can be a logical device (also known as a virtual sensor). A virtual sensor is a software-based sensor that can mimic sensor-type functionality by “impersonating” a sensor and providing data to the platform. Virtual sensors can be used to simulate real sensors to help the development process, as you’ll soon see.

Each sensor requires a driver that facilitates the connection between Windows 7 and the hardware device. This integration is achieved via a user mode device (UMD) sensor driver – shown as number 2.

To make it easier to write a device driver that exposes a sensor to Windows 7, the platform provides a sensor class extension – shown number 3. This is essentially a driver utility library that implements the common code required for sensor drivers. We are not going to talk about hardware or drivers in this post, however we have two excellent videos (Windows 7 Sensor and Location - Developing Drivers Part 1, and Part 2) with Gavin Gear describing in great detailed how to write a sensor driver.

After a sensor is installed and integrated, it becomes discoverable to the application via the sensor API – shown as number 4.

One of the main advantages that the Windows 7 Sensor and Location offers is that it enables multiple (different) applications to receive data from the same sensor at the same time – show as numbers 5 With previous Windows versions, devices usually used virtual COM ports to communicate with the system. One of the problems with virtual COM ports is that they don’t scale and can’t support multiple consumer applications at the same time; therefore, having a platform that supports multi-concurrency is a great advantage.

The last component of platform is the Location and Other Sensors dialog, which is part of the Control Panel. This dialog – show as number 6 enables users to control permission settings and other parameters the sensor provides. The following image is a screen shot of my Sensor and Location Control Panel. As you can see, I currently have two sensors installed – the Sensor Development Kit and the Virtual Light Sensor, and both are enabled.

SensorAndLocationControlPannel

The last topic to cover before we jump into the APIs is to explain how sensors are represented in the platform.

As we've seen above, a sensor can be either a physical device or a logical (virtual) sensor. Regardless of the sensor’s type, all sensors share similar properties, as explained in the following list:

  • Category -- A collection of sensors that are somehow related. For example weather station might include temperature, barometric pressure, wind speed, and other environmental sensors
  • Type - The definition of the physical phenomena that is being measured, like wind speed or amount of light
  • Properties - The meta-data information that a sensor can contain, for example, the sensor-friendly name. There are read-only and read-write properties. The sensor-friendly name and its serial number are examples of read-only properties, while the requested data report interval is an example of a read-write property.
  • Data Types - The actual data types a sensor reports for the defined type that it measures. For example, light is measured in LUX units, which are reported in a float variable. Location information includes latitude and longitude, and both are float variables. However as you will soon learn, location might also include civic address as a valid location, which is a set of strings. Data types change from sensor to sensor and it is assumed that you know what data types your sensor will return in its data report.
  • Events - The main way the Sensor and Location platform communicates with your application, informing it when there is new data to consume or when the sensor state changes
  • State - The definitions of the possible operational states for sensors, answering questions such as: “Is the sensor ready for use?” or “Has the user enabled the sensor?”

Armed with the above information, you are ready to start working with sensors and dive into the API. But to do this, you will have to read the next blog about the sensor and location platform.

Additional blog posts on this topics:


The Windows 7 PDC Boot Camp Recordings Are Online

During PDC, I had the amazing opportunity to join a group of remarkable engineers in presenting part of the Windows 7 Boot Camp pre-con event. As I’ve reported live, the event took place on November 16th, in a room filled with 750 attendees who heard about the changes to Windows 7 and Server R2 Kernel, as well as some of the new “user-mode” APIs such as Taskbar, Libraries, touch, sensors, and DirectX.

This post (a little overdue), gives you the opportunity to see the video recordings and download the presentations and demo code. So even if you missed this pre-con you can enjoy it all from the comfort of your PC.

Mark Russinovich, Technical Fellow and the man behind SysInternals and many of the improvements in Windows 7, opened the day with a short introduction to the work done by the Kernel team and as a setup for the following two sessions. You can watch Mark’s presentation recording (time code – 00:00:00 – 00:13:45) and download his slides.

Arun Kishan, a Principal Architect for the process management components, described his work around the thread and process allocation that frees the kernel from its thread dispatcher locks and gives Windows 7 the ability to scale seamlessly to many (256) cores. Arun also talked about the new User Mode Scheduling in Windows 7 that enables quicker context switches between threads (since the threads run in user mode context), while at the same time allowing the kernel to “control” blocking threads, and thus not lose the LP to a thread outside its control. You can watch Arun’s presentation recording (time code 00:13:45 – 00:54:26) and download his slides.

The last speaker in the opening session was Landy Wang, a Distinguished Engineer in the Kernel team. Landy really drilled into the changes to Windows 7 Memory Management, and the amazing work done by the team to reduce the memory footprint, making the entire operating system run fast (real fast). Landy described the work being done to optimize the memory working sets, demystified some of the questions about the Task Manager’s main screen, and how the Task Manager shows the memory working set, along with some other useful information. You can watch Landy’s presentation recording (time code 00:54:26 – 01:50:43) and download his slides.

Get Microsoft Silverlight

After lunch, we switched gears and reviewed the API for some of the UI elements of Windows 7. Jaime Rodriguez started the second part of the day with a great talk about the Windows 7 Taskbar, showing multiple ways (native and managed, using Window API Code Pack and WPF 4) to add great Taskbar functionality to your application. You can watch Jaime’s presentation recording (time code 00:00:00 - 00:44:07)

I followed with quick Windows libraries overview, focusing on the things you need to remember as developers since libraries may sometimes break your application. Here are the Windows 7 library presentation and code demos. You can watch the presentation video recording (time code 00:44:07 – 01:19:05)

My Second presentation that day was about the Windows 7 Sensor and Location Platform. I just love this platform, as it offers such great ways for developers to enable their applications respond to changes in the computer's environment. Showing the light optimizing MSDN Reader and the racing game always gets great reactions from the audience. Here is the Windows 7 Sensor and Location Platform presentation. You can watch the presentation recording (time code 01:20:04 – 02:10:43 ) and download the slides.

Next, Michael Oneppo explained the changes in the Windows 7 graphics stack. Michael's presentation is very interesting, as it describes some of the DirectX API that was down-ported to Windows 7 as a part of the Platform Update for Windows Vista and the Platform Update for Windows Server 2008. You can watch Michael’s presentation recording (time code 00:00:00 – 00:50:03) and download his slides.

Jaime was the last speaker of the day, covering Windows 7 Multitouch. Jaime explained the concept of multitouch using the native API, but switched to WPF 4.0 support for multitouch. You can watch Jaime’s presentation video recording (time code 00:53:50 - 01:34:37).

Last but not least, I want to express my appreciation and say a very big thank you to everyone who participated and helped make the boot camp a success. First to Jaime Rodriguez who made this event possible and helped set up and organize it, to the great speakers Mark Russinovich, Arun Kishan, Landy Wang, and Michael Oneppo, and for the entire crew of PDC.

See you at the next PDC! I am sure I will be there talking about Windows …

Most of the content presented during this day is based on the Windows 7 Training kit that is available from the Channel 9 Learning Center


Windows 7 Test Drive – A New Developer Resource

A few days ago, we launched the Windows 7 Test Drive site. This site offers developers a chance to get first-hand experience in developing for Windows 7, even if they don’t have Windows 7 installed on their development environment. Using the Windows 7 Test Drive site, you can learn about developing on Windows 7 in a virtual environment. This experience provides the user with a guided tour of Windows 7 features from a developer's perspective with the goal of engaging and enabling them to develop on the Windows Platform. You can

The idea behind the Test Drive lab is to create a very low barrier-to-entry development experience for Windows 7. It is a free tool for you to use whenever you want and requires no special software installation (besides a single ActiveX). All you need is a Windows Live ID, a few clear hours, and a visit to the Windows 7 Test Drive for Developers to take a guided tour of Windows 7. The short virtual labs and supporting videos will give you a chance to explore Windows 7 feature by feature with no installation required. Try out a few of the virtual labs and watch a few videos today to learn how and why you should develop on the Windows.

WIn7_TestDriveSite

The first version of the Windows 7 Test Drive includes the majority of the Windows 7 Training kit topics, but not all of the labs. For example, the Test Drive includes the following labs:

  • Taskbar (without the Thumbnail Preview or customer switcher due the Basic Windows 7 Video Driver used to facilitate this virtual lab)
  • Libraries
  • Version Control
  • Version Checking
  • Troubleshooting Platform
  • Windows Ribbon
  • Sensor and Location
  • IE8

WIn7_TestDriveSite2

This content along with the Windows 7 Training Course on Channel 9 Learning Center, is a great resource for developers.


Developing for Windows 7 Taskbar - Thumbnail Toolbars

It is time to return to our usual routine of describing Windows 7 APIs. We already covered the basics of the Windows 7 Taskbar in Developing for the Windows 7 Taskbar – Application ID, and how you can create a Jump List for your application in Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 1, Part 2, and Part 3). This post focuses on using thumbnail toolbars to enhance end user productivity while surfacing specifics common to the Thumbnail Preview.

To make sure everyone understands the concepts, let’s dive into a quick review. If you are already familiar with what thumbnail toolbars are, then feel free to jump towards the middle of this post – where the fun starts with some real code.

As we said, thumbnail toolbars are an amazing productivity feature that enables users to access the application’s functionality even when the application is not in focus (or even visible). Specifically, this enables you to access to the application without the need to  switch to it (make it the active window.) Thumbnail toolbars are a set of up to seven buttons at the bottom of the taskbar’s icon thumbnail preview.

A good, well known example is the Windows Media Player thumbnail toolbar as shown in the following image. Here you can see that when your hover your mouse pointer over the Media Player icon while the application is running, three buttons display: Play / Pause, Next song, and Previous song. Clicking on each button will trigger the expected result as suggested by the button name.

Taskbar_ThumbnailToolbar1

Another great example we mentioned few weeks ago is the Fishbowl for Facebook application. This application uses the thumbnail preview to provide quick and easy access to the most common task any Facebook user performs, surfacing actions like view your home's or friend’s feeds to the thumbnail toolbar. As you can see in the following image, the Fishbowl thumbnail toolbar has five buttons (actually six, but we’ll get to this in a second.)

thumbnail button

Now that we established the need for using this cool taskbar feature, let’ see what it takes to implement it. First, few ground rules:

  • You can display up to seven buttons with a fix and predefined size of 16x16 pixels (or up to 24x14 pixels for high DPI)
  • You can set a thumbnail toolbar button to each active window in your application (that assumes you have multiple windows clustered together and you want each to show different thumbnail toolbar
  • Once the buttons are set, usually at the time the taskbar icon is constructed, you can’t add or delete buttons from the toolbar; however, if you want to, you can hide the buttons

As usual, we’ll start with native code (Win32) implementation. You can find the following example in the Windows 7 SDK.

To add a thumbnail toolbar button you need to use the ITaskbarList4 Interface that exposes methods that allow you to dynamically add, remove, and activate items on the taskbar. Specifically, for working with the thumbnail toolbar you need to use the following methods:

  • ThumbBarAddButtons - Adds a thumbnail toolbar (a toolbar embedded in a thumbnail image of a window in a taskbar button flyout) with a specified set of buttons to the thumbnail image of a window in a taskbar button flyout
  • ThumbBarSetImageList - Specifies an image list that contains button images for a toolbar embedded in a thumbnail image of a window in a taskbar button flyout
  • ThumbBarUpdateButtons - Shows, enables, disables, or hides buttons in a thumbnail toolbar as required by the window's current state

Like every Taskbar icon-related operation, you need to make sure you have a Taskbar icon to work with; to ensure that you have one, you need to register the “TaskbarCreatedMessage” using the RegisterWindowMessage method. Then you need to wait for the message to arrive to your Win32 WndProc method. Once your application receives this message, you are safe to go ahead and create the thumbnail toolbar buttons. The same WndProc method will also receive the WM_COMMAND message when any of the thumbnail buttons you created is clicked. The lower word of the wParam parameter holds the specific button id, signifying which button was pushed, while the upper word is just set to THBN_CLICKED. The following code snippet illustrates this process

LRESULT CALLBACK WndProc(
                    HWND hWnd, UINT message, 
                    WPARAM wParam, LPARAM lParam)
{
    static UINT s_uTBBC = WM_NULL;
 
    if (s_uTBBC == WM_NULL)
    {
        // Compute the value for the TaskbarButtonCreated message
        s_uTBBC = RegisterWindowMessage(L"TaskbarButtonCreated");
 
        // In case the application is run elevated, allow the
        // TaskbarButtonCreated and WM_COMMAND messages through.
        ChangeWindowMessageFilter(s_uTBBC, MSGFLT_ADD);
        ChangeWindowMessageFilter(WM_COMMAND, MSGFLT_ADD);
    }
 
    if (message == s_uTBBC) //wmTaskbarButtonCreated)
    {
        // Once we get the TaskbarButtonCreated message, we can create
        // our window's thumbnail toolbar.
        CreateThumbnailToolbar(hWnd);
    }
    else switch (message)
    {
        case WM_COMMAND:
        {
            int const wmId = LOWORD(wParam);
            switch (wmId)
            {
                case IDTB_BUTTON1:
                case IDTB_BUTTON2:
                case IDTB_BUTTON3:
                {
                    WCHAR szMsg[100];
                    StringCchPrintf(
                            szMsg, ARRAYSIZE(szMsg), 
                            L"Thumbnail toolbar button clicked, 
                            ID=%d", wmId);
 
                    MessageBox(hWnd, szMsg, L"Application", MB_OK);
                    break;
                }
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
 
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

Note that right after you register to listen for the TaskbarCreatedMessage message, you call the ChangeWindowMessageFilter method. This method adds or removes a message from the User Interface Privilege Isolation (UIPI) message filter. You need to do so in case you are running elevated application. In short, the Taskbar is part of the explorer.exe process, which runs in medium integrity level – that is, as a standard user. Since Windows Vista and the introduction of UIPI, lower level privileged applications can’t send Windows messages to high level applications. Therefore, you need to change the filter to allow specific messages to be received from a lower integrity sender, specifically the result of the TaskbarCreatedMessage and WM_COMMAND. This looks like a topic for another post just about UIPI, which I’ll write sometime soon.

Back to our topic, you can see that we handle the WM_COMMAND in a very simple way, extracting the specific button ID from the lower word of the wParam parameter. We don’t really do anything with it (the switch is the same for all buttons); it is just an example.

Next let’s describe what it takes to register the thumbnail toolbar. In the above code snippet, we call the CreateThumbnailToolbar helper method. The following is the relevant code snippet.

HRESULT CreateThumbnailToolbar(HWND hWnd)
{
    ITaskbarList4 *pTaskbarList;
    HRESULT hr = CoCreateInstance(
                    CLSID_TaskbarList, 
                    NULL, 
                    CLSCTX_INPROC_SERVER, 
                    IID_PPV_ARGS(&pTaskbarList));
 
    if (SUCCEEDED(hr))
    {
        hr = pTaskbarList->HrInit();
        if (SUCCEEDED(hr))
        {
            // Figure out what bitmap to use for the 
            // thumbnail toolbar buttons - we decision 
            // based on the system's small icon width. 
            // This will make us DPI-friendly.
            struct 
            {
                PCWSTR pbmp;
                int cx;
            } 
            const bitmaps[3] =
            {
                { MAKEINTRESOURCE(IDB_BUTTONIMAGES_96),  16 },
                { MAKEINTRESOURCE(IDB_BUTTONIMAGES_120), 20 },
                { MAKEINTRESOURCE(IDB_BUTTONIMAGES_144), 24 }
            };
 
            int const cxButton = GetSystemMetrics(SM_CXSMICON);
 
            int iButtons = 0;
            for (int i = 0; i < ARRAYSIZE(bitmaps); i++)
            {
                if (bitmaps[i].cx <= cxButton)
                {
                    iButtons = i;
                }
            }
 
            HIMAGELIST himl = ImageList_LoadImage(
                    g_hInstance, 
                    bitmaps[iButtons].pbmp,
                    bitmaps[iButtons].cx, 
                    0, 
                    RGB(255,0,255), 
                    IMAGE_BITMAP, 
                    LR_CREATEDIBSECTION);
 
            if (himl)
            {
                hr = pTaskbarList->ThumbBarSetImageList(hWnd, himl);
                if (SUCCEEDED(hr))
                {
                    THUMBBUTTON buttons[3] = {};
 
                    // First button
                    buttons[0].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
                    buttons[0].dwFlags = THBF_ENABLED | THBF_DISMISSONCLICK;
                    buttons[0].iId = IDTB_BUTTON1;
                    buttons[0].iBitmap = 0;
                    StringCchCopy(buttons[0].szTip, 
                                    ARRAYSIZE(buttons[0].szTip), L"Button 1");
 
                    // Second button
                    buttons[1].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
                    buttons[1].dwFlags = THBF_ENABLED | THBF_DISMISSONCLICK;
                    buttons[1].iId = IDTB_BUTTON2;
                    buttons[1].iBitmap = 1;
                    StringCchCopy(buttons[1].szTip, 
                                    ARRAYSIZE(buttons[1].szTip), L"Button 2");
 
                    // Third button
                    buttons[2].dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS;
                    buttons[2].dwFlags = THBF_ENABLED | THBF_DISMISSONCLICK;
                    buttons[2].iId = IDTB_BUTTON3;
                    buttons[2].iBitmap = 2;
                    StringCchCopy(buttons[2].szTip, 
                                    ARRAYSIZE(buttons[2].szTip), L"Button 3");
 
                    // Set the buttons to be the thumbnail toolbar
                    hr = pTaskbarList->ThumbBarAddButtons(
                                            hWnd, 
                                            ARRAYSIZE(buttons), 
                                            buttons);
                }
                ImageList_Destroy(himl);
            }
        }
        // It's OK to release ITaskbarList3 here; 
        // the thumbnail toolbar will remain.
        pTaskbarList->Release();
    }
    return hr;
}

First, you need to Co-Create the ITasbarList4 COM interface. Next as standard practice, you need to call HrInit to initialize the Taskbar list object. This method must be called before any other ITaskbarList methods can be called. Next, set up a bitmap list to work with. Note that you need to check the recommended size of the width (in pixels) of a small icon: your DPI setting can affect this. Finally, call ThumbBarSetImageList to set the icons of the buttons. When you download the source code, try to comment this line and run the app. What do you think happens?

Next, we create an array of three THUMBBUTTONs and for each button we set the bitmap, tooltip, and flags. This is used to configure the toolbar button. For example, the bitmap value indicates that the value of the iBitmap field (part of THUMBBUTTON) is valid. The THB_FLAGS is more interesting as you can use it to specify the button's states and behaviors, like enable, disable, or hidden. You can find more options in the SDK. We also set the button ID to distinguish between each button once it is clicked; this ID is sent with the WM_COMMAND message.

Last, we call the ThumbBarAddButtons method to pass the current hWnd and the array of buttons. This registers the thumbnail toolbar so the next time you hover your mouse pointer above your application Taskbar icon, you will see three colored buttons as shown in the following image. Taskbar_ThumbnailToolbar2

You can use the Windows API Code Pack to create thumbnail toolbars for managed code applications. The following is part of the Windows 7 Training Kit that is available on the Channel 9 Learning Center. The Taskbar Concepts demo, created by Jaime Rodriguez, is a WPF application that showcases EVERY little feature the Windows Taskbar has to offer developers. We’ll explore just the thumbnail toolbar part, and I will leave the rest for you to explore on your own. From time to time, we’ll use this as base to our managed code samples for WPF applications.

As always while using the Windows API Code Pack, you don’t have to worry about registering or handling any Windows messages. Just use the TaskbarManager. Specifically, you want to work with ThumbnailToolbars, which has an AddButtons method that you need to use while adding ThumbnailToolbarButton objects. The ThumbnailToolbarButton represents a taskbar thumbnail button through which you can enable or disable the taskbar button, change its icon or tooltip, and control its visibility. You can also attach an event handler to the button Click event, as you would expect from managed code (note: there is no need to handle funky Windows Messages). You can find the following code snippet in the ToolbarButtons.xaml.cs file. It shows how easy it is to add thumbnail toolbars to your managed code application

private void CreateToolbarButtons()
{
    buttonFirst = new ThumbnailToolbarButton(
                        TaskbarConcepts.Resources.first, "First Image");
    buttonFirst.Enabled = false;
    buttonFirst.Click += buttonFirst_Click;
 
    buttonPrevious = new ThumbnailToolbarButton(
                        TaskbarConcepts.Resources.prevArrow, "Previous Image");
    buttonPrevious.Enabled = false;
    buttonPrevious.Click += buttonPrevious_Click;
 
    buttonNext = new ThumbnailToolbarButton(
                        TaskbarConcepts.Resources.nextArrow, "Next Image");
    buttonNext.Click += buttonNext_Click;
 
    buttonLast = new ThumbnailToolbarButton(
                        TaskbarConcepts.Resources.last, "Last Image");
    buttonLast.Click += buttonLast_Click;
 
    TaskbarManager.Instance.ThumbnailToolbars.AddButtons
    (
        new WindowInteropHelper(Application.Current.MainWindow).Handle,
        buttonFirst, 
        buttonPrevious, 
        buttonNext,     
        buttonLast
    );
}

The rest of the code in this file is responsible for the logic and handling of different events. This results in the ability to control the different images displayed in the main application as you can see in the following image.

Taskbar_ThumbnailToolbar3

I hope by now you see the value of including thumbnail toolbar (where appropriate), and how easy it is to implement.

I still owe you explanation for the reason there are six buttons and not five in the Fishbowl thumbnail toolbar (see image). If you take a careful look at the image, you’ll notice that the four left buttons directly effects the application’s behavior, where the right single button simply lunch your default browser and automatically loads Facebook website. Therefore it makes sense to a graphical separation between the different sets of buttons. The application creates six buttons, but the fifth one is hidden, creating the illusion of space between the buttons. To do so, you need to use ThumbBarUpdateButtons for Win32 application.

Managed developer will find it much easier to hide a ThubmnailButton. A closer look into the Windows API Code pack, you will find that the ThubmnailButton class has a Visible property for controlling the visibility of the specific toolbar button. At the end of the Visible Set section you will find a call UpdateThumbnailButton() function which is basically a wrapper for the native ThumbBarUpdateButtons method.

You can download the Win32 Native sample

You can download the managed code (WPF) sample

You can find more Windows 7 Taskbar training at the Channel 9 Learning Center


Developing with the Windows API Code Pack for Microsoft .NET Framework

During PDC, we announced the availability of a new version of the Windows API Code Pack (version 1.0.1). That same day, I had the pleasure of demo-ing how to use the API Code Pack to build great Windows 7 applications. If you missed the session (or weren't able to attend PDC), you can check out the video recording and grab the decks from session page - Developing with the Windows API Code Pack for Microsoft .NET Framework.

While Windows 7 is an awesome operating system that runs faster while consuming fewer resources than its predecessor, it also includes new exciting features and capabilities that both users and developers can enjoy. Taskbar, Sensor and Location platform, Libraries, Multitouch, new DirectX capabilities, and graphics improvements are just a few of the many technologies and features that Windows 7 offers developers to help your applications shine while running on Windows 7.

The number of commercial applications that leverage the various Windows 7 technologies is too long to list, but here are a few popular applications that we demonstrated during the PDC Keynote and that shine on Windows 7: iTunes, Kindle for PDC, Autodesk Project Cooper, and Seesmic Desktop.

While not all of the above-mentioned applications use the API Code Pack (some are not even managed), they all tap Windows 7 features to enhance the user experience. The Windows API Code Pack enables managed code developers to take advantage of such features and build great windows applications. During the session, I presented a few examples of managed applications that leverage Windows 7 features:

  1. Fishbowl for Facebook is a great example of amazing Taskbar functionality - (video time code 00:05:02 – 00:07:41)
  2. Photo View (AKA XP2Win7) is another example of a developer reference application that showcases a lot of Windows 7 features - (video time code 00:08:33 – 00:10:12)
  3. Kindle for PC is the Windows version of Amazon Kindle that you can download today. Specifically, I showed the Taskbar integration and the multitouch support (video time code 00:07:42 – 00:08:23)

Next we dived into a few demos showcasing implementation of the Windows API Code Pack. I included the code for each demo:

  • Jump Lists Demo – is a very simple Win Form application shows the basic usage of the Taskbar API, focusing specifically on jump lists. (video time code 00:26:30 – 00:34:27)
  • Zoobar (download Part1, Part2) – is a bit more functional WPF application that showcases how the Taskbar can be used to show more than windows and documents. This application uses multiple Taskbar controls, like overlay icons, progress bar, thumbnail buttons controlling images, custom switcher and previews showing specific animals. (video time code 00:35:15 – 00:40:50)
  • Library Manager – is one of the samples we use in the Windows 7 training course. It goes through every API method that the Windows Shell API has to offer for working with Library. (video time code 43:04 – 42:27)
  • MSDN Reader (binaries only) – is a WPF application that uses a light sensor to change the way we display content. The MSDN reader displays articles from MSDN, mostly text with some images. When used with a light sensor, we can change the size of the font and use of colors to change the contrast and enhance the readability (video time code 00:50:14 – 00:51:36)
  • Racing Game– is a cool XNA racing game that features a red car (it always has to be a red car) that you can control using an accelerometer sensor that that measures the Earth's gravitational power and provides information about the orientation of the device relative to Earth. The sample is very simple and cool, as playing games is always great fun. (video time code 00:51:55 – 00:57:15)
  • Session Q&A (time code 01:00:24 – 01:07:32)

You can download the updated deck including the speaker notes and watch the video.

You can learn about the above mentioned technologies and on developing for Windows 7 using the Windows 7 Training Kit for Developers or by viewing Windows 7 videos on Channel 9.


Fishbowl for Facebook Using the Windows 7 Taskbar for Extra Spice

During Wednesday’s keynote, Brian Goldfarb demoed an amazing Silverlight 4 client for Facebook. Beyond its amazing looks, this Silverlight 4 demo provides a full and complete desktop client application for Windows (and Mac). SilverFace is built on top of Silverlight 4 – also announced during the keynote. If you want a cool Facebook client application to work on from your Windows desktop, you should take a look at the Fishbowl for Facebook Preview. Fishbowl is a great WPF application that you can install and enjoy as a user, and at the same time it is a great code sample for developers whom are looking to write WPF applications that use Windows 7 features.  If you are interested, you can download the source code for Fishbowl.

In today's world, the client’s experience is more important than ever before. Your application doesn’t just have to be fun and interesting; it has to be good looking, polished, and functional, providing a “natural” user experience that just works. As a developer, you need to push the envelope and use any available technical tool that the OS provides or any other available means (if installed on mobile devices) to provide a superior user experience, or users will switch to the next guy. In such a competitive scenario, using the Windows 7 Taskbar to shave a few seconds from day-to-day tasks looks like a very obvious choice.

Both Silverlight 4 demo and Fishbowl applications each provide a great UX and enhance user productivity. Scott Guthrie also announced the Facebook SDK for managed code applications that combines the latest in Web and Client platform innovations with leading Social technologies (services) to help developers plug into Facebook. But, beside the new Facebook SDK and beside the great looks, the Fishbowl application is a great WPF (3.5) example that demonstrates how to write applications that produce amazing experiences on Windows 7.

As a WPF application, Fishbowl runs on multiple Windows versions, including Windows XP, Windows Vista, and Windows 7, and it integrates with the Windows 7 Taskbar and Multitouch. One of the main ideas behind the Taskbar is to provide users with quick and easy access to their content and help them accomplish tasks and navigate between windows easier and with more confidence. For example, JumpList provides a great tool for surfacing common work items and tasks. If you have a task that you perform once or twice a day, taking two or three clicks to perform the task is not that bad. However, if you have a task that you perform 10, 20, or even 30 more times, using JumpList tasks or items in the recent category list goes a long way. Facebook users often check their wall, write notifications and messages, view friends' pictures, and so on. Therefore, in some scenarios, the Taskbar JumpList tasks, icon notification, thumbnail buttons, and other functionality become major tools in the application.

Fishbowl uses the taskbar to provide a quick, easy, and seamless integration with Facebook functionality directly from your Taskbar. Let’s review some of the user functionality before jumping into code behind.

The Fishbowl taskbar offers a few tasks even before you start your application. You can go to Facebook.com, or you can actually “jump” directly and see your wall, friend's picture, and more, as the following image shows.
One of the amazing things in Fishbowl for Facebook is that it changes it functionality between the different modes of the application. Being able to use the taskbar differently for
TaskbarBeforeStart

different scenarios provides an amazing user experience in heavily used application like Fishbowl.

When Fishbowl runs in normal mode, the Taskbar JumpList reflects items and tasks that you can actually perform in the context of a running application, like viewing the last few notifications and messages that you received without opening the application, as shown by the following image.

TaskbarAfterStart If you hover with the mouse above the Fishbowl control, you see the thumbnail preview provided by Windows 7 taskbar. However, Fishbowl uses the thumbnail button again allowing you to both view a preview of the application and act immediately upon the thumbnail preview as shown in the following image.

If you hover with the mouse above the Fishbowl control, you see the thumbnail preview provided by Windows 7 taskbar. However, Fishbowl uses the thumbnail button again allowing you to both view a preview of the application and act immediately upon the thumbnail preview as shown in the following image.

thumbnail button

(And thank you Raman for writing so many PDC tweets J)

Fishbowl also has a mini-mode operation mode. This mode shows just one message in a small window. As you can see in the following image, a small arrow allows you to switch between messages. When you hover over Fishbowl taskbar icon, you can see the preview but you can also control the message, again using the taskbar thumbnail preview.

 minimode

Besides great Taskbar integration, Fishbowl offers a great Multitouch experience, allowing you to scroll between messages using your finger to touch the touch screen. It is a little hard to illustrate Multitouch with screen capture so you will have to trust me on this one.

We've covered most of the Fishbowl features unique to Windows 7, and in the next post I will dive into the API that enabled these Taskbar and Multitouch features. If you are interested, you can download the source code for Fishbowl.


New Windows API Code Pack Version

I am glad to announce that today we shipped a new version of the Windows API Code Pack – version 1.0.1. This is not a major version with a lot of new features, but rather a minor version focused on fixing bugs, improving performance, adding demos and few features updates (new wrappers…)

But before we dive into this new version of the Windows Code Pack let’s better understand what this Windows API Code Pack is all about.

Windows 7 offers new features like the taskbar, libraries, and the Sensor and Location platform, to name a few. These features enable new scenarios and create new opportunities for developers to make their applications shine on Windows 7. All these great features are exposed via the Win32 native API. Currently there is no “Windows 7” namespace in the .NET Framework, and no easy way to use these features from managed code applications. To help managed code developers access them, we released version 1.0 of the Windows API Code Pack for the .NET Framework in August (just after Windows 7 RTM).

The Windows API Code Pack is a free, managed Source Code Library provided by Microsoft as is. You should consider this library as if you wrote it yourself, as if it is your own code. It is a great starting point and provides a really good and solid solution for managed code developers. It covers a lot of the new Windows 7 features as well as some more fundamental core features from the Windows Vista timeframe. You may think of the Windows API Code Pack as the closest thing to an “official” managed API for Windows. But you need to remember that it’s not a product with 24x7 technical support available from Microsoft Customer Service and Support. We believe it is a great solution, and that the codebase is very solid and high quality.

Our goal with the code pack is to enable managed code developers to take advantage of Windows APIs that are not part of the .NET Framework. We feel that as a shared source that is separate from the .NET runtime libraries, the Windows API Code Pack provides an optimal compromise between the Microsoft Win32 managed wrapper, short time-to-market -we released the Windows API Code Pack just a month after the Win7 RTM, and we ship full source code of the library.

The Windows API Code Pack includes a great deal of managed API for Windows (7). For example:

  • Extensive integration with the Windows Shell namespace, with support for the Windows Shell property system, providing control like explorer browser and access to Windows Libraries
  • A completely 100% feature parity with the native Taskbar API including (but not limited to) JumpLists, Icon Overlay, Progress bar, Thumbnail, custom switcher, Thumbnail Button, etc…
  • Windows Task Dialogs , other controls
  • Support for Direct3D 11.0 and DXGI 1.0/1.1 APIs
  • Support for the Sensor Platform APIs
  • Extended Linguistic Services APIs
  • Windows Restart Manager
  • Power APIs
  • And many other features

Each technology represented in the Windows API Code Pack has multiple demos and examples (including source) in C# and VB. We are planning on releasing updates to the Windows API Code Pack roughly every three months. We will be investing mainly in stability (meaning fixing bugs), fundamentals, testing and documentation, as well as new feature support (based on customer feedback).

You may ask yourself, “Why isn't the Windows API Code Pack part of the .NET Framework?

We ship open source code that we might bring into the runtime sometime in the future, if we feel it's sufficiently core to the entire framework to be worth the size increase. Remember the .NET Framework runs on both Windows Vista and Windows XP. However, Windows 7 is here now, and we want to enable you to access this set of free, open source library sooner rather than later. We’re shipping this library in a community-supported form and, as you can see, we intend to keep updating it. While this version (1.0.1) is a minor release, we are planning on another release in the next few months. In the meantime, you get the best of both worlds in a package that you can use as a whole or in parts without restriction.

Another question you may ask is, “Will .NET 4 replace the need to use the Windows API Code pack?”

When .NET 4 ships, you will be able to use its Windows 7 features such as Taskbar and multitouch integration with WPF, DirectWrite support, and the location API via the Devices namespace. Continue to access other features such as libraries, Restart Manager, and Sensors via the Windows API Code Pack.

Last but not least, we are looking for feedback from the community – that is you the .NET developer using this library to write managed code applications for Windows 7. On the Windows API Code Pack site, you can ask questions, provide feedback, report bugs, and follow open bugs. Your input is critical for the continuation of this library, so please send us your feedback and questions.

To learn more about how to use the Windows API Code Pack check the Windows 7 Training on Channel 9


Programming Windows 7 Using Visual Studio 2010

A few weeks ago, just two days before Windows 7 become generally available, Visual Studio 2010 hit its own major milestone with the release its second Community Technical Preview of Visual Studio, known as Visual Studio 2010 Beta 2. To me, it is always exciting to see how the different tools and frameworks evolve and add new features.  It seems that with every release the products get bigger and better, offering an even



VSLogo

greater number of programming  languages, and addressing an ever growing number of areas of development such as Web, client, mobile, parallel, consoles, and devices.

Despite being a “beta” product, it is much easier to work with Visual Studio 2010 than with VS 2008. It is much easier to control your solutions and, even more importantly, much easier to write and document code. The user interface is much improved; it uses the Windows Presentation Foundation (WPF) to reduce clutter and visual complexity, and modernizes the interface by removing outdated 3D bevels. Using WPF enables us to help developers focus on content areas by opening up negative space between windows and drawing attention to the current focus with a dominant accent color and a distinctive background. There are also some cool, small, and simple perks like the ability to control the size of text. You can also drag a single window from the main Visual studio application to a second monitor (just like that) and with that you have multi-monitor support via the VS client application.

Improvements to the IntelliSense allow it finally to work well for C++ projects. And let’s not forget the new debugger window that supports parallel computing debugging and lets you view your parallel stacks.

There is even a new language, F# (F stands for Functional programming), and numerous upgrades to C#, like support for dynamic keywords. Dynamic objects' operations are resolved at runtime (check out a good post about this by Scott Hanselman). There is also support for the next version of the C++ language specification, C++X0, like Lambda Expressions. Speaking of C++, we've built the C++ solutions using MSBuild, which should make everyone happy.

As always, backward compatibility is super critical, and it is important to mention that Visual Studio 2010 supports multi-targeting. Visual Studio 2010 can target .NET 2.0 through .NET 4.0 on a per-project basis, which means you can work with your older project on the new VS 2010 and enjoy all the goodies mentioned above (and many more).

But I want to focus this post on using Visual Studio 2010 to program Windows 7. There are quite few technologies and features in Visual Studio 2010 to help you write better applications targeting the specific features of Windows 7. Below are just a few of the Visual Studio 2010 features that we’ll write more about really soon.

.NET 4 and Windows 7

Visual Studio 2010 brings a complete new CLR version – version 4. This is not just an incremental upgrade on top of CLR 2 (.NET Framework 2). This enables new language enhancements like the dynamic keyword. And the new WPF brings support in a few other areas like shell and Taskbar integration, and multitouch.

WPF & Taskbar Integration

As you know, you program jump lists using the JumpList class. This exposes several methods and properties that manipulate the exposed jump lists for the application. It also has an attached property that you can apply to your application class to create, modify, and remove jump list items. If you work with specific files, you can use the JumpList.AddToRecentCategory method to add that file to the recently used file list managed by the shell.

There are two types of jump lists – tasks and items; you work with each using a JumpTask, or a JumpPath respectively. You can work with these in XAML, code-behind, or a combination of the two. The following code snippet shows a simple integration of tasks into a jump list.

<JumpList.JumpList>
   <JumpList>
      <JumpTask ApplicationPath="notepad.exe" 
                         CustomCategory="External Tools" 
                Description="Take Notes" 
                Title="Start Notepad" 
                IconResourcePath="notepad.exe" 
                IconResourceIndex="0" />

      <JumpTask ApplicationPath="calc.exe"
                         CustomCategory="External Tools" 
                         Description="Perform some calculations" 
                        Title="Start Calculator"
                        IconResourcePath="calc.exe" 
                        IconResourceIndex="0" />
    </JumpList>
</JumpList.JumpList>

In a similar way, you can use XAML to add Thumbnail Toolbar buttons as shown by the following code snippet.

<TaskbarItemInfo.ThumbButtonInfos>
   <ThumbButtonInfo DismissWhenClicked="True" 
                    ImageSource="images/booktrip.png"
                    Command="{Binding BookItinerary}"
                    Description="Book the itinerary now" />
</TaskbarItemInfo.ThumbButtonInfos>

WPF Common File Dialog Supports Libraries (Finally!)

For some strange reason, WPF 3 and 3.5 Common File Dialog (CFD) didn’t support the updated version of the CFD introduced with Windows Vista. The CFD was upgraded in Windows 7 to support libraries and provide a better user experience. It now allows seamless search integration as well as some advanced user functionality. With WPF 4, applications enjoy the power of the “new” CFD directly from WPF, and don’t need to import CFD from the WinForm namespace (which was the only way to show the updated CFD from WPF 3 and WPF 3.5).

WPF Supports Multitouch

WPF 4.0 introduces multitouch support directly into the WPF API– with no need to interop to a native service. These new features are only available on Windows 7 and are automatically deprecated when running under older operating systems, so you don’t have to detect the operating system yourself. WPF 4.0 adds a new manipulation API to the UIElement base class. This new support allows developers to track multiple touches and generate both cumulative and individual manipulations across the touches. Basically, this enables you to transform your object on the X and Y coordinates, rotation, and scale.

WPF will supply these manipulation events if the IsManipulationEnabled property on the element is set to true. It defaults to false, so you will need to turn on this property for each element where you want to manage manipulations. This is as simple as adding IsManipulationEnabled=true to your XAML as shown in the following code snippet.

<Border Margin="10,5" 
    BorderBrush="DarkGoldenrod" 
    BorderThickness="2" 
        CornerRadius="10" 
    MinHeight="75" 
    IsManipulationEnabled="true">

Optionally, you can also hook the ManipulationStarting and ManipulationCompleted events to provide code behind the implementation of these events.

WPF 4 also supports low-level touch messages, or raw touch input. You can interact with the raw touch events on any UIElement using TouchDown, TouchMove, and TouchUp events, all of which have preview event versions. This can be useful if you are trying to track multiple touches that are not manipulating the same object, or if you want to provide different behavior for touches and the mouse. We’ll soon write more about Windows 7 multitouch in general and WPF specifically.

MFC Updates

In Visual Studio 2010, C++ and MFC received a healthy dosage of “coolness” factor, adding useful features such as IntelliSense enhancements and C++0x features. The MFC Library received a major upgrade, especially in regard to the Taskbar, Multitouch, and Restart and Recovery:

Taskbar

The MFC Taskbar provides all the functionality that the native taskbar COM API provides. There is nothing that the one can do that the other cannot. The MFC simply wraps the Win32 APIs (as it always does) into a more “MFC-like” API that corresponds to the MFC Framework programming style guidelines. For example, the following code snippet sets the overlay icon.

CMainFrame* mainFrm = 
dynamic_cast<CMainFrame*>(AfxGetApp()->GetMainWnd());
if (mainFrm)
    mainFrm->SetTaskbarOverlayIcon(IDI_ICON_INFO,L"Info");

First you need to obtain a handle (a pointer) to the application's main window (the top-level window), which corresponds to Win32 HWND. Then, simply call the SetTaskbarOverlayIcon passing HICON and a string that provides an alt text version of the information conveyed by the overlay to meet accessibility requirements. Simple, right?

In MFC, the CFrameWnd class provides the functionality of a Windows single document interface (SDI), overlapped, or pop-up frame window. With the new MFC, this class was updated and now supports Taskbar functionality such as icon overlay, progress bar, jump lists, and thumbnails.

In MFC, Taskbar thumbnail preview support is built in, so the Taskbar thumbnails will show any rendering within the views. Therefore, other than implementing your own View drawing, you need not provide any explicit code to update those Thumbnails.

To enable Taskbar Thumbnails in an MFC application while using the MFC application wizard, all the user needs to do is select the “Multiple documents” application type with the option “Tabbed documents” enabled. When the application runs, MFC will take a snapshot of each view and send it to the Taskbar APIs to display as thumbnails.

image

And the output could like this:

image

Multitouch

In Visual Studio 2010, MFC also supports multitouch. By default, on a touch-enabled device (such as touch screen), Windows 7 sends gesture touch messages to any application; that is, by default Windows 7 sends WM_GESTURE messages to the target windows. All that MFC is doing is mapping these messages to its own message handlers. MFC provides a number of message handler overrides that can receive each of the gesture types, and each returns a Boolean value. If a gesture input is processed by the application, the corresponding override should return TRUE; otherwise, it returns FALSE. Therefore if you wish to handle the zoom gestures, all you need to do is implement the relevant handler. Here is the list of supported handlers.

// Gesture handlers
virtual BOOL OnGestureZoom(CPoint ptCenter, long lDelta);
virtual BOOL OnGesturePan(CPoint ptFrom, CPoint ptTo);
virtual BOOL OnGestureRotate(CPoint ptCenter, double dblAngle);
virtual BOOL OnGesturePressAndTap(CPoint ptFirstFinger, long lDelta);
virtual BOOL OnGestureTwoFingerTap(CPoint ptCenter);

 

Similarly, you can register to receive raw touch messages and the default gesture messages. In Windows 7, gestures messages and raw touch are mutually exclusive. If you register to receive the raw touch messages for a particular window, that window will stop receiving gestures messages. If you opt-in to handle raw touch messages, you need to implement the following handler:

virtual BOOL OnTouchInput(
                        CPoint pt, 
                        int nInputNumber, 
                        int nInputsCount, 
                        PTOUCHINPUT pInput);

MFC makes your life easier by providing a lot of the information per each touch point, for example, the client coordinates for the actual point where the touch-enabled device has been touched. MFC also provides the ID of the touch point, that is, the first, second, or third finger, as well as the total count of current touches.

Restart and Recovery (Restart Manager)

In Visual Studio 2010, MFC also provides native support of the Restart Manager. Restart Manager is a feature introduced by the Microsoft Windows Vista operating system. It can help applications maintain their data when an update needs to shutdown the application or when an unexpected software error or crash occurs. Instead of shutting down abnormally, Restart Manager enables an application to perform an application save before it is terminated. Furthermore, it can re-invoke the application, enabling it to restore its state from before the shutdown or crash.

For new MFC applications, you can get the application restart and recovery feature for free by using the MFC Application Wizard as you can see from the following image:

clip_image001

All configurable parts of the restart manager API are exposed to the user through virtual members that can be over-ridden. Needless to say, you can expect some more blogging about this feature.

.NET 4 and Location

.NET 4 has a new Device namespace that supports the Windows 7 Location API (part of the Windows 7 Sensor and Location. The System.Device.Location namespace allows application developers to access the user's location easily using a single API. Location information may come from multiple providers, such as GPS, Wi-Fi triangulation, and cell phone tower triangulation. The System.Device.Location classes provide a single API to encapsulate the multiple location providers on a computer and support seamless prioritization and transitioning between them. An application developer using this API does not need to know which location-sensing technologies are available on a particular computer and is freed from the burden of tailoring an application to a specific hardware configuration.

To begin accessing location, you need to create a GeoLocationProvider. This object is the main “location manager” object through which you can register for LocationChange notifications and synchronously read the latest location information. Next you need to call Start to start the acquisition of data from the current location provider. You can check the Status property to determine if data is available. If data is available, you can get the location once from the Location property, or receive continuous location updates using the LocationChanged event. The following code snippet is a VERY simple code sample showing how to retrieve the current GeoCoordinates (latitude, longitude).

GeoLocationProvider provider = new GeoLocationProvider();
provider.Start();
GeoCoordinate coordinate = provider.Location.Coordinate;
if (coordinate != GeoCoordinate.Unknown)
{
  //Business logic here
}

Unfortunately, .NET 4 supports only the Location API and not the full Sensor and Location Platform – meaning that the .NET location implementation is still missing the Sensor piece. Use the Windows API Code Pack to access sensor from managed code.

Parallel Computing and Windows 7 Multi-Core

Parallel programming in Visual Studio 2010 has many aspects, for example, Parallel LINQ and other .NET enhancements for supporting parallel computing, including statements like Parallel.For that use System.Threading.Tasks.Task. C++ developers will be happy to learn that the Task concepts also exist in C++ Version 10, which ships with VS 2010. For native code, Concurrency Runtime (ConcRT) has implicit knowledge of Win7 processor groups and will schedule work on up to 256 cores; ConcRT also takes advantage of User Mode Scheduling of threads. Therefore, any workload that sits on top of ConcRT immediately benefits. In other words, because both the Parellel Pattern Library (PPL) and Asynchronous Agents are included in Visual C++ 10 CRT and are built on top of ConcRT, any workloads you build on them will scale to 256 cores--

just like that! (Well, you will still need to write the code, but the scaling is free.)

For managed code applications, the story is less bright. Management of the managed stack thread sits on top of the .NET ThreadPool (System.Threading.ThreadPool) by default. This does not use the new processor group APIs in Windows 7, and therefore doesn’t automatically benefit from the Windows 7 ability to scale. The maximum number of processes that the threadpool can utilize is 64. But not everything is lost, it is possible to write a custom TaskScheduler that targeted more than 64 procs, and use the rest of the Task Parallel Library with that special scheduler. This would be a cool CodePlex project, right?

Overall Visual Studio 2010 includes tons of new technologies and improvements--all of it icing on the Windows 7 cake!


Reporting Live from the Windows 7 Seminar: Boot Camp

Here we are at the LA Convention Center, attending the FREE Windows 7 Seminar: Boot Camp. We managed to “sell out” (just a reminder-- it is free) this event, getting more than 1200 registrations. This day is all about learning what’s new in the Windows 7 kernel, how developers can take advantage of these feature, and then learn how to take advantage of some “user mode” features like multitouch, taskbar, sensor and location, and others. image

Today started with Mark Russinovich, Technical Fellow and the man behind SysInternals and many of the improvements in Windows 7, describing some of the changes made to the Windows 7 kernel. Immediately after Mark, Arun Kishan, a Principal Architect for the process management components, described his work around the thread and process allocation that frees the kernel from its thread dispatcher locks and gives Windows 7 the ability to scale seamlessly to 256 cores. Then Landy Wang, a Distinguished Engineer in the Kernel team, described changes made in Windows 7 memory management, mainly focusing on memory Working Set and memory trimming.

image

After lunch, Jaime started his run, giving some insight and very useful tips about using the Taskbar, from understanding the difference between Application ID and Program ID to the effective use of custom previews. Jaime has only 60 minutes, but I am sure his tips for working with the Taskbar will prove very useful. For example:

  • Tip1 – when writing your own jump list item or link, make sure you remember what items you wrote, because you can’t just “read” the jump list items
  • Tip2 – if you decide to invest in cutom switcher and provide your own thumbnail preview and Aero Peak make sure you “save the state” of your application and images as DWM will not always perform for you.

I'll be up next, explaining Windows 7 libraries in depth, with a focus on useful tips for programming Windows 7 libraries, and specifically how to stay in sync with library updates. We have already had plenty of Windows 7 libraries posts - Windows 7 Programming Guide – Libraries, so I am not going into great detail. However, I do want to hand out the presentations and code samples used. All my demos as well as Jaime’s are part of the Windows 7 Training kit.

Right after our discussion about libraries, we will take a deep dive into the Windows 7 Sensor and Location platform. I just LOVE the endless amount of innovation and opportunity developers have generated while using this platform. After the Windows 7 launch on October 22nd, we saw a large number of laptop models coming out with built-in sensors. Developers will most probably use these to create truly adaptive applications that adjust their functionality and UI based on sensor input. 

After our Sensor and Location Platform discussion, it will be Michael Oneppo's turn to explain the changes in the Windows 7 graphics stack. Michael's presentation is very interesting, as it describes some of the DirectX API that was down ported to Windows 7 as a result of the Platform Update for Windows Vista and the Platform Update for Windows Server 2008. For example, did you know that the Microsoft Direct3D API DirectCompute feature allows your applications to use a new pipeline stage in the GPU, the compute shader stage, to implement highly data-parallel algorithms with unmatched speed and performance? This means that now you can use GPU power for parallel programming, freeing your CPU to do other things. It is amazing how powerful these GPUs have become; allowing them remain idle would be a huge waste of resources. If you want to learn more, you can always view Chas Boyd PDC session – DirectX11 DirectCompute.

To close the learning part of the day, Jaime Rodriguez takes us through a quick tour of Windows 7 multitouch. Jaime is taking his usual practical teaching approach of focusing on a few tips and tricks that will make it easier for you to start using multitouch.


Windows7 Trigger Start Services – Part 2: Building a Trigger Start Optimized Service

In the last post Windows 7 Trigger Start Services – Part 1: Introduction, we introduced Windows7 Trigger Services as a great way to optimize your services to have better performance and improved security. In this post you will learn how to convert a standard automatic-start service to a trigger-start service that starts up only when a certain event occurs in the system. We’ll use a WPF application (obviously managed code) that registers and monitors a service (also implemented using .NET). To bridge between the .NET world and the native Win32 APIs that we saw in the previous post, we use a C++/CLI interoperability layer.

This sample application has 3 parts:

  • A C++/CLI interoperability layer that provides a regular and easy .NET API to the controller application
  • A WPF controller application that lets you register and run the service
  • A simple .NET service that looks for a USB storage device (disk on key) and on it, a specific folder named “ToCopy” from which to copy files to your local “C:\FromUSB” folder

The following image illustrates the solution structure.

image

Let’s start by reviewing the .NET Service code implementation. This is a simple Windows service written in C#. The purpose of this service is to copy pictures automatically to your local hard-drive- “c:\FromUSB” from the USB storage device that is plugged into your computer.

The service implementation can be found at USBService.cs. This class inherits the ServiceBase base class and overrides the OnStart and OnStop methods. This class has a DoWork method that actually does all the copying of images from the USB disk to your local drive. The DoWork method writes to a log file that we will be monitoring.

The real interesting part of the service implementation is the OnStart method. This method is called once the service is started. Notice that the first line of code checks whether the service is configured as a trigger start service. If the “if” statement returns false, we create a new instance of a timer and have it poll every 5 seconds. Before Windows7, this was the only way to implement such a service, that is, by regularly polling the system to check for a USB device. Therefore, the service needs to run 24x7 to poll the system. This is highly wasteful of resources and keeps the system from transitioning to a low-power state, increases the application attack surface, among other negative things.

But, with Windows7, you can configure such a service with a USB device arrival trigger. This means that the service will not run until a USB device arrives, specifically a USB generic disk device. We’ll get to that part of the solution in a second, but for now, if you look at the OnStart method, you will notice that we check whether the service is configured as a trigger start service; if it is, we simply call the DoWork method on another thread, as shown by the following code snippet. This should work just fine because the service is NOT running, and will start to run only when the trigger happens. And then it will not default to the timer, but rather use the thread pool to queue the work.

 protected override void OnStart(string[] args)
 {
   if (ServiceControl.IsServiceTriggerStart(ServiceName))
   {
      ThreadPool.QueueUserWorkItem(_ => DoWork());
   }
   else
   {
     _timer = new Timer(_ => DoWork());
     _timer.Change(0, 5000);
   }
 }

The ServiceControl namespace contains the C++/CLI interop layer. This layer uses C++/CLI as the binding element between the native API and the WPF application. The main ServiceControlInterop.cpp file contains all the functionality that we need and that is used by the WPF application. For example using the controller application we can use AddService(…) or RemoveService(…) to add or remove a service respectively. We can also configure the service as a trigger start service for either a USB device arrival or first available IP address by using SetServiceTriggerStartOnUSBArrival or SetServiceTriggerStartOnIPAddressArrival respectively. Reviewing both function implementations reveals that basically both are following identical paths. They:

  • First, use OpenSCManager to get a handle to the Service Control Manager (SCM)
  • Then use the SCM handle OpenService, to get an actual service handle that we wish to configure
  • Finally call ChangeServiceConfig2 to set the specific trigger

All this was explained in detail in the last post (Windows7 Trigger Start Services – Part 1: Introduction

You can download the code sample for this application. Note that you will have to run Visual Studio as administrator (see image below) because you will need to register, start, and stop services. . You will also need to Windows 7 SDK to compile the C++ part of the solution.

image

When compiling and running the default solution (the WPF application) you will see the following image.

image

This is the main WPF controller application. From here, you can create the service by clicking the Create Manual button.

Next, open the Services Window by typing “Services” in the Start Menu search box. You should see the Service window. Locate the USBCopyService; it should appear as in the following image.

image

Click the Run button and then the Refresh button in the Services window, or just press F5. You will not notice a great deal of change, but the USBCopyService changed from Manual to Started, as shown in the following image.

image

 

A second look at the actual application reveals the service activity in the log file. As you can see in the following image, the services awaken every 5 seconds and poll the system, looking for USB devices:

image

Click the Stop button to stop the service and then click the Delete Service to delete it. Now click the Trigger Start button to register and configure the service as a trigger start service that is triggered once a USB Generic disk arrives. If you check the Service window, you will see the USBCopyService listed as “manual” where in reality it is configured as triggered start service (there is just no graphical representation of that).

If you plug in a USB disk with a “ToCopy” folder the service will kick into action and copy the files to c:\FromUSB. Not the best implementation, but hey, it is only a demo. The following image shows a single line in the log file because the service actually ran only once; it executed the DoWork method and then quit. It didn’t run and poll the system every 5 seconds and didn’t waste resources or become a security liability.

image

To conclude

Developing a service with Windows 7 trigger start service in mind might be a little more difficult than a regular “auto-run” service that just runs in idle from boot to shutdown. But in practice, all it takes is only a few lines of code, no more. And these few lines of code can have a very big affect in terms of resource consumption and security. So the next time you build a new Windows Service, try to incorporate triggers.

You can learn about Windows 7 using the Windows 7 Training Kit for Developers or by viewing Windows 7 videos on Channel 9.

You can also get hands-on experience for Windows 7 Trigger Start Services using the Windows 7 Online training that is part of the Channel 9 Learning Center


Windows7 Trigger Start Services – Part 1: Introduction

We introduced Service 0 Isolation a few weeks ago as an application compatibility topic. It is only natural that we continue our conversation about services in the context of Windows 7. But this time, we will talk about some of the benefits to service optimization that are available in Windows 7. This post focuses on a new feature in Windows 7 called Trigger Start Services. But before we jump into the API, let’s provide some background about services.

What Are Services?

A service is an integral mechanism built into Microsoft Windows operating systems. You can think of services as “special applications” that run with no regard to the current user context. Services are different from “regular” user applications because you can configure a service to run from the time a system starts up (boots) until it shuts down, without requiring an active user to be present – that is, services can run even though no users are logged on.

We like to think about services as running tasks for us in the background without interfering with user operations. Services on Windows are responsible for all kinds of background activity that do not involve the user, ranging from the Remote Procedure Call (RPC) service, through Printer Spoolers, to the Network Location Awareness service.

Over the years, Windows has grown and with it the number background services. But to be honest, background services in Windows are a pain – the operating system ships with a lot of them in the box. On top of that, ISVs and their applications add even more services, like software updates to name only one. With that said, some of these services are critical and are required during boot sequences, some are required later when a specific user logs on, while others don’t need to execute until they are called upon. Nonetheless, when you look at the currently running services, you see a lot of services that really don’t need to run 24x7.

What’s Wrong with Services Running 24x7?

There are several issues with having services run 24x7:

First, why have something run (even in the background) when there is no need for it to run? Any running process (services included) uses valuable memory and CPU resources that could be used by other applications and services. If you total up all the services that are running at any given time, they add up to quite a lot of memory, handles, threads, and plenty of CPU usage. All of these “wasted” resources reduce the overall computer performance, decrease its responsiveness, and make users think their computers are sluggish and slow. Also, since most of the running services are configured as Auto-Start (start running upon system log-on), these services have an impact on the computer's boot time.

Second, these wasted resources, have a direct impact on power consumption. The more demands we place on the CPU, the more power our computer uses. This can be critical for laptops, and could reduce battery life from four hours to three hours.

Third, having non-productive software run all the time may lead to memory leaks and overall system instability. This can lead to application crashes and ultimately computer crashes.

Last, but not least, if a service is running 24x7, and this services is well known (any popular application might have one – like the PDF Reader), it provides a larger attack surface. A hacker might use the knowledge that a certain popular application installs a service that runs 24x7, and try to hack into that service to gain privileged access to the computer.

Given all of the above, it makes you wonder why so many developers configure their services to run all the time when there are other options. Even before Windows 7, there were several service start-up options:

  • Disabled completely disables the service and prevents it and its dependencies from running—this means that the user must start the service manually from the Control Panel or the command line
  • Manual starts a service as required (defined by dependencies to other services) or when called from an application using the relevant API as shown later in this post
  • Automatic starts the services at system logon
  • Automatic Delayed is a newer startup type introduced in Windows Vista that starts the service after the system has finished booting and after initial demanding operations have completed, so that the system boots up faster

Unfortunately, many ISVs (Microsoft included) still choose to configure their services to Automatic (or Automatic Delayed) because it is the easy solution for everyone. A service simply runs 24x7 and is always available, eliminating the need to check any dependencies or verify that the service is running.

There are many examples of existing services that can become more resource friendly and more secure by not running 24x7. For example, think of an update service that checks for new application updates. If the computer is not connected to a network and has no IP available, why should the update service run? It can't reach anywhere, so why run a program that does nothing? Think about a policy management service that is invoked when a group policy changes or when the computer joins or leaves a domain, but right now the computer is connected to my home network and again the service works in vain.

Introducing Windows 7 Trigger Start Services

The solution for the above problems is to move the service out of its “forever running state” into other types of background activity, such as scheduled tasks or trigger-start services. This post focuses on Windows 7 Trigger Start Services. Windows 7 Scheduled Tasks include a lot of valuable information that we will describe in another post.

Trigger-start services are new to Windows7. A trigger-start service is a regular service that you can configure to run (or stop running) only when it is triggered, that is, only when certain criteria and conditions that you define are met (for example, when the first network IP address becomes available, or when the last network IP is lost). Here is a list of the available triggers that you can use to configure the Start-Up mode of a given service:

  • Device interface arrival or departure
  • Joining or leaving a domain
  • Opening or closing a firewall port
  • Group policy change
  • First IP address available/ last IP address leaving
  • Custom event – Event Tracing for Windows (ETW)

The last item in the list represents the extendibility point. As a developer, you can configure any ETW event as a trigger for services, which gives you a very good tool to fine-tune your control over starting and stopping services from your application.

So what exactly is a trigger?

A trigger consists of:

  • A trigger event type
  • A trigger event subtype
  • The action to be taken in response to the trigger event
  • One or more trigger-specific data items (for certain trigger event types)

The subtype and the trigger-specific data items together specify the conditions for notifying the service of the event. The format of a data item depends on the trigger event type; a data item can be made up of binary data, a string, or a multistring.

Working with Trigger Start Services

Unfortunately, Windows 7 Services MMC UI does not include a graphical representation of the trigger start services. However, you have two options. You can still use the old and good sc.exe (Service Configuration command line tool), or you can use the WIN32 ChangeServiceConfig2 method to configure the service start option programmatically as demonstrated in this post.

Using SC.exe to Query Service Trigger Information

It's time to start have some fun. First, let’s start with just extracting some configuration information from a few services. The generic form for using the service configuration is:

sc <server> [command] [service name] <option1> <option2>...
Where server is optional and by default you work with the local computer:
  • command is the operation you wish to perform like querying trigger information
  • service name is the name of the service you wish to work with
  • options are the different values (options) you can pass to configure the service

Let’s start by querying a specific service for its trigger start configuration. To do so you need to launch a Windows Shell window:

  1. Open the start menu.
  2. Type CMD in the search box.
  3. Choose cmd.exe.
    This will open a Windows Shell window.
  4. Type sc qtriggerinfo w32time and press enter

This is how it should look:

image

As you can see, we queried the trigger information of the W32time service, which is configured to start when the computer is joined to a domain and stop when the computer leaves the domain.

Microsoft updated the sc.exe command-line tool for Windows 7 to support configuring and querying a service for supported triggers. Type sc triggerinfo in the Windows shell window and press enter. The result looks like the box below, and lists all the different triggers and how to configure a service to use trigger start services.

C:\>sc triggerinfo
DESCRIPTION:
        Changes the trigger parameters of a service.
USAGE:
        sc <server> triggerinfo [service name] <option1> <option2>...
OPTIONS:
 start/device/UUID/HwId1/... <Start the service on arrival of the
                             specified device interface class UUID
                             string with one or more hardware ID
                             strings and/or compatible ID strings>
 start/custom/UUID/data0/.. <Start the service on arrival of an
                             event from the specified custom ETW
                             provider UUID string with one or more
                             binary data items as hexadecimal
                             string format such as ABCDABCD to
                             set 4 byte data>
 stop/custom/UUID/data0/... <Stop the service on arrival of an
                             event from the specified custom ETW
                             provider UUID string with one or more
                             binary data items as hexadecimal
                             string format such as ABCDABCD to
                             set 4 byte data>
 start/strcustom/UUID/data0/.. <Start the service on arrival of an
                             event from the specified custom ETW
                             provider UUID string with one or more
                             optional string data items>
 stop/strcustom/UUID/data0/.. <Stop the service on arrival of an
                             event from the specified custom ETW
                             provider UUID string with one or more
                             optional string data items>
 start/networkon             <Start the service on first IP address>
 stop/networkoff             <Stop the service on zero IP addresses>
 start/domainjoin            <Start the service on domain join>
 stop/domainleave            <Stop the service on domain leave>
 delete                      <Delete the existing trigger parameters>

For example, to configure a service to start when the first IP address becomes available, all you need to do is type sc triggerinfo [your service name] start/networkon, where “your service name” is replaced with the name of the service that you wish to configure.

Configuring Trigger Start Services Programmatically Using ChanceServiceConfig2

The more interesting aspect, from a developer's point of view, is writing services that are trigger aware and using code to configure a service. In Windows 7, you can use the ChangeServiceConfig2 function to configure service trigger information and the QueryServiceConfig2 function to query it.

Service trigger registration is performed by calling ChangeServiceConfig2, passing SERVICE_CONFIG_TRIGGER_INFO for the dwInfoLevel parameter, and providing the trigger registration information in a SERVICE_TRIGGER_INFO structure through the lpInfo parameter. In addition, one or more trigger-specific data items can be specified. The following is an example of a service installer function that creates a USB device trigger for a service that is named MyService:

define SERVICE_NAME L"MyService"
//set the device guid
static const GUID GUID_USBDevice = {
0x53f56307, 0xb6bf, 0x11d0,
{0x94, 0xf2, 0x00, 0xa0, 0xc9,
0x1e, 0xfb, 0x8b }};

BOOL _SetServiceToStartOnDeviceTrigger()
{
BOOL fResult = FALSE;

SC_HANDLE hScm = OpenSCManager(
NULL, //local machine
NULL, //active database
SC_MANAGER_CONNECT);

if(hScm != NULL)
{
SC_HANDLE hService = OpenService(
hScm,
SERVICE_NAME,
SERVICE_ALL_ACCESS);

If( hService != NULL)
{

LPCWSTR lpszDeviceString = L"USBSTOR\\GenDisk";
SERVICE_TRIGGER_SPECIFIC_DATA_ITEM deviceData = {0};
deviceData.dwDataType = SERVICE_TRIGGER_DATA_TYPE_STRING;
deviceData.cbData =
(wcslen(lpszDeviceString)+1) * sizeof(WCHAR);
deviceData.pData = (PBYTE)lpszDeviceString;



SERVICE_TRIGGER st;
st.dwTriggerType =
SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL;
st.dwAction = SERVICE_TRIGGER_ACTION_SERVICE_START;
st.pTriggerSubtype = (GUID *) &GUID_USBDevice;
st.cDataItems = 1;
st.pDataItems = &deviceData;


SERVICE_TRIGGER_INFO sti;
sti.cTriggers = 1;
sti.pTriggers = &st;
sti.pReserved = 0;

fResult = ChangeServiceConfig2(
hService,
SERVICE_CONFIG_TRIGGER_INFO,
&sti);
}
CloseServiceHandle (hService);
}
CloseServiceHandle (hScm);

if(!fResult)
{
printf("Service trigger registration failed (%d)\n",
GetLastError());
}
return fResult;
}
Note: all services are controlled by the Service Control Manager (SCM), which we’ll touch on in a different post.

In the above code snippet, you can see that first we get a handle (hScm) to the SCM by calling openSCManager. Next, we call openService and pass the handle to the SCM- hscm,and the service name – SERVICE_NAME that we wish access. The last parameter, SERVICE_ALL_ACCESS, indicates that we have complete access to the services. Assuming we got a valid handle to the service, we now start to build the specific structure that we’ll soon use to configure the service.

SERVICE_TRIGGER_SPECIFIC_DATA_ITEM defines the trigger event type. It contains trigger-specific data for the service trigger event. In our case we define the string that represents a USB gen disk arrival.

Next we define the SERVICE_TRIGGER structure, which represents a service trigger event. Note that this is where we define the trigger type (device arrival), the action (start the service), and the trigger sub type (the specific family of the USB device). Then we define one device that will trigger the service. Note that you can define an array of devices and their GUIDs. You should also note that we don’t want the service to be triggered upon just any USB device arrival like a mouse or a camera. We want the service to start only when a USB disk arrives.

Finally, we define the SERVICE_TRIGGER_INFO structure, which contains trigger event information for a service. This structure simply points to the SERVICE_TRIGGER struct that we defined previously, and the number of triggers that, in this case, is one.

Now we can call the ChanceServiceConfig2 function and pass the handle to the service we wish to configure, a SERVICE_CONFIG_TRIGGER_INFO parameter that indicates that we wish to configure the service trigger, and a null.

That is all there is to it. If we are successful, then our service will run after we insert a USB hard drive.

In the next post, we'll review how to write a simple implementation of a .NET service that we’ll program to start upon arrival of a USB generic disk.

You can learn about Windows 7 using the Windows 7 Training Kit for Developers or by viewing Windows 7 videos on Channel 9.

You can also get hands-on experience for Windows 7 Trigger Start Services using the Windows 7 Online training that is part of the Channel 9 Learning Center


Windows 7 GA – Time for Some New Windows 7 Developer Resources

Windows 7 is now available to the public and anyone can buy and install Windows 7, whether for a new computer or an existing one. Soon, people from around the world will run your applications on Windows 7. They will expect the application to work and to feel as though it is a native Windows 7 application that takes advantage of new Windows 7 features and technologies like the Taskbar, libraries, touch, and sensors.

As Windows 7 approached GA, we continued to release new developer content to help you get up to speed with the new operating system. Now that it's here, Windows 7 GA is a great “excuse” for us to give you a quick update on all the Windows 7 developer content that is available to help you learn how to write a great Windows 7 application.

Below is a list of locations where you can find Windows 7 developer content.

Updated Windows 7 Training Kit – (Download it now)

image To help you get your application onto Windows 7 as soon as possible, we updated the Windows 7 Training Kit for Developers. You can still find all the previous topics such as Taskbar, Sensor and Location, Libraries and Shell, Multitouch, Ribbon, etc. New to the kit are labs that work with VS2010 and use the new MFC improvements in VS2010 (download VS2010). We also added VB to all of our managed solutions – truly, no developer is left behind.

 

Windows 7 Online Training on Channel 9 Learning Center

Let’s assume you are interested in learning about Windows 7 libraries, or how to add some cool Taskbar functionality to your application, but you don’t want to download the entire training kit. Well with the Windows 7 Online Training Kit located on the Channel 9 Learning Center, you have immediate access to all Windows 7 learning units individually. Each learning unit (like the Taskbar) includes a few hands-on-labs and related videos. This gives you quick and easy access to most of our training material. For the rest of the content, like PowerPoint presentations and additional demos, you will have to download the Windows 7 Training Kit for Developers. The following image shows part of the managed code hands-on-lab for the Taskbar.

image

As always, the Windows 7 Topic Area on Channel 9 still features specific Windows 7 videos and screencasts. Over the past few weeks, we created new videos that I am sure you will find exciting and helpful, including a new Mark Russinovich video. As a friendly reminder, the last video Mark did, “Mark Russinovich: Inside Windows 7, was a Channel 9 blockbuster. If you haven't already viewed it, I highly recommend it, and make sure you see Mark’s new video Mark Russinovich: Inside Windows 7 Redux. Don’t forget to stay up-to-date with other topics:

  • Using Windows 7 – Contains consumer- and user-related videos such as how to install Windows 7 and how to set up a home group network
  • Programming Windows 7 – I don’t really need to explain what goes here, right?
  • Last but not least, “Under the Hood” –Covers deep architectural Windows concepts

MSDN Developer Center

The MSDN Developer Center also received a “Windows 7 GA refresh” and now sports a new look and much improved functionality. The MSDN Developer Center includes a lot of Windows 7 material that extends the training content on available on Channel 9. You can think of the MSDN Developer Center as a hub for the Windows 7 content that will give you a great head start as you develop applications that will shine on Windows 7. You can find information about specific topics, review different programming models, learn about the developer tools that you can use, watch videos, and read blogs.

image

A New Book for Windows 7 Developers

Among the other things that you will find on the MSDN Developer Center, is a list of recommended Windows 7 books for developers. It turns out that over the past few months, I’ve been busy writing a Windows 7 book with three amazing co-authors: Laurence Moroney, Sasha Goldshtein, and Alon Fliess. Together, we wrote Introducing Windows 7 for Developers. It covers most of the exciting Windows 7 features like the Taskbar, Libraries, Sensor and Location, Multitouch (including new WPF 4 support with VS2010), and even Silverlight out of image

browser (including touch :). As far as I know, this is the first Windows 7 developer book, and I hope you will find it useful. Mark Russinovich found this book helpful while integrating Windows 7 features with the Sysinternals tools and he wrote the foreword for this book.

I hope this list will help get you on your way to writing amazing Windows 7 applications.


Windows 7 Labs @ PDC

PDC 2009 takes place at the LA Convention Center on November 17th, 18th, and 19th. As I wrote before, The Professional Developers Conference is the one event each developer has to attend. Windows 7 will become generally available (GA) to the public on October 22nd. With the pre-release veil of secrecy lifted, during this year's PDC we can dive deep (very deep) into Windows 7 to extend our understanding of how Windows 7 works and, even more importantly, how developers can take advantage of all the great new improvements and features Windows 7 has to offer.

Just in case you missed my previous announcement, there is a FREE Windows 7 (seminar) Boot Camp led by top Microsoft Windows experts like Mark Russinovich, Landy Wang, and Arun Kishan. Then, during the PDC proper, we’ll have several deep-dive Windows 7 sessions.

During this year's PDC, we’ll host the Windows 7 Developer Center. The Windows 7 Developer Center gives you the opportunity to test your application on Windows 7, identify and solve problems with a group of consultants, and eventually get your application Logo-certified. Applications can be loaded onto a secure Windows 7 test platform in a private developer lab environment for Logo testing and submission. Our Windows Applications Developer Consultants can also help with Windows Compatibility questions or offer specific guidance for how you can make your application shine on Windows 7. You can pre-book a time slot right away, book a time when you get to the PDC, or just stop by Room 504/505. And guess what? It is all free; all you need to do is register.

Registration

You can pre-register for a 1-hour timeslot in the lab as outlined below. You can also register upon arrival at PDC09 by signing up at the reception station located in Room 504/505, or just stop by to talk about developing applications for Windows 7.

Monday 11/16

10:00 am

11:00 am

1:00 pm

2:00 pm

3:00 pm

4:00 pm

Tuesday 11/17

11:00 am

1:00 pm

2:00 pm

3:00 pm

4:00 pm

5:00 pm

Wednesday 11/18

11:00 am

1:00 pm

2:00 pm

3:00 pm

4:00 pm

5:00 pm

Thursday 11/19

8:30 am

9:30 am

10:30 am

11:30 am

1:30 pm

2:30 pm

 

Getting Started

Logo Test - To help maximize your time in the lab at PDC, we are asking that you run the Logo test and submit the .xml result report to our team for review prior to the event. Our consultants will analyze your results and prepare a report to review with you on-site at PDC.

VeriSign & WinQual IDs – In order to submit your product for Windows 7 Logo, you will need to obtain both of these credentials. Once obtained, you will be able to work directly with a Microsoft consultant through the submission process while on-site at PDC. (More info here - https://winqual.microsoft.com/.)

Follow these simple steps to register and prepare for PDC 2009:

1. Email srglabs@microsoft.com with 3 timeslots in order of preference from those listed above.

2. Download the Logo toolkit from MS Connect and follow the instructions for testing.

3. Send the .xml result report generated by the Logo toolkit to srglabs@microsoft.com for analysis.

4. Sign up for VeriSign & WinQual IDs that will be required for Logo submission by visiting https://winqual.microsoft.com/.

Additional Resources

• For general questions contact srglabs@microsoft.com

• For questions and more details about the Windows 7 Logo Program visit MS Connect

This is a great opportunity to prepare your applications for Windows 7, but there is limited availability so be sure to register early to get your preferred time slot.

You can learn about Windows 7 using the Windows 7 Training Kit for Developers or by viewing Windows 7 videos on Channel 9