I was talking with a colleague earlier today. A few days ago the requirements for a short project specified a service / application that would monitor an input folder (e.g., c:\temp\DocFolder) for *.doc (Word) files and generate in an output folder (e.g., c:\temp\PDFFolder) a *.pdf (Portable Document Format) version of the files. The application / server was implemented and tested.
As usual, requirements tend to change. Yesterday they did. The issue is that clients running on the same machine need to generate a copy of the *.doc files and copy them to the input folder. Of course clients may generate the copy directly in the input folder eliminating the need for the copy operation. Instead of modifying the application / service that converts the files, the client could easily (as shown in this blog) could generate a link to an input *.doc file and copy the link to the input folder.
Let’s place a *.doc file in the c:\temp\DocFolder and from a command prompt execute the following:
C:\> dir c:\temp\docfolder
Volume in drive C is OS
Volume Serial Number is 26E8-87B0
Directory of c:\temp\docfolder
10/14/2016 04:03 PM <DIR> .
10/14/2016 04:03 PM <DIR> ..
10/14/2016 03:36 PM <SYMLINK> bar.doc [c:\temp\foo.doc]
1 File(s) 366,080 bytes
2 Dir(s) 785,369,051,136 bytes free
The results show that we have a bar.doc file that we copied to the c:\temp\DocFolder but it is a <SYMLINK> to the c:\temp\foo.doc file (the actual file we want to generate a PDF. A client application / server could execute the following code:
C:\> linkapp
<<< symbolicLink ==>c:\DocFolder\bar.doc<==
<<< fileName ==>c:\temp\foo.doc<==
The code takes the original foo.doc file and generates a bar.doc symbolic link to be processed by the application / server that converts *.doc files to *.pdf.
Following is a screen capture of the application / service used to convert *.doc files to *.pdf:
C:\> java -jar c:\temp\wordtopdf.jar
<<< args:
<<< inFileName ==><==
<<< theDocFolder ==><==
<<< thePDFFolder ==><==
<<< configFile ==>c:\ProgramData\ISng\config.json<== NOT found
<<< theDocFolder ==>c:\temp\DocFolder<==
<<< thePDFFolder ==>c:\temp\PDFFolder<==
<<< sleeping …
<<< sleeping …
<<< docFile ==>C:\Temp\DocFolder\bar.doc<==
<<< pdfFile ==>c:\temp\PDFFolder\bar.pdf<==
Oct 14, 2016 3:43:35 PM org.artofsolving.jodconverter.office.ProcessPoolOfficeManager <init>
INFO: ProcessManager implementation is PureJavaProcessManager
Oct 14, 2016 3:43:36 PM org.artofsolving.jodconverter.office.OfficeProcess prepareInstanceProfileDir
WARNING: profile dir ‘C:\Users\John\AppData\Local\Temp\.jodconverter_socket_host-127.0.0.1_port-2002’ already exists; deleting
Oct 14, 2016 3:43:36 PM org.artofsolving.jodconverter.office.OfficeProcess deleteProfileDir
SEVERE: could not delete profileDir: Unable to delete file: C:\Users\John\AppData\Local\Temp\.jodconverter_socket_host-127.0.0.1_port-2002\user\uno_packages\cache\uno_packages.pmap
Oct 14, 2016 3:43:36 PM org.artofsolving.jodconverter.office.OfficeProcess start
INFO: starting process with acceptString ‘socket,host=127.0.0.1,port=2002,tcpNoDelay=1’ and profileDir ‘C:\Users\John\AppData\Local\Temp\.jodconverter_socket_host-127.0.0.1_port-2002’
Oct 14, 2016 3:43:36 PM org.artofsolving.jodconverter.office.OfficeProcess start
INFO: started process
Oct 14, 2016 3:43:38 PM org.artofsolving.jodconverter.office.OfficeConnection connect
INFO: connected: ‘socket,host=127.0.0.1,port=2002,tcpNoDelay=1’
<<< OpenOffice started
<<< document converter created
<<< PDF generated in 12852ms
<<< PDF file created
Oct 14, 2016 3:43:51 PM org.artofsolving.jodconverter.office.ProcessPoolOfficeManager stop
INFO: stopping
Oct 14, 2016 3:43:51 PM org.artofsolving.jodconverter.office.ManagedOfficeProcess doEnsureProcessExited
INFO: process exited with code 0
Oct 14, 2016 3:43:51 PM org.artofsolving.jodconverter.office.OfficeConnection$1 disposing
INFO: disconnected: ‘socket,host=127.0.0.1,port=2002,tcpNoDelay=1’
Oct 14, 2016 3:43:51 PM org.artofsolving.jodconverter.office.OfficeProcess deleteProfileDir
SEVERE: could not delete profileDir: Unable to delete file: C:\Users\John\AppData\Local\Temp\.jodconverter_socket_host-127.0.0.1_port-2002\user\uno_packages\cache\uno_packages.pmap
Oct 14, 2016 3:43:51 PM org.artofsolving.jodconverter.office.ProcessPoolOfficeManager stop
INFO: stopped
<<< OpenOffice stopped
<<< sleeping …
We now may look in the output folder as illustrated by the following screen capture:
C:\> dir c:\temp\pdffolder
Volume in drive C is OS
Volume Serial Number is 26E8-87B0
Directory of c:\temp\pdffolder
10/14/2016 04:12 PM <DIR> .
10/14/2016 04:12 PM <DIR> ..
10/14/2016 04:12 PM 326,367 bar.pdf
1 File(s) 326,367 bytes
2 Dir(s) 785,368,989,696 bytes free
The proper bar.pdf file was generated. The foo.doc (symlink) was deleted and the original foo.doc file in the c:\temp\ folder was left untouched. The C# code that generates the symbolic link follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.IO;
namespace LinkApp {
class Program {
[DllImport(“kernel32.dll”)]
static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, SymbolicLink dwFlags);
[DllImport(“kernel32.dll”)]
static extern int GetLastError();
enum SymbolicLink {
File = 0,
Directory = 1
}
static void Main (string[] args) {
string symbolicLink = @”c:\temp\bar.doc”;
string fileName = @”c:\temp\foo.doc”;
Console.WriteLine(“<<< symbolicLink ==>” + symbolicLink + “<==”);
Console.WriteLine(“<<< fileName ==>” + fileName + “<==”);
bool success = CreateSymbolicLink(symbolicLink, fileName, SymbolicLink.File);
if (!success) {
Console.WriteLine(“<<< CreateSymbolicLink failed”);
int error = GetLastError();
Console.WriteLine(“<<< error: ” + error);
}
// **** ****
return;
}
}
}
As you can see, the client application / server could easily change a few lines and address the new requirement.
If you have comments or questions on this blog entry, please do not hesitate and send me an email message.
John
john.canessa@gmail.com