SuperSecretary

The following is the beginning of a series of posts with detailed information on my open source personal projects. The intention is to provide information about the application, development, design decisions and lessons learned.  Enjoy!

Overview

I don’t recall exactly when I started working on SuperSecretary, but I originally looked at a folder of various photos on my machine and set out to look for a way to keep them under control. I looked for software to sort photos by date taken and couldn’t find anything to meet my criteria. It didn’t seem that there were any options that were user-friendly, and there certainly weren’t any that were free.

I started building SuperSecretary specifically as an app to manage photos, but quickly realized that the concept could be expanded upon to manage all types of files. There are even some features, such as sorting music files by ID3 tags that are on my to-do list for future versions.

Design

I knew from the beginning that I wanted the application to eventually support plugins for users to handle files in any matter that they deemed necessary. This led me to the creation of the “Handler” in SuperSecretary. It is essentially just a simple, verbatim implementation of the Strategy pattern. Each handler has a Do method that passes in the path to the file that is being acted upon, along with some options that have been selected by the user. The handler returns the name of the folder that the file should be sorted into.

For example, when the user chooses to sort a photo by the Date taken attribute, the system uses a DateTakenHandler. The sorting engine loops through the files that need to be sorted and runs the DateTakenHandler for each one. The DateTakenHandler will retrieve the Date taken property from the EXIF data and format it based on the format selected by user. For cases when the user chooses to sort based on multiple attributes, the system will return and then move on to the next Handler. The handlers all inherit from the same interface, allowing a plugin system to be implemented.

The only thing I dislike about this design is that it is not the most efficient option. The system loops through each file, then loops through each of the handlers and acts before moving on to the next. However, some processes are more efficient when grouped together. For example, if the user chooses to sort on two EXIF attributes, say Camera Model and Camera Maker, it makes sense to retrieve that information together. However, batching these operations together makes the system less extensible. Ultimately I chose the more modular approach.

Development

I started development on a proof of concept right away. Since the application was meant to be a small utility that I used myself, I did not put much effort into researching features or deciding on what options to provide right off the bat. I kept the user interface compact and simplified as possible.

After completing the proof of concept, I began to think about the bigger picture of all of the things that could be possible. I pondered on a plugin system and the possibility of multiple interfaces, including a console front end for automating the application as a scheduled task. I even started building a WinRT front-end, which didn’t go so well. More on that in another post.

All of these more end user focused features led to many development decisions. I re-factored the application into two projects, a core library and the Windows Forms application. I focused on keeping the Windows Forms view as thin as possible and moved all of the logic to the core library.  I moved detailed output of the results of each run to an update event that could be implemented in to display information in the UI, a log file, or any manner that is specific to the target platform.

Packaging

Releasing a desktop application as a product was an entirely new concept for me. All applications need a few common elements, one of which is a deployment package. I had very little knowledge on creating a Windows installer. I really only knew that Visual Studio Installer Projects had been recently discontinued and that I needed to find a new option.

I discovered the WiX Toolset, a fantastic framework for building MSI installers. I admit that my implementation is very simple, but to this point I have not run into anything that I needed that I could not achieve using WiX.

The other common element that an application needs is assets and branding. I come from a primarily web focused background and working as a part of a team, so I had never had the complete responsibility of creating assets for a project. Icons, logos, screenshots and information were all things that I had never created and compiled from scratch. I am not a designer so I tackled those to the best of my ability. Paint.NET became my friend.

Distribution

I initially built the Razium web site specifically for hosting an installer for SuperSecretary. I created the site in a format that was more focused on the end user as a target audience, rather than toward developers. I will do a post in the future entirely focused on the creation of the Razium site, since there are some interesting tidbits there.

Originally I hosted the files there as well, but I have since moved those to Sourceforge. Hosting on Sourceforge obviously requires that your application be open source, but for those that are, it provides the added benefits of handling bandwidth costs and also the exposure that you get from being included in their library. In the first day on Sourceforge I had more downloads than the whole time that SuperSecretary was up on the Razium site.

Thanks for reading.  For more information on SuperSecretary, or to download version 1.1, click here.  To view the source code or fork the project, visit the GitHub repository.

Razium

