Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation
Orphan excel process started via automation Orphan excel process started via automation
Orphan excel process started via automation
Go Back  Xtreme Visual Basic Talk > > > Orphan excel process started via automation


Reply
 
Thread Tools Display Modes
  #1  
Old 06-17-2009, 05:12 PM
imachabeli imachabeli is offline
Newcomer
 
Join Date: Jun 2009
Posts: 8
Default Orphan excel process started via automation


I’m using excel via interop in application. Sometimes users kill application that created excel instance and that results in excel instance sitting in memory without any chance of disposing it.

First I tried to tackle this using ROT(running object table) looks like not all instances of excel are registered there.
Than I tried to somehow mark excel process after it is started via interop.

Code:
        public ExcelWrapper(bool visible, string caption)
        {
            Process curProc = System.Diagnostics.Process.GetCurrentProcess();
            int myPid = curProc.Id;
            
            //does not work
            //curProc.StartInfo.EnvironmentVariables.Add(caption, string.Format("{0} ParentPID:{1} ", caption, myPid));
            

            _excelApp = new Microsoft.Office.Interop.Excel.Application();
            if (_excelApp == null)
            {
                throw new ApplicationException("EXCEL could not be started. Check that your office installation and project references are correct.");
            }
            //this is useless if visible is false
            _excelApp.Caption = string.Format("{0} ParentPID:{1} ", caption, myPid);
             
            _excelApp.Visible = visible;
            _excelApp.DisplayAlerts = false;
            //disable remote calls to this instance
            _excelApp.IgnoreRemoteRequests = true;

            
            GetWindowThreadProcessId(new IntPtr(_excelApp.Hwnd), out _pid);
            Process excelProcess= Process.GetProcessById(_pid );
            excelProcess.MainWindowTitle = string.Format("{0} ParentPID:{1} ", caption, myPid);
            //_handle = new MySafeFileHandle(Process.GetProcessById(_pid).Handle);
            
        }
This works as long as excel is visible but in my case excel window is invisible.

All I need is to somehow mark process that started via automation with the parent PID, so that later I can kill it if parent does not exist.

Any ideas?
Reply With Quote
  #2  
Old 06-18-2009, 06:13 AM
DennisW's Avatar
DennisW DennisW is offline
Junior Contributor
 
Join Date: Mar 2006
Location: Östersund, Sweden
Posts: 268
Default

See if one of the approaches explained in the following blogpost will get You on the right track:
Access running instances of Excel in VB
__________________
Kind regards,
Dennis

.NET & Excel | 2nd edition PED | MVP
Reply With Quote
  #3  
Old 06-18-2009, 08:38 AM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

Hi imachabeli,

I am not certain that the Excel.Application needs to be visible in order to access the process id via the MainWindowHandle. I find that *sometimes* it seems to need to be visible, especially when a lot of concurrent access is going on from multiple threads. So I think you *should* be able to get by without making your Excel.Application visible.

What I have found, however, is that there absolutely *must* be a visible (that is, a non-hidden) workbook open within the application, even if the application itself is not visible.

A few thoughts here:

(1) My first thought would be to ensure that there is a workbook open within the Excel.Application before trying to access the ProcessID. Open up a new workbook if you have to, since the application itself is not visible anyway.

(2) My next attempt would be to make the Excel.Application visible, just for a moment, in order to get the process id. The process id will remain stable, so you can count on it reamaining the same. Excel would be visible just for a brief instance, so I doubt that this would be too big of a burden on your users.

(3) If making Excel visible even for an instance is absolutely intolerable, then you could consider getting the process ids for all running Excel.Application instances, then open up your new Excel.Application instance, and then get all of the process ids for all running Excel.Application instances again. There should be one new process created, and this would be the one for your newly-created Excel.Application instance.

I detail the approach that looks at all of the running Excel.Application processes here. You should use the hash table version that I show there in order to ensure that more than one Excel.Application process wasn't created within the same timeframe. (If using .NET 2.0 or above, one should use a Dictionary<> class, instead of a HashTable, of course.)

I detail the approach that uses the main window handle ("hwnd") in order to get the process id for the Excel.Application instance here.

