Friday, June 5, 2020

Executing a Method on the Main Thread With C#/.NET

Copyright © 2020, Steven E. Houchin. All rights reserved.

I recently updated some C# code to use the async/await feature to offload some processing to a background thread.  Mine is a WPF GUI application using .NET Framework 4.6.1.

A problem I immediately ran into was this: my background thread calls back into the UI to show status updates. But, when that call was made to show a line of status text, the app caused an unhandled exception (System.InvalidOperationException). I realized immediately what the problem was, having dealt with it many times in other multithreaded applications.  You cannot update user interface controls from secondary threads.  I knew the answer for C++ wxWidgets applications, but had to figure out what to do for C# and WPF.

I, of course, did a lot of digging online and got sidetracked with likely-looking solutions, which then turned out to be for WinForms applications.  Ultimately, I found that the answer lies with the System.Windows.Threading.Dispatcher class.  The documentation states it "Provides services for managing the queue of work items for a thread."  Sounds like just what I needed.

In my method that outputs the status line of text, it appends the new text to a TextBlock control. Before doing that, though, the method now needed to check whether it was running in a background thread, or the primary thread of the UI.  Here is the new method I wrote to determine this:

/// <summary>
/// Determine if current thread is secondary or primary (which
/// is determined from this object's dispatcher)
/// </summary>
protected bool IsBackgroundThread()
{
    return (this.Dispatcher != Dispatcher.CurrentDispatcher);
}

This IsBackgroundThread method is implemented in the main window class derived from System.Windows.Window, so is a class created with the application primary thread's dispatcher.  Thus, "this.Dispatcher" returns that primary thread Dispatcher object.  The static property "Dispatcher.CurrentDispatcher" returns the Dispatcher object for the currently running thread.  So, comparing the two thus determines background versus primary thread.

Now that I had the ability to determine the thread context, I could use it when updating the UI control with the new status text.  I did this in an AppendOutput method.

/// <summary>
/// Append the given text string to the control that shows
/// operation results.
/// </summary>
/// <param name="text" />The new text to append.
protected void AppendOutput(string text)
{
    if (IsBackgroundThread())
    {
        // Method was called from secondary thread, so dispatch
        // again to the primary thread using it's dispatcher
        this.Dispatcher.Invoke(() => AppendOutput(text),
                                DispatcherPriority.Normal);
    }
    else
    {
        // Method was called from primary thread, so do the work here
        textBlockResult.Text = textBlockResult.Text + "\n" + text;
    }
}

The above is a generalized way to determine the primary thread on a particular window, but the control on that window can be queried, too. In this simpler method, the code merely calls the DispatcherObject.CheckAccess method, as follows:

if (!textBlockResult.CheckAccess())
{
    this.Dispatcher.Invoke(() => AppendOutput(text),
                                DispatcherPriority.Normal);
}

When executing in the primary thread, the given text string is simply appended to the TextBlock control's current text value as a new line. When running in a background thread, the primary thread's Dispatcher is called to invoke the given Action, which is in the form of a Lambda expression that simply recursively calls the same method, but now in the primary thread's context.

Note that the Invoke method is of the form Invoke(Action, DispatcherPriority), where the first argument implicitly creates an Action delegate object for the method call. The documentation states, for Invoke, "Executes the specified Action synchronously at the specified priority on the thread the Dispatcher is associated with."  They key here is this is a synchronous call in a different thread context.

And that's it. With this change, all the status messages from the background thread show up just fine in the TextBlock control.






Tuesday, April 21, 2020

JavaFX desktop application on macOS - Part III

Copyright © 2020, Steven E. Houchin. All rights reserved.

This is the third and final post in this series, which deals with installing a JavaFX desktop application on macOS, when it was developed on a Windows system.  In my first post on this subject, I left two issues unresolved, the first of which I discussed in the second post.

Here, I discuss the second lingering issue left over from that first post, namely that the application's title in the macOS system menu bar shows as simply "java," instead of my application's title, "MapApp." This happens when I merely double click on the app's JAR file to run it.

To solve the problem, I had to create an installation package on the Mac, then run that package so the app is properly placed in the Mac's Applications folder, thus appearing like any other Mac application.


Build Steps on Windows


The key to making all that happen starts back on my Windows machine, and my build steps in NetBeans.  Since my app is made up of an application JAR, a library JAR, and some support files (like image files), I needed to integrate them together in a single JAR for the Mac.

  1.  I included the support files in my NetBeans Java package, along with the java source files for the application. That bundles those support files as Java package resources, instead of separate files on the disk.
  2.  I modified the application package's 'build.xml' file to add a new Run Target named "package-for-store."  It is intended to run after all the sources are compiled into their JARs. I show that new target script below.
  3.  Once the sources were built into JARs, I used NetBeans to execute the new Run Target. This is done by …
    1. Open a Files window on NetBeans
    2. Right-click the application's 'build.xml' file
    3. Select Run Target
    4. Select Other Targets
    5. Select the target "package-for-store," which runs the packaging script
  4. Once the packaging script runs, the resulting application JAR file is found in the folder 'store', which is a peer to the project's 'dist' folder. This is the JAR file that contains everything, including libraries, that can then be copied over to the Mac. The script must be run manually anytime the application is changed.
So, what is in this packaging script that I added to the 'build.xml' that performs this magic?  It is a custom "target" I added, and it looks like this:

<target name="package-for-store" depends="jar">
 <property name="store.jar.name" value="MapApp"/>
 <property name="store.dir" value="store"/>
 <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>
 <echo message="Packaging ${application.title}
 into a single JAR at ${store.jar}"/>
 <delete dir="${store.dir}"/>
 <mkdir dir="${store.dir}"/>
 <jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
  <zipgroupfileset dir="dist" includes="*.jar"/>
  <zipgroupfileset dir="dist/lib" includes="*.jar"/>
  <manifest>
   <attribute name="Main-Class" value="mapapp.MapApp"/>
  </manifest>
 </jar>

 <zip destfile="${store.jar}">
  <zipfileset src="${store.dir}/temp_final.jar"
  excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
 </zip>
 <delete file="${store.dir}/temp_final.jar"/>
</target>


Here are key items to note in the target script above.  The properties at the top specify the application name, the 'store' folder, and the jar file to create in the 'store' folder.  The "message" displays in NetBeans when the script is run. The 'store' folder is deleted and remade anew. A temporary JAR is created, which includes all JARs in the 'dist' folder and in the 'dist/lib' folder. The application's main startup class is specified by package name (mapapp) and class name (MapApp) in the "Main-Class" attribute. The finalized MapApp.jar is created from the temp JAR, and the temp is deleted.

When the script is done, "store/MapApp.jar" should exist, ready to be copied to the Mac.

Packaging Steps on Mac


So, I must copy the final JAR from above over to the Mac so it can be made into a macOS .pkg file.

