Convert images to a PDF with iTextSharp

I just finished working on a project that required multiple images to be combined into a single PDF document. I used iTextSharp to create the PDF, and I’m pretty happy with the solution that I came up with. There were only two functions required: one that converts an image to a smaller size & lesser quality and one that combines the images into PDF.

Here’s the code:

/// <summary>
/// Takes a collection of BMP files and converts them into a PDF document
/// </summary>
/// <param name="bmpFilePaths"></param>
/// <returns></returns>
private byte[] CreatePdf(string[] bmpFilePaths)
{
    using (var ms = new MemoryStream())
    {
        var document = new iTextSharp.text.Document(iTextSharp.text.PageSize.LETTER.Rotate(), 0, 0, 0, 0);
        iTextSharp.text.pdf.PdfWriter.GetInstance(document, ms).SetFullCompression();
        document.Open();
        foreach (var path in bmpFilePaths)
        {
            var imgStream = GetImageStream(path);
            var image = iTextSharp.text.Image.GetInstance(imgStream);
            image.ScaleToFit(document.PageSize.Width, document.PageSize.Height);
            document.Add(image);
        }
        document.Close();
        return ms.ToArray();
    }
}

/// <summary>
/// Gets the image at the specified path, shrinks it, converts to JPG, and returns as a stream
/// </summary>
/// <param name="imagePath"></param>
/// <returns></returns>
private Stream GetImageStream(string imagePath)
{
    var ms = new MemoryStream();
    using (var img = Image.FromFile(imagePath))
    {
        var jpegCodec = ImageCodecInfo.GetImageEncoders()
            .Where(x => x.MimeType == "image/jpeg")
            .FirstOrDefault();

        var encoderParams = new EncoderParameters(1);
        encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)20);

        int dpi = 175;
        var thumb = img.GetThumbnailImage((int)(11 * dpi), (int)(8.5 * dpi), null, IntPtr.Zero);
        thumb.Save(ms, jpegCodec, encoderParams);
    }
    ms.Seek(0, SeekOrigin.Begin);
    return ms;
}
Advertisements

Force the Mango Update

I have a Focus v1.3 on AT&T, and it was announced that the Mango update was available for me. I got home from work super excited, but when I went to my computer, Zune told me that there was no update.

After a few minutes of googling, I found this link that tells you how to trick/force Zune into letting you have the update, though! It worked for me, so give it a try if you’re in the same boat 🙂

http://www.wpcentral.com/force-mango-update-early-through-zune-software

Programmatically Start & Stop IIS Web Sites in C#

I was recently working on a web application that did business processing for a customer in a clustered environment. The customer wanted the web application to be included in the cluster, but it would be problematic if there were more than one instance of the application running due to shared network resources. The solution that I came up with was to build functionality into a Windows service that would stop and start the web site in IIS as the service is started and stopped. That Windows service can then be added to the cluster services, and everything works great!

This solution uses WMI to access IIS. I tested and verified that it works on Windows Server 2003 (IIS6), Windows Server 2008 (IIS7), and Windows 7 (IIS7.5).
IMPORTANT! For IIS7+, you must install the optional Windows component IIS 6 WMI Compatibility.

I used this CodeProject site as the basis for my solution.

I’ll present my entire solution at the bottom, but I wanted to highlight a few points individually. I developed and tested the solution in a new .NET Framework 3.5 Console Application. I had to add two references to my project: System.DirectoryServices and System.Management.

The class has properties for user, password, server, and website. The user and password can be used to specify authorized credentials, if necessary. I always included the domain in the user while testing (“MyServer\MyUser”), but that may not be necessary. User and password are both optional. Server and website are required. The default values that I’m using in my application are localhost and Default Web Site, respectively.

The helper function GetSiteIdFromWebSiteName is used to translate the website name (“Default Web Site”) to a numeric SiteID, which can then be used to get the ManagementObject that’s used to stop or start the web site.

You’ll notice that my Stop and Start functions both execute asynchronously. The reason for this is that my application hung on the mgmtScope.Connect once. I wasn’t able to figure out why, but I decided to run it on a separate thread so that I could specify a timeout.

Here is my complete solution:

public class WebSiteController
{
    public string Password { get; set; }
    public string Server { get; set; }
    public string User { get; set; }
    public string WebSite { get; set; }

    /// <summary>
    /// Returns the site ID from the specified WebSite name
    /// </summary>
    /// <returns>Site ID</returns>
    private string GetSiteIdFromWebSiteName()
    {
        var path = string.Format(@"IIS://{0}/W3SVC", Server);
        var root = new DirectoryEntry(path);

        return root.Children.Cast<DirectoryEntry>()
            .Where(x => x.SchemaClassName == "IIsWebServer"
                && x.Properties["ServerComment"].Value.ToString()
                    .Equals(WebSite, StringComparison.CurrentCultureIgnoreCase))
            .Select(x => x.Name)
            .FirstOrDefault();
    }

