Escaping ampersand in a path to Outlook VSTO add-in - outlook

I have a VSTO add-in for Outlook. It is loaded by a helper add-in through code by manually adding relevant values to the registry, contacting Outlook to launch the add-in and then cleaning the registry.
It happened so that for one of the customers the path to the add-in contained an ampersand (&) symbol. This prevents the add-in from being loaded with the following exception:
System.ArgumentException: Value does not fall within the expected range.
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.GetManifests(TimeSpan timeout)
at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.InstallAddIn()
After some research I have found that the ampersand in the path was to blame. I am looking for a way to overcome this limitation. I've created a simple empty test add-in and tried to install it via the *.vsto file that is located in a folder with ampersand symbol in the path it succeeded. Outlook loaded the add-in just fine. So I know there is definitely a way how VSTO does it.
I've tried escaping the path to manifest using && or &amp ; but it didn't help. Is there some other way I can approach this? Here is a sample of the way I am loading the add-in from the code:
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Office\Outlook\Addins", true))
{
key.DeleteSubKey("MyAddIn", false);
using (RegistryKey addinKey = key.CreateSubKey("MyAddIn"))
{
addinKey.SetValue("Manifest", $"{ new Uri(addInPath).AbsoluteUri) }|vstolocal");
addinKey.SetValue("Description", "My Outlook Addin");
addinKey.SetValue("FriendlyName", "My Outlook Addin");
addinKey.SetValue("LoadBehavior", 0);
}
_outlookApplication.COMAddIns.Update();
key.DeleteSubKey("MyAddIn", false);
}
foreach (COMAddIn comAddin in _outlookApplication.COMAddIns)
{
if (comAddin.Description == "My Outlook Addin")
{
ConnectAddIn(comAddin);
break;
}
}

Try to url encode (%26) the ampersand.

Related

Uninstall VSTO Outlook Add-In while Outlook remains open

I have created my VSTO Add-In installer using "ClickOnce". I am using "VSTOInstaller.exe" to install and uninstall using PowerShell script. The uninstallation works fine when the Outlook is not running. However, when it is running, even though uninstall does not show any error, it does not uninstall the add-in. None of the relevant registry entries are deleted. Is there any "force" option to uninstall it? How can it be done when Outlook is up and running?
I think forcefully closing outlook will not solve your problem as maybe user is working on some mails and if you close it forcefully user will loss unsaved mails.
However, if you still want to do it.
you can create a new form along with your project
and use this code
if (System.Diagnostics.Process.GetProcessesByName("OUTLOOK").Length > 0)
{
System.Diagnostics.Process proc = System.Diagnostics.Process.GetProcessesByName("OUTLOOK")[0];
proc.Kill();
}
Otherwise you can put a popup to tell user to close the outlook from its end so that user can save its already opened work before closing outlook.

Is there a way to see if a specific Add-In is installed?

Is there a way (API or other?) to find out if an add-in is installed?
I'm looking at augmenting the Exchange install to insert my own button to tell my user if an Outlook add-in is installed or not?
Is there an API for finding out?
The Office Object Model has a COMAddins collection accessible from the Outlook.Application object that you can use to iterate through all registered add-ins. Any add-in that is loaded will have COMAddin.Connect set to True (which you can set to False to unload the add-in).
https://msdn.microsoft.com/en-us/library/ff870066.aspx
The trick to doing this in Exchange and OWA (not desktop Outlook) is to use JS to manually open the Add-Ins pane and try to click your add-in. Not perfect, I realize, but it does satisfy the original requirement even though there is no direct API support.
Edit the file named, microsoft.owa.mail.compose.js and find a good place to enter something similar to the following.
var workDocument = (this.bh.bz) ? $(this.bh.bz.document) : window.document;
var yourAddIn = $(workDocument).find('iframe[title="Your_Add-In_Name"]');
if (yourAddIn.length > 0) {
yourAddIn[0].contentWindow.postMessage({ id: 'Look_for_your_id_using_DevTools_F12_and_Find_the_id', message: 'send'}, '*');
return;
} else {
// Click Add-in button, click the add-in name in the add-ins list
var addInsButton = $(workDocument).find("button[title='Add-ins']");
if (addInsButton.length <= 0) {
return;
}
addInsButton[0].click();
}

Cyrillic characters are corrupted when using body.getAsync

I've developed a simple task pane add-in for testing Cyrillic characters, but when using body.getAsync() the Cyrillic characters appear to be encoding incorrectly.
Is there a workaround for getting Cyrillic html from an email body? Here’s the code I’m using:
var message = Office.context.mailbox.item;
message.body.getAsync(Office.CoercionType.Html, function (result) {
if (result.status === Office.AsyncResultStatus.Succeeded) {
$("#gridResult").html(result.value);
}
});
Here’s the result I get. All the Cyrillic characters are messed up.
Edit
I ran the code through the Visual Studio debugger and set a break point on the result.value prior to invoking .html(). The corrupted values are visible. The same thing happens when attaching to the IE Process using F12 developer tools:
This has been discovered to be a bug. It will be fixed in an upcoming update for C2R builds. Tentatively, if the build is AFTER 16.0.7117.1000, it should be fixed. This build number is not the exact number that will come up, but when a update comes out, if the number is AFTER that build, the fix should be in.
I can't confirm that this fix will make it until the actual patch comes out though.
The fixes for MSI Outlook 2016 and MSI Outlook 2013 will come afterward. I will update with the KB's and Patches for those updates once they are scheduled to be released.
Thanks for reporting this issue. It was a regression in Outlook Desktop and the fix will get to clients in about two months.
In the meantime the workarounds are calling the API with Office.CoercionType.Text
var message = Office.context.mailbox.item;
message.body.getAsync(Office.CoercionType.Text, function (result) {
if (result.status === Office.AsyncResultStatus.Succeeded) {
$("#gridResult").html(result.value);
}
});
Or using your addin in OWA (Outlook on Web).

