Why does my VSTO Outlook Add-In hang on first run? - vsto

I've written this little MS Outlook 2003 VSTO Add-In using C# and Visual Studio 2008. It is meant to check each Mail Item being sent for the word "attach" in the body and if found, then check the number of attachments. If that number is zero, then ask the user if they really mean to send the message. It's supposed to work like the Gmail labs feature which does the same thing.
The odd thing is that it works, but the first time I run it, I get a pause, like the mail item window is hung for about 45 seconds. Once it gets past that, it runs very fast for the rest of the time I have Outlook open. If I close Outlook though, then the next time I re-open it and send a message, I will have this wait again.
Any ideas, peoples?
Here's the code for my Add-In:
namespace OutlookAttacher
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.ItemSend += new Outlook.ApplicationEvents_11_ItemSendEventHandler(Application_ItemSend);
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
void Application_ItemSend(object Item, ref bool Cancel)
{
if (Item is Microsoft.Office.Interop.Outlook.MailItem)
{
Microsoft.Office.Interop.Outlook.MailItem currentItem = Item as Microsoft.Office.Interop.Outlook.MailItem;
Cancel = true;
if (currentItem.Body.Contains("attach"))
{
if (currentItem.Attachments.Count > 0)
{
Cancel = false;
//MessageBox.Show("This message will be sent now.");
currentItem.Send();
}
else
{
DialogResult ans = MessageBox.Show("This message has no attachments. Are you sure you want to send it?", "OutlookAttacher", MessageBoxButtons.YesNo);
if (ans.Equals(DialogResult.Yes))
{
Cancel = false;
//MessageBox.Show("This message will be sent now.");
currentItem.Send();
}
}
}
else
{
Cancel = false;
//MessageBox.Show("This message will be sent now.");
currentItem.Send();
}
}
}
}
}
Any suggestions for improving the code are welcome as well, since this is my first stab at an Outlook Add-In.
Update: I am running this on a 5-year Dell laptop, 2 GB of Ram and I-don't-know-which Intel CPU. I like the idea of adding a trace / debugging it. I will have to go figure out how to step through the code so I can see where it might be taking the longest time. Thanks y'all!

OK, I'm really embarrassed. The delay I was seeing was just Outlook synching with my Exchange server. I was at home when I was testing and Outlook was still connecting via HTTP. I am seeing it work fast today, in the office, so no HTTP. Thanks for the replies anyway.
:-)

Related

ItemChange in Outlook VSTO AddIn gets called several times after save to appointmentItem