I have taken a little bit of time away from updating the blog lately to work on a few little personal projects. Some of these were ideas that started years ago that never got into any kind of working order and others were utilities that I wanted to create simply because there was no free option available. A few of these projects have been open sourced and in development for some time. From a glance at my GitHub history you can see that my development schedule is a little bit scattered to say the least. A good summary would be to say that I work on what I want when I want to and I develop selective amnesia regarding the rest of the projects until I find my way back to them. After all, they are personal projects, right?

To break from my habits I have been putting some effort into seeing a couple of these projects through to usable applications. I have done that with the 1.0 release of SuperSecretary, my file sorting application, and I am near that point with MembershipManager, my ASP.NET Membership utility. Most developers are used to relying on GitHub for open source projects, but since these applications are more than just developer tools, it makes sense to have something more than a GitHub repository where the source code can be pulled and built. Enter Razium.

Razium is a site where I will provide more end-user targeted information about these projects. This may be lists of features, screen shots or comparisons depending on the project. It will also be where your average user goes to download compiled binaries and installers for the applications (via SourceForge). The site is very basic at the moment and only contains detailed information for SuperSecretary, but will be evolving over the coming months.

In the near future, I will be posting blog entries about each of my open source projects. I hope to provide a brief overview of the current state of each of the projects with some challenges and lessons learned from development to date. I am excited to document and share the knowledge that I have gained throughout the process of turning an open source project into a product. Stay tuned!

Generating an Image of a PDF Page

I recently completed a project that required a thumbnail image automatically be generated from the first page of every PDF file that is uploaded to the system.  I was rather surprised to find that there was no drop in solution for such a thing.  There are many libraries out there that can create a PDF file from HTML content or an image, but no standalone libraries that could go from PDF to an image.  After testing out a couple of methods, I was able to find what I believe to be the easiest and least invasive method to implement it in a web application..

What You Will Need

To generate images from PDF in your project, you will need a couple of things.

Ghostscript, a set of libraries for working with a PDF.  You will need to download the version specific to your environment (32 bit/64 bit).  You can download those here.

GhostscriptSharp, a wrapper for using the Ghostscript libraries in .NET.  You can download it here.  It is written in C#, so if you are using VB.NET you will need to create a code sub-directory in your Web.config to use the file in your project.

Setup

You will need to do a couple of things to get the Ghostscript components to function before you write any code.  First, you need to extract the gsdll file to a location on your system.  (Either gsdll32.dll or gsdll64.dll depending on your CPU.)

Then, you need to modify GhostscriptSharp.cs to specify the path to the Ghostscript library that you extracted before.  Look for this code on line 12 of the GhostscriptSharp.cs file:

#region Hooks into Ghostscript DLL

[DllImport("gsdll64.dll", EntryPoint = "gsapi_new_instance")]

private static extern int CreateAPIInstance(out IntPtr pinstance, IntPtr caller_handle);

[DllImport("gsdll64.dll", EntryPoint = "gsapi_init_with_args")]

private static extern int InitAPI(IntPtr instance, int argc, string[] argv);

[DllImport("gsdll64.dll", EntryPoint = "gsapi_exit")]

private static extern int ExitAPI(IntPtr instance);

[DllImport("gsdll64.dll", EntryPoint = "gsapi_delete_instance")]

private static extern void DeleteAPIInstance(IntPtr instance);

#endregion

You will need to change the paths in the DllImport constructors to the location of the file on your machine.  The DllImportAttribute only accepts a constant string, so you cannot pass a variable with the path or using a Web.config value.  This prevents you from using Server.MapPath to generate the path to your project’s bin folder, which is also unfortunate.

The Code

The actual implementation of the image generation from PDF is very simple once you have reached this point.  You just need to make a call to the GhostscriptWrapper.GeneratePageThumb method with the path to the PDF, and the path where the image should be saved.  You also specify the page number you want to generate from and the height and width of the final image.  A call to GeneratePageThumb might look like this:

// Creates a 100 x 100 thumbnail of page 1.
GhostscriptWrapper.GeneratePageThumb(pdfFileName, outputFileName, 1, 100, 100);

You will also need to import the GhostscriptSharp namespace in your code file.  That is all that there is to it!  After running your application, you will see the image file in the specified path.

Its important to note that GeneratePageThumb is a shortcut method that will only generate a JPG image.  If you need to have more control over the output of your image, then you will need to use the GenerateOutput method and pass in a GhostscriptSettings object that contains all of your required values.  The GhostscriptSharp link above provides more detailed examples if you need them.