Both of these examples use VB.NET code (this is a VB forum, afterall!), but I think you should have no trouble following it. If you need any help translating it into C#, just let us know...

Hope this helps!
Mike
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb
Reply With Quote
  #4  
Old 06-18-2009, 10:11 AM
imachabeli imachabeli is offline
Newcomer
 
Join Date: Jun 2009
Posts: 8
Default

Quote:
Originally Posted by Mike_R View Post
Hi imachabeli,

I am not certain that the Excel.Application needs to be visible in order to access the process id via the MainWindowHandle. I find that *sometimes* it seems to need to be visible, especially when a lot of concurrent access is going on from multiple threads. So I think you *should* be able to get by without making your Excel.Application visible.

Mike
Mike that's not a problem at all. I can get PID of excel anytime whether there is workbook , visible or hidden.
Visible property is important if I want to access the caption of window later on to figure out orphan excel instances. If visible is is false caption (header text on top of the window) is not available, so even I assigned some header text when excel started later on I cannot use this property.
I also tried to manipulate environment variable but since excel is started via automation it does not pick up callers environment. There is other possibility to inject code into running process but I think this is overkill for the goal I'm trying to achieve
Reply With Quote
  #5  
Old 06-18-2009, 11:06 AM
imachabeli imachabeli is offline
Newcomer
 
Join Date: Jun 2009
Posts: 8
Default

Quote:
Originally Posted by DennisW View Post
See if one of the approaches explained in the following blogpost will get You on the right track:
Access running instances of Excel in VB
Dennis, excellent collection
This is interesting
'Check to see if (at least) one Excel session is running.
If Process.GetProcessesByName("Excel").Length > 0 Then
xlApp = CType(GetObject(, "Excel.Application"), Excel.Application)

Does excel has some kind of internal string collection that user can write to?
May be instead of caption of excel's window I can simply keep PID of parent inside excel?
Reply With Quote
  #6  
Old 06-18-2009, 11:21 AM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

Quote:
Originally Posted by imachabeli View Post
Mike that's not a problem at all. I can get PID of excel anytime whether there is workbook , visible or hidden.
Yes, I agree. This is the way it should be.

Quote:
Visible property is important if I want to access the caption of window later on to figure out orphan excel instances.
Ah, I see.. only resort to Process.Kill if necessary. Ok, this makes some sense... On the other hand, you could always just call Process.Kill for good measure in any case. It can't hurt.

The truth is, I use careful cleanup procedures such as I wrote about in these posts:

(1) How to properly clean up Excel interop objects in C#

(2) .NET Office Automation

I have never needed to resort to using Process.Kill when following these guidelines.

If I were to decide to use Process.Kill, however, I would just use it. Get the process ID and then do the standard cleanup procedure. Then using the process ID try to get the process. If you can and it is still alive, then call Process.Kill. I don't see why you need the caption in this case? What you really need is the process id. The caption can be used to get the process id, but you already have that.

Referring to your first post:

Quote:
All I need is to somehow mark process that started via automation with the parent PID, so that later I can kill it if parent does not exist.
You could just store the PID for your application in a field. Or if you have multiple applications running, you could store the PID keyed by the Excel.Appication within a Dictionary.

But maybe I'm still not quite understanding your needs here?

Mike
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb
Reply With Quote
  #7  
Old 06-18-2009, 11:30 AM
imachabeli imachabeli is offline
Newcomer
 
Join Date: Jun 2009
Posts: 8
Default

Quote:
Originally Posted by Mike_R View Post
You could just store the PID for your application in a field.
Mike
If app ends on its own it cleans up everything and if necessary kills excel, that's not a problem.

I wrote in the beginning that user might kill my application from task manager and believe me they do it often(do not ask for reasons)

if user kills app that started excel from task manager than excel remains there and what I want is next time I start app just iterate over all excel instances and kill only instances that were initially started by my app and have no parent process associated with it.
Reply With Quote
  #8  
Old 06-18-2009, 11:52 AM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

Ugh...

