net, vs comments edit

As of 2012.1.4, the DXCore “About” box no longer displays ProductModule contents. If you’re working with that version or later, don’t bother with this. You won’t see the results of your efforts.

Have you ever looked at the DevExpress menu in Visual Studio and selected the “About” option? There’s a list in there of all the installed “products” with associated version information, a textual description, and even a graphic with the product logo:

DXCore "About"
box

If you have the CR_Documentor plugin installed, you’ll notice it also shows up in that box:

DXCore "About" box showing the CR_Documentor
information

If you want to “make your plugin an official product” and show up in the “About” box, the way to do that is to implement a ProductModule.

Before we get into this, something to consider: You probably don’t need or want to implement a ProductModule for every plugin you write. Doing this is something for larger plugins or, better still, suites of multiple plugins that get distributed as a single product. If every plugin did this, that “About” box would get pretty noisy really quick… and does everyone need to see that little hotkey plugin in the “About” box? That said, if you have a sizable plugin or a plugin suite, here’s how you get into the “About” box…

This tutorial assumes your plugin(s) are all in one assembly. You may need to tweak a few things to get it to work for a multi-assembly suite, but the general principles should remain the same.

First, make sure your assembly is marked with title, version, copyright, and description attributes. We’ll use these attributes to generate the text that shows up in the “About” box.

[assembly: AssemblyTitle("Product Module Demo")]
[assembly: AssemblyCopyright("Copyright © 2010 Travis Illig")]
[assembly: AssemblyDescription("Demonstration that shows how the ProductModule works to get a plugin into the About box.")]
[assembly: AssemblyVersion("1.0.0.0")]

Next, create your logo graphic. The image should be a 536 x 201 PNG image and should have your product logo as well as the name of your product. If you look at the above “About” box images, you’ll see a blue gradient that has the logo and product name on top - that’s what you’ll be creating. Your image should include the gradient and everything - that doesn’t get put in for you. To make it good, you’ll probably need to take a little time with a paint program of your choice. Just put your logo on the background; the little “version” information in the top right corner gets inserted for you by the “About” box.

For convenience, here’s a PNG image of the gradient background that I created and you can use to start with:

Gradient for "About" box
logos

Add your logo image to your plugin project as an embedded resource. Drag it into your plugin project so it gets added in there and make sure in the properties the image is set as “Embedded Resource.”

Embedded resource
properties

Add a class to your project that derives from DevExpress.CodeRush.Common.ProductModule. This is where all the information for the “About” box comes from.

In your derived ProductModule, you need to define some constants:

  • The path to the embedded resource that is your product logo graphic.
  • A GUID that uniquely identifies your product. Note that there is ONE product GUID, but there may be many plugins in that product. This GUID is not the same as the plugin IDs.
  • The minimum DXCore version that your product works with. This will be used to help DXCore determine if your product is compatible with the user’s installation.
  • A string with the short name of your plugin assembly (“MyPlugin.dll”). You could technically calculate this on the fly, but chances are it’s not going to change much (or ever) so it’s fairly safe to just hardcode it.

This will end up looking something like the following:

private const string LogoPath = "ProductModuleDemo.ProductModuleLogo.png";
private static readonly Guid ProductId = new Guid("0CB93ADC-7188-4632-B469-98D161074E48");
private static DevExpress.CodeRush.Common.Version MinEngineVersion = new DevExpress.CodeRush.Common.Version(10, 1, 6, 0);
private const string PluginAssemblyName = "ProductModuleDemo.dll";

Add a static constructor to your ProductModule to calculate some values based on the assembly. You need to calculate and store:

  • The assembly title.
  • The assembly copyright information.
  • The assembly description.
  • The assembly version, converted to a DXCore version value.

Get that information from the attributes you added to the assembly. For a ProductModule class called “About,” that’ll look like:

private static readonly string AssemblyTitle;
private static readonly string AssemblyCopyright;
private static readonly string AssemblyDescription;
private static readonly DevExpress.CodeRush.Common.Version AssemblyVersion;

static About()
{
  var assembly = typeof(About).Assembly;
  var version = assembly.GetName().Version;
  AssemblyVersion = new DevExpress.CodeRush.Common.Version(
    version.Major,
    version.Minor,
    version.Build,
    version.Revision,
    DevExpress.CodeRush.Common.ReleaseType.Release);
  AssemblyTitle = GetCustomAttribute<AssemblyTitleAttribute>(assembly).Title;
  AssemblyCopyright = GetCustomAttribute<AssemblyCopyrightAttribute>(assembly).Copyright;
  AssemblyDescription = GetCustomAttribute<AssemblyDescriptionAttribute>(assembly).Description;
}

private static T GetCustomAttribute<T>(Assembly asm) where T : Attribute
{
  var attributes = (T[])asm.GetCustomAttributes(typeof(T), true);
  return attributes[0];
}

In your ProductModule, override and implement the following:

  • Copyright1 property: Return the assembly copyright information.
  • Description property: Return the assembly description information.
  • ID property: Return the Product ID GUID you created.
  • MinimumEngineVersion property: Return the minimum engine version value you created.
  • ModuleType property: This indicates what kind of product you have. If it’s a community/free plugin, return ModuleTypes.Free; if it’s a paid product, return ModuleTypes.Full.
  • Name property: Return the assembly title information.
  • SupportedLanguages property: This property returns an array of language strings that indicate what languages your plugin is valid for. You can find these values in the “Language” dropdown on the DevExpress options menu. At the time of this writing, they are: Basic, C/C++, CSharp, HTML, JavaScript, Plain Text, and XML. 
  • Version property: Return the assembly version information.

There are other properties you can override to return additional information, but these pretty much handle the stuff that shows up in the “About” box.