Thanks for reading!  If you have any troubles with the process, feel free to leave a comment below.

Fixing reCAPTCHA.net 404 Errors

Last week, Google decommissioned the reCAPTCHA API components that were hosted on recaptcha.net.  According to reCAPTCHA support, the change was supposed to have occurred back in April, but for some reason or another the site has only now been replaced with a 404 error.

The good news is that Google has not made any changes to the reCAPTCHA API, so you will just need to change the reCAPTCHA path from the old location to the new location hosted with Google.

In your application, all instances of this URL:

http://api.recaptcha.net

need to be replaced with this:

http://www.google.com/recaptcha/api

You will need to change all references to that URL, including the recaptcha.js or recaptcha_ajax.js files and the /verify URL.  It is as simple as that.  Keep in mind that if your site uses SSL then you need to change the “http” in the URL to “https”.

Many Joomla users have been affected by this problem as well.  Luckily a proposed fix has already been committed to Joomla’s GitHub repository.  To view those changes or to download the updated file, click here.  If you’re not confident enough to fix the issue on your own, a formal patch should be on it’s way from Joomla soon.

Feel free to leave a comment if you have any questions.  Thanks for reading!

Iterating Over an Enumerable – Creating a “Days of the Week” Drop Down Menu

Enumerations are extremely valuable for managing sets of numeric values such as status codes or days of the week.  Most of the time, you would create an enumerable to simplify values used in multiple points that have the same representation, in order to improve the readability and re-usability of your code.  However, there are some situations where using the enumeration’s name and value directly on the presentation layer can make sense.

For example, let’s say we have a form where we need the user needs to choose a day of the week to assign to a particular record.  We can easily generate a drop down list of values using the built in DayOfWeek enum that is included by default in the System library.

Code

Let’s create a Drop Down List on our page.  We will generate the list items in code behind, so we will just leave those blank.  It should look something like this:

<br />&lt;asp:DropDownList ID="ddlDay" runat="server"&gt;&lt;/asp:DropDownList&gt;<br />

In our code behind file, we will use a couple of helpers from the System.Enum namespace to allow us to loop through our enumerable's values and get their names for use in the list item.  Here's the code for our page load event:

<br />Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load<br /><%%KEEPWHITESPACE%%>    If Not Page.IsPostBack() Then<br /><%%KEEPWHITESPACE%%>        ' Get the values of the DayOfWeek Enum (0-6).<br /><%%KEEPWHITESPACE%%>        Dim daysOfTheWeek = System.Enum.GetValues(GetType(DayOfWeek))<br /><br /><%%KEEPWHITESPACE%%>        For Each value In daysOfTheWeek<br /><%%KEEPWHITESPACE%%>            ' Get the name that corresponds to each value.<br /><%%KEEPWHITESPACE%%>            Dim name = System.Enum.GetName(GetType(DayOfWeek), value)<br /><br /><%%KEEPWHITESPACE%%>            ' Add a new list item, using our name and value.<br /><%%KEEPWHITESPACE%%>            ddlDay.Items.Add(New ListItem(name, value))<br /><%%KEEPWHITESPACE%%>        Next<br /><%%KEEPWHITESPACE%%>    End If<br />End Sub<br />

It's that simple.  Now you know that the value that gets posted back to the server will match directly with the values defined in the enumeration, even if the values were to change at a later date.

A Caveat

One thing to keep in mind are that this is only a user friendly option for single word names.  For example, if you have a value that represents a process' status that is named "InProgress", it would appear as a single word in the drop down as well.  You could parse the name to add the space, but there are cases where that could over complicate the process.

Thanks for reading!

Integrating Google Apps With Your Application Using GData and Extension Elements

Google Apps for Business is quickly becoming the go-to solution for email, calendar and file applications.  Thanks to the available web service API for developing extensions and utilities on Google Apps, you can easily integrate your existing systems as needed.

What You Will Need

I’ll be using the GData API for .NET and the Google Calendar Service for the below examples, but you can access Google’s web services in pure XML form on any platform.  Alternatively, Google provides many pre-built libraries for many popular programming languages.  You can find them here.

You can also interchange any of the other Google Apps services, such as the Contacts Service and perform the same actions to meet your needs.

Extension Elements

Extension Elements are configurable attributes that can be attached to all Google Apps entities.  These attributes are only able to be accessed through the API, so your end users will not notice any difference in how they use Google Apps.