On the Mac, I created a working folder 'MapApp/packaging' under my Documents. In it, I placed the JAR, and a .css file I need in the package. Under the 'packaging' folder, I also created a 'package/macosx' folder. As part of the process, the macOS java packaging utility looks for certain files there (all optional), which it uses to customize the package. The files are:

  • Info.plist - this is a standard macOS bundle configuration file for setting application properties, such as version number and copyright string.
  • MapApp-background.png - this is an image that displays at the lower left of the installation window when the package executed.
  • MapApp.icns - the application's custom icon file.
  • MapApp-post-image.sh - a script to run after the application image is populated.
Here is a shell script file I created to automate all of this to conveniently create the package (.pkg) file, which I run from a Bash terminal window:



#/bin/bash
#
# Create a .pkg file for the java MapApp app
#
jdk="/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home"

# Run the packager utlity
$jdk/bin/javapackager -version
$jdk/bin/javapackager -deploy -native pkg -name MapApp
-Bappversion=1.0.0 -srcdir . -srcfiles MapApp.jar:mapapp.css
-appclass mapapp.MapApp -outdir out -outfile MapApp
-description "MapApp description"
-title "MapApp Title"
-vendor "Company Name" -v

# Copy the new package
rm -f ./mapapp-installer.pkg
cp out/bundles/MapApp-*.pkg ./mapapp-installer.pkg

# List the results
ls -l


The key here is the "javapackager" utility, which is part of the installed JDK on my system.  The input sources to this are the MapApp.jar and mapapp.css files, as seen in the -srcfiles option.

The result is the file 'mapapp-installer.pkg' in my 'packaging' folder.  When I execute this, it installs my MapApp application in the usual macOS Applications folder, like any other application.

So, after all this, I've accomplished two things: a standard application installation and, when it executes, the title "MapApp" shows properly in the system menu bar.




Monday, March 9, 2020

JavaFX desktop application on macOS - Part II

Copyright © 2020, Steven E. Houchin. All rights reserved.

In Part I of this topic, I showed snippets of Java code that help your JavaFX desktop application run correctly on macOS, even when you've developed and built it on a Windows system, as I have. I left off last time with two unfinished issues for my MapApp program. They occur on macOS when simply executing the application's JAR file by opening it directly, such as double-clicking it:

  1. The application's title in the system menu bar is "java," instead of "MapApp."
  2. The application's dock icon is the standard Java coffee cup image.

The first I will defer to my next post. The second is discussed here.

Setting the Dock Icon


Setting the program icon using "stage.getIcons().add()" in the Java code works fine to set a title bar icon, but doesn't affect the Dock icon. The Dock icon requires calls to a special package from Apple, named "com.apple.eawt", which should exist on your macOS system, but isn't available for development on Windows. Unfortunately, Apple's documentation of this package has gone extinct, or is buried somewhere far, far away. The best docs I have found for it are at:

  https://coderanch.com/how-to/javadoc/appledoc/api/com/apple/eawt/Application.html

In that package is an Application class that contains methods to do interesting Mac-only things, like to set the Dock icon. So, here's the code I used, which requires using Java Reflection since the package is not available on Windows for linking.

First, you must obtain the package's Application class:

    Class<?> applicationClass;
    try
    {
        // get the eawt Application class
        applicationClass = Class.forName(
               "com.apple.eawt.Application");
    }
    catch (ClassNotFoundException ex)
    {
        Alert alert = new Alert(
                Alert.AlertType.ERROR, ex.toString());
        alert.showAndWait();
        return false;
    }

Second, load the icon image you wish to use, which in my case is a 48x48 JPEG embedded in the JAR as a resource. You could also load the icon from a file installed separately with the JAR. The embedding of the image file is accomplished on NetBeans by simply including the JPEG file in the project sources folder.

    // get the dock icon from the jar's embedded resources
    java.awt.image.BufferedImage image =
        ImageIO.read(getClass().getResourceAsStream("MyApp-48.jpg"));

Next, use the Application class (obtained above) to call methods that set the icon, using Reflection:

    try
    {
        // use reflection to access the
        // com.apple.eawt.Application methods
  
        // com.apple.eawt getApplication()
        // factory method to get an instance of
        // com.apple.eawt.Application
        Method getApplicationMethod =
            applicationClass.getMethod("getApplication");
  
        // com.apple.eawt Application.setDockIconImage()
        // Application class instance method to
        // set the Dock icon
        Method setDockIconMethod = applicationClass.getMethod(
                                     "setDockIconImage",
                                     java.awt.Image.class);

        // get an instance of the Appication class
        Object macOSXApplication =
            getApplicationMethod.invoke(null);
  
        // set the image as the dock icon
        setDockIconMethod.invoke(macOSXApplication, image);
    }
    catch (NoSuchMethodException
            | IllegalAccessException
            | IllegalArgumentException
            | InvocationTargetException ex)
    {
        Alert alert = new Alert(
                Alert.AlertType.ERROR, ex.toString());
        alert.showAndWait();
        return false;
    }

My application calls this code right away in the application class's "start(Stage stage)" method. When you run the application, you will see the standard Java coffee cup Dock icon at first, then your application's icon will load and take its place.

Note that all of the above will become moot if you create a package for your application on the Mac, where you can specify your own Mac icon file (.icns) and other things to customize its installation in the Applications folder. More fodder for subsequent posts!

Tuesday, March 3, 2020

JavaFX desktop application on macOS - Part I

Copyright © 2020, Steven E. Houchin. All rights reserved.

This posting is first in a series, whose purpose is to show what is necessary to get a JavaFX desktop application to work reasonably on macOS.

Environment


In my case, I am running macOS High Sierra (10.13.6) with Java 8 (version 1.8.0_231). My development environment is Windows 10, Java 8 (version 1.8.0_241), NetBeans 8.2 and JavaFX Scene Builder 2.0.

The Application


Mine is a desktop application that loads map images and allows for smart panning, zooming, and custom annotations. It is intended to run on Windows and macOS, and thus I chose Java as the language, and JavaFX for the User Interface components.

Code Unique for macOS


In several places in the code, it was necessary to recognize macOS differences. In many cases, to do this, I had to know it was running on macOS, and not Windows. Here's the method I used to do this, which takes advantage of the built-in system properties Java provides:

/**
 * Return true if the running OS is Mac OS,
 * otherwise Windows is assumed.
 *
 * @return - True if Mac OS, else assume Windows.
 */
public static boolean isMacOS()
{
    String os = System.getProperty("os.name");
    return os.startsWith("Mac") || os.startsWith("mac");
}

Also, I had to make sure file paths use the proper path separator character for the OS:
// get fully qualified path to the map file
String fullFilePath = myRootFolderPath +
                 File.separator + "mymap.jpg";
Then there is the application's menu bar. By default, when it runs on macOS, the menus appear atop the application's main window, just like on Windows. But, of course, that isn't what we want on the Mac; it should appear on the standard Mac menu bar at the top of the screen. Here's the trick to make that happen:
@FXML
private MenuBar menuBar;
if (isMacOS())
{
    // place the program menus on the standard
    // macOS menu bar
    menuBar.setUseSystemMenuBar(true);
}
Two more useful snippets of code that help get things right on the Mac.

First, how to find the user's home directory.

/**
 * Get the user's home directory path, appending the
 * system path separator to it.
 *
 * @return - The full path to the user home directory
 *    (ending in a path separator), or null if error
 */