Override the BuildDefenition method. The “BuildDefenition” method (yes, it is misspelled) is responsible for defining which assemblies make up your complete product. For the purposes of this tutorial it’s just the one assembly, which makes it easy. For each assembly, you call the “DefinePlugIn” method and pass in the string name of the assembly (the constant string you defined earlier):

protected override void BuildDefenition()
{
  this.DefinePlugIn(PluginAssemblyName);
}

Override the GetImage method. This is the method that grabs the embedded logo image and returns it for display in the “About” box. It’s a pretty simple two-line implementation where you get the embedded resource stream from your assembly and convert it to a bitmap, like this:

public override System.Drawing.Image GetImage()
{
  Assembly current = typeof(About).Assembly;
  return new System.Drawing.Bitmap(current.GetManifestResourceStream(LogoPath));
}

That’s all you have to do for the ProductModule. The last thing you have to do is mark your assembly so DXCore knows to look for your ProductModule.

Add a DXCoreProductAttribute to your assembly. The DXCoreProductAttribute points to your ProductModule so the “About” box knows what to look for. Really simple:

[assembly: DXCoreProduct(typeof(ProductModuleDemo.About))]

That’s it! Now fire up Visual Studio with your plugin in place and you should see your product information - with your logo, version, description, etc. - all in the DevExpress “About” box.

I’ve got a solution you can download with a working demo in it so you can see what the complete package looks like:

[ProductModuleDemo.zip (11KB)]

Hopefully this will help you larger plugin developers to make some really cool “official” DXCore products!

downloads, vs, coderush comments edit

It’s been a while in the making, but the new version of CR_Documentor is out.

It took a while because I did two pretty major updates to it.

First, I totally overhauled the syntax preview generation so each preview style (NDoc or Sandcastle) uses the same syntax preview engine. As part of that, I added a bunch more testing and support for complex syntax like multiple type parameters with multiple type constraints per parameter. What? What does that mean? It means you can see stuff like this in your preview:

And, of course, it works in VB, too (which, based on the way Sandcastle does it, actually all ends up on one line…):

The other thing I did was add support for serving images and other files, so now when you look at the preview for a class and see all the members listed, you see the associated icons, too. Not a huge deal, but it does make the preview more authentic.

Hopefully that adds to you documentation preview enjoyment.

As always, it’s free. Go get it!

personal, gaming comments edit

I know technology is fallible and I know my standards are probably far too high for things, but I find that once a technology or gadget has shown its imperfections to me by way of failing or misbehaving, I have a really difficult time being excited about it or trusting it again.

For quite some time I was absolutely addicted to playing drums on Rock Band. I’ve always thought I would be a decent drummer and while I know it’s not “real drums” it’s fun and fulfills that tiny dream. I bought the Ion Drum Rocker kit and totally rocked out. Until, of course, I found a problem during practice mode where hitting the yellow cymbal changes the tempo on you. After switching out the drum kit controller like three times with Ion Support (which, by the way, sucks), it turns out the problem is software-based. I also started noticing things start randomly misbehaving, like the kick pedal not registering (or going off by itself), hits not registering on the pads… and that turns out to be a funky combination of static buildup, needing to unplug the drum controller for a few seconds, and bad luck.

During the course of solving that problem, I honestly lost my feel for it. I don’t play nearly as often now, and it’s because I don’t trust the technology to behave. To do what it’s intended to do. Playing it has become a bit less fun and a bit more worry and stress over why it’s not working.

Last week I got a Droid X. Love it. Had a bit of a weird issue where the speakers suddenly lost volume but fixed it by a simple power cycle. Then we went to the Oregon Coast Aquarium this past weekend and I noticed that there’s a flaw with the camera CMOS censor such that in darker shots there’s a noticeable magenta spot, like there’s something on the lens. Suddenly, I’m slightly less trusting, and slightly less enamored with it. I still like the phone, but I find I’m not tinkering with it or messing around with it as much since I saw that.

I stopped at the Verizon store and I’m getting a replacement unit, so it should be fixed when the new unit arrives in a day or two. It’s just… I hope I don’t lose my passion for it. My enthusiasm. It’s shown me weakness, fallibility, and it’s going to take some time for me to trust it again.

I am, admittedly, a perfectionist. I hold myself to very high standards and “it works” is generally not good enough. I’m thinking, though, that even if “it works” is good enough, there’s another question to be asked: is it trustworthy? Can I trust a product or service not to break in the middle of an operation? Even if a product isn’t super-feature-rich, if it does one thing and one thing really well, I’m fine with that.

Reliability is high on my priority list. Is it high on yours?

General Ramblings comments edit

Every year for Jenn’s birthday we take a trip to the beach with some friends of ours. This year we decided to go down to the Oregon Coast Aquarium in Newport.

I took several pictures that I’ll have to post later, but I did get a nice video of the Passages of the Deep exhibit where you walk under the various fish. This particular video shows the sharks in the exhibit.

windows comments edit

I’m running Windows Server 2008 R2 as a non-admin user with User Account Control turned on. The stupid Adobe Reader update thing pops up in the corner saying “Update available” and when I tell it to install, I get:

Error 1625: Update failed. Update not permitted by system policy.

Last time I fixed this by using Autoruns and removing the Adobe Updater thing from the list of programs to run. Of course, that means no updates unless I apply them manually, either. Today I found this forum thread with the actual answer:

  1. Open C:\Program Files (x86)\Common Files\Adobe\ARM\1.0 in Windows Explorer.
  2. Right-click AdobeARM.exe and “Run As Administrator.”
  3. When the “update available” balloon pops up in the corner, tell it to install. It should work now because it has the right permissions.

Done and done. Sort of annoying that Adobe hasn’t fixed this but… well, it is what it is.