Visual Studio – ClickOnce Deployment

ClickOnce is a feature of Visual Studio 2008 that allows a developer to quickly and fairly easily create a deployment package for their software.

ClickOnce Publish Wizard Dialogue
ClickOnce Publish Wizard Dialogue

The ClickOnce feature supports two types of applications – installed applications and online applications. The installed applications are similar to traditional Windows applications that appear in the start menu and can be removed with Add/Remove Programs. The online applications are hosted in the browser and not actually installed on the local machine.

As Wikipedia notes:

ClickOnce enables the user to install and run a Windows application by clicking a link in a web page. The core principle of ClickOnce is to bring the ease of deployment of web applications to the Windows user. In addition, ClickOnce aims to solve three other problems with conventional deployment models: the difficulty in updating a deployed application, the impact of an application to the user’s computer, and the need for administrator permissions to install applications.

ClickOnce applications can be deployed to a computer from a web site, a network share, and from traditional media like CD and DVD.

You may be wondering why I’m talking about such a seemingly trivial process… Well, in the past week, I’ve been working with ClickOnce, and while it is easy, and it does make deployment of an application really simple, it has a few quirks that are rather annoying.

It seems so simple!
It seems so simple!

When you’re creating an application you will often add additional files to the project, important files that are needed to ensure the application works properly. My recent project had a couple of PGP Key Rings that it absolutely had to have in order to operate.

Visual Studio assumes that the files you’ve added are only there to be viewed and that those files are not important to the running of your application. Therefore, those files are excluded, by default, when you create a deployment package with ClickOnce.

After a bit of trial and error, and a number of Google searches, I finally came across an excellent tutorial on including important files in the deployment package for ClickOnce. If you’re fighting with ClickOnce, like I was, please check out Neil Knobbe’s ClickOnce Deployment – Deploying files with your application.

Enjoy!


PGP Decryption with C#

PGP Decryption Pictogram
PGP Decryption Pictogram

One of my recent projects was to create a Windows desktop application that would allow a user to select a PGP encrypted file, select and output destination and click a button to have that file decrypted. There were a few other things the application needed to do, like verify the information in the file, but that was the easy part.

The real challenge was to load up the public and private key rings and decrypt the source file. I have a pretty good understanding of the concepts behind PGP (symmetric key) encryption, so it seemed like a fairly straight forward project. However, as most software developers know, perception and reality rarely align.

I started out looking for a .Net library that would encapsulate all of the PGP processes for me. Turns out, there are several, but most of them are commercial products and there just wasn’t any money in the project budget for that. So I keep looking and eventually, I came across the Legion of the Bouncy Castle, which provides an extensive encryption library. It was originally for Java, but has been ported to C#. Perfect!

This thing's got class(es)!
This thing's got class(es)!

I downloaded the non-IDEA library, referenced it in my project and voila! Except, not so much. There was a ton classes, but nothing referencing OpenPGP directly, and that’s what I needed.

I read through a ton of information on the Bouncy Castle site, and it looks like there should be a .OpenPgp class included. So I spent a bit more time searching through Google to find an example or two of others that were already using Bouncy Castle in C#.

If you’ve been trying to do the same thing, you already know that there aren’t very many good samples out there. I did find an excellent piece on how to encrypt files using PGP and the Bouncy Castle library by the .Net Geek. If you’re looking to encrypt files, this is a great place to start. I’ve incorporated this code into my crypto library that is below. I’ve also included links to a number of sites and articles that I read while working on this project. I hope you will find this information useful as well.

With a good example in hand, I started working out how to make the decryption side of things work. Again, its fairly straightforward, you just need to know what sort of stream you’re looking for at each stage of the process. Similar to the .Net Geek, I like to figure out how I’m going to consume the provider before I write it. That helps to make sure that the classes are easy to use and work like I’m expecting. I’ve provided a sample application and a crypto wrapper library at the bottom of this entry. Feel free to jump ahead.

All I wanted to do from my application was call the decryption routine and pass in the path to the encrypted file.

?View Code CSHARP
1
2
3
4
public bool DecryptFile(string encryptedFilePath)
{
    return decryptInputFile(encryptedFilePath);
}

The next step is setup the crypto wrapper and actually decode the file. I decided that I would simply remove the .gpg from the end of my encrypted file and use that as the destination file. In my case, I also had to process this intermediate file to ensure that all of the information was valid.

?View Code CSHARP
1
2
3
4
5
6
string outputFile = extractOutputFileName(encryptedFileName);
 
private string extractOutputFileName(string encryptedFileName)
{
      return encryptedFileName.Substring(0, encryptedFileName.LastIndexOf('.'));
}

