views:

842

answers:

8

I am playing with Microsoft word document from ASP.NET/C# program.

My programs opens up word docs internally. using

app = new Word.Application();
app.Documents.Open

it creates a instance of winword.exe process, I can see it in Task Manager.

even if I closes Doc using close() and app.quit(). it should kill the process. but this process doesnt get killed.

any idea how to kill this process programmatically.

+2  A: 

Office apps do not "destroy" the first instance created. You will find the same issue when using excel.

See this and others

50 Ways to Kill Excel

How to kill a process given a name

astander
The second link is not needed, you can use System.Diagnostics.Process. There is a method called GetProcessesByName that returns an array of processes. Take that array loop and kill each one. Wrap it around a try / catch block and catch any exceptions.
JonH
+1  A: 

Look into System.Diagnostics.Process.GetProcessesByName and System.Diagnostics.Process.Kill

Try something like

string processName = "ProcessName";
Process[] processes = Process.GetProcessesByName(processName);

foreach(Process process in processes)
{
 process.Kill();
}
splatto
You have to throw a WaitForExit in there otherwise word may be trying to close.
JonH
A: 

You should be able to grab each process of word and kill it:

foreach(Process p in System.Diagnostics.Process.GetProcessesByName("winword"))
 {
   p.kill();
   p.WaitForExit();
 }

Also you should try seeing the document object to null?

JonH
A: 

This was driving me crazy until I found this post on this site. The second solution on that page worked for me - the first one looks simpler, but it actually can get difficult to keep track of all the hidden COM objects you have a reference to. The second method always works - you don't have to track every object.

Mark Byers
A: 

Just to be said: Office Applications are not supposed to run on a server. They are also not to supposed to be uses from a Service or WebApplication.

Yes - we also had requirements that forced us to use Office Products at the Server. And we always hat troubles.

If there is a chance not to use Office (dealing with WordML, the new Office XML format) then do that.

Arthur
+1  A: 

Most safe approach for using (Microsoft) Office on the server is to create a service that can accept streams and creates an instance of Word (or any other Office app) do it's thing and then kills the app. If you do not do this a reference to the running office app will remain within your asp worker process. This means that a lot of processes will keep running until your asp worker process is recycled. This is a large potential memory leak.

This is how we did it. Costs a lot of time to build this correctly but is the most safe way.

Ivo Limmen
+3  A: 

To begin, I agree with Arthur and Ivo: don't use Word automation on the server... it's not supported and it's painful.

  1. If you can, try supporting Word input/output via the DOCX format (fully documented XML format packaged using compression that's supported by the .NET Framework and supported by pre-Office 2007 with a plugin)
  2. If not create a service that handles the requests in a queue to prevent multiple threads using it at the same time (ala Ivo's answer)

If you must use Word automation:

  1. Make sure you are setting as many Application options as possible to prevent dialogs
  2. Make sure you are passing in WdSaveOptions.wdDoNotSaveChanges to Document.Close
  3. Have a look through this document: How To: Dismiss a Dialog Box Displayed by an Office Application with Visual Basic .NET (also applies to C#, obviously)
  4. Make sure you call Marshal.ReleaseComObject on both the Document and Application objects, and make sure it's in a finally block.

The winword.exe should go away if you follow the above, you should not need to kill the process.

Edit: Not really an answer to your question, but on topic nonetheless. Keep in mind that you're also going to have problems on the server with permissions. Make sure you create a specific user for it and use that user as your AppPool identity (or service identity). You'll then need to do the following:

  1. Make sure you've installed the automation components, obviously
  2. Run "dcomcnfg"
  3. Component Services -> Computers -> My Computers -> COM+ Applications
  4. "Microsoft Word document" (or "{000209FF-0000-0000-C000-000000000046}") -> Properties
  5. Security tab -> Launch and Activation permissions -> Customize
  6. Click "Edit" and add your AppPool user from above
  7. Repeat steps 5-6 but select "Access Permissions"

On top of all that, you still might need to run winword.exe once as your AppPool user directly from the server, despite the dialog options above, to initially setup the profile.

Richard Szalay
+1: The more detailed answer :-)
Arthur
Thanks Richard... but something fishy happening now. I have followed all the steps. and It worked. Now thing is I wanted to reproduce the bug so that I can boil down to particular modifications which made it working. but Now I reverted back to old code. rebuilt it...still I cant see winword.exe in TM. and old code gives me expected behaviour but no winword.exe :(
sandip
It was probably the calls to Marshal.ReleaseComObject (the others just protect you against bizarre scenarios when you switch over to your automation user - see edit above). If you can't see winword.exe at all, it might be because it was started by another user and you haven't ticked the "show processes from all users" checkbox
Richard Szalay
A: 

Thanks Richard & Mark Bayers... It seems like working but something is fishy.

I have followed all the steps. and It worked. Now thing is I wanted to reproduce the bug so that I can boil down to particular modifications which made it working. but Now I reverted back to old code. rebuilt it...still I cant see winword.exe in TM. and old code gives me expected behaviour but no winword.exe any type of caching happening?

sandip