With an Extension Element, we can add an external identifier for an outside system that will allow us to connect the two entities as necessary in the future.  For example, let’s say that we want to use a custom system that contains metadata for calendar events specific to our business and we want to keep them synchronized.  We can create a calendar event using the API and attach the ID to our system’s records.

Creating a Record With Extension Data

Here is an example of how to create a new calendar event with an external identifier.

public EventEntry CreateEvent(Guid Id)
{
	EventEntry entry = new EventEntry();

	// Set the information for your event here.
	entry.Title.Text = "Event Title";

	// Create an ExtensionElement and add your external system's ID.
	ExtendedProperty prop = new ExtendedProperty();
	prop.Name = "ExternalIdentifier";
	prop.Value = Id.ToString();

	entry.ExtensionElements.Add(prop);

	// Create the service and insert the new event.
	CalendarService service = new CalendarService("YourAppNameHere");
	service.setUserCredentials("UserName", "Password");

	return service.Insert(new Uri("https://www.google.com/calendar/feeds/default/private/full"), entry);
}

Getting the Extension Element Value with LINQ

Once we have our events created with our external identifier, we need to be able to access that information later when we synchronize the metadata.  Here is a quick shortcut for handling that with LINQ.

// Get events from Calendar.
CalendarService service = new CalendarService("YourAppNameHere");
service.setUserCredentials("UserName", "Password");

EventQuery query = new EventQuery("https://www.google.com/calendar/feeds/default/private/full");

EventFeed events = service.Query(query);

foreach (EventEntry entry in events)
{
	// See if our entry contains the external identifier.
	ExtendedProperty prop = entry.ExtensionElements.SingleOrDefault(x => x is ExtendedProperty && ((ExtendedProperty)x).Name = "ExternalIdentifier");

	if (prop != null)
	{
		// Do our work for each system here.
	}
}

Conclusion

This only scrapes the surface of what is possible with Google Apps.  You could add any type of data here that you would like.  You could even store all of the information that your application needs on the event itself instead of in an external database.  The Google Apps API makes custom integration with your systems easy.

Thanks for reading.  Any questions?  Feel free to leave a comment!

.NET Decompiler Software Options

Every once in a while a project comes along that requires integrating with a third-party library or working with existing compiled code.  On occasion those libraries can come with either poor or no documentation at all.  This can make debugging a nightmare.  In this case, having a peek at the source code can point you in the right direction or even solve the problem altogether.  Believe it or not, there are several solutions available for decompiling .NET code on any budget, including many that are completely free.  You can even (gasp!) make changes to the library and re-publish!  Here is a look at the options.

Red Gate .NET Reflector

Reflector was previously the only solution available for decompiling .NET assemblies.  They offer a complete desktop application and an option for Visual Studio integration.  I say “previously” because .NET Reflector recently switched to a paid application, which spurred many of the competitor products.  Pricing for Reflector starts at $95.

Jetbrains dotPeek

dotPeek is my favorite .NET decompiler application.  It has a clean, familiar design and also has many IDE-like features for navigating through the decompiled code.  My only complaints are that it only decompiles to C# code at the moment and that it does not allow direct editing of the library.  You can however save the code as Visual Studio project and rebuild it on your own.  Best of all, it’s free.

Telerik JustCompile

JustCompile has many of the same features as dotPeek including the ability to create Visual Studio projects.  It is also very fast and provided free of charge.  I ended up using JustCompile for a recent project because it is compatible with Reflexil, a plugin that allows you to directly edit the library.  It is not as simple as just writing new code, but it is very helpful for situations where you just need to make small changes and don’t want to rebuild.  (Note: Reflexil also works with Reflector, but JustCompile is the only free application that it supports.)

CodeReflect

CodeReflect is a decompile-only product, meaning that it does not provide any of the Visual Studio project features of some of the other options.  It has a very simple interface and is also free of charge.  CodeReflect can decompile .NET code into either VB.NET or C#, whichever you prefer.

ILSpy

I have not used ILSpy, but I wanted to include it in the roundup since it is the only open source .NET decompiler.  ILSpy can decompile to either VB.NET or C# and save as a project in C#.  If you are a developer who is curious about decompiling, you can check out the source code to learn how it all works.

Thanks for reading.  Do you have a favorite .NET decompiler that is not on the list?  Feel free to leave a comment!