Wednesday, February 3, 2010

Sharing a struct definition between managed and native code

By defining a struct in IDL the struct definition can be used in managed and native code.

When the IDL file is compiled the C++ bindings are automatically generated in a header file.  This allows you to use the struct definition from C++.

When the resulting type library is imported by the type library importer the struct gets created along with any other visible IDL type definitions (e.g., interfaces, coclasses, enums, etc…).  This creation involves translating the IDL into IL metadata (you can see the metadata with ildasm).

Troubleshooting:

  1. Make sure the native code builds a type library and that the type library is registered.
  2. Use OleView to see the types included in the type library.  The struct should show up in this list of types.
  3. Don’t typedef the struct in the IDL; although this will compile the type library importer will ignore the resulting alias.  If you want the typedef for use in native code create it manually.
  4. Use the Object Browser or ILDASM to verify that the type library imported the struct.

Thursday, January 28, 2010

Quick Hit: Speeding up Visual Studio builds for Solutions with Managed and Unmanaged projects

Unload the native projects (right click native project in solution explorer –> unload).  Any subsequent builds will not build the native projects which usually take much longer to build.

Visual Studio’s memory of which projects are unloaded in a solution appears to be stored locally so it won’t be checked in when the solution is checked in (you’re not checking in .suo files are you?)

Of course this isn’t helpful if you’re working on the native projects but greatly speeds things up when you’re only working on managed code.

Friday, January 22, 2010

Which Control Properties can be automatically saved and loaded with ApplicationSettings?

ApplicationSettings automatically persist and bind property values for a component under the following circumstances:

  1. The component implements IBindableComponent.
  2. The component has either:
    1. A PropertyChanged event for the specific property (e.g., TextChanged, ValueChanged, etc…)
    2. or the component implements INotifyPropertyChanged.

Since all controls inherit from System.Windows.Forms.Control and Control implements IBindableComponent for controls you really only need to worry about the 2nd requirement.  If the control has a property changed event for the specific property then it will probably be automatically persisted when connected to an ApplicationSetting property.

Wednesday, January 13, 2010

Application Resiliency for Standard Users

Windows Installer has a feature called “Application Resiliency” which, in a nutshell, attempts to make sure that an application’s components are in order before executing the application.

Application Resiliency checks are invoked on a few occasions:

  1. When the user clicks an installer shortcut (which is different from a regular shortcut though the difference isn’t entirely germane to this post).
  2. When the user starts the application via file association (e.g., double clicks on a file extension that’s handled by the app).

These features are configured by registry entries.  The presence of a special key, called a Darwin Description (and described here), causes Windows Installer to do the extra Application Resiliency checks possibly resulting in an automatic repair.

So far so good.  I’m happy to have extra help keeping an application’s components intact.

What happens if the application was installed by an Administrator but the first resiliency check occurs in the context of a user without admin privs?  For example, the administrator installs it then leaves.  The first user to use the application is a user without admin privs.

Some of the resiliency checks require accessing the msi installer package.  This package, at least for one particular installer creating program, is by default left in a location specific to the user that performed the install.

Since non-admin users can’t read this default location, they should fail the resiliency check.

The twist in this particular case is that the user only fails the resiliency check when it is invoked by file extension (e.g., they double click on a file extension that is handled by the app).

A few solutions come to mind.

  1. Use Windows Installer in the “no registry” mode.  This will fix the problem but you give up a lot of functionality provided by Windows Installer.
  2. Manually disable Application Resiliency by deleting the “Darwin Descriptor” registry value after install.  This is bad for several reasons not the least of which is that it relies on an implementation detail that might change.  It’s also hard to do because the registry value appears to be read-only.
  3. Make sure that msi installer package gets installed into a directory that any user can read (e.g., CommonAppData).

1 and 2 are tempting but IMHO these are hackish approaches with too many drawbacks to justify their use.  3 seems to be the way to go but is not entirely without drawbacks: some systems may be so tightly configured that there are effectively no directories that can be read by any user.

The (software) Rockstar’s Muse

Had to share some great linkage about the “Rockstar’s Rockstar” type of developer.

I don’t think having one or more of these types around can magically turn an awful business plan into the next iPhone (or whatever business plan included the iPhone). 

Amazon, as discussed in “Done, and Gets Things Smart”, is a case in point though I’d be surprised if there weren’t a few poking around in the beginning - if only to get the seemingly embryonic technology of the time working well enough to make a business.

However, they might just buy you enough time to make a mediocre business plan into a stellar one.  They do this mainly in 2 ways:

  1. The software they produce and/or architectures they put into place result in far fewer fires to put out.
  2. The software they produce and/or architectures they put into place tend to interface with other software/architectures well.

How do these 2 points conspire to make Rockstar’s Rockstar developers make-or-break components of a software team?  I’ll expand on these in a later post.

Wednesday, January 6, 2010

Why are unused properties accidents waiting to happen?

When it comes to class design I’ve tended to shy away from using what database types would call “de-normalized” objects.

In the world of Object Oriented Design the analogue of de-normalized tables are objects that have lots of fields most of which are null or unset.

These kinds of objects should be avoided because they depend on hidden knowledge.  They increase the amount of hidden knowledge necessary to work with a given system.

In a perfect world the purpose of an object would be obvious based on its name.  The same goes for its properties.  But when most of an objects properties are not used at any given moment you usually have an object that can take on radically different roles based on which set of its properties are set (or not null).

How is someone new to the code going to know which role the object is in at the time they’re looking at it?  <== There’s that hidden knowledge!

Although it’s tempting in a pinch to pile on the properties/fields of an object, especially when it’s sitting right there and you really need a piece of data, I urge you to resist the temptation.  The befuddlement you’re hoisting into the future my just land in the lap of your future self.

As always this rule of thumb should be taken with a healthy dose of skepticism.  Sometimes it’s necessary to de-normalize; either for performance reasons or because the design genuinely calls for it.

Friday, December 18, 2009

From Santa: Continuous Integration, Progress Bars, Build Scripts, Oh My!

Continuous Integration is a wonderful concept.  The basic idea is to get integration-level feedback as quickly as possible.  It’s done wonders for cutting down on “it builds on my machine but not on anyone elses” phenomenon.

A piece of software, the free version of CruiseControl.NET in this case, runs on a PC and checks the version control repository periodically (usually every 15mins or so).  Once it detects changes it grabs them and runs the build.  So when you forget to check in that COM library that a library your library depends on needs you find out within 15mins or so instead of the next morning.  Nightly builds are nice but continuous builds are nicer.

The rules of thumb that I’ve seen are for Progress bars are:

  • If an action takes up to 3 seconds to complete show an hourglass/busy cursor.
  • If an action takes 10 seconds or more then it needs to have a Progress Bar.

Progress Bars are pretty much the first thing to go when deadlines are tight so the holidays present a wonderful time to go back into those UIs on top of long running processes and add a progress bar.

When you've got a mix of managed and native code (a mixed blessing?) Visual Studio’s otherwise stellar dependency checking may show signs of wear.  This is probably due to the cobbled together mixture of post-build scripts and external bat (or NAnt) scripts that represent your “evolutionary” build.  The holidays are a wonderful time to make the build process less “evolutionary” and more “cultured” so-to-speak.