I'm getting an intermittent error when using Outlook interop within my program. I get users reporting this error every now and then, but it's impossible to reproduce on my end. What's even stranger is that if they restart the program and try again, the error is gone.
Here's the code I'm using to get a reference to Outlook.
public class CommonStuff
{
public static void Initialize()
{
olk = new Microsoft.Office.Interop.Outlook.Application();
olk.ItemSend += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(OutlookInterop_ItemSend);
}
public static Microsoft.Office.Interop.Outlook.Application GetOutlook()
{
if (Process.GetProcessesByName("OUTLOOK").Count() == 0) //previous attempt at fixing this issue, and i'm not sure if i even need this
{
olk = new Microsoft.Office.Interop.Outlook.Application();
}
return olk;
}
}
And the code that's used when sending the actual email.
public void SendEmail()
{
Microsoft.Office.Interop.Outlook.MailItem eMail = (Microsoft.Office.Interop.Outlook.MailItem)CommonStuff.GetOutlookApp().CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
eMail.Subject = String.Format("Subject");
eMail.To = "email#things.com";
eMail.Companies = "Company";
eMail.Body = "blah blah blah";
eMail.Attachments.Add(GetCrystalReportPDF());
((Microsoft.Office.Interop.Outlook._MailItem)eMail).Display();
}
Unfortunately I don't know where exactly the error is happening because I can't reproduce the bug. Does anyone have any clues as to what's going on?
This is the classic kind of problem with process interop, you get to troubleshoot all of the bugs and crashes of that other process as well. "RPC server is not available" is a very generic error and doesn't mean anything more than "the process doesn't work anymore". A few simple reasons for that, it could simply have crashed or the user terminated it. Outlook is in general a troublemaker, it isn't exactly the most stable program in Office.
Your work-around with Process.GetProcessesByName() is a fair attempt but it is unlikely to work. Users commonly already have Outlook running for their own use, you'll see that instance as well. You can't tell if that process you see is the one that you started and matches your olk instance or is the one that user is looking at.
The proper workaround is to re-create your olk instance when you get the exception. That can be hard to deal with since it might be generated while you are deeply nested in your code. But it is best to not fix that case, because that hints at your code inducing the crash, you don't want to hide that problem. Implement a "canary test", just sniff at an innocent property before you start doing something non-trivial. If that induces the exception then recreate the instance. Do test this, I'm not 100% sure that the old olk instance is going to bomb your program when it gets finalized. You ought to get a repro by killing Outlook.exe with Task Manager.
Related
I have an MVC app running on IIS 7 using windows authentication and Elmah logging.
Normally when an error happens, we call something like "logger.LogError" which is a wrapper for:
Elmah.ErrorLog.GetDefault(null).Log(new Elmah.Error(new Exception(message)));
We have a remote system set up to run jobs that pings the web application periodically, in order to wake it up and tell it to run a specific job. The remote application uses HttpClient::GetAsync(...) to connect to the site.
The page that the remote ping hits, executes the job it needs to run in a thread but does not await, since we want the ping to respond immediately. Unfortunately, this has the added drawback of breaking the Elmah logging.
If we have any kind of logged error occur during the job execution, when we get to the "LogError" method, Elmah throws an "ObjectDisposedException" with the message "Safe Handle has been closed" (probably bubbled up from trying to access the current users identity). I checked in the watch window while debugging, and the part that is throwing the error is:
new Elmah.Error(new Exception(message))
if I call just "new Elmah.Error()" it works fine, and "new Exception(message)" also works fine, but when passing an exception as the parameter to the error constructor, that's when it fails. Also, I cannot assign an exception after creating a new error object, as the property is read-only.
I'm pretty sure that it's because the current windows identity has gone out of scope in the parent thread when it finishes. Is there any way of getting around this issue without resorting to an await on the job execution? The problem is that the jobs can take a very long time to run, and we don't want the remote ping app to either timeout or hang for a long time while waiting for a response.
In case someone else runs across this, here's what I ended up doing:
In a situation where you'd normally call
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
Call this function instead:
public static void LogError(Exception ex)
{
if (HttpContext.Current == null)
{
var errorlog = Elmah.ErrorLog.GetDefault(null);
var error = new Elmah.Error();
error.Message = ex.Message;
error.Detail = ex.ToString();
error.Time = DateTime.Now;
error.Type = ex.GetType() + "[NoContext]";
error.HostName = Environment.MachineName;
errorlog.Log(error);
} else {
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
Caveats apply:
All this does is log to your default log. It won't send e-mail or do
any of the other fancy things Elmah can do with an HttpContext
You won't get the full yellow screen of death - just the ToString() representation of the exception, which is less useful.
I have a huge problem here at the moment. It happens to me when I try to bind to dictionaries, do reflection or like in this case use transitions.
When I try to start the app I get the following error:
Unable to activate Windows Store app [App-Name here]. The activation request failedith error 'Windows was unable to communicate with the target application. This usually indicates that the target application's process aborted. More information may be available in the Debug pane of the Output windows (Debug->Windows->Output).
See help for advice on troubleshooting the issue.
The Output windows does not offer any further information regarding the issue. In fact it even says that the app launched properly.
I have already checked like every blog or forums-entry on the internet but nothing seems to help. I have reinstalled my VS 2012 and the error still occurs. In this case, the following code causes the error (regardless of which transition I use on what element)
<StackPanel.ChildrenTransitions>
<PopupThemeTransition/>
</StackPanel.ChildrenTransitions>
I am REALLY out of ideas. In another case the following code caused that crash:
public class PresentColorsView
{
static PresentColorsView ()
{
List<PresentColorsView> ColorsList = new List<PresentColorsView>();
IEnumerable<PropertyInfo> Properties = typeof(Colors).GetTypeInfo().DeclaredProperties;
foreach (PropertyInfo property in Properties)
{
PresentColorsView tmpAddColors = new PresentColorsView();
if (property.Name.Length < 7)
{
tmpAddColors.ColorName = property.Name;
tmpAddColors.Color = (Color) property.GetValue(null);
ColorsList.Add(tmpAddColors);
}
}
AllColors = ColorsList;
}
public string ColorName { get; set; }
public Color Color { get; set; }
public static IEnumerable<PresentColorsView> AllColors { get; set; }
}
I am really out of ideas and don't know what to do anymore. I frequently get this error on stuff I even have copied exactly word or word from a book or something. This is limiting my developing abilities on a high scale!
I really appreciate every piece of advice. I am thinking about downloading VS 2013 and check weather the bug will still occur.
Thank you very much!
Greetings, FunkyPeanut
Most likely your code throws an unhandled exception. You should handle exceptions at least in the Main method, log them or otherwise let yourself know something went wrong.
In the particular piece of code this line is most likely causing the issue:
tmpAddColors.Color = (Color) property.GetValue(null);
If you read the documentation, you'd quickly figure out it says “Returns the property value of a specified object.” The important part being bold. You are passing a null. Hence either GetValue fails immediately, throwing an exception, or the cast to Color throws an InvalidCastException (in case Color is a value type).
I just have got the same error when trying to debug a WPhone App.
Spite of my issue is not related whit this one, and after long time reading threads and trying eveything related with it, i have found where the problem is and I would like to share it.
I had a Dictionary instantiation at main class App.cs. When performing test phases I didn't realized that I have added a duplicate key and this simply raised the error reported on this post.
In my Windows Phone app I use Application.UnhandledException to catch all unhandled errors. If that kind of error happens then my app shows a simple MessageBox with a request to send an error report to developers via email. It looks like this:
protected virtual void OnUnhandledException(
object sender, ApplicationUnhandledExceptionEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
var result = MessageBox.Show(
"Would you like to send a report to developers?",
"Error",
MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
var task = new EmailComposeTask();
task.To = "feedback#site.com";
task.Subject = "Error";
task.Body =
e.ExceptionObject + "\n" + e.ExceptionObject.StackTrace;
task.Show();
e.Handled = true;
}
});
}
In most cases all works fine.
But many users complains that sometimes the app simply crashes with no messages. I have some crash reports in my developer's dashboard but these reports have a very small amount of useful information. And I can't understand what kind of error can cause this. I only have an assumption that some error happens in one of background threads.
Is Application.UnhandledException works properly in all cases? Could some exceptions stay unhandled? What can be done in situation described above?
Thanks.
In addition to the points in the other answers, you can't guarantee the Dispatcher is still running or that the UI thread will execute again.
Of course any attempt to do almost anything could fail if the app or OS is in a bad state (especially with OutOfMemory). So the less you do the better - that way you won't mess up the crash reports that the phone collects and uploads to the Store.
You should instead write the exception detail to IsolatedStorage and detect the presence of a past exception the next time you start your app.
Unhandled exceptions in worker threads or those scheduled by Task are not reported in the Application.UnhandledException, AFAIK.
Have a read at this: http://www.markermetro.com/2013/01/technical/handling-unhandled-exceptions-with-asyncawait-on-windows-8-and-windows-phone-8/, there seems to be a good approach to making sure you can catch those unhandled in async code.
Not all exceptions can be handled. Basically, all exceptions that may endanger the runtime stability won't be handled. By my experience, the most frequent one is the OutOfMemoryException.
I am working on an Excel Addin using C#, Visual Studio 2012. I am trying to get the instance of Excel's Application object so as to keep track of the currently active workbook and worksheet (ActiveWorkbook, ActiveWorksheet).
I see that most other related questions on SO have replies suggesting to use the following:
(Excel.Application)Marshal.GetActiveObject("Excel.Application");
I have also tried using this:
(Excel.Application)Globals.ThisAddIn.Application;
In both of the cases I get NullReferenceException. After looking at the workaround suggested here: http://support.microsoft.com/kb/316125/en-us, I tried the following to test both methods.
public CurrentSpreadSheet()
{
try
{
this.CurrentApplication = (Excel.Application)Globals.ThisAddIn.Application;
}
catch (NullReferenceException)
{
MessageBox.Show("Excel application object not registered. Trying plan B..");
//Getting Excel's application object instance
int iSection = 0, iTries = 0;
tryAgain:
try
{
iSection = 1; //Attempting GetActiveObject
this.CurrentApplication = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
iSection = 0; //GetActiveObject succeeded so resume or go for normal error handling if needed
this.CurrentApplication.Visible = true;
}
catch (Exception err)
{
System.Console.WriteLine("Visual C# .NET Error Attaching to Running Instance of Office Application .. yet.");
if (iSection == 1)
{
//GetObject may have failed because the
//Shell function is asynchronous; enough time has not elapsed
//for GetObject to find the running Office application. Wait
//1/2 seconds and retry the GetObject. If we try 20 times
//and GetObject still fails, we assume some other reason
//for GetObject failing and exit the procedure.
iTries++;
if (iTries < 20)
{
System.Threading.Thread.Sleep(500); // Wait 1/2 seconds.
goto tryAgain; //resume code at the GetObject line
}
else
{
MessageBox.Show("GetObject still failing. Process ended.");
}
}
else
{
//iSection == 0 so normal error handling
MessageBox.Show(err.Message);
}
}
}
}
The output is:
Excel application object not registered. Trying plan B..
GetObject still failing. Process ended.
In some rare cases "plan B" does work; I don't see the second message box.
CurrentSpreadSheet is a singleton and I intend to update it during startup from the provided class ThisAddIn.
In ThisAddIn I have something like:
private CurrentSpreadSheet css = CurrentSpreadSheet.Instance;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
///...Some code
css.updateCurrentSpreadSheet();
}
Is there a better way of getting the Application object? If this is not possible right during the startup, is there a better way by which I can keep track of currently active worksheet/workbook right from the startup of excel/my add-in? Currently I am depending on the Application object (e.g. (Excel.Workbook)this.CurrentApplication.ActiveWorkbook;) and some event handlers to keep track of the current workbook and worksheet.
I tried using ExcelDNA:
this.CurrentApplication = (Excel.Application)ExcelDna.Integration.ExcelDnaUtil.Application;
This works some of the times but mostly gives this error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> ExcelDna.Integration.XlCallException: Exception of type 'ExcelDna.Integration.XlCallException' was thrown.
Keep in mind that an Office add-in runs inside the Office process. So you never want to find an external process. The boilerplate ThisAddIn class that you get when you use a Office project template hands you the Application object you are looking for on a silver platter, use its Application property. The first time you can get to it is in the Startup event, make sure you don't try it earlier. So don't do anything drastic in your constructor and don't initialize class members with initialization expressions, wait until Startup fires.
The relevant MSDN page is here, "Accessing the Object Model of the Host Application" section.
You might take a closer look at http://netoffice.codeplex.com/ There you can find more stuff about Add-In's for Word/Excel/Powerpoint.
Also keep in mind the GuidAttribute when you load your Add-In, because depending on your Office version it won't work anymore and also, check to kept your project whether 32/64-bit, best is Any CPU. Also, keep in mind to register your Add-In into the registry for further usage. If you want further information, don't hesitate to write me a mail.
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.guidattribute.aspx
I've been starting at this code for the best part of 2 hours (literally) but I can not seem to grasp why this would fail. This method below does not report any exceptions, yet it seems to return false:
public bool SaveFile(string filename, object source)
{
bool result = true;
StringBuilder exportText = new StringBuilder(source.ToString());
try {
File.WriteAllText(filename, exportText.ToString());
}
catch (Exception e)
{
OnPluginError(new ErrorEventArgs(e));
result = false;
}
return result;
}
The problem is: the file is properly written at the requested path, is complete, and readable. No exceptions are thrown, because the OnPluginError() handler invocation method isn't called - any message would be logged in that case, but there is nothing logged. It can't be a permission problem because the file does exist after the call.
And still, the method result is false.
The problem only appears in a Release build. In Debug builds, all seems to work OK. Hence, I can't use the debugger to step through.
This is called from a web application. Any ideas appreciated.
As a temporary troubleshooting step, add another try catch to block any exceptions and then see if the function is still returning false.
public bool SaveFile(string filename, object source)
{
bool result = true;
StringBuilder exportText = new StringBuilder(source.ToString());
try {
try {
File.WriteAllText(filename, exportText.ToString());
} catch(Exception e) { }
}
catch (Exception e)
{
OnPluginError(new ErrorEventArgs(e));
result = false;
}
return result;
}
If it is returning true, then you have isolated the problem and determined that an exception is being thrown, causing the block with result = false to be run.
If it is still returning false, then you can be certain the problem is outside of this function, as the rules of control flow would dictate that the result variable would never be changed.
One possibility is you have an issue with either the code you think is being run is not really being run. For example some issue with the build process not picking up your most recent code changes or redirection. Checking the versions of the website project DLLs, doing clean/rebuild, adding additoinal code to write out trace messages, are all things you should try to cross check to verify your most recent code is being run.
Another possibility is a problem in the code that is checking the return value.
Well...I do feel a bit silly here. I finally found the problem, and it is (as some posters questioned) not related to the WriteAllText() method at all.
FYI: this code ran deep inside an extensive plugin library. Not all that code was designed and written by me, and has been around for almost 2 years without running into problems.
As I mentioned, the WriteAllText() ran fine. It did. Problem was that the location of the file saved, was stored in a Dictionary, which in turn was requested from the plugin currently running. That Dictionary (containing plugin settings) turned out to be created from scratch with each call to that property! So I could add to it as much as I wanted....at the next call to that property, the newly added items would 'disappear' magically since the Dictionary was created anew.
Since it never surfaced before, and that code ran in a lot of other plugins with no problems, I didn't check that property. My bad.
Apologies to everyone that responded for wasting their time. Rest assured it won't happen any time soon! Lesson learned...