Scott Hanselman

The Weekly Source Code 45 - Kicking Butt on Windows 7 *and* Windows XP

September 1, '09 Comments [11] Posted in Source Code | Win7 | Windows Client
Sponsored By

image I really advocate folks reading as much source as they can because you become a better writer by reading as much as writing. That's the whole point of the Weekly Source Code - reading code to be a better developer.

There's a very cool developer context going on right now called "Code7." If you code a Windows 7 application between now and October 7 you could win a giant bag of money and/or a trip to PDC.

There's a pile of new APIs in Windows 7 (as well as existing and useful Vista APIs) like these:

  • Windows 7 Taskbar Integration
  • Transactional File System
  • I/O Optimization
  • Event Tracing for Windows (ETW)
  • Windows 7 Libraries
  • Windows 7 Sensor and Location Platform
  • Aero Glass

In some of these instances, there isn't hardware (yet) for things like Ambient Light Sensors. One dude has taken a Webcam and hooked it into the Windows 7 Sensors API and made a program to dim his monitors with the new Monitor Configuration API*. He might even make it turn off his machine when he walks away.

XP2Win7 - Windows 7 Sample Code/Application

I've been checking out what sample applications there are to start learning about Windows 7. The coolest so far as been the "PhotoView" application. Don't sweat the fact it's YAPA (Yet Another Photo Application) and consider it a loosely confederated collection of samples.

MainWindow

What's cool about this application is that it works on Windows XP and Windows Vista and Windows 7. This may be obvious and even a silly statement to you, Dear Reader, but it's a nice reminder that and app can be awesome on all three platforms. 99% of the apps that I use work great on Windows 7. Sure, some drivers and wacky VPN things will need to be updated, but it's comforting to me to know I can write an app for Windows that will, um, work on Windows. ;)

This PhotoView application, also called XP2Win7 is written managed code and uses plugins to "light up on up-level platforms." That's fancy Microsoft talk that means if your operating system has a feature the app will detect it and use it.

There's a great overview Word Document that explains the app and how it is written. The MSI will install the app, then optionally the source in ~\MyDocuments\Xp2Win7 if you have trouble finding it. You'll need Visual C++ if you want to build a few parts...just read the readme. It's a pretty extraordinarily broad sample with examples on how to make MMC ReportViewer snapins, delayed services, register scheduled tasks, piles.

(Unfortunately the guys that wrote this didn't use MEF for their plugin model, but I'll talk to them. It would allow them to remove a lot of boilerplate plugin monkey code.)

It uses the Windows API Code Pack (I talk about this below) to do a lot of its work. Here's a few fun parts.

TaskBar JumpLists

When the app is run under Windows 7 it includes "jumplists" when you right-click (or swipe-up) on the taskbar button:

image

This is easily added with the Taskbar API. Notice the multiple categories, user tasks, recent items, and custom categories.

Taskbar.JumpList.CustomCategories.Clear();
Taskbar.JumpList.UserTasks.Clear();
Taskbar.JumpList.KnownCategoryToDisplay = KnownCategoryType.Recent;

CustomCategory allAlbumsCategory = new CustomCategory("All Albums");
//...snip out enumerating of the filesystem to get photo albums
Taskbar.JumpList.CustomCategories.Add(allAlbumsCategory);

Taskbar.JumpList.UserTasks.Add(
new JumpListLink()
{
Title = "Reset configuration",
Path = typeof(XP2Win7.VistaPlugins.ConfigurationResetter.Program).Assembly.Location,
Arguments = XP2Win7.VistaPlugins.ConfigurationResetter.Program.ResetCommand
});
Taskbar.JumpList.UserTasks.Add(
new JumpListLink
{
Title = "Launch indexing task",
Path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Constants.ServiceCommandLine),
Arguments = Constants.ServiceAsTaskCommandLine
});
Taskbar.JumpList.UserTasks.Add(
new JumpListLink { Title = "Open albums directory", Path = Host.UserConfiguration.AlbumRepositoryPath });

Taskbar.JumpList.RefreshTaskbarList();

Windows 7 Libraries

You can also add Windows 7 Libraries for your application:

//Create new shell library under the default Libraries
using (ShellLibrary library = new ShellLibrary("XP2Win7", true))
{
library.LibraryType = LibraryFolderType.Pictures;
library.IconResourceId = GetPictureLibraryIcon(); //Set the same Icon as the Picture library
library.IsPinnedToNavigationPane = true;


foreach (string folderPath in GetPicturesFolders())
{
library.Add(folderPath);
}

library.ShowManageLibraryUI(Application.Current.MainWindow,
"Manage the XP2Win7 library", "You can manualy add or remove folders",
true);
}

User Access Control (UAC)

Windows Vista and Windows 7 both include User Access Control (UAC). You'll recognize the little shield icon next to a button that will require a prompt from the user in the dialog below.

Application reconfiguration

Their application uses this in a few places. First, can we even show the little shield? We only want to do that if UAC is enabled:

protected override BitmapSource BitmapSource
{
get
{
if (UacHelpers.UserAccountControl.IsUacEnabled)
{
return Microsoft.SDK.Samples.VistaBridge.Library.StockIcons.StockIcons.Shield;
}
else
{
return ImageFromResource(Assembly.GetExecutingAssembly(),
"UserAccountControl.StartService-128x128.png");
}
}
}

Then, if they do click the button, and we want to launch some process as Administrator, we'll need to call a special API to do that. This is mean easy by helper APIs.

if (UacHelpers.UserAccountControl.IsUacEnabled || !UacHelpers.UserAccountControl.IsUserAdmin)
{
UacHelpers.UserAccountControl.CreateProcessAsAdmin(
typeof(ServiceStarter.Program).Assembly.Location, "XP2Win7ImageDataService");
}
else
{
Process.Start(typeof(ServiceStarter.Program).Assembly.Location, "XP2Win7ImageDataService");
}