public static String getUserHomeFolderPath()
{
    // get the user home directory from a standard
    // environment variable
    String folder = isMacOS() ? System.getenv("HOME") :
                                System.getenv("HOMEPATH");
    if (null != folder)
    {
        folder += File.separator;
    }
    return folder;
}

Second, how to get the name of the user's Documents folder.


/**
 * Get the user's Documents folder name.
 *
 * @return The folder name for Documents on this OS.
 */
public static String getDocumentsFolderName()
{
    if (!isMacOS())
    {
        String os = System.getProperty("os.version");
        double version = Double.parseDouble(os);
        if (version < 7.0)
        {
            // name of Documents folder for Windows 2000
            // and XP
            return "My Documents";
        }
    }
    // name of Documents folder for macOS and
    // Windows 7.0+
    return "Documents";
}

Installing the Application to Test


My application links with a library, which I also developed, which does the heavy lifting for drawing and manipulating the map. When I copy the application JAR (MapApp.jar) to my test folder on the Mac, my maps library JAR (MapLib.jar) must be placed in a "lib" subfolder below the test folder. At this point, I can execute the app on the Mac by double-clicking MapApp.jar, and it starts up. But, two things show up that aren't yet right:
  1. The application's title in the system menu bar is "java," instead of "MapApp."
  2. The application's dock icon is the standard Java coffee cup image.
I will discuss solving these problems and others in a future post.

Thursday, January 16, 2020

Opening an About dialog box with JavaFX

Copyright © 2020, Steven E. Houchin. All rights reserved.

I was recently putting the finishing touches on a demo desktop application written in Java 8 using JavaFX. The UI consists of a single FXML file attached to a controller class. My next task was to add a nice looking About box - something better than an Alert.  So, I created an About.fxml using JavaFX Scene Builder 2.0.  I wanted to attach the About.fxml to the same application controller class I already had, so the About's OK button would dispatch its event there.  That, apparently, was a mistake that caused much grief, because loading the About.fxml kept giving me a non-specific LoadException error.  Postings at online help sites didn't seem to match my situation. Most of them dealt with file path problems to the user's FXML file, resulting in a NullPointerException, but my FXML is embedded within my application JAR file.

I eventually came to the conclusion that the FXMLLoader did not like loading a second FXML specifying the same controller class as my main FXML. So, how to load my About.fxml to get the result I wanted - its use of the same controller class?

Okay, here's what I did.  First, I removed any reference to a controller in About.fxml.  That meant I had to specify the controller some other way.  Here's my code in the controller class handler for the About menu event:


// load the About box FXML document
javafx.fxml.FXMLLoader loader = new javafx.fxml.FXMLLoader(
                    MyMainApp.class.getResource("About.fxml"));
loader.setController(this); // set 'this' as its controller
Parent root = loader.load(); // load UI objects from the FXML document

It turns out the magic I needed was the "setController" method above.  Specifying the controller class in the FXML file tries to create a new instance of the controller class, I assume, which must be the origin of my earlier LoadException error.  So, without that, the above loads fine.

Once the UI was loaded into a root Parent object (above), then it was time to configure the About dialog just the way I wanted: modal, no extra window decorations (i.e. Utility), owned by the main window, always on top, and not resizable ...

// create the dialog stage and set up its attributes
javafx.stage.Window owner = MyMainApp.getStage().getScene().getWindow();
Stage dialog = new Stage();
dialog.initStyle(StageStyle.UTILITY);
dialog.initModality(Modality.WINDOW_MODAL);
dialog.initOwner(owner);
dialog.setAlwaysOnTop(true);
dialog.setTitle("About MyMainApp");
dialog.setResizable(false);

Lastly, it was time to show the dialog:

// create the scene and set onto the stage
Scene scene = new Scene(root);
dialog.setScene(scene);
dialog.sizeToScene();
dialog.showAndWait();

At that point, my nice About box with a title and the system close button pops up!  The underlying main window cannot gain focus.  When I press the About's 'OK' button, I then get its event callback in my same controller class, which then closes the About box:

@FXML
public void onButtonHelpAboutDismissAction(ActionEvent event)
{
    Stage stage = (Stage)buttonHelpAboutDismiss.getScene().getWindow();
    stage.close();
}

Now, I'm sure there's a stupidly simpler way to do this in JavaFX, but I didn't see any other online examples for an About box like this. So, this is my contribution, as a relative Java newbie.

Any comments?

Friday, June 22, 2018

Finding the default application for a file extension in WIndows

Copyright © 2018, Steven E. Houchin. All rights reserved.

A client of mine has a Windows application that lists various data files, and when a data file is clicked, opens the associated application for the file's extension, using an established API to do that.  It has worked fine for a long time, but gives unexpected results on Windows 10 for html files. The default program for html on the system is configured for MS Edge, but a click on the html file in the application always brought up Internet Explorer.

Sure enough, following the traditional file association scheme in the Registry showed IE, not Edge.  The traditional scheme is:

HKEY_CLASSES_ROOT\.html
    (Default) = program_identifier
HKEY_CLASSES_ROOT\program_identifier\shell\open\command
    (Default) = full path to default program

By doing more research, I discovered that M*Soft changed the file association scheme starting, I think, with Vista.  The old scheme may still work for some file types, but finding the right browser requires using the new scheme.

The new post-Vista scheme I found requires looking into file associations for Window Explorer and following from there.

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\
  FileExts\.html\UserChoice
    ProgId = program_identifier
HKEY_CLASSES_ROOT\program_identifier\shell\open\command
    (Default) = full path to default program

In the new scheme, for MS Edge, the ProgId value could be something strange like "AppXq0fevzme2pys62n3e0fbqa7peapykr8v", whereas the Firefox browser may be "FirefoxURL". The obvious advantage of this new scheme is that using HKEY_CURRENT_USER allows for user-by-user default program setting, where, I think, the traditional scheme sets it for all users.

So, by writing my own Registry traverser for the new scheme, I finally got MS Edge to open as the default browser. If the new scheme fails to find the default program, my code falls back to the traditional scheme shown before.



Friday, September 22, 2017

Making a Modal Dialog with C# and WPF

Copyright © 2017, Steven E. Houchin. All rights reserved.

For a unit test program I'm developing to validate a new library API, I created a window to show some attributes of an object. I wanted that window to display as follows:

  • normal modal dialog
  • centered on parent window
  • not shown in taskbar
  • can be resized
  • can be minimized

I'm using .NET Framework 4, C# and WPF on a Windows 10 system.

Here are some observations about how to properly set up a dialog as I describe above.

First, to show as a modal dialog, I call the Window class's ShowDialog method to open and show the dialog from the parent Window class:


    // Create the Detail View Controller object
    IDetailViewControl view_controller =
            app.MakeDetailViewController();

    // Create the Detail View Object, passing in this
    // Window class as a parent
    MyDetailView detail =
            new MyDetailView(myDataObject, view_controller, this);
                
    // Show the Detail dialog
    detail.ShowDialog();

