One of my favorite sayings is, “You can bet it wasn’t an exercise freak who invented power steering.” Necessity may be the mother of invention, but laziness is often the midwife: sometimes you just want an easier way.
Being able to convert files to PDF is something many people ask for, and Datalogics offers a tool for just that purpose: FLIP2PDF, a command line application that takes Microsoft Word documents, Excel spreadsheets, PostScript files, and image files and converts them all to PDF automatically.
However, FLIP2PDF is a command line application that is designed to be used in a script or from the command line. What about just using a good old mouse? I’d like to be able to just drop my files in a window and have them converted to PDFs. Fortunately, with a little scripting glue, we can get FLIP2PDF to do just that.
This idea is what’s known as a hot folder: a folder that scans whatever is put into it and carries out an action. Windows has a built-in scripting engine called PowerShell that is ideal for this sort of setup.
PowerShell is a command line shell and scripting language included with Windows. It lets you automate common operations and repetitive tasks. Better yet, it includes an event monitoring system: you can start a background script that will watch a folder and carry out actions when something appears in it. This is just what we need for a conversion folder. So let’s get started!
But first, let’s review how to run FLIP2PDF. Running FLIP2PDF from the command line looks like this:
flip2pdf --input <input filename> --output <output filename> --profile <profile>
The input parameter is the file we want to convert, and the output is the name of the new PDF we’re going to convert it to. The profile is JSON file of settings that affect how the file will be converted. This is optional: if we don’t supply a profile, default options will be used. Each of the parameters is specified with a keyword; if the profile won’t be used, the keyword should not be present.
This is all good, but before we start, we should answer some questions about what we’re trying to build:
- Where should the PDFs we create be made? They will be placed in a second folder, as if ‘moved’ from the first.
- What will happen to the original file? It will be copied to the same place as the PDF, so that it doesn’t get lost as an input.
- What will happen if we drop in a file FLIP2PDF can’t convert? In that case, we’ll just copy the file to the second folder without a conversion.
- How will we start the hot folder? We can start it with a single command; once running, the folder will be ‘active’ and try to convert anything dropped into it. This could be run as a task at login.
- How will it know which is the hot folder, or where to put the converted files? We’ll take some parameters on the command line that give the path to the watched folder and the destination.
- Will we have any record of what was converted? We’ll keep a log file in the output folder, with an entry for every file we try to convert, and an indication of success or failure.
- Will we be able to configure how the conversion happens? Since FLIP2PDF can take a JSON profile of conversion options we’ll use, we’ll keep that in the hot folder and use it if it’s there, or else use our default values.
With that in hand, let’s look at the code.
Starting at the top, we first declare a block of parameters this script will take. We need both a source path (for the folder we are watching) and a destination path (for the folder we’re sending the output to). Since we can’t really function without both, they are both declared as mandatory: the script won’t run without them. We also take a path to an output log file, but this is optional—if the user doesn’t supply one, we supply a default name.
Next, we declare a small function ‘Write-Log’ to append a message to our log file. This takes the supplied message and appends it to the log, along with a date stamp.
In order to watch a folder, you have to set up an IO.FileSystemWatcher and then register it as an object event and provide it with code to run when the event occurs. We create the object in lines 15-18, telling it to look for any file that is created or changed. We also watch all sub-folders in this folder.
Next, we register the watcher, giving it an identifier ‘FileConverted’. ‘-Action’ specifies the code to carry out whenever a file appears; this takes up the rest of the script.
The first thing we do is collect the name of the file we received an event for. This is provided by the ‘$Event’ object, which is available to us in the Action block. We also determine the extension of the input file, and the path to the destination PDF we are going to create.
In lines 26-29, we take care of a couple hiccups. First, when FLIP2PDF converts a Microsoft Office document, it temporarily creates a ‘lock’ file in the same folder; this file always starts with the string “.~lock.”, followed by the name of the input. We don’t want to try and convert this (FLIP2PDF will delete it when it’s done), so we ignore any file starting with that name. Second, we want to be able to place JSON profiles in the hot folder to configure the conversion process—but we don’t want to actually convert these files. In both cases, we simply return before trying to convert.
Using the profile happens in the next lines: if a file named “profile.json” is present, we want to pass it to FLIP2PDF. Remember from above that FLIP2PDF takes the profile as a keyword parameter…so we need to present both the keyword and the path to the profile, but if there is NO profile, we don’t want to pass either. We use two string variables, one for the keyword and one for the profile path. If the profile is present, both are filled in; otherwise, both are blank.
Next we come to the heart of the converter. We use ‘Invoke-Command’ to call FLIP2PDF, passing in the input file name, the output file name, and the profile name (if present). The output from the command is collected in ‘$result’, and once it’s done, we move the input file to the destination folder with ‘Move-Item’.
We still need to log the result of the conversion. Fortunately, PowerShell captures the return code from the shell command as ‘$LASTEXITCODE’. FLIP2PDF returns 0 for a successful conversion; otherwise, it returns an error code corresponding to the problem (you can see the meanings of these in the documentation). We could do a lookup of the code and print our own error message.
However, we captured the output of the command, and FLIP2PDF already prints a descriptive message in the case of a failure. What ‘$result’ actually contains is an array of each string FLIP2PDF printed to the console; the last of these is the error message. If ‘$LASTEXITCODE’ is non-zero, we can just write the last item in ‘$result’ to the log.
To run the script, we start it as a command from the PowerShell command shell:
ConvertFile.ps1 -source <path to hot folder> -destination <path to destination folder> -logpath <path to log file>
This starts it running the background. From now on, any file dropped into the hot folder will be converted and saved to the destination (assuming it can be handled by FLIP2PDF). To stop the script from running, use:
Unregister-Event -SourceIdentifier FileConverted
And that’s it! With less than 50 lines of code, we’ve turned FLIP2PDF into a versatile automated tool for converting files with a simple drag and drop.