Now I need to get everything ready to call the decrypt and verify method in the cryptography library. In my particular implementation, I wanted to be able to say that the decryption failed, but it wasn’t important to the end user exactly why, so it’s just true or false.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private bool decryptInputFile(string encryptedFileName)
{
     bool returnCode;
     string outputFile = extractOutputFileName(encryptedFileName);
     try
     {
          SPL.Crypto.PgpEncryptionKeys keys = new PgpEncryptionKeys(publicKeyRingPath, secretKeyRingPath, passPhrase);
          PgpDecrypt decryptor = new PgpDecrypt(keys);
          Stream encryptedStream = new StreamReader(encryptedFileName).BaseStream;
          decryptor.DecryptAndVerify(encryptedStream, outputFile);
          returnCode = true;
     }
     catch (Exception)
     {
          // If there was an error, we're going to eat it and just let the user know we failed.
          returnCode = false;
     }
     return returnCode;
}

Once the decryption object had been setup, it was just a matter of invoking DecryptAndVerify. This method works through all of the different streams and transforms each into the next, finally resulting in the clear text document that we write out to the file system. None of the streams used in the decryption process are saved any where, they’re just kept in memory while they’re being used.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void decryptAndVerify(Stream inputStream, string outputFilePath)
{
     PgpPublicKeyEncryptedData publicKeyED = extractPublicKeyEncryptedData(inputStream);
     PgpObject message = getClearCompressedMessage(publicKeyED);
 
     if (message is PgpCompressedData)
     {
         message = processCompressedMessage(message);
         PgpLiteralData literalData = (PgpLiteralData)message;
         using (Stream outputFile = File.Create(outputFilePath))
         {
            using (Stream literalDataStream = literalData.GetInputStream())
            {
                Streams.PipeAll(literalDataStream, outputFile);
            }
         }
     }
 
     return;
}

I’ll leave the details of how it all works to the samples and the cryptography library below. All of the source is included for your reference.

9/23/2009 UPDATE

I added the sample files from this post to GitHub. Feel free to access the sample files there too.

More Information:

  • Bouncy Castle – http://www.bouncycastle.org/
  • Karmin’s Blog – http://karym6.blogspot.com/2009/06/pgp-decryption-with-c.html
  • .Net Geek – http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx
  • Jesse’s Blog – http://elian.co.uk/post/2009/07/29/Bouncy-Castle-CSharp.aspx
  • Aaron Johnson – http://cephas.net/blog/2004/09/03/pgp-decryption-using-c/

Sample Files:

Working with Twitterizer

I’ve been working on a custom FTP application for the past few days. The application is designed to read a list of remote resource files and go and download each file.

This application will be automated once its setup in production. No one will have to interact with it on a daily basis – it will just go and do the job it was designed for. Part of that job is to log its actions, so that the IT staff can review what’s happened and track down any issues that may come up.

Twitter
Twitter

If you’re on the web at all these days, you’ve no doubt, heard of Twitter. Its simple format makes it a great tool for sharing status information. It seemed to me that having the application tweet its status would be an easy, fun way to use Twitter and provide some semi-useful information.

Twitter exposes an extensive application programming interface, API, for third party developers to use. I briefly considered rolling my own wrappers for the Twitter API. However, that really wasn’t in the best interest my small project’s time line.

Instead, I decided to do a little searching for a pre-written, community supported, API wrapper for .Net. That’s when I found Twitterizer. The project is hosted on Google Code, so getting the files was a snap.

I downloaded the most recent, stable release (1.0.1.99 as I write this), and added it into my C# project. I had already setup a new account with Twitter for the application to use when broadcasting it’s status updates, so I had everything ready to go.

As I wrote the FTP application, I included a number of events that could be logged. Each log item, like the start of a download, had a “level” associated with it. The “level” allowed me to make the application really talkative, or fairly mute, depending on the configuration files.

Knowing that I wouldn’t want everything out on the application’s Twitter feed, I setup a special “log to twitter” minimum level for logging. If the log message was below the threshold, then the application would tweet it too. I also included a setting in the configuration file to disable the Twitter logging completely.

Working with Twitterizer couldn’t have been any easier. Their API wrapper has everything you need to easily send a status update.

?View Code CSHARP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void statusUpdate(string message, Utilities.LogLevel logLevel)
{
       string tweet = string.Concat(message, " #fr");
       if (tweet.Length > 140)
       {
           tweet = tweet.Substring(0, 140);
       }
 
       if (this.twitterEnabled && logLevel < = this.twitterLogLevel)
       {
           Twitter twitter = new Twitter(this.twitterUserName, this.twitterPassword);
           twitter.Status.Update(tweet);
       }
}

That’s all it took. Two lines of actual code to implement the status update using Twitterizer.

Is an application that tweets all that useful? Probably not. It was, however, fun to make it all work.