Second, to center the dialog on its parent window, the MyDetailView dialog class's constructor sets its Owner property to the Window object passed by the caller:


    public partial class MyDetailView : Window
    {
        public MyDetailView (MyData dataObject,
                             IDetailViewControl controller,
                             Window owner)
        {
            this.Owner = owner;   // set parent window as owner
            InitializeComponent();

            // other constructor initialization
        }
    }



Note that, in the above code, the parent Window code could have set itself as Owner using the 'detail' object before calling ShowDialog, but I chose to have the dialog take care of that. Finally, to complete a centered dialog when open, the dialog Window's XAML properties must specify:

    WindowStartupLocation="CenterOwner"

Third, I set the dialog Window's XAML property to not show in the taskbar:

    ShowInTaskbar="False"

Set to False, it means this dialog will not show in the taskbar, but Restoring the parent window from the taskbar brings the MyDetailView dialog to the top with it.

Lastly, I set the dialog Window's XAML property so it can be resized and minimized:

    ResizeMode="CanResize"

The ResizeMode setting can instead be set to CanMinimize if resizing isn't desired. The CanResize value implies CanMinimize, since minimizing and maximizing is assumed to be part of any resize operation.

So, with the WPF Window implemented this way, it acts like a classic modal dialog we're all accustomed to.

Monday, August 28, 2017

Design Pattern example: Singleton and Observer (Part III)

Copyright © 2017, Steven E. Houchin. All rights reserved.

In my last two postings on this subject, I outlined a Logger class used by my Parser class for logging errors.  In this article, I show a more sophisticated approach for the application to register and unregister as an interested Observer with Logger, so it is notified when an error message is posted to Logger.

First, the Observer class must derive from the ILoggerObserver interface:

///
/// Interface to be implemented by objects who wish to
/// observe changes on the Logger object's data.
///
public interface ILoggerObserver
{
    void didAddLogMessage(string message);
}


In my original posting, I showed the following code snippet showing the Observer register and unregister sequence:


public class MyParser : ILoggerObserver
{
    ...

    public void MyParseLogic()
    {
        // Register to log any parsing errors
        Logger log = Logger.Instance;
        log.Attach(this);

        // Parse my data file
        Parser p = new Parser(my_file_path_to_be_parsed);
        p.Parse(); // will call the same Logger instance

        log.Detach(this); // resign as a Logger observer

        ...
    }

    /// Implement the ILoggerObserver interface
    public void didAddLogMessage(string message)
    {
        // Output the message to a TextBlock control or
        // pop up a Message Box.
        ...
    }

} // end class MyParser

Note that before parsing is done, the MyParser class calls Logger's Attach method to register as an observer, and after finishing with the parsing, calls Detach to unregister. But I later came up with a better design so Detach can be done automatically. I accomplish this by taking advantage of the .NET IDisposable interface.

I created a new container class named LoggerObserverDisposer, derived from IDisposable. Its only job is to call Logger's Detach for the Observer when it's being disposed by .NET. The target Observer object is provided to its constructor and remembered for when the Detach is done.

Here is that new Disposer class:


/// Container class for an observer, which terminates its observing
/// when out of scope.
public class LoggerObserverDisposer : IDisposable
{
    protected ILoggerObserver _observer = null;
    public LoggerObserverDisposer(ILoggerObserver observer)
    {
        // Remember the observer object to be disposed
        _observer = observer;
    }

    public void Dispose()
    {
        Dispose(true);  // call our Dispose method below
        // prevent redundant Dispose during garbage collection
        GC.SuppressFinalize(this); 
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Get the Logger object
            Logger logger = Logger.Instance;

            // Make operation atomic
            Monitor.Enter(logger);
            if (_observer != null)
            {
                // Remove the observer from Logger
                logger.Detach(_observer);
                _observer = null;
            }
            Monitor.Exit(logger);
        }
    }
}   // end class LoggerObserverDisposer


Previously, here is what Logger's Attach method looked like:


    /// Add an Observer object to the list of those
    /// to be notified of changes.
    public void Attach(ILoggerObserver observer)
    {
        if (null != observer)
        {
            // Add this observer to the list, but just once
            Detach(observer);
            _observers.Add(observer);
        }
    }


Now, it is changed to make use of our new LoggerObserverDisposer class. Attach returns a new LoggerObserverDisposer instance for the Observer, but only if requested by the caller.


    /// Add an Observer object to the list of those to be notified
    /// of changes, and return a Disposer object for the observer,
    /// if requested.
    /// 
    /// Params:
    /// "observer" - The Observer object to add to the list.
    /// "doMakeDisposer" - true to return a Disposer object.
    /// Returns: A Disposer object, if requested, or null
    public LoggerObserverDisposer Attach(ILoggerObserver observer,
                                       bool doMakeDisposer = false)
    {
        if (null != observer)
        {
            // Add this observer to the list
            Detach(observer);
            _observers.Add(observer);
        }

        // Return an object the caller can include in a
        // 'using' statement so the observer is automatically
        // removed when the Disposer goes out of scope
        return (doMakeDisposer) ?
                new LoggerObserverDisposer(observer) : null;
    }


Finally, the MyParser class changes to use this new version of Logger's Attach, but never needs to explicitly call Detach:

    public void MyParseLogic()
    {
        // Register to log any parsing errors
        Logger log = Logger.Instance;
        using (logger.Attach(this, true))
        {
            // Parse my data file
            Parser p = new Parser(my_file_path_to_be_parsed);
            p.Parse(); // will call the same Logger instance
        }

        ...
    }

The changed code takes advantage of the C# "using" statement, which expects an IDisposable-derived object. When the "using" block goes out of scope, that object's Dispose method is called. In our case, the new Attach method returns a LoggerObserverDisposer object (rather than void as before), which remains in scope throughout the "using", even though I never assign it to a variable. Thus, LoggerObserverDisposer::Dispose is called when the "using" block loses scope, which in turn calls Logger's Detach for the Observer MyParser class.

This logic saves the programmer from having to remember to manually Detach, and possibly leave a dangling Observer that has since been destroyed.

Monday, August 21, 2017

Design Pattern example: Singleton and Observer (Part II)

Copyright © 2017, Steven E. Houchin. All rights reserved.


In my previous post on this subject, I introduced a class named Logger, which is used by my parser class to log parsing errors. It is implemented using the Singleton design pattern. The Logger class also uses the Observer design pattern where other interested objects can register with Logger to be notified when new messages are logged.

This article shows the notification logic used by Logger.  But first, a quick review of Logger:

public class Logger : object
{
    // The Singleton instance
    protected static Logger _instance;

    // List of Observer objects to be notified of
    // changes to the log
    protected List(lt)ILoggerObserver(gt) _observers;

    /// Hidden constructor
    private Logger()
    {
         _observers = new List(lt)ILoggerObserver(gt)();
    }

    ...

    /// Add an Observer object to the list of those
    /// to be notified of changes.
    public void Attach(ILoggerObserver observer)
    {
        if (null != observer)
        {
            // Add this observer to the list, but just once
            Detach(observer);
            _observers.Add(observer);
        }
    }

    /// Remove an Observer object from the list.
    public void Detach(ILoggerObserver observer)
    {
        if (null != observer)
            _observers.Remove(observer);
    }

