300 likes | 441 Vues
Dive deep into advanced programming techniques tailored for Windows 7 with Kate Gregory. This guide covers essential topics including Libraries management, task integration with Jumplists, and the critical aspects of restart and recovery processes. Learn to leverage user awareness with UAC, implement efficient power management, and design applications that react instead of poll. Discover how to utilize Windows features like service triggers, DPI scaling, and file path management to create user-friendly applications that seamlessly integrate into the Windows 7 ecosystem.
E N D
DEV304 Advanced Programming Patterns for Windows 7 Kate Gregory Gregory Consulting www.gregcons.com/kateblog, @gregcons
Agenda • Libraries • Tasks that set Status or send commands • Restart and Recovery • Trigger Started Services • Managed code only
Call to Action • Windows 7 has been here for almost two years • You’ve made your app work on Windows 7 • UAC • DPI scaling • Hardcoded file paths • You’ve lit up your app with visuals • Jumplists • Taskbar overlays • Ribbon • Now take the next step
Windows 7 is more than eye candy • Stop polling! You can be notified • Power management • Network awareness • Service triggers • Be considerate • Restart and recovery • Work the way the user thinks • Libraries • Jumplists
Windows 7 Recipes • Samples on Code Gallery • Yours to use, change, learn from • Dependency on Code Pack • http://code.msdn.microsoft.com/Windows-7-Taskbar-Single-4120eafd • http://code.msdn.microsoft.com/Windows-Restart-and-cc461aa9 • http://code.msdn.microsoft.com/Windows-Trigger-Start-f75f0fbb
Libraries • Aggregation of (pointers to) folders • Don’t have to be on the same machine • Users can control what folders are in a library • More control for them, less coding for you
Libraries demo
Create and Manage Libraries • var lib = new ShellLibrary("KateDemo", false); • lib.Dispose(); • ShellLibrary.ShowManageLibraryUI("KateDemo", • new WindowInteropHelper(this).Handle, • "Demo Library Manager", "Manage the KateDemo Library", • true);
Delete a Library • string librariesPath = Path.Combine( • Environment.GetFolderPath( • Environment.SpecialFolder.ApplicationData), • ShellLibrary.LibrariesKnownFolder.RelativePath); • string libraryPath = Path.Combine(librariesPath, "KateDemo"); • string libraryFullPath = Path.ChangeExtension(libraryPath, • "library-ms"); • File.Delete(libraryFullPath);
Use a Library to open files • using (varlib = ShellLibrary.Load("KateDemo", true)) • { • varpickLocationDialog = new CommonOpenFileDialog(); • pickLocationDialog.Title = "Open a file"; • pickLocationDialog.DefaultDirectoryShellContainer = • ShellFolder.FromParsingName(lib.ParsingName) as ShellContainer; • pickLocationDialog.InitialDirectoryShellContainer = • ShellFolder.FromParsingName(lib.ParsingName) as ShellContainer; • pickLocationDialog.AllowNonFileSystemItems = false; • pickLocationDialog.IsFolderPicker = false; • pickLocationDialog.Multiselect = false; • var result = pickLocationDialog.ShowDialog(); • if (result == CommonFileDialogResult.Cancel) { MessageBox.Show("You cancelled"); } • else { MessageBox.Show("You selected " + pickLocationDialog.FileName); }
Watching a library • watcher = new ShellObjectWatcher(lib, true); • watcher.AllEvents += Watcher_LibraryChanged; • watcher.Start(); • void Watcher_LibraryChanged(object sender, • ShellObjectNotificationEventArgsargs) • { • // args will tell you what’s going on • . . .
Tasks • Jumplist tasks launch another exe • Open the help in help viewer, the readme in notepad • Launch a companion app • But what if you want tasks to communicate to the running app? • The exe you launch is your own exe again • Has to be modified to be “single instance”
Single Instance for Tasks • SingleInstanceManager manager = • SingleInstanceManager.Initialize(GetSingleInstanceManagerSetup()); • // . . . • private static SingleInstanceManagerSetupGetSingleInstanceManagerSetup() • { • return new SingleInstanceManagerSetup("WpfSample") • { • ArgumentsHandler = • args => ((App)Application.Current).ProcessCommandLineArgs(args), • ArgumentsHandlerInvoker = new ApplicationDispatcherInvoker(), • DelivaryFailureNotification = • ex => MessageBox.Show(ex.Message, "An error occurred") • }; • }
Adding Tasks to the Jumplist • string cmdPath = Assembly.GetEntryAssembly().Location; • JumpListjumpList = JumpList.CreateJumpList(); • jumpList.AddUserTasks( • new JumpListLink(cmdPath, Status.Online.ToString()) • { Arguments = Status.Online.ToString() }, • new JumpListLink(cmdPath, Status.Away.ToString()) • { Arguments = Status.Away.ToString() }, • new JumpListLink(cmdPath, Status.Busy.ToString()) • { Arguments = Status.Busy.ToString() }); • jumpList.Refresh();
Restart and Recovery • Prevent lost data • Your own code is called when app is terminating • Store ephemeral data • On startup, check for a restart hint • Restore ephemeral data • Problem: too much freedom • What to store, and where? • File format • How to structure restart hint?
Restart and Recovery Recipe • Leverages Serialization • You write a document class, call it anything, add attribute • Use generics to instantiate a helper based on that document • Methods of the helper • Check for restart • Register for restart and recovery • Helper takes care of the rest • naming the file • serializing into or out of it (XML or Binary) • Constructing the restart hint
Restart and Recovery demo
Restart and Recovery • private RestartRecoveryHelper<SampleDocument> rrh; • // ... • rrh = new RestartRecoveryHelper<SampleDocument>(); • SampleDocumentrecovereddoc = rrh.CheckForRestart(); • if (recovereddoc != null) • { • doc = recovereddoc; • // ... • } • rrh.RegisterForRestartAndRecovery("TestHarness", • "Recover", doc, 50000, • FileType.Xml, • RestartRestrictions.None);
Trigger Started Services • Windows Services consume a significant amount of memory and CPU • Autostarted services make startup slow • Delayed start really didn’t work • Trigger started services can be ideal • More responsive (happy users) • No wasted CPU waking and polling (happy users) • Less code to write (happy developers)
Trigger Started Services Recipe • A TriggerStart class on which you set triggers • It configures the service for you after it’s installed • Helper classes for triggers • Join or leave domain • Open or close a specific port on the firewall • Group policy changes • First IP address is gained or last IP address is lost • A specific ETW custom event is raised • A specific device (eg USB drive) is connected or disconnected
Handle the After Install Event • TriggerStartts = new • TriggerStart(USBServiceInstaller.ServiceName); • GuidGuid_USBDevice = new Guid( • "53f56307-b6bf-11d0-94f2-00a0c91efb8b"); • const string DeviceName = @"USBSTOR\GenDisk"; • ts.Triggers.Add( • new DeviceInterfaceArrivalTrigger( • ServiceTriggerAction.ServiceStart, • Guid_USBDevice,DeviceName)); • ts.CommitChangesToService();
Next Steps for You • Make your Windows app a Windows 7 app • Code Pack can help, or WPF4 • Think about going beyond the visual • Power awareness, network awareness • Libraries • Restart and Recovery • Trigger Started Services • Take advantage of what the platform has to offer!
DEV Track Resources • http://www.microsoft.com/visualstudio • http://www.microsoft.com/visualstudio/en-us/lightswitch • http://www.microsoft.com/expression/ • http://blogs.msdn.com/b/somasegar/ • http://blogs.msdn.com/b/bharry/ • http://www.microsoft.com/sqlserver/en/us/default.aspx • http://www.facebook.com/visualstudio
Resources • Connect. Share. Discuss. http://northamerica.msteched.com Learning • Sessions On-Demand & Community • Microsoft Certification & Training Resources www.microsoft.com/teched www.microsoft.com/learning • Resources for IT Professionals • Resources for Developers http://microsoft.com/technet http://microsoft.com/msdn