Posts Tagged ‘Managed Code’

Displaying the UAC Shield in WPF with an Adorner

2009/11/22 4 comments

Since creating an elevated managed COM object, I have, on odd occasions, given thought to how to display the UAC Shield Icon in a WPF application.  After some research failed to uncover any useful information, I embarked on the task of creating a manageable method for displaying the icon.  While a full general purpose solution might be nice, a button that can display the icon as needed, should be sufficient for most purposes and demonstrates a methodology to follow for other controls.

Since I limited my implementation to a button, I created the UACShieldButton derived from Button.  By deriving from Button, all of the click and commanding handling were already done.  I left the final decision to display the icon with the UACShieldButton class.  The caller simply indicates that it desires the shield to be displayed if all other conditions, elevation state and UAC enabled operating system, are correct.

The obvious items required are a method of the calling code to indicate the desire for the shield and the shield icon itself.  Since I wanted binding to work with these properties, they were implemented as dependency properties.  The DesiresShield dependency property represents the calling code’s desire to have the shield displayed.  The ShieldIcon dependency property is an ImageSource for the image to display.  This property will default to the system shield icon, System.Drawing.SystemIcons.Shield through the default value set in the UACShieldButton’s static constructor.

If you have been following along, you have noticed I keep indicating the code utilizing the UACShieldButton class indicates a desire to have the shield displayed.  By allowing the UACShieldButton class to make the final decision to display the shield, some complication is hidden from the caller and code is consolidated into one location.  The shield will be displayed if the three following conditions are true:  the shield is requested, the operating system’s major level is 6 or above (Vista and Server 2008 and higher) and the caller is not already elevated.  The test for elevation is the only one that is not entirely straight forward.  As it happens, the old Win32 API call IsUserAnAdmin supplies the needed information.  Even though the documentation indicates membership in the Administrator’s group, under UAC enabled systems, it indicates that the user is currently elevated to administrator status.

The other nicety provided is the automatic handling of different ToolTips depending on elevation state.  Generally, the non-elevated state indicates that the associated out-of-process COM server has not been created.  Since it is not created, any state information that it would supply is unavailable.  By providing for the automatic handling of the display to different ToolTips according to the elevation state, the UACShieldButton control automatically provides the user with the correct ToolTip.  For example, assume you have a Service Controller Interface COM server and Start and Stop buttons to stop or start a service.   Until such time as the COM server is created, the state of the service is unknown.  The ToolTipNotElevated version of the ToolTip could indicate the lack of state information along with the effect of clicking the button.  Once the COM server is created, the ToolTipElevated ToolTip would be displayed simply indicating the effect of clicking the button.

The only logic that the caller must provide is the setting of DesiresShield to false, once the elevation is provided for any button.  You might be wondering why?  The elevation done here is elevating an out-of-process COM object as opposed to the program elevation that the UACShieldButton class can detect.

The trick to easily displaying the shield is to use an Adorner.  The alternative is to provide an alternate control template for the button and having created an alternate control template once, I do not relish doing it again.  The UACShieldAdorner class derives from Adorner and manages all aspects of displaying the shield.  The only tricky part of this code is the sizing and positioning algorithm.  The shield is resized proportionally to be four pixels less than the hosting button’s height.  It is then placed two pixels below and to the right of the upper left corner of the button.  Since the adorner layer is the topmost layer, the shield can obscure the text or the image in the button.

While this solution is not an end-all solution to displaying UAC Shield Icons, it is a starting point to that can be easily adapted to other controls and positions algorithms.

The code is here

Categories: Windows Development Tags: , , ,

Reusable ListView Sorting – The Easy Way

2009/10/15 Leave a comment

This week I finally decided to write the code to allow users to sort WPF ListView controls by clicking the headers. Of course, my first stop was Bing with WPF & ListView & sort as the search term. This yielded about 186,000 results. Three results on the first page were each useful in a unique way, but they each left something to be desired. They were not flexible enough, had too much code behind or required sub-classing controls. This situation led me to try to roll the good parts of each article into one piece of easy to maintain and easy to use code.

To give credit where due, my starting points were articles by Josh Twist, Michael Kuehl and Michael Brown.  I really liked Michael Brown’s concept of providing attached properties to control the sorting and the fact that his solution only had extra markup on the ListView itself instead of on every column in the associated GridView. I liked the use of the Adorner by Kuehl. Josh’s article was just a good introduction to the problem and an overview of the solution and the first to introduce me to the SortDescription class.

My static class, ListViewSorter, provides read/write and read-only attached properties to control and report on the current sort. In the default use it is invoked with a single piece of XAML, ListViewSorter.IsSortable=”true”. In most cases that is all that is required to properly sort on a single column and best of all, no extra code. You may also indicate that a given column is not sortable or you may override the default property for sorting.

The key to this ease of use is in the liberal use of attached properties. You should notice that some of the properties are attached to the ListView type and others are attached to the GridViewColumnHeader type.

The IsSortableProperty is the starting point. It is set on a ListView control to indicate that it allows sorting. The changed event for this property either adds or removes the Click event handler. Thanks to Michael Brown for this trick.