    ...

    public void LogError(string msg)
    {
        // ... do something to log the error somewhere ...
    }
}

Objects wishing to be notified must implement the abstract interface Logger calls:

///
/// Interface to be implemented by objects who wish to
/// observe changes on the Logger object's data.
///
public interface ILoggerObserver
{
    void didAddLogMessage(string message);
}

Now, let's look at the implementation of the LogError method. It needs to notify the observers that a message has been logged, so:


    public void LogError(string msg)
    {
        if ((null == msg) || (0 == msg.Length))
           return;

        // Prepend an identifier prefix, then notify observers
        Notify(@"[Error] " + msg);
    }

    ///
    /// Notify all observers of the logged message.
    ///
    protected void Notify(string message)
    {
        foreach (ILoggerObserver observer in _observers)
        {
            // Notify the Observer of the logged message
            observer.didAddLogMessage(message);
        }
    }


Above, we have given substance to the LogError method, which in turn calls the Notify method to do the actual work of notifying the observer objects. The observer objects each implement the didAddLogMessage method, where the message reaches it's ultimate destination, such as a log file or a UI control. With the Notify method separated out like this, the class can easily be enhanced to add LogWarning and LogInfo methods, which prepend a different prefix to show the message's severity.

In a follow-up posting, I'll show an improved way to attach and detach an observer object from the Logger class.

Friday, July 21, 2017

Design Pattern example: Singleton and Observer (Part I)

Copyright © 2017, Steven E. Houchin. All rights reserved.

I've lately been developing a parser library for a certain standard file format used for data interchange between some programs.  At various points in the parsing process, my code detects errors, and I wanted a mechanism to log those errors.  The parser consists of a gaggle of classes (in C#) that encapsulate various data structures, any of which may generate errors or warnings about file format issues.  I certainly didn't want to pass a reference to a logger object as a parameter to every method in every class to accomplish the error logging.

Thinking about the functionality of logging errors, multiple instances of a logger object didn't make sense.  So, I designed a logger class based upon the Singleton design pattern, where one instance of the class is created at first use, and that same instance is retained for subsequent uses:


public class Logger : object
{
    // The Singleton instance
    protected static Logger _instance;

    /// Hidden constructor
    private Logger()
    {
    }

    /// Get the only instance of the class
    public static Logger Instance
    {
        get
        {
            // Get the only instance, creating new if necessary
            if (_instance == null)
            {
                _instance = new Logger();
            }
            return _instance;
        }
    }
        
    public static void Free()
    {
        // Free the only instance when done with the parser
        _instance = null;
    }

    public void LogError(string msg)
    {
        // ... do something to log the error somewhere ...
    }
} // end class Logger

The parser library methods simply get a reference to Logger's class instance like this:

   
    Logger log = Logger.Instance;
    log.LogError("Parse error.");

Each call to the Logger's Instance property returns the same object instance, no matter where in the code it is called.

My next design task was to decide how and where to log the error message itself.  Ultimately, I decided the Logger class shouldn't be burdened with the detail of "where" to log the error. What if App1 wants the library to log to a file, and App2 wants the log rendered to the UI?  At first, I just dumped the messages into an ArrayList, and the parent App would pull them out at its leisure at a later time.  But that was inelegant and didn't notify the App of the error in real time.

The key word I just used there is "notify."  That idea implies a callback, and that brought to mind the Observer design pattern, for which notification is a central part of the concept. For example, Object-A's state changes via some event, and it notifies Object-B of the change. In Observer, though, notifications may also be sent to Objects C and D and E.  So, Objects B through E must register as interested observers with Object-A, and unregister when no longer interested.

To implement Observer, my Logger class needed a callback interface for the observers, registration/deregistration methods, and a structure of some kind to keep track of each observer.

First, the callback interface:


///
/// Interface to be implemented by objects who wish to
/// observe changes on the Logger object's data.
///
public interface ILoggerObserver
{
    void didAddLogMessage(string message);
}

Each of the observer classes must derive from the above ILoggerObserver interface and implement the didAddLogMessage method, which allows the observer to do whatever it wishes to log the message.

Next, a List to keep track of the observer registrations:


public class Logger : object
{
    // The Singleton instance
    protected static Logger _instance;

    // List of Observer objects to be notified of
    // changes to the log
    protected List(lt)ILoggerObserver(gt) _observers;

    /// Hidden constructor
    private Logger()
    {
         _observers = new List(lt)ILoggerObserver(gt)();
    }

    ...

}

Of course, the (lt) and (gt) above are really < and > that don't render well in the HTML code snippet above.

Now, we need the registration/deregistration methods in the Logger class.  These will be made more sophisticated in a follow-on posting.

    /// Add an Observer object to the list of those
    /// to be notified of changes.
    public void Attach(ILoggerObserver observer)
    {
        if (null != observer)
        {
            // Add this observer to the list, but just once
            Detach(observer);
            _observers.Add(observer);
        }
    }

    /// Remove an Observer object from the list.
    public void Detach(ILoggerObserver observer)
    {
        if (null != observer)
            _observers.Remove(observer);
    }

So, finally, the user's parser code initializes logging by registering as an Observer, and calls the parser:

public class MyParser : ILoggerObserver
{
    ...

    public void MyParseLogic()
    {
        Logger log = Logger.Instance;
        log.Attach(this); // become a Logger observer

        Parser p = new Parser(my_file_path_to_be_parsed);
        p.Parse(); // will call the same Logger instance

        log.Detach(this); // resign as a Logger observer

        ...
    }

    /// Implement the ILoggerObserver interface
    public void didAddLogMessage(string message)
    {
        // Output the message to a TextBlock control or
        // pop up a Message Box.
        ...
    }

} // end class MyParser

With follow on postings, I'll show the Logger's notification logic, and a better way to unregister as an observer.

Wednesday, July 29, 2015

UITableViewCell and backgroundView


Copyright © 2015, Steven E. Houchin. All rights reserved.

I have some code that modifies a table view cell so that it acts like a gradient-colored button within a grouped table view. I'm developing for iOS 6.1. When the cell is to be shown (via tableView:willDisplayCell:forRowAtIndexPath:) the gradient color is rendered into a UIView using a CAGradientLayer object.  Actually, I create two of these UIViews: one for the normal button state and one for the pressed state.  Each of these two views are saved into the UITableViewCell's "backgroundView" and "selectedBackgroundView" properties, thus giving the button-like behavior.

But, while doing this, I ran into a problem: cell reuse. In my tableView:cellForRowAtIndexPath: callback, I was using dequeueReusableCellWithIdentifier: to get all of my table's cells - even the gradient-colored ones. One of the issues with cell reuse this way is that you must make sure to reset the reused cell's properties to a known default state.  Otherwise a cell can inherit properties set for a completely different cell last time through.

Well, I was doing just that - resetting properties - except for "backgroundView" and "selectedBackgroundView".  By not resetting those, the gradient colors appeared in cells where they were not intended.  So, I added this to my cell reset code:
[tableView setBackgroundView:nil];
[tableView setSelectedBackgroundView:nil];
Well, the result was a mess.  All of the grouped table view cells lost their rounded-edge borders.  It turns out that these background view properties have view objects set by default that provide the grouped table view cells their rounded look, so can't be set to null.  I suppose I could have copied the values and saved them somewhere to restore later when resetting the reused cell properties, but that seemed like the wrong thing to do.

