views:

39

answers:

3

I am trying to print pdf, ppt, and word documents from my windows service using ShellExecute.

Process printingProcess = new Process
                        {
                            StartInfo =
                                {
                                    FileName = filePath,
                                    WindowStyle = ProcessWindowStyle.Hidden,
                                    CreateNoWindow = true,
                                    UseShellExecute = true,
                                    Verb = "Print"
                                }
                        };
printingProcess.Start();

This works in most cases. But for word documents that are corrupt, the Process.Start method never completes and the service hangs.

Basically, word pops up the "bad document! repair" dialog. I want the service to identify that word is not playing nice and kill the process and proceed with the next document in its queue.

What should I do?

[UPDATE]

Guys, here is the code to reproduce the issue:

static void Main(string[] args)
{
    string filePath = @"d:\corruptdocument.docx";

    PrintDocument(filePath);

    Console.WriteLine("Completed!");
    Console.ReadKey();
}

private static void PrintDocument(string filePath)
{
    Process printingProcess = new Process
                                {
                                    StartInfo =
                                        {
                                            FileName = filePath,
                                            WindowStyle = ProcessWindowStyle.Hidden,
                                            CreateNoWindow = true,
                                            UseShellExecute = true,
                                            Verb = "Print"
                                        }
                                };
    using (printingProcess)
    {
        Console.WriteLine("Starting process...");
        printingProcess.Start();
        Console.WriteLine("Completed start...");
    }
}

And here is a screenshot : http://twitpic.com/23jwor

A: 

try adding the /q and /x command-line switches to your StartInfo.

Via MS documentation, those switches start Word in quiet mode (/q), and respond to one DDE request (you may try omitting the /x)

Josh E
I'm not invoking winword.exe directly, but using Shell Execute to automatically figure out the command and do the printing. As per the registry, when I print a .doc file, this is command that is executed:WINWORD.EXE /x /n /dde
LightX
+2  A: 

Nah, that cannot be accurate. Neither ShellExecuteEx nor CreateProcess can block. It is surely the next statement in your code, the one you didn't post. I'd guess at Process.WaitForExit(). Note that it has an overload that accepts a timeout.

Not that it will work reliably, Word is a single-instance process. Using Microsoft.Office.Interop.Word is the better mousetrap. The Application.Document.Open() method accepts an OpenAndRepair argument.

Hans Passant
@hans - No dude! Process.Start is blocking! See this: http://twitpic.com/23jwor Updated the question with the complete code to reproduce the issue.
LightX
Well, hard to argue with that. Maybe it is because you use the verb. Anyhoo, I'd still recommend the interop approach.
Hans Passant
Yes, according to [MSDN](http://msdn.microsoft.com/en-us/library/bb762154%28VS.85%29.aspx) `ShellExecuteEx` (which is internally called) may delegate execution to Shell extensions (data sources, context menu handlers, verb implementations) that are activated using Component Object Model (COM). This is the case here and it seems the initialization of the COM object (i.e. Word) does never return due to the blocking modal box.
0xA3
I'll buy that. The DDE crap that Office supports is also pretty opaque these days.
Hans Passant
Indeed. @LightX: You should follow Hans' recommendation and use COM interop. That will not prevent Word from hanging in this case but it's easier to control the Word process and kill it after a defined timeout period.
0xA3
A: 

Okay Guyz, here is what I found out!

ShellExecute for word uses DDE. So the process.Start() method returns only after the command is complete (in my case, "printing the document"). [Not sure if this is accurate, but atleast that is my experience with word]

So what are our options?

  1. As @Hans mentioned, use COM interop.
  2. Run the printing job in a seperate thread and wait for the thread to complete for a predefined interval and terminate the corresponding word process after this interval.

I chose option 2 as I was dealing with other document types like PDF,PPT and I was too lazy to change the implementation! :)

LightX