static private void OnIsSortableChanged (DependencyObject obj, DependencyPropertyChangedEventArgs e)
  ListView         lv = obj as ListView;

  if (obj != null)
    if (e.NewValue is bool)
      if ((bool)e.NewValue)
          new RoutedEventHandler(OnColumnHeaderClick));
         new RoutedEventHandler(OnColumnHeaderClick));
} /* method ListViewSorter OnIsSortableChanged */

The click event handler will find the associated ListView and only continue if the ListView is still marked as sortable.

static public void OnColumnHeaderClick (object sender, RoutedEventArgs e)
  GridViewColumnHeader   gvch = e.OriginalSource as GridViewColumnHeader;
  ListView               lv;

  if (gvch != null && GetAutoSort(gvch))
*   Make sure the ListView is still marked sortable
* */
  if (((lv = GetListViewFromColumnHeader(gvch)) != null) &&
    SortByColumn(gvch, lv); }
} /* method ListViewSorter OnColumnHeaderClick */


The SortByColumn (GridViewColumnHeader, ListView) method (see the attached code) does all the actual work for setting up the adorner and sorting. It uses the read-only attached properties to track last column sorted and the sort direction of each column. It is intentionally designed to remember to toggle the sort direction on each click of a column instead of only on consecutive clicks of a column. In other words, if column A is sorted descending and then column B is clicked the next click of column A will sort it ascending.

The SortByColumn (GridViewColumnHeader) method (see the attached code) is supplied as a simple entry from external code to sort on a column. This method bypasses all the checks for allowing sorting.

An up and down arrow is placed into the column header by using an Adorner. This seems simpler than the switching column header templates to include the correct arrow display method shown in several articles. The template solution could be more flexible, but of course, the arrow could be put into a resource instead of being hardcoded as in my solution. Just in case you are wondering what I did, I got a little fancy and produced an arrow that fades in from the top to the bottom. I am not sure if it is a good user experience or not, but it was fun to do and it looks cute. The hardest part of the Adorner is doing the display.

protected override void OnRender (DrawingContext drawingContext)
  drawingContext.PushTransform(new TranslateTransform(AdornedElement.RenderSize.Width-14,
  drawingContext.DrawGeometry(ArrowBrush, null, sda_render_geometry);
} /* method SortDirectionAdorner OnRender */

I cannot take too much credit for this code. Kuehl presented the basic idea. The transform moves the arrow to the right side of the column and the vertical center of the header. (Note that if the right of the column is not visible, the arrow will not be visible either.) The constants in the transform represent the fact that my arrow is an isosceles triangle with the base of four and a height of eight centered in a (non-displaying) rectangle 14 wide and 18 high.

I think I reached my goal of ease of use. I applied this code to six ListView controls in about 1 minute by simply copying and pasting ListViewSorter.IsSortable=”true” into each ListView in my project.

The Code is here

Creating and Using Managed Elevated COM objects

2009/08/23 1 comment

Why elevated COM you might ask.  Answer, because elevated COM is the ‘best’ way to allow an application that does not normally need administrator privileges to gain them for the unusual task.  Why managed you ask.  Because managed code in C# or VB allows the developer to deploy only one application to both x64 and x86 platforms.  As soon as you touch C++ you must compile the code for the specific mode you wish to run.  Further driving my quest for the use of managed code was the fact that I arrived here with minimal experience with COM.  In fact, I had never written any COM objects and did not relish the thought of learning ATL, or worse, at this point in my career.  Armed with the ‘knowledge’ that managed COM was easy, I set out on the development path.

There are several articles available that discuss some part of creating or access a managed elevated COM object.  I could not find one that filled in all the pieces.  I found Phil Wilson’s article, Build and Deploy a .NET COM Assembly, to be particularly helpful the uninitiated.  Christoph Wille has published three articles on the subject of managed elevated COM objects.  The last one, UAC Elevation in Managed Code: Guidance for Implementing COM Elevation, is the best resource and provides a good framework and it was my starting point.

I ran into several difficulties along my way to actually being able to access a managed COM object.  Perhaps the most insidious is the 64 bit versus 32 bit issue.  A COM object, managed or unmanaged, must be registered as 32 bit or 64 bit according to how it is going to be used.  The reality of this statement is that the object must be registered as both 32 bit and 64 bit when used on a 64 bit system.  Managed COM can be handled fairly easily by running both versions of REGASM.  (A 64 bit system has a second copy of REGASM in the Framework64 directory tree under the Microsoft.NET directory.)  Since either of these versions can be run from a 32 bit or 64 bit (elevated) command prompt, I created two bat files, REGASM32 and REGASM64, that call the correct REGASM and then I created a REGASM bat file that invokes both of these bat files.  That way I can conveniently invoke either or both versions of REGASM as needed.  (Check out the post at for information about registering 32 and 64 bit unmanaged COM objects.)  The other registration issue that I ran into is that the TYPELIB must be registered or activation will fail.  That may be written down somewhere or COM gurus may know this, but it was news to me.  The way that I have discovered that works and is easily done is to simply add the /tlb option to REGASM.  The third registration issue has to do with where the DLL actually is.  There are some people that believe that the DLL must be in the GAC to be registered.  That is not true.  If you add the /codebase option to REGASM, it will add the path to the registry and the COM object can be activated from any other path on the system.

In his third article Christoph discusses automatically adding the elevation information to the registry as the object is registered by using the ComRegFunction and ComUnregisterFunction attributes.  Well, again I ran into issues.  After much trial and error, I discovered that these attributes must be fully specified as [ComRegisterFunctionAttribute()] and [ComUnegisterFunctionAttribute()].  If you leave of the () or the word Attribute, you will not get a compile error, but the methods will not be called.  As a note, all the examples I found showed these two static functions to be public.  In reality, it is best practice that they be private.  Following’s Christoph’s lead I have reduced these two functions to a minimal and produced a helper class that does all the actual work.

private static void ComRegister (Type typeToRegister)
    ClassGuid, AppIdGuid, 100);