    /// <summary>
    /// Stops the specified WebSite
    /// </summary>
    public void Stop()
    {
        if (!ExecuteAsync("Stop").WaitOne(30000))
        {
            Console.WriteLine("Stop operation timed out");
        }
    }

    /// <summary>
    /// Starts the specified WebSite
    /// </summary>
    public void Start()
    {
        if (!ExecuteAsync("Start").WaitOne(30000))
        {
            Console.WriteLine("Start operation timed out");
        }
    }

    /// <summary>
    /// Executes the specified function asynchronously
    /// </summary>
    /// <param name="function">Function to execute</param>
    /// <returns>WaitHandle that will be set when execution completes</returns>
    private WaitHandle ExecuteAsync(string function)
    {
        var wh = new AutoResetEvent(false);
        ThreadPool.QueueUserWorkItem(x =>
        {
            Execute(function);
            wh.Set();
        });
        return wh;
    }

    /// <summary>
    /// Executes the specified function
    /// </summary>
    /// <param name="function">Function to execute</param>
    private void Execute(string function)
    {
        var options = new ConnectionOptions
        {
            Username = User,
            Password = Password,
            Authentication = AuthenticationLevel.PacketPrivacy
        };
        var mgmtPath = new ManagementPath
        {
            Server = Server,
            NamespacePath = "root/MicrosoftIISv2"
        };
        var mgmtScope = new ManagementScope(mgmtPath, options);
        mgmtScope.Connect();

        var siteId = GetSiteIdFromWebSiteName();
        if (!string.IsNullOrEmpty(siteId))
        {
            var selectQuery = new SelectQuery("SELECT * FROM IIsWebServer WHERE Name = 'W3SVC/" + siteId + "'");
            using (var managementObjectSearcher = new ManagementObjectSearcher(mgmtScope, selectQuery))
            {
                foreach (ManagementObject objMgmt in managementObjectSearcher.Get())
                {
                    objMgmt.InvokeMethod(function, new object[0]);
                }
            }
        }
    }
}

Clean TFS Workspaces with Scorch & Treeclean

If you’ve been working with a TFS workspace for a long time, you know it can get filled up with all kinds of built objects and temporary files. There’s a super-easy way to clean-up using the TFS PowerTools, though.

Check out these two commands:

  • tfpt scorch – Ensure source control and the local disk are identical
  • tfpt treeclean – Delete files and folders not under version control

(Taken from this MSDN forum post.)

7/2/2013 Update:
A co-worker and I were reviewing the scorch command and whether or not pending changes will be deleted through its use. That concern is addressed directly in the help text for the command, accessed by running tfpt scorch /? from the command prompt. Note the last line in the excerpt below, highlighted in red.

Items not in source control will be deleted from disk, just as with the tfpt treeclean command. Items determined to be different on disk from the workspace version will be redownloaded from the server. Items missing on disk will also be redownloaded. Items with pending changes are exempted.

So, it is safe to use scorch while you have pending changes; they will simply be ignored.

.NET Framework Interoperability with Java RMI

I’m currently working on a project that requires a connection from a .NET Framework client to a java RMI application server. I’ve never worked with java RMI before but figured it should be trivial with everything in the .NET Framework. That was so not the case, though. I’ve been working my way through examples all day, and I was able to get it working. Now that I’ve gotten this far, I must say–it’s pretty slick!

Since I’m so proud of what I accomplished, I wanted to put together my own tutorial.

What you’ll need

  • IIOP.NET source code (here)
  • Java SDK (here)
  • Visual Studio (here)

Build IIOP.NET

Once you’ve downloaded the IIOP.NET source code, extract it somewhere on your desktop. You can build it using nmake (included with Visual Studio; read more here). I had problems building the entire directory tree, but it looked like there was a problem with something in the Examples folder. So instead, I just base build by using the command nmake build-base. Most of what I needed to complete this example could be found in the folder IDLToCLSCompiler\IDLCompiler\bin. In addition to those three files, I also needed to copy orb.idl from IDLToCLSCompiler\ILD.

Building the java server

The java server can be built with just a few, small files. Open up your favorite text editor, and create the following files. Note that your directory structure should correspond to the package names.

When you’re done, you should have a directory structure that looks like this:

\
-ILDPreprocessor.dll*
-IDLToCLSCompiler.exe*
-IIOPChannel.dll*
-MySearchServer.java
-orb.idl*
\adamprescott\wordpress\
-SearchRequest.java
-SearchResponse.java
-SearchServer.java
-SearchServerImpl.java

* denotes the files copied after building IIOP.NET

SearchRequest.java

package adamprescott.wordpress;

import java.io.Serializable;

public class SearchRequest implements Serializable  {