Ok, I think I see the issue now. I still wouldn't rely on the caption though. I think I would save the process id and the main window handle in a file when your application first opens Excel. Then when your application closes excel, remove the process id and the window handle.

If your program ever opens up and finds a process id and window handle from a previous run, it could iterate the Process.GetProcessesByName("Excel") and see if any have the same process id and window handle. If so, kill it. There is some risk of handle reuse here, so I cringe a bit, but if the process is (1) an Excel process, (2) has the same process id, and (3) has the same main window handle, and (4) is not visible, then it has to be extremely likely to be a process previously created by your own application.

If you wanted to be more certain, then your application could try the Marshal.BindToMoniker approach that Dennis shows here: Access running instances of Excel in VB. I am not certain, however, that this will run on a non-visible instance of Excel. There are many commands like this (such as Marshal.GetActiveObject or VBA.GetObject) that do not work on non-visible Excel instances.

-- Mike
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb
Reply With Quote
  #9  
Old 06-26-2009, 09:09 AM
yoshijg yoshijg is offline
Newcomer
 
Join Date: Jun 2009
Posts: 7
Default excel process cleaning

Hi,

I'm having the exact same problem. I was thinking of doing the same thing, and just recording the Excel PIDs, that my application launches. And then on the next startup...kill it.

However, if the Excel interop object generated some worksheets...and then the application was killed/crashed (leaving the Excel process running). The worksheets/files now cannot be opened because the Excel process still has a lock on the file. Basically, I still have to kill the Excel process still...or re-run my application (which will kill any old Excel PIDs from the previous run).

Does that make sense?
Reply With Quote
  #10  
Old 06-26-2009, 11:02 AM
yoshijg yoshijg is offline
Newcomer
 
Join Date: Jun 2009
Posts: 7
Default excel process interop (attach?)

Normally in C#, when you launch a thread you can specify it to be a "background" or "foreground" thread. When it's background, the thread will automatically die if the parent thread dies.

Can we do something like that with the the Excel Process? Can the thread that Excel runs on be a background thread to my main thread?

Or are they just completely seperate, and that's that ???

Josh
Reply With Quote
  #11  
Old 06-26-2009, 02:25 PM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

Hi Josh,

Welcome to the forum.

Quote:
Originally Posted by yoshijg View Post
I'm having the exact same problem. I was thinking of doing the same thing, and just recording the Excel PIDs, that my application launches. And then on the next startup...kill it.

However, if the Excel interop object generated some worksheets...and then the application was killed/crashed (leaving the Excel process running). The worksheets/files now cannot be opened because the Excel process still has a lock on the file. Basically, I still have to kill the Excel process still...or re-run my application (which will kill any old Excel PIDs from the previous run).

Does that make sense?
Yes, this makes perfect sense and is a real serious problem. The advantage that we have, though, is that what we are dealing with here is not a corrupt, hanging instance, but a 100% still viable Excel process. It was the stand-alone program that was doing the automating that died...