private static void ComUnregister (Type typeToUnRegister)
    ClassGuid, AppIdGuid);

ClassGuid and AppIdGuid are constants in the class to be registered.  Again I followed Christoph’s example, but made a few cosmetic changes.

#region Interface ISCUtility
public interface ISCUtility: IDisposable
  // Add COM accessible methods and properties here

#region Class SCUtility
public class SCUtility: ISCUtility, IDisposable
  public const string    ClassGuid = “DE177E01-C449-4987-A1E0-C98567EB3047”;
  public const string    InterfaceGuid = “5C10AA8E-4A8F-464f-8882-2B95DA4A993E”;
  private const string   AppIdGuid = “AD1C0896-F21B-42be-80E3-A31D0F031CEE”;


As a note, by adding the ComVisible(true) to the interface and class definitions, you do not have to set ComVisible(true) for the entire assembly.  Of course, it should go without saying that you should not reuse my GUIDs in your projects.

A note.  As you read further it may appear that I am disparaging Christoph’s code.  That is far from my intent.  Without his groundbreaking work, I would not have completed this project and I would have turned in another direction.  I hope that I have simply built upon a predecessor’s work in a constructive manner.

The code in the helper functions is similar to Christoph’s but with some simplification and additions.  In particular, his UnRegister function does not clean up enough information and leaves registry entries for items that have been unregistered.

public static void Register (string assemblyLocation, string classToElevate,
  string appId, int localizedStringId)
  RegistryKey    class_key;
  RegistryKey    elevation_key;
  RegistryKey    hkcr_app_id;
  RegistryKey    key;

    Need a good check here for a system that requires UAC elevation

  class_key = Registry.ClassesRoot.OpenSubKey(@”CLSID\{” + classToElevate + “}”, true);
*    Add the appid and the prompt string to the class’s entry
* */
  class_key.SetValue(“AppId”, “{” + appId + “}”, RegistryValueKind.String);
  class_key.SetValue(“LocalizedString”, “@” + assemblyLocation + “,-” +
*    Enable elevation
* */
  elevation_key = class_key.CreateSubKey(“Elevation”);
  elevation_key.SetValue(“Enabled”, 1, RegistryValueKind.DWord);

  hkcr_app_id = Registry.ClassesRoot.OpenSubKey(“AppID”, true);
*    Add the AppId key and tell it to use DLLSurrogate
* */
  key = hkcr_app_id.CreateSubKey(“{” + appId + “}”);
  key.SetValue(null, Path.GetFileNameWithoutExtension(assemblyLocation));
  key.SetValue(“DllSurrogate”, “”, RegistryValueKind.String);
*    Add the AppId guid
* */
  key = hkcr_app_id.CreateSubKey(Path.GetFileName(assemblyLocation));
  key.SetValue(“AppID”, “{” + appId + “}”, RegistryValueKind.String);


public static void UnRegister (string assemblyLocation, string classToElevate, string appId)
  RegistryKey    class_key;
  RegistryKey    hkcr_app_id;

  class_key = Registry.ClassesRoot.OpenSubKey(@”CLSID\{” + classToElevate + “}”, true);
  if (class_key != null)
  hkcr_app_id = Registry.ClassesRoot.OpenSubKey(“AppID”, true);
  if (hkcr_app_id != null)
    hkcr_app_id.DeleteSubKey(“{” + appId + “}”,false);

One last item of difficulty was the inclusion of the resource string required for registration.  This string is displayed to the user in the UAC prompt.  I found a method that works, but I would not propose it a seriously good method.  Maybe someone can give me a better method.

I took a .RC file from a CPP+ project and removed everything but four lines.   The result was

    100 “Put the prompt message here

The 100 is the 100 that is last parameter in the call to ElevatedComRegistration.Register.  I then added a Post Build event of rc $(ProjectDir)app.rc and then set the resource file on the Application tab to the full path of the resulting RES file.  Of course this does not handle alternate languages correctly, but it is a start.

Categories: Windows Development Tags: , ,