The solution was to create a pool of separate reusable cells for the gradient cells. For these cells, which are within their own table view sections, I used the table view method dequeueReusableCellWithIdentifier:forIndexPath:, specifying a different identifier string for it than for the standard cells.  But, one glitch with this approach is that, to use this method, I also had to first register the cell identifier string for the class in my viewDidLoad method:
[[self tableView] registerClass:[UITableViewCell class]
               forCellReuseIdentifier:@"GradientCellId"];
Once I did that, then cell reuse in tableView:cellForRowAtIndexPath: worked great for both the gradient cells and the normal cells since they now draw from different reuse pools:
UITableViewCell *cell;
NSString *cellid;
if (MyTableSectionGradient == [indexPath section])
{
        cellid = @"GradientCellId";
        cell = [tableView dequeueReusableCellWithIdentifier:cellid
                                               forIndexPath:indexPath];
}
else
{
        cellid = @"NormalCellId";
        cell = [tableView dequeueReusableCellWithIdentifier:cellid];
}
if (!cell)
{
        cell = [[UITableViewCell alloc]
                                  initWithStyle:UITableViewCellStyleDefault
                                reuseIdentifier:cellid];
}


Monday, January 14, 2013

OSX AuthorizationExecuteWithPrivileges example

Copyright © 2013, Steven E. Houchin. All rights reserved.

I've read various posts online about developers' travails with OSX's AuthorizationExecuteWithPrivileges API, and misunderstanding about how it works.  So, here is some of what I've learned about it.

Apple's documentation states that it "Runs an executable tool with root privileges."  But, users soon discover that the new process does not, in fact, run as root.  In reality, the new process executes at an elevated privilege level that allows it to become the root user by calling 'setuid(0)'.  For example:

// Fork a child process
pid_t child_pid = fork();
if(child_pid == 0)
{
  // This is done by the child process
           
  // Change to the root user
  uid_t userid = getuid();
  setuid(0);  // set root permissions 

  // Do things as root ... 

  // Restore normal permissions
  setuid(userid);
  exit(0);
}

Note that there is danger in using AuthorizationExecuteWithPrivileges.  For example, your app might invoke a helper tool named 'grok' that will execute with the elevated privileges.   If a hacker figures out that 'grok' is started this way, he can replace 'grok' with his own trojan binary, which can then make itself root and thus do nasty things to your system. It isn't really hard for a hacker to determine that 'grok' is invoked this way, because the MAC's Console utility logs that AuthorizationExecuteWithPrivileges was called to execute 'grok.'   So, if you must execute 'grok' this way, your app should first validate the 'grok' binary in some way to make sure it has not been tampered with.  What I did was to open 'grok' as a binary data file and then I scan it for a known string used in the code, such as an innocuous printf format string.

The first parameter to AuthorizationExecuteWithPrivileges is an AuthorizationRef object.  This is obtained via a call to AuthorizationCreate:

AuthorizationRef authorizationRef;
OSStatus status = AuthorizationCreate(NULL,
                       kAuthorizationEmptyEnvironment,
                       kAuthorizationFlagDefaults,
                       &authorizationRef);
if (status != errAuthorizationSuccess)
{
    // Notify user of the error ...
}

The actual elevated rights you request are specified via a call to AuthorizationCopyRights, at which time the user is prompted to enter his password.  Along with requesting certain rights, you can specify a custom icon and text for the password popup.  Note however that your icon will not appear if it resides in a directory beneath any ancestor directory that lacks Everyone access.  Here's what the icon specification looks like, which is passed as the AuthorizationEnvironment parameter to AuthorizationCopyRights:

AuthorizationItem kAuthEnv[1];
const char *iconPath = "/Applications/MyApp.app/Resources/myicon.icns";
kAuthEnv[0].name = kAuthorizationEnvironmentIcon;
kAuthEnv[0].valueLength = strlen(iconPath);
kAuthEnv[0].value = (void *)iconPath; // fully qualified path
kAuthEnv[0].flags = 0;
AuthorizationEnvironment authorizationEnvironment;
authorizationEnvironment.items = kAuthEnv;
authorizationEnvironment.count = 1;

Next, in order to use AuthorizationExecuteWithPrivileges, you must request the "system.privilege.admin" right.  You set this up as follows:

const char *grokPath = "/Utilities/grokUtil/grok";
AuthorizationItem executeRight = {
                        kAuthorizationRightExecute,
                        strlen(grokPath)
                        (void *)grokPath,
                        0};
AuthorizationRights rightsSet = {1, &executeRight};

Note that kAuthorizationRightExecute is defined as "system.privilege.admin" in the Security framework's AuthorizationTags.h.  This is then used in AuthorizationCopyRights to actually acquire the rights for the AuthorizationRef object:

AuthorizationFlags flags =
                  kAuthorizationFlagDefaults |
                  kAuthorizationFlagInteractionAllowed |
                  kAuthorizationFlagPreAuthorize |
                  kAuthorizationFlagExtendRights;

// Call AuthorizationCopyRights to determine
// or extend the allowable rights
OSStatus status = AuthorizationCopyRights(
                                authorizationRef,
                                &rightsSet,
                                &authorizationEnvironment,
                                flags,
                                NULL);
if (errAuthorizationCanceled == status)
{
    // User canceled authentication  ...
}
else if (status != errAuthorizationSuccess)
{
    // Notify the user of the error ...
}

All that's left at this point is to execute the privileged helper tool:

FILE *fpStdout = NULL;
status = AuthorizationExecuteWithPrivileges(
                        authorizationRef,
                        (const char *)grokPath,
                        kAuthorizationFlagDefaults,
                        argv,  // normal argv array of program args
                        &fpStdout);
bool success = (status == errAuthorizationSuccess);
pid_t newProcId;
if (success)
{
   // Get the new process id
   newProcId = fcntl(fileno(fpStdout), F_GETOWN, 0);
   fclose(fpStdout);
}
else
{
   // Notify user of the error ...
}

AuthorizationExecuteWithPrivileges returns as soon as the new process has started.  It does not execute it as a child of the current process, so a waitpid on the resulting process id gives an error.

Friday, February 10, 2012

Learning to hate AllocateAdapterChannel

Copyright © 2012, Steven E. Houchin. All rights reserved.

I have a scatter-gather device I'm supporting in a Windows PNP driver. Normally, a driver developer would use the GetScatterGatherList API to map multiple IRP buffers to a device's DMA capabilities. However, in my case, my device has peculiar buffer alignment requirements that I can't count on GetScatterGatherList to handle. But, no worries. The AllocateAdapterChannel API is available.

Wait! Not so fast. In order for my device to perform at peak speed, multiple Read and Write IRPs are simultaneously active and mapped to the DMA. What this means is, I can't wait for the occurrence of an interrupt and an IRP completion before mapping the next IRP to the DMA; I map dozens or hundreds of them to the DMA in advance.