	public String Criteria;

}

SearchResponse.java

package adamprescott.wordpress;

import java.io.Serializable;

public class SearchResponse implements Serializable  {

	public String Response;

}

SearchServer.java

package adamprescott.wordpress;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface SearchServer extends Remote {

	public SearchResponse[] Search(SearchRequest request) throws RemoteException;

}

SearchServerImpl.java

package adamprescott.wordpress;

import java.rmi.Remote;
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;

public class SearchServerImpl extends PortableRemoteObject implements SearchServer {

	public SearchServerImpl() throws java.rmi.RemoteException {
		super();     // invoke rmi linking and remote object initialization
	}

	public SearchResponse[] Search(SearchRequest request) throws RemoteException {
		SearchResponse[] response = new SearchResponse[1];
		response[0] = new SearchResponse();
		response[0].Response = "You searched for " + request.Criteria + "!";
		return response;
	}
}

And, finally, MySearchServer.java

import javax.naming.InitialContext;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject;
import adamprescott.wordpress.SearchServer;
import adamprescott.wordpress.SearchServerImpl;

public class MySearchServer {

	public static void main(String[] args) {
		try {
			
			// Instantiate the service
			SearchServerImpl searchSvr = new SearchServerImpl();

			// publish the reference with the naming service:
			Context initialNamingContext = new InitialContext();
			initialNamingContext.rebind("searchServer", searchSvr);

			System.out.println("Server Ready...");

		} catch (Exception e) {
			System.out.println("Trouble: " + e); e.printStackTrace();
		}
	}
}

Now that you’ve got all the files, compile and run the code by executing the following commands:

javac -classpath . MySearchServer.java
rmic -classpath . -iiop adamprescott.wordpress.SearchServerImpl
rmic -idl adamprescott.wordpress.SearchServerImpl
IDLToCLSCompiler.exe -o N_SOURCES\bin MySearchServer adamprescott\wordpress\SearchServer.idl
start orbd -ORBInitialPort 1050 
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1050 -cp . MySearchServer

Building the .NET client

The hard work is all done now, and we just need to create our .NET client. When you ran IDLToCLSCompiler.exe, it created a DLL file for you in the specified folder, N_SOURCES\bin. Making a functional client involves referencing this DLL along with IIOPChannel.dll. Create a new console project, reference those DLLs, and create your Program.cs like so:

using System;
using System.Runtime.Remoting.Channels;
using Ch.Elca.Iiop;
using Ch.Elca.Iiop.Services;
using omg.org.CosNaming;

namespace adamprescott.wordpress
{
    [Serializable] public class SearchRequestImpl : SearchRequest {}
    [Serializable] public class SearchResponseImpl : SearchResponse {}

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                const string nameServiceHost = "localhost";
                const int nameServicePort = 1050;

                // register the channel
                IiopClientChannel channel = new IiopClientChannel();
                ChannelServices.RegisterChannel(channel);

                // access COS nameing service
                CorbaInit init = CorbaInit.GetInit();
                NamingContext nameService = init.GetNameService(nameServiceHost, nameServicePort);
                var name = new[] { new NameComponent("searchServer", "") };
                
                // get the reference to the adder
                var adder = (SearchServer)nameService.resolve(name);

                var req = new SearchRequestImpl { Criteria = "Hello, World!"};
                var result = adder.Search(req);

                foreach (var r in result)
                    Console.WriteLine("result: {0}", r.Response);
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: " + e);
            }

            Console.ReadLine();
        }
    }
}

Important notes:

  • Each java class must have a *Impl implementation. The reason for this is that the java classes are exported as abstract. If there were any abstract methods, they would need to be implemented as well. Since my classes only contain properties, no additional implementation is needed.
  • The .NET classes must be public, have a public parameterless constructor, and be tagged as Serializable.
  • The java and .NET classes must have the same namespaces. (This threw me off for a while!)

With the java server running, start up the .NET client and feel like a winner!

Private Builds in TFS

My team has configured TFS to automatically kick-off continuous integration (CI) builds when developers check-in changes. The build depends on the affected area, and the time to complete depends on the build. Some of our builds contains hundreds of projects and thousands of unit tests, and these can take the better part of an hour to complete. We also have nightly builds that build even more and take even longer.

Occasionally, I’ll have some changes to check-in at the end of the day. I check them in, and I get a notification that I broke the build when I’m halfway home. Crap. I need to fix the change before the nightly build starts, or it’s going to break, too.

Wouldn’t it be great if there was a way to run a build with my pending changes and then check them in automatically if the build succeeds? Well… There is! TFS has support for private builds (or “buddy builds”) that you can queue with a shelveset.

When I choose to queue a build, I choose to build with local sources plus a shelveset. Then I specify which shelveset, and I have the option to check-in my changes if the build succeeds. Splendid!