in my Addin I attached to the ItemChange event like this;
public void attachEvents()
{
_CalendarItems.ItemChange += Item_Change;
and I wrote a function like this:
public void Item_Add(Object item)
{
Outlook.AppointmentItem myAppointment = item as Outlook.AppointmentItem;
if (myAppointment != null)
{
[...]
My problem is that this method does not get called just once when I call myAppointment.save() but 3-4 times. Why is that?
And there are only get() calls in the eventhandler so there is NOTHING changed in the appointmentItem (which would probably trigger further events of course).
Best regards
Hannes
That is expected. Especially with Exchange profiles configured in Outlook. You may find similar forum threads like the following one - Outlook 2016 produces an extra ItemChange event after an appointment is created.

Handling ExecuteFilesInUse with Retry and resolving used files

I'm having a custom Managed Bootstrapper Application for my installer and I am hooking into the ExecuteFilesInUse event to show a UI to the user. In this UI I list the processes provided in the event and 2 buttons: Retry and Cancel. Everything seems to work fine. When I lock some of my files and I press retry, it checks again for files in use. If I press cancel the installation aborts. When I resolve the files in use by closing all applications the installation/uninstallation continues when pressing retry.
But then the problem starts: The msiexec.exe process gets stuck. It utilizes 1 CPU core at 100%. Almost as if it is in an endless loop doing nothing. The logfiles do not contain any details that something is done and nothing happens.
My code looks like this:
// bootstrapper.ExecuteFilesInUse += Bootstrapper_ExecuteFilesInUse;
private void Bootstrapper_ExecuteFilesInUse(object sender, ExecuteFilesInUseEventArgs e)
{
if (!Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.Invoke(new EventHandler<ExecuteFilesInUseEventArgs>(Bootstrapper_ExecuteFilesInUse), sender, e);
return;
}
IList<string> files = e.Files;
if (files == null || files.Count == 0)
{
e.Result = Microsoft.Tools.WindowsInstallerXml.Bootstrapper.Result.Ignore;
return;
}
var hasEmptyRecords = e.Files.Any(string.IsNullOrEmpty);
if (hasEmptyRecords)
{
e.Result = Microsoft.Tools.WindowsInstallerXml.Bootstrapper.Result.Retry;
return;
}
var window = new FilesInUseWindow();
window.DataContext = new FilesInUseViewModel(e.Files);
var result = window.ShowDialog();
if (result == true)
{
e.Result = Microsoft.Tools.WindowsInstallerXml.Bootstrapper.Result.Retry;
}
else
{
Cancelled = true;
e.Result = Microsoft.Tools.WindowsInstallerXml.Bootstrapper.Result.Cancel;
}
}
```
The default WiX bootstrapper by default only provides the options to close them automatically or to schedule a reboot afterwards. But I want the user to manually close everything clean and then continue with the installation. I also attached the debugger ot my MBA to check if ti might be still firing the event
Is this workflow not supported or am I simply doing something wrong here?
Update: I decided also to file an issue on the Wix project page as I was able to reproduce this hang also on a fresh project.

Outlook VSTO Addin - NormalEmail.dotm not saved

I'm trying to register a handler for the WindowSelectionChanged event. It works, but when quitting Outlook, it will discard any changes to NormalEmail.dotm file.
For example, any changes to the Quick Part Gallery (Insert->Text->QuickParts) will only be visible during the current session; closing Outlook and starting it again will show the previous list of elements, even if they were deleted, or new ones were added).
Deleting the file :
C:\Users[USER]\AppData\Roaming\Microsoft\Templates\ NormalEmail.dotm
should prompt Outlook to create a new one, but this won't happen when the Addin is enabled.
This can be reproduced by registering even an empty method to the WindowSelectionChange event:
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.Inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(RegisterChangeHandler);
}
void RegisterChangeHandler(Outlook.Inspector inspector)
{
Microsoft.Office.Interop.Word.Application app = Application.ActiveExplorer().ActiveInlineResponseWordEditor?.Application;
--> app.WindowSelectionChange += WinSelectionChange; <-- this line causes the bug
}
private void WinSelectionChange(Selection Sel)
{
/* nothing */
}
...
}
This causes no exceptions; the result is the same when putting try/catch blocks in place, or when the callback is unregistered in the Application.Quit event.
Question: How can Outlook be made to commit the NormalEmail.dotm file, while also being able to register a callback for WindowSelectionChange event ?
(the project type is "2013 and 2016 VSTO Addin")

MailItem event not firing without Visual Studio

I want to handled the BeforeAttachmentAdd event from an Outlook mail item. But my code works in Visual Studio environment but not out. Have you an idea?
This is my code:
namespace MyOutlookProject
{
using Microsoft.Office.Interop.Outlook;
using OutlookApplication = Microsoft.Office.Interop.Outlook.Application;
using OutlookAttachment = Microsoft.Office.Interop.Outlook.Attachment;
using OutlookInspector = Microsoft.Office.Interop.Outlook.Inspector;
using OutlookMail = Microsoft.Office.Interop.Outlook.MailItem;
class MailManager
{
public void StartUp(OutlookApplication application)
{
_inspectors = application.Inspectors;
_inspectors.NewInspector += Inspectors_NewInspector;
}
private void Inspectors_NewInspector(OutlookInspector Inspector)
{
if (Inspector.CurrentItem is OutlookMail)
{
OutlookMail mail = (Inspector.CurrentItem as OutlookMail);
mail.BeforeAttachmentAdd += Mail_BeforeAttachmentAdd;
}
}
private void Mail_BeforeAttachmentAdd(OutlookAttachment Attachment, ref bool Cancel)
{
/*Never called without Visual Studio*/
}
}
}
Thanks for your help.
The object firing the events (mail variable in your code) must be on the global/class level to prevent it from being garbage collected. The variable is local in you case.
On a general note, you can have multiple inspectors open, so it might make sense to have a wrapper object that holds references to the inspector and its mail item, and have a list of such wrappers in your addin.
From what I see you may be hitting a My button stopped working issue
From the book Of E. Carter and E. Lippert VSTO 2007
It states
One issue commonly encountered when beginning to program agains Office events in .NET is known as the "my button stopped working" issue. A developer will write some code to handle a Click event raised by a CommandBarButton in the Office toolbar object model. This code will sometimes work temporarily but then stop. The user will click the button, but the Click event appears to have stopped working. The cause of this issue is connecting an event handler to an object whose lifetime does not match the desired lifetime of the event. This tipcally occurs when the object to which you are connecting an event handler goes out of scope or gets sets to null so that it gets garbage collected.
I think in your case that the .NET RCW object of type OulookMail manipulated with variable mail that is the culprit. Its lifetime is not properly handled. The fact that this does not happen in Visual Studio is that you are probably in Debug mode that changes a little the Garbage Collection so your object is not destroyed yet when you do the testing.

How to let the user cancel my AutoCAD command

I'm currently developing an AutoCAD 2008 Addin in Visual Basic (.Net 3.0, VisualStudio 2010).
I'm able to define my own command and I want the user to be able to cancel my command by hitting the ESC key.
In AutoCAD 2010 or higher there exists the
HostApplicationServices.Current.UserBreak
method. But not in ACAD 2008.
Does anyone has any suggestions, how the user may be able to cancel my command?
Not sure if this is what your looking for, but I'll throw it out there. In the following example, it prompts the user for input and stores it to the getPointResult. If the user selects "Escape" at this time, the getPointResult.Status will not be PromptStatus.OK, therefor it will not execute the code in the 'if' statement.
Sorry, this is written in C#, but should be easy enough to understand the general idea.
[CommandMethod("test", CommandFlags.Session)]
public void Test()
{
PromptPointOptions getPointOptions = new PromptPointOptions("Select the top-left location for the view: ");
Document currentDocument = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
PromptPointResult getPointResult = currentDocument.Editor.GetPoint(getPointOptions);
if (getPointResult.Status == PromptStatus.OK)
{
//Do work
}
else
{
//what to do if 'ESC' is pressed during GetPoint()
}
}