GetScatterGatherList handles all this just fine as long as each IRP has its own associated separate DMA_ADAPTER object. In theory, AllocateAdapterChannel should be able to do the same, but it can't. There is this sneaky little note in the WDDK documentation that throws a fly into the oatmeal:

Only one DMA request can be queued for a device object at any one time. Therefore, the driver should not call AllocateAdapterChannel again for another DMA operation on the same device object until the AdapterControl routine has completed execution.

The key phrase there is "device object." DEVICE_OBJECT is a parameter to AllocateAdapterChannel. So, even if I have a separate DMA_ADAPTER object for each mapped IRP, it still uses just the one DEVICE_OBJECT. The note above blandly states "until the AdapterControl routine has completed execution." Exactly how do I know when it completes execution? If the driver is executing its assembly "ret" instruction, it is technically still in the AdapterControl callback, so anything I do inside it to notify another thread to proceed is too early.

I believe the issue here is that DEVICE_OBJECT is placed on a wait list by the kernel when the DMA is not immediately available. Thus, we can't have that object placed twice on a list. Maybe the answer is to create a separate, fake DEVICE_OBJECT for each IRP, just like I do with DMA_ADAPTER.

Charging ahead, I created a pool of DEVICE_OBJECTs, copied from the original, and used them round-robin for each simultaneous AllocateAdapterChannel, preventing any more calls if none available.

No luck. The failure manifests itself by the AdapterControl being called back twice in a row for the same IRP - i.e. two calls to AdapterControl for an IRPs single call to AllocateAdapterChannel. Now, maybe I am still doing something wrong managing my fake DEVICE_OBJECTs. For example, when do I really know that a DEVICE_OBJECT is available for reuse? It's the fly and oatmeal problem again with the AdapterControl callback: when has it really "completed execution?"

For now, I don't have a workable solution to this. I'll let you know if I figure it out.

Monday, October 24, 2011

Computing the viewport size within a WPF Border control

Copyright © 2011, Steven E. Houchin. All rights reserved.

I have a WPF application that renders a photo bitmap inside a System.Windows.Controls.Image control that is contained within a System.Windows.Controls.Border. If the photo bitmap is too large for the app window (either in the horizontal or vertical direction), I set the Image's corresponding size attribute(s) to 'Auto' (i.e. Double.NaN) within the Image's SizeChanged event handler. If the bitmap is smaller than the app window, I set the Image's size to the actual fixed size of the bitmap, so it doesn't get scaled.

But, that left a problem when I resized the app window smaller: a fixed-size Image was truncated by the border when the window shrank smaller than the photo's bitmap size. And, because the Image's width/height weren't set to Auto, its SizeChanged event wasn't firing.

However, the Border's SizeChanged event was firing. So, I added that handler for the Border control, planning to set the Image's proper width/height after resize.  That left another problem in this new event handler: how to calculate whether or not the Image control's width/height should be Auto or fixed.  Put another way, what was the size of the viewport inside the Border control where the Image would be rendered?

The Border's SizeChanged event handler is passed a SizeChangedEventArgs parameter that provides the new width/height of the Border control. The size available to the Image control inside that will clearly be smaller, but by how much? Here is the algorithm in C# that I came up with (keep in mind that a negative BorderThickness means the border is drawn outside the control's drawing area):

// Calculate the Border control's new viewport
// size within the drawn border where the Image control
// is rendered (add in any padding and non-negative
// border thickness).
Size viewport = new Size();
viewport.Width = e.NewSize.Width -
    (border.Padding.Left + border.Padding.Right) -
    ((border.BorderThickness.Left > 0) ?
        border.BorderThickness.Left : 0) -
    ((border.BorderThickness.Right > 0) ?
        border.BorderThickness.Right : 0);
viewport.Height = e.NewSize.Height -
    (border.Padding.Top + border.Padding.Bottom) -
    ((border.BorderThickness.Top > 0) ?
        border.BorderThickness.Top : 0) -
    ((border.BorderThickness.Bottom > 0) ?
        border.BorderThickness.Bottom : 0);
This viewport variable now holds the size available for the Image control inside the border. Now, all I have to do is determine if the Image needs to be scaled down in the viewport or set to a fixed size. One thing I discovered is that the Image's Margin value must be taken into account, since it is also rendered inside the viewport along with the photo bitmap. The code to determine the right sizing, in this case for the width is:

// Calculate the image's real width to determine if
// scaling is needed
double imageWidth = _bitmapActualSize.Width +
    image.Margin.Left + image.Margin.Right;
if (viewport.Width > imageWidth)
{
    // Restrict the Image control's width to the
    // bitmap's actual width
    image.Width = _bitmapActualSize.Width;
}
else if (viewport.Width < imageWidth)
{
    if (Double.NaN != image.Width)
    {
        // Set the Image control's width to 'Auto' so
        // it will scale down to fit
        image.Width = Double.NaN;
    }
}
The same calculation is done for the Image height immediately after. This results in the proper change to the photo bitmap size just at the right time.

Wednesday, August 31, 2011

Eliminating Visible Image Borders on Blogger

Copyright © 2011, Steven E. Houchin

Something that has driven me crazy for quite awhile about Blogger is its propensity to place a thick white border around any image I added to my postings. Editing the HTML of the img element to include border="0" or a style="border: none;" or anything else like that was simply ignored. What the heck was happening?

Then, I found a hint on another site, where it referred to Blogger's "template style sheet." After some poking around in Blogger, I stumbled across it. When logged in, navigate to the Dashboard page, then select the Design tab (or link), then click the Edit HTML link along the top. This brings up a screen that allows editing of your blog template, which contains the HTML, CSS, and Javascript that is the basis for every posting. On this template page, it suggests you download your existing template before messing with it, which sounds like good advice. Under the Edit Template heading is the text of the template which you can alter.

Okay. Now to the nuts and bolts of what I did to eliminate the image border. In my template, there was a CSS directive like this:

.post-body img,  .post-body .tr-caption-container { 
   padding: 8px;
}

The 8 pixels of padding is the border I saw, because it seems to inherit a white background color from elsewhere. My images are controlled by the ".post-body img" class. So, I deleted that class specification from the above and created a new one that had the padding and background specifications I wanted:

.post-body .tr-caption-container {
  padding: 8px;
}

.post-body img {
  padding: 8px;
  background: $(post.background.color);
}

This keeps the padding (which I like since it provides some separation between the image and the text) and makes the background color for the image's box the same as the post's color. The $(post.background.color) value is, I think, a variable handled by Blogger's XSL processing that is replaced in the final output with the actual color (or "transparent" in my case).

Once I saved these CSS changes to my template ... voila! The image borders in all my posts (new and old) vanished. In reality, all I really did was change the background color of the padding for just the images.

Thursday, August 11, 2011

Finding IWin32Window in WPF

Copyright © 2011, Steven E. Houchin

I'm developing a WPF desktop application (C# and .NET 3.5) that needs to pop up a dialog window allowing the user to browse for a folder.  .NET provides a convenient (and bland) dialog that does this: System.Windows.Forms.FolderBrowserDialog. To pop up this dialog as modal from my app, I must call its ShowDialog method. Since I want it to be a child of my main window, I need to pass it the parent window, which should be straightforward given the "owner" parameter to the method in question:

DialogResult ShowDialog(System.Windows.Forms.IWin32Window owner);

The problem is, the would-be parent window of that dialog is of type System.Window, not IWin32Window, so "this.Owner" won't match the datatype of ShowDialog's "owner" parameter.  So, given that I have a WPF System.Window-derived parent class, where do I obtain an IWin32Window object?

Well, it turns out I have to write a tiny bit of code for it. Specifically, I must implement the IWin32Window interface on the parent window's class:

public partial class Main : Window,
    System.Windows.Forms.IWin32Window
{
...
   #region IWin32Window implementation
   IntPtr System.Windows.Forms.IWin32Window.Handle
   {
      get
      {
         return ((HwndSource)
             PresentationSource.FromVisual(this)).Handle;
      }
   }
   #endregion
...
}

With the IWin32Window.Handle property now implemented in the parent class, I can simply call ShowDialog(this). Note that you must also include a "using System.Windows.Interop" for this to work.


Wednesday, September 22, 2010

Kernel Driver Signing - Part III

Copyright © 2010, Steven E. Houchin

In Parts I and II of this article, I discussed the requirement for driver signing, digital signatures, and how to go about testing signed drivers.

The last step is the actual signing of the binaries that you integrate into the customer product. In order to do this, you must first purchase a digital certificate from a reputable certificate authority (CA). In fact, for kernel mode drivers, you must purchase your digital certificate from Verisign. Certificates from other vendors can be used to sign the binaries, and Windows installs them, but it refuses to execute those binaries (as of Windows 7).

As I've mentioned in the earlier parts of this article, the step-by-step procedures for driver signing are contained in a document at the Windows WHDC site, and need not be repeated here. It contains a section titled "The Kernel-Mode Code-Signing Process." The important decision to make is whether to set up the digital signature via a catalog file (specified in the INF file), or to sign the binaries directly. A cartalog is preferable, especially if you are signing multiple files; but that won't work if your binaries start at boot time (see StartType in your INF fle). In that case, signing the binarys themselves is required. Microsoft has another site, titled "Signing Drivers for Public Release", that gives more details about the files you may receive from your CA.

When you distribute your product for the customer to install, the installer package must include, in addition to the binaries, the INF file, signed catalog files (if any), and the public key portion of your digital certificate. The public key digital certificate (.spc or .cer file) must be installed on your customer's system. Your original private key digital certificate (.pvk file) should be locked away, because it is used in the signing process.

Monday, August 9, 2010

Kernel Driver Signing - Part II

Copyright © 2010, Steven E. Houchin

In Part I of this article, I explained that all kernel drivers on 64-bit Windows systems must be digitally signed.

There are two ways of signing kernel drivers: embed the signature in the driver binaries themselves, or use a signed catalog file. To peform driver signing, you really must have the latest Microsoft WDK installed on your signing system.

For drivers that start at boot time (see StartType in your INF fle), the binary itself must be signed.  Use of a catalog file is not enough, though is also required if installing the driver package via INF file.  For other types of drivers - especially those that contain multiple files - a signed catalog file can be used to identify all the files in a driver package. 

Use of a catalog file requires that the driver package be installed via an INF file, because that is where the catalog file is specified. For example, ADriver.inf will have the following line included in its [Version] section:
CatalogFile=ADriver.cat
After your driver binaries are all built and copied to a "package" directory (which includes the INF file), a catalog file is created using the WDK's Inf2Cat utility. For example, if your package files are in C:\MyDriverPackage, the catalog file (in this case for Win2K and Win64 systems) is created via:
Inf2Cat /driver:C:\MyDriverPackage\ /os:2000,Server2003_X64
This utility will scan all INF files in the given directory and create catalog files for each one using the "CatalogFile" line.

Once the catalog files are created, they must be signed using WDK's SignTool utility and your digital certificate information.  The details for catalog file creation and signing, and driver binary signing, are at the Windows WHDC site, which contains white paper that has decent step-by-step procedures.

The catalog file and INF file go together as a pair wherever the signed driver package is to be installed.  If your INF file is also used for 32-bit drivers, then your 32-bit installer should comment out the "CatalogFile" line in the [Version] section so that a signing certificate isn't needed on those systems.

Tuesday, July 27, 2010

Kernel Driver Signing - Part I

Copyright © 2010, Steven E. Houchin


Back in January of 2006, Microsoft announced - much to developers' dismay - that all kernel drivers on 64-bit Windows systems must be signed. Signing is defined as:
the process of assigning an encrypted digital signature to executables in order to confirm the software's author and to guarantee that the code has not been altered or corrupted
Once I ported my client's driver code to 64-bit, I found myself in an "uh-oh" situation: how do I test the changes on my development systems without having my client's digital signing certificate?  A digital certificate is:
a digital signature from a certificate authority (CA) that contains a private key used to sign some software, which must match the public key in the CA's certificate installed on a user's system
The private key (PK) is necessary for me to sign the driver executables, and is something that the software vendor (my client) must not pass around to anyone else - including me - lest it fall into the wrong hands and be used for malicious signing. That gets us back to my dilemma: how do I test without the PK?

The answer provided by MSFT is Test Signing. The Windows WHDC site contains a good white paper on this subject that has decent step-by-step procedures. The basic idea is this: a developer can create a Test Certificate, which is used on the development systems to sign and validate executables.  The catch is, the executables will only work if the target test system is configured to boot into a special Test Signing mode. This is done on the target system with the BCDEDIT command. Note that, in the past, it was also possible to boot Windows into a "Disable Driver Signature Enforcement" mode, where signatures were ignored. That option, while still visible via F8 boot options, does not actually work anymore.

Next time: Test Signing using catalog files.

Thursday, September 3, 2009

The Mysterious Missing Attribute

Copyright © 2009, Steven E. Houchin

Something about my XP system has been driving me crazy for a long time. I use Visual Source Safe for source control of my development projects on. VSS makes use of Windows’ Read Only file attribute to prevent modification of source-controlled files in a project’s working directory. When a file is checked out of VSS, that attribute is cleared, and the user can then change the file. When checked back in, Read Only is set again.

So, what was my problem? It’s this: the Read Only attribute on those source-controlled files (and others) would simply disappear periodically. I’d have to go through all my files and reassert Read Only by hand. I looked into a number of causes: that VSS was doing it, or Visual Studio; maybe it was compiling the files over a network share; maybe it was my anti-virus software.

Then I stumbled across the cause: backing up the files to a CD via Windows Explorer. It seems that somebody in Redmond Land decided it would be a clever idea to clear the Read Only attribute for all files burned to a CD. When I searched the web for others with this problem, I actually saw the opposite complaint: that files retained their R/O attributes on a CD. Okay, so what? The CD is … wait for it … wait for it … READ ONLY!

Maybe there is some obscure Windows setting that will stop this behavior on my system. Let me know if you find one. In the meantime, I now have to first copy my files into a zip file, then back up the zip – a real pain.

So, call me crazy. This problem has certainly driven me mad.