Pretty slick and easy to code. The Windows API Code Pack makes all these APIs and dozens more easy for managed code developers (C#, VB, and everyone else.)

Windows API Code Pack

Another great pile of Windows sample code is the Windows API Code Pack. This thing is a gold mine of samples and they are all in C# and VB. There's like 20+ samples. Here's a few:

Power Management

It's nice if your app knows the power status of the machine it's on and avoid doing crazy stuff if it's on batteries.

Power Management

You can get all sorts of great power-related info:

private void GetPowerSettings()
{
settings.PowerPersonality = PowerManager.PowerPersonality.ToString();
settings.PowerSource = PowerManager.PowerSource.ToString();
settings.BatteryPresent = PowerManager.IsBatteryPresent;
settings.UpsPresent = PowerManager.IsUpsPresent;
settings.MonitorOn = PowerManager.IsMonitorOn;
settings.MonitorRequired = PowerManager.MonitorRequired;

if (PowerManager.IsBatteryPresent)
{
settings.BatteryShortTerm = PowerManager.IsBatteryShortTerm;
settings.BatteryLifePercent = PowerManager.BatteryLifePercent;

BatteryState batteryState = PowerManager.GetCurrentBatteryState();

string batteryStateStr = string.Format(
"ACOnline: {1}{0}Max Charge: {2} mWh{0}Current Charge: {3} mWh{0}Discharge Rate: {4} {0}Estimated Time Remaining: {5}{0}Suggested Critical Battery Charge: {6} mWh{0}Suggested Battery Warning Charge: {7} mWh{0}",
Environment.NewLine,
batteryState.ACOnline,
batteryState.MaxCharge,
batteryState.CurrentCharge,
batteryState.ACOnline == true ? "N/A" : batteryState.DischargeRate.ToString() + " mWh",
batteryState.ACOnline == true ? "N/A" : batteryState.EstimatedTimeRemaining.ToString(),
batteryState.SuggestedCriticalBatteryCharge,
batteryState.SuggestedBatteryWarningCharge
);

settings.BatteryState = batteryStateStr;
}
}

There's also lots of power-related events you can be notified of:

PowerManager.IsMonitorOnChanged += new EventHandler(MonitorOnChanged);
PowerManager.PowerPersonalityChanged += new EventHandler(
PowerPersonalityChanged);
PowerManager.PowerSourceChanged += new EventHandler(PowerSourceChanged);
if (PowerManager.IsBatteryPresent)
{
PowerManager.BatteryLifePercentChanged += new EventHandler(BatteryLifePercentChanged);

// Set the label for the battery life
SetLabelButtonStatus(batteryLifePercentLabel, string.Format("{0}%", PowerManager.BatteryLifePercent.ToString()));
}

PowerManager.SystemBusyChanged += new EventHandler(SystemBusyChanged);

Stock Icons

A lot of folks don't realize that there's a pile of stock icons that are available in Windows and you can access them programmatically.

image 

That means if you need the stock icon for a BluRayRom or a ZipFile, you can just ask for it.

Task Bar Progress

One of the nicest subtle features of Win7 is that if you've got a Progress Bar doing something in your application you can make its progress known in the Taskbar icon itself. This is fantastic for long-running processes like file copies, etc.

Notice the progress bar in this application and the taskbar button in the bottom right reflects it.

image

There's also icon/image overlays and other nice touches. Even better, this is epic-easy:

// When the user changes the trackBar value,
// update the progress bar in our UI as well as Taskbar
progressBar1.Value = trackBar1.Value;

TaskbarManager.Instance.SetProgressValue(trackBar1.Value, 100);

Since your app can have multiple progress bars, you have to manually decide what you want the taskbar progress to look like.

Core Helpers

Finally there's some nice "CoreHelpers" to make your applications easy to read and run on XP, Vista and Win7 at the same time:

//example
if (CoreHelpers.RunningOnXP()) { ... }
//example
if (CoreHelpers.ThrowifNotWin7() { ... }
// and all the others you'd expect for XP, Vista, Win7

I've just touched the surface of these samples. If you're doing Windowe Client development be sure to check out http://windowsclient.net/ and http://www.msdn.com/windows for more and start writing your application for the https://www.code7contest.com.

1. Get Windows 7 and the SDK

2. Develop and Test Your Application

3. Get the Windows 7 Logo

4. Light Up Your Application with Windows 7

Related Links

* Note the (lightweight) parameter I passed into this MSDN URL. Check out the new "Lightweight" MSDN Library and give the team feedback on the site!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Tuesday, September 01, 2009 4:40:10 AM UTC
Ha! He is wearing his undies like I sometimes do. Great kid!
Tuesday, September 01, 2009 7:08:40 AM UTC
Hi Scott,

Thanks for this post. As one of the developers who wrote this app, I can tell you that the next release will indeed use MEF for plugin extensibility.

Another minor correction is that the UacHelpers class you show in a couple of snippets is not in fact part of the Windows API Code Pack. It's a separate project I'm maintaining on CodePlex (http://uachelpers.codeplex.com).

Sasha
Tuesday, September 01, 2009 5:13:00 PM UTC
Thanks for the update, great stuff here. I also like what I hear about porting this over to use MEF.
Wednesday, September 02, 2009 4:04:56 PM UTC
The problem with the XP2Win7 application is that there's no source code available!

I downloaded the file described as "source code", which was a Windows Installer package. There was an option to install the source code, which I selected, but after the installer completed, there was no sign of the source code.

Also, uninstalling the application doesn't work unless you mess around with the NTFS permissions on the "C:\ProgramData\Fabrikam" folder. The folder name isn't obviously related to the application, but thankfully the error message from the uninstaller identifies the problem quite well.

The application sounds like a good sample, so I hope they get around to releasing the source code at some point.
Richard
Wednesday, September 02, 2009 4:29:34 PM UTC
Richard - there is source code, and it IS install of you run the installer. I agree ibshould be a simple zip file download, but it's not (yet).

The source, as I mention above, is in you c:\users\yourname folder.
Wednesday, September 02, 2009 6:06:27 PM UTC
Strange - when I installed it, I checked my profile folder, the folder I'd told it to install in, the default installation folder, and the ProgramData folder, and I couldn't find any source code. I've just tried again, but left the installation directory as the default, and the source code has appeared under my Documents folder.

Thanks for the quick reply!
Richard
Wednesday, September 02, 2009 6:10:07 PM UTC
Richard - Just to be clear, it's TOTALLY lame that it's in a random place. ;) I'll talk to them.
Saturday, September 05, 2009 6:25:48 AM UTC
UAC is User Account Control, NOT User Access Control.
virgola
Monday, September 07, 2009 11:01:44 AM UTC
when i see scott gu in short form gu
i have a fun
because in india we say gu for potty
Wednesday, September 09, 2009 1:04:57 AM UTC
windows 7 the the most fashion one in windows family, but it also have lots of new knowledge which we must spend time learning!
Thursday, September 10, 2009 4:50:38 PM UTC
@anirudha

ROTFLAO!!!
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.