Outlook add-in creating spurious folders in new PSTs

I'm maintaining an Outlook 2010 addin produced by my company. Some of our clients have reported that spurious folders named &Dont prompt me about this again., &Dont prompt me about this again.1, &Dont prompt me about this again.2, etc. are appearing. I was able to duplicate this issue by creating a new PST file; each time I re-open Outlook, a new folder is created.
Some research indicates that people have reported similar issues with Outlook Social Connector and the Norton Antispam Outlook Addin. I verified that neither of the above is causing our issue. It seems to me that this is an issue among Outlook add-ins. Is there something we can do to fix it in our Outlook add-in?
When you execute the method 'GetDefaultFolder' with any value, if the folder doesn't exist in the new .pst file, the Outlook create it:
Outlook.NameSpace ns = OutlookApp.Session;
Outlook.Store store = ns.Stores[1];
store.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDrafts);
Sometimes, for no reason, the Outlook creates strange folders, like in my question:
Outlook.Store.GetDefaultFolder creates a stranger folder
I'm still dont understand why...

Outlook addin has failed to find Office control by ID

I've just built an MS Outlook Add In using Visual Studio and Office 2010. I've installed it ok on 4 machines, but one user is getting the following error -
Error found in Custom UI XML of "...."
...
...
Failed to find Office control by ID
Everyone is running Windows 7 and Outlook 2010 - not sure why this person is having a problem. Can anyone suggest how to diagnose this?
For those having similar issues, you don't have to remove any add-in.
What is happening is: Outlook will try to load all ribbons (found in your ribbon xml) into any window the user goes to. Then it'll complain about not finding ID x or y.
Just make sure your GetCustomUI method in Ribbon.cs does not load the entire ribbon XML at once but rather loads it per fragment.
If you're not sure what IDs you need to target, use a breakpoint in GetCustomUI then start Outlook, surf different views (main, new email, new appointment, calendar...etc) in order to gather the IDs for the views wherein you need to show you add-in.
In my case, I needed Microsoft.Outlook.Explorer, Microsoft.Outlook.Mail.Compose and Microsoft.Outlook.Appointment.
Therefore I changed my GetCustomUI to:
public string GetCustomUI(string ribbonID)
{
switch (ribbonID)
{
case "Microsoft.Outlook.Explorer":
return GetResourceText("MyAddin.RibbonsForOutlookExplorer.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("MyAddin.RibbonForOutlookMailCompose.xml");
case "Microsoft.Outlook.Appointment":
return GetResourceText("MyAddin.RibbonForOutlookAppointment.xml");
default:
return null;
}
}
Of course, I had to break down my Ribbon.xml into the three XML files mentioned above. The result: Outlook will ONLY load the fragment needed for a given screen (appointment, new email ...) and will not complain about "not finding an ID on screen X or Y".
Finally, for those who are not sure why some users get that error while others don't: it's because of "Show add-in user interface errors" option (in Options -> Advanced). If that is unchecked then Outlook will ignore the malformed ribbon XML errors. If it checked, users will get related errors about your add-in (if any exists) and also about other add-ins.
If it works for everyone except one user. As #Brijesh Mishra mentioned check if the user has got any other addin and if he is having own quick access tool bar customized.
If he has got any of this then, remove the other addins and try to install or reset the quick access tool bar customization.
For all of you that use a Designer-based VSTO plugin, and not the XML solution.
I searched all the web for this problem, but only found XML-based solutions.
There's nothing for Visual Designer on the web, because in this case you don't have to override the "GetCustomUI" method.
Ribbons designed by using the Visual Designer return a RibbonManager by default.
This RibbonManager object represents all Ribbon (Visual Designer) items in the project and is automatically handled in background through the active window inspector.
So you don't have to write any special code to handle different windows.
To configure it correctly you just have to:
Add one extra Visual Designer Ribbon for every window the user goes to
in the Ribbon Object go under "RibbonType", open the checkbox list an only activate the corresponding window, where the ribbon should appear.
If there is more than one window checked in the list, Outlook trys to insert the ribbon in all the marked windows. Even if the corresponding window is currently not opened. That's the reason, why the error "Failed to find control ID" appears.
the actual fix for me was to separate the ribbon XML files containing the customUI and redirecting to the correct one in the GetCustomUI method (implemented using Office.IRibbonExtensibility)
in example:
public string GetCustomUI(string RibbonID)
{
switch (RibbonID)
{
case "Microsoft.Outlook.Mail.Read":
return GetResourceText("namespace.type1.xml");
case "Microsoft.Outlook.Mail.Compose":
return GetResourceText("namespace.type2.xml");
default:
return null;
}
}

Resources