So what we should record, then, is not the process id, but the main window handle returned by the Excel.Application.Hwnd property. Then on the next bootup, if we find an Excel process with that window handle, we can grab that instance and shut it down properly, call Workbook.Close() on each workbook, and then call Excel.Application.Quit. (You'd also need to call Marshal.FinalReleaseComObject() on all these instances as well.)

We can get the Excel object via the main window handle using the technique shown in the article Getting the Application Object in a Shimmed Automation Add-in by Andrew Whitechapel. It would be some work to implement, but is pretty much copy-and-paste. (It works as is, I've tried it before.)


Quote:
Originally Posted by yoshijg View Post
Normally in C#, when you launch a thread you can specify it to be a "background" or "foreground" thread. When it's background, the thread will automatically die if the parent thread dies.

Can we do something like that with the the Excel Process? Can the thread that Excel runs on be a background thread to my main thread?

Or are they just completely seperate, and that's that ???

Josh
This is neat thinking, but the problem is not the thread itself, but any references to Excel objects. These can be (a) local variables, (b) fields, or (c) variable or fields awaiting garbage collection.

So a terminating thread certainly gets rid of any local variables being used, but they could still be awaiting garbage collection, and this does not change the situation with any static variables...

You could make use of thread local storage, I suppose, for your static variables, in this way, when your thread is gone, they would be gone too, but I don't have experience actually doing that. But, in theory, if you called GC.Collect() and GC.WaitForPendingFinalizers() after your thread terminated (obviously called in your other, surviving thread) then this should work.

I think that this is a bit much to be honest. I would prefer to call GC.Collect() and GC.WaitForPendingFinalizers() to clear out the objects that I no longer have a reference to, and then call Marshal.FinalReleaseComObject() on the variables and fields to which I do have a named reference. This is the way I do it.

Mike
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb
Reply With Quote
  #12  
Old 06-27-2009, 11:04 PM
CMF CMF is offline
Newcomer
 
Join Date: Jun 2009
Posts: 5
Default

I'm having the same problem with Excel and it's becoming quite annoying and I've resorted to killing the orphaned process(es) to clear it up.

Code:
        private static void KillpIDs(String appName)
        {
            Process[] currentP = Process.GetProcessesByName(appName);

            foreach (Process p in currentP)
            {
                if (p.MainWindowHandle.ToInt32() == 0)
                {
                    p.Kill();
                }
            }
        }
I'm also using code I found on MSDN to call Marshal.ReleaseComObject on each variable I've instantiated.

Code:
        private static void NAR(object o)
        {
            try
            {
                Marshal.ReleaseComObject(o);
            }

            catch { }
            
            finally
            {
                o = null;
            }
        }
I've also found a suggestion to not use two dots when initializing Com Objects, so I've made a change to my code, but there is still an Excel process with a 0 for the MainWindowHandle.
Reply With Quote
  #13  
Old 06-28-2009, 06:30 AM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

Hi CMF,

Thanks for your comments and welcome to the forum!

Yes, this is a *VERY* complex subject and it can be quite frustrating to try to hunt down what is causing Excel to hang.

I discuss this in some detail in the Automating Office Programs with VB.NET tutorial. It's written for VB.NET, but, although the syntax is slightly different, the concepts are exactly the same for C#. I'm sure you'll be able to follow it with no trouble.

There are also a few threads on StackOverflow that I have participated on regarding this topic:

(1) How to properly clean up Excel interop objects in C#

(2) Shutting down PowerPoint cleanly in C#

(3) c# and excel automation - ending the running instance in C#

The third thread is still ongoing, and you can see it's quite messy. The poster can go with my approach or Gary's approach, either way will work. He needs to show his updated code though for us to be able to help him further...

-- Mike
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb
Reply With Quote
  #14  
Old 06-29-2009, 12:56 PM
CMF CMF is offline
Newcomer
 
Join Date: Jun 2009
Posts: 5
Default

Thanks for the information, Mike. I will attempt to digest them and join the other active thread you linked. But just to throw a screw into the works, I did a quick test here at work with the same code I was using at home, and it does not generate a ghost process. Main difference is at home, I'm using Vista Home Premium and at work I'm using Windows 7.
Reply With Quote
  #15  
Old 06-29-2009, 01:30 PM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

Well, it's good to know, then, that Windows 7 might be processing things in a way that makes it less likely to have a hang. (Although, this doesn't strike me as an operating system issue.)

That said, it could be other things that are far-from-obvious. You could use 100% clean automation code that should release, but an add-in within Excel itself (if done improperly) can cause a hang. The add-in might not cause Excel to hang when opened and closed by the user, but will when you use automation. Block the add-in and then the automation runs without hanging.

I've seen this happen myself. I've also heard that anti-virus and similar things can cause this. I've not seen that personally, but since I know that an add-in that does not properly clean up its references can cause this problem, I am quite sure that it is true.

So when one has a hang, it actually might not be your fault. There can be a lot of factors to nail down. When I am in doubt, I create an extremely simple automation that is too simple to hang, and, well, see if it hangs. If it runs clean, then it is likely that it is our own complex code causing the hang. If the extremely simple automation example hangs, then try tuning off the add-ins to see if the cause can be isolated.
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb

Last edited by Mike Rosenblum; 06-29-2009 at 04:50 PM.
Reply With Quote
  #16  
Old 06-29-2009, 03:55 PM
CMF CMF is offline
Newcomer
 
Join Date: Jun 2009
Posts: 5
Default

Now that's an interesting perspective. Antivirus software is different at home, where I use Norton, and it does scan the file, when I open a workbook, so I'll have to see, if I can shut that off and run a test.
Reply With Quote
  #17  
Old 06-29-2009, 04:54 PM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

That would be cool to try. Let us know how it goes...
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb
Reply With Quote
  #18  
Old 06-30-2009, 12:27 AM
CMF CMF is offline
Newcomer
 
Join Date: Jun 2009
Posts: 5
Default

Well, I can't seem to turn my antivirus off, or rather Excel continues to report that it is running a scan, even though I've disabled the Office integration and shut off the Norton service. I even rebooted for the test, but I still received the "running virus scan" message.

Simple code I ran was:

Code:
        private static void ExcelTest(String S_Directory, String FileName)
        {
                xls.Application ExcelObj = null;
                ExcelObj = new xls.Application();

                ExcelObj.DisplayAlerts = false;
                ExcelObj.Visible = true;

                xls.Workbook eBook;
                xls.Workbooks wb = ExcelObj.Workbooks;
                eBook = wb.Open(S_Directory + FileName, 2, false,
                    5, "", "", true, xls.XlPlatform.xlWindows, "",
                    false, false, 0, false, true, 0);

                eBook.Close(true, S_Directory + FileName, false);

                ExcelObj.Quit();
        }
I think I'll try some of the other suggestions from the thread you linked, and if that doesn't work, I'll be even more annoyed.
Reply With Quote
  #19  
Old 06-30-2009, 08:05 AM
Mike Rosenblum's Avatar
Mike Rosenblum Mike Rosenblum is offline
Microsoft Excel MVP

Forum Leader
* Guru *
 
Join Date: Jul 2003
Location: New York, NY, USA
Posts: 7,848
Default

The minimal automation example that I use is even simpler:

Code:
void AutomateExcelMinimal()
{
    Excel.Application excelApp = new Excel.Application();
    excelApp.Visible = true;

    MessageBox.Show("Ready to clean up?");

    // Cleanup:
    excelApp.Quit();
    Marshal.FinalReleaseComObject(excelApp);
}
Of course this can't hang under normal circumstances, but if an add-in running within Excel is improperly done, the this simple test can hang. That said, some add-ins hook Workbooks and Worksheets as part of their event handling, so your test, which involves a Workbook and Worksheet object, is probably better.

I don't know why you cannot turn off the anti-virus? You should be able to right-click it within the System Tray within the Task Bar and choose 'Disable' or the like. If that doesn't work, then use the Control Panel to go to the Security Center. Is this a work computer where the administrators might be preventing you from disabling the anti-virus as per policy?
__________________
My Articles:
| Excel from .NET | Excel RibbonX using VBA | Excel from VB6 | CVErr in .NET | MVP |
Avatar by Lebb

Last edited by Mike Rosenblum; 06-30-2009 at 09:03 AM.
Reply With Quote
  #20  
Old 06-30-2009, 08:50 AM
CMF CMF is offline
Newcomer
 
Join Date: Jun 2009
Posts: 5
Default

I'm not sure, why Norton isn't shutting off, even though I disable it, turn off the Office integration and even shut the service that runs Norton off. I think that's a can of worms I do not want to open.

Your test did not produce any ghost processes. So, I commented out my workbook code, and was able to start and stop Excel without a ghost process.

I then uncommented 1 line at a time until there was a ghost process left, and it occured with opening the workbook.

Code:
                eBook = wb.Open(S_Directory + FileName, 2, false,
                    5, "", "", true, xls.XlPlatform.xlWindows, "",
                    false, false, 0, false, true, 0);
I guess one of these options must be set incorrectly, but from what I recall, none of these are documented very well.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation Orphan excel process started via automation
Orphan excel process started via automation
Orphan excel process started via automation
 
Orphan excel process started via automation
Orphan excel process started via automation
 
-->