Call to a method never returns - c#

I am working with a COM component. There is a method that does this call to the component, and this method is used many times in my application, for each document to be processed, this method is called.
One weird thing happens sometimes suddenly, doesn't matter the amount of documents processed, it can happen after processing 60, 100 or 300 documents, or just don't happen. The weird thing: the call to the component doesn't return. The method stays stuck into the call line. Do you know any COM particularity that could be causing this problem?

From your question I get that your are doing COM automation with documents. If your COM object is a document processing application (Would MS Office be the right guess?) then it might be that the application is simply blocked by a popup.
This phenomenon happens quite frequently when you automate e.g. Word or Excel. You should do several things to work around this problem (I'm talking about MS Word here):
disable alerts by setting Application.DisplayAlerts accordingly
install the complete products to avoid Windows Installer popups asking for missing features
implement a time-out mechanism that will kill the application if any modal dialog is requesting user input. The reason for that is that there are certain types of popups which cannot be suppressed (If you need further information please ask).

Related

Excel interop automation periodically freezes for 40-60 seconds

My program uses C# and interop to create complex Excel documents. The generation process runs against an invisible background instance of Excel. One particular interop call sometimes runs incredibly slowly. Most individual interop commands take just a few milliseconds, but assigning to the Font.Bold property can sometimes take 40-60s.
The 'slow' runs of this line of code are intermittent but follow a pattern. After a slow run, all successive runs will be fast for about 7-10 minutes, after which the next call will be slow. It is like there is a 'timer' which is reset on each slow run. While the timer is counting down all interop runs smoothly. Once the timer has expired, the next assignment to Font.Bold will be slow. It will be slow no matter whether the call comes immediately after the timer has expired, or if I leave the computer idle for a couple of hours and run the code again.
Restarting my program has no impact on this invisible timer. In other words I can run my code, wait for a slow run, and then exit the process. Then if I immediately start my code again, I will get fast runs for the next 7-10 minutes. I have ensured there are no instances of Excel or other Office apps running, including hidden ones lingering in the background. The only thing which 'resets' the timer is restarting my machine. It is like the timer exists on a system level outside of Excel or my code.
This applies in Debug and Release solution configurations, running with and without the debugger attached.
There is one other crucial piece of evidence. If I manually open an instance of Excel from the Start menu (i.e. driving it using mouse and keyboard rather than interop), there are repro steps for what looks like the same problem.
Create blank workbook
In the Home ribbon click Cell Styles
Right-click a style and click Modify...
Click the Format... button
Excel completely freezes for 40-60 seconds, then finally the dialog opens and behaves as normal
The freeze in the final step follows the same 7-10 minute cooldown behaviour as when I assign to the Font.Bold property in interop. The invisible 'timer' in the background is apparently shared between the Excel dialog and the interop code. In other words a slow run in interop will be followed by 7-10 minutes of Excel not freezing. And a frozen dialog in Excel is followed by 7-10 minutes of fast interop.
I have phrased this question as one about interop since that is how I first came across the problem. It may in fact just be a general Excel problem or bug, but it was only after many fruitless days of debugging my code, trying desperate garbage collection/Marshal.ReleaseComObject nonsense etc. that I discovered the Excel GUI symptom.
What is causing this slowness and what can I do about it?
Windows version: Windows 10 Home 21H1 (19043.2006)
Excel version: version 2209 Build 16.0.15629.20152 64-bit
I have a partial answer or at least explanation to my own question.
My deduction is, Excel hangs while trying to contact an offline printer. Work around the problem by setting the Windows default printer to one which is available.
The key was finding a post (archive 1, 2) where someone describes the Excel freezing dialog symptom, and suggests changing the system default printer. My Windows default printer was set to a network-attached HP LaserJet which Windows Printers & scanners says is Online even though it's not been connected to the network or powered on in months. Changing the default printer to Microsoft Print to PDF eliminated the hangs both from interop and the live usage of Excel GUI.
This is speculation, but I imagine when the freeze happens Excel is trying to contact the printer, perhaps to determine which device fonts it supports. The Excel GUI thread (!) is ultimately blocked on a network call which times out. The 40-60 seconds is presumably the network timeout on trying to reach the printer, and the 7-10 minute 'timer' is an actual OS-wide timer which says 'if connection to a network printer fails assume it is unreachable and don't try to contact it again in this interval'.
I've tried on another machine with a different offline default printer, but I could not reproduce. Presumably the problem is only with specific printer drivers.
I'm not sure what can be done to prevent this problem in the wild when the code is running on other systems. Hopefully the problematic configuration is rare. I feel the blame could equally lie with Excel, a printer driver, or the Windows OS, so a bug fix seems unlikely.

How can I use iTunesLib in unattended mode?

I'm making a little app to automate my iPod update. My purpose is sync my iTunes library with my actual one and reencode songs in a lower quality for the iPod.
I use the Interop "iTunesLib" from iTunes.exe and I'm working on C#.
My program works pretty well but I have a big issue with iTunes. If a modal box is opened by iTunes during the process (could be "error while importing song", or just even "a new update is available" at iTunes startup...), then my app is completely stuck and must wait for the user to close the popup.
This is annoying because I expected to run my app at night and the process of reimporting/reencoding takes a while.
Is there any way to either tell iTunes to not pop any message, or to ask it to close an already opened one?
Maybe try calling the IiTunes.VisualsEnabled method passing in FALSE.
From the iTunes COM SDK:
HRESULT IiTunes::VisualsEnabled ( [in] VARIANT_BOOL shouldEnable )
Set whether visuals should be displayed.
Parameters:
shouldEnable True if visuals should be displayed.
Return values:
S_OK The operation was successful.
E_ACCESSDENIED Visuals cannot be enabled or disabled. For example, this can happen if the iTunes Store is currently being viewed.
E_FAIL An unexpected error occurred.
Well, after having this question open for more than a year, the correct answers seems to be: I can't
However there are several alternative libraries that might be useful.

Directions and Opinions on Creating Update System for the Application

I just try to figure out a good solution on designing the update process for a windows form application i created. I think of a button inside the app for manual checking of an update and checking when starting the app. Only I'm not familiar with technics. I though to have the update setup file in a FTP Server and checking the server for an update with a txt file in there with filename and version info. When app is finished downloading the update, closing and starting the update setup file.
Any suggestions, opinions on the subject?
Application updates these days are one of those necessary evils. Thinking of applications that update automatically, I tend to group them into two categories:
Clean updating, once a month or less often, a speedy update without a lot of nagging or clicking. And definitely no sneaky software included like toolbars and desktop search programs... Firefox tends to be "nice" about updates, though its addons can be naggy.
The other group nags constantly, requires a lot of button clicks or that you reboot, takes a long time to 'unpack' (Adobe Acrobat, looking at you), changes settings against your wishes (Java), or is just generally unpleasant.
With those points in mind, design your automatic update to be as user-friendly as possible, and plan on your users sometimes wanting to skip the update (unless it is critical to operation).
At my company we have a small application that requires updates, but also must function in a very time-sensitive environment. To facilitate updates, we have it do the following:
At startup, a text file is checked on an internal URL (this could be an HTTP or FTP call). The version number is compared to the contents of the file.
If the software is up to date, nothing more is done. If not, a dialog is presented informing the user that the application must perform an update. (In our case there is no option to cancel or wait, but I highly recommend it if you can.)
A setup file is downloaded from the same site, and launched via Process.Start command, with some switches to perform an unattended install/update.
The application is launched after installation and the interruption to user is minimal.
Some things you may want to do differently:
If not checking for updates at startup, provide an option to schedule update checking or manually perform an update check from (for example) a Help menu.
If possible allow the user to cancel or delay an update; there's nothing more frustrating than trying to get work done with a popup dialog asking you to perform an update every few minutes.
Make sure you test your install packages or patches before deployment! (Voice of experience!)
Use ClickOnce http://msdn.microsoft.com/en-us/library/t71a733d%28VS.80%29.aspx
http://www.15seconds.com/issue/041229.htm
Kind regards.

Prevent Process 'A' from spawning Process 'B' which then shows up on top of what should be the "TopMost" Process 'C'

I have a windows form application which needs to be the TopMost. I've set my form to be the TopMost and my application works as I'd like it to except for in one case.
There is a 3rd party application (referred to as player.exe) that displays SWF movie files on a portion of the screen that popup on top of my application.
Using Process Monitor I determined that player.exe application calls
flash.exe <PositionX> <PositionY> <Width> <Height> <MovieFile>
in my case:
flash.exe 901 96 379 261 somemovie.swf
Since flash.exe is being spawned in a new process after my form has been set to the TopMost it is appearing on top of my application.
First thing I did was make my application minimize the player.exe main application window hoping that this would prevent the Flash from appearing also. But, unfortunately it doesn't... even with the window minimized whenever the flash movie starts it shows up at the pixel location (901,96). I then tried creating a timer to keep setting the form.TopMost property to true every 10ms. This sort of works but you still see a very quick blip of the swf file.
Is there some type of Windows API call which can be used to temporarily prevent player.exe from spawning child processes which are visible? I admit it sounds a little far fetched. But, curious if anyone else has had a similar problem.
Addendum:
This addendum is to provide a reply to some of the suggestions layed out in Mathew's post below.
For the emergency situation described in the comments, I would look at possible solutions along these lines:
1) How does the third party application normally get started and
stopped? Am I permitted to close it
the same way? If it is a service, the
Service Control Manager can stop it.
If it is a regular application,
sending an escape keystroke (with
SendInput() perhaps) or WM_CLOSE
message to its main window may work.
Easiest way to close the app is to CTRL-ALT-DEL, then kill process. -OR-
The proper way is to Hold ESC while clicking the left mouse button... then input your username and password, navigate some menu's to stop the player.
There is no PAUSE command... believe it or not.
I don't think using WM_CLOSE will help since minimizing the application doesn't. Would that kill the process also? If not, how do you reopen it.
2) If I can't close it nicely, am I permitted to kill it? If so,
TerminateProcess() should work.
I can't kill the process for two reasons. 1) Upon relaunch you need to supply username/password credentials... There may be a way to get around this since it doesn't prompt when the machine is rebooted but... 2) Whenever I kill the process in task manager it doesn't die gracefully and asks if you want to send an error report.
3) If I absolutely have to leave the other process running, I would try
to see if I can programmatically
invoke fast user switching to take me
to a different session (in which there
will be no competing topmost windows).
I don't know where in the API to start
with this one. (Peter Ruderman
suggests SwitchDesktop() for this
purpose in his answer.)
I got really excited by this idea... I found this article on CodeProject which provides a lot of the API Wrapper methods. I stopped implementing it because I think that in order for desktop's to work you must have explorer.exe running (which I do not).
EDIT2: On second thought... maybe explorer.exe isn't needed. I'll give it a try and report back.
Edit3: Was unable to get the code in that article working. Will have to put this on hold for a moment.
Answer Summary
As one might have expected, there is no simple answer to this problem. The best solution would be to problematically switch to a different desktop when you need to guarantee nothing will appear over it. I was unable to find a simple C# implementation of desktop switching that worked and I had a looming doubt that I would just be opening a whole new set of worms once it was implemented. Therefore, I decided not to implement the desktop switching. I did find a C++ Implementation that works well. Please post working C# virtual desktop implementations for others.
Setting the TopMost property (or adding the WS_EX_TOPMOST style to a window) does not make it unique in the system. Any number of topmost windows may be created by any number of applications; the only guarantee is that all topmost windows will be drawn 'above' all non-topmost windows. If there are two or more topmost windows, the Z-order still applies. From your description, I suspect that flash.exe is also creating a topmost window.
Aside from periodically forcing your window to the top of the Z-order, I think there is little you can do. Be warned, however, that this approach is dangerous: if two or more windows are simultaneously trying to force themselves to the top of the Z-order, the result will be a flickering mess that the user will likely have to use the task manager to escape.
I recommend that your program not attempt to meddle with other processes on the computer (unless that is its explicit purpose, e.g. a task manager clone). The computer belongs to the user, and he may not value your program more highly than all others.
Addendum:
For the emergency situation described in the comments, I would look at possible solutions along these lines:
How does the third party application normally get started and stopped? Am I permitted to close it the same way? If it is a service, the Service Control Manager can stop it. If it is a regular application, sending an escape keystroke (with SendInput() perhaps) or WM_CLOSE message to its main window may work.
If I can't close it nicely, am I permitted to kill it? If so, TerminateProcess() should work.
If I absolutely have to leave the other process running, I would try to see if I can programmatically invoke fast user switching to take me to a different session (in which there will be no competing topmost windows). I don't know where in the API to start with this one. (Peter Ruderman suggests SwitchDesktop() for this purpose in his answer.)
You can use the Process class to start flash.exe directly - and use an appropriate ProcessStartInfo settings to show the window in a hidden state - or with a WindowStyle of hidden or minimized.
You could also consider using the SetWindowsHookEx API to intercept the process start API calls, and when the process is flash.exe run some code to restore you window to top-most status.
Matthew's answer is excellent, but I suspect you may be asking the wrong question. Why does your application need to be topmost? If you're trying to create a kiosk or some such, then topmost is not the way to go.
Edit: After reading your response to Matthew's comment, I'd suggest creating a new desktop and switching to it before displaying your alert. (See CreateDesktop and SwitchDesktop in MSDN.)

How do I stop MS Graph component popping up during Interop?

When using Office Interop in C#, if you insert a chart object into a MS Word document, the Grap application loads up very briefly and then goes away. Is there a way to prevent this from happening? I have tried setting the Visible property of the application instance to false to no effect.
EDIT: The Visible property does take effect when used against Word when interopping, and it does not pop up. I would expect there is a similar way to do this for MS Graph.
This is common behaviour for a lot of component hosted in an executable binary. The host application will startup and then do the job. I don't know if there is a surefire way to prevent that since you have no control over the component nor over the process until the application is started and is responding.
A hack I tried in the past (for something totally unrelated) was starting a process and constantly detecting if its main windows was created. As soon as it was created, I was hiding it. You could do this with the main module of the faulty application and hope it will be fast enough to hide the window before the user notices. Then you instanciate your component; the component will usually recycle an existing process, hopefuly the one with the hidden main window.
I can't garentee you this will work in your situation, but it's worth a try it the issue is that important, or if you don't find a better way of course.

Categories

Resources