I have developed an Outlook 2010 Add-in which works perfectly on any machine that has had the project opened in Visual Studio (2010), however which fails on all other computers, with the error message:
"The call to GetCustomUI() for RibbonID Microsoft.Outlook.Explorer failed"
This tells me that the very call to the IRibbonExtensibility interface method failed. It's a runtime error, however I have no idea how or why it is happening.
The "same" add-in worked previously with Ribbon Designer classes, and has now been changed to use Ribbon XML to support some added context menu features for the add-in.
The effect of the error is that, despite the add-in being "active" and loaded into Outlook, none of its buttons, etc. are shown, because the error occurs before any XML Ribbon design can be displayed.
In various troubleshooting articles I found, there were many suggestions for what could be wrong, and one of them is that perhaps the code I have written matches what fits Outlook 2007 and doesn't work for 2010, however I do not know where potential differences lie.
Here is some code from various places in the Add-in structure:
In MyOutlookAddIn.cs:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
return new Ribbon();
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
In Ribbon.cs:
public string GetCustomUI(string ribbonId)
{
Debug.WriteLine(ribbonId);
//Return the appropriate Ribbon XML for ribbonID
switch (ribbonId)
{
case "Microsoft.Outlook.Explorer":
return GetResourceText("OutlookAddIn.RibbonDesignXML.Explorer.xml");
case "Microsoft.Outlook.Mail.Read":
return GetResourceText("OutlookAddIn.RibbonDesignXML.MailReadRibbon.xml");
case "Microsoft.Outlook.Appointment.Read":
return GetResourceText("OutlookAddIn.RibbonDesignXML.AppointmentReadRibbon.xml");
default:
return null;
}
}
public void Ribbon_Load(Office.IRibbonUI ribbonUI)
{
this.ribbon = ribbonUI;
}
And my XML returned for "Microsoft.Outlook.Explorer" ("OutlookAddIn.RibbonDesignXML.Explorer.xml"):
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<ribbon>
<!-- Når en mail er valgt i kalender oversigten -->
<tabs>
<tab idMso="TabMail">
<group id="groupTabMail" label="Jira">
<button id="sendToJiraBtn" onAction="ExplorerSendToJiraButtonClicked" label="Send til Jira" getImage = "GetImage" size="large" />
<button id="jiraSettingsBtn" onAction="ExplorerSettingsButtonClicked" label="Indstillinger" getImage="GetSettingsImage" size="large" />
<button id="jiraSupportBtn" onAction="ExplorerSupportButtonClicked" label="Hjælp" getImage="GetSupportImage" size="large" />
</group>
</tab>
</tabs>
<!-- Når en aftale er valgt i kalender oversigten -->
<contextualTabs>
<tabSet idMso="TabSetAppointment">
<tab idMso="TabAppointment">
<group id="groupTabAppointment" label="Jira">
<button id="sendToJiraBtnAppointment" onAction="ExplorerSendToJiraButtonClicked" label="Send til Jira" getImage = "GetImage" size="large" />
<button id="jiraSettingsBtnAppointment" onAction="ExplorerSettingsButtonClicked" label="Indstillinger" getImage="GetSettingsImage" size="large" />
<button id="jiraSupportBtnAppointment" onAction="ExplorerSupportButtonClicked" label="Hjælp" getImage="GetSupportImage" size="large" />
</group>
</tab>
</tabSet>
<tabSet idMso="TabSetReccurringAppointment">
<tab idMso="TabRecurringAppointment">
<group id="groupTabRecurringAppointment" label="Jira">
<button id="sendToJiraBtnRecurringAppointment" onAction="ExplorerSendToJiraButtonClicked" label="Send til Jira" getImage = "GetImage" size="large" />
<button id="jiraSettingsBtnRecurringAppointment" onAction="ExplorerSettingsButtonClicked" label="Indstillinger" getImage="GetSettingsImage" size="large" />
<button id="jiraSupportBtnRecurringAppointment" onAction="ExplorerSupportButtonClicked" label="Hjælp" getImage="GetSupportImage" size="large" />
</group>
</tab>
</tabSet>
</contextualTabs>
</ribbon>
<contextMenus>
<contextMenu idMso="ContextMenuMailItem">
<menuSeparator id="MailSeparator"/>
<button id="SendToJiraMailItem"
getImage = "GetImage"
label="Send til Jira"
onAction="ExplorerSendToJiraButtonClicked"/>
<dynamicMenu id="DynamicMenuMail" label= "Send til Jira som..." getImage="GetImage" getContent="GetContent" />
</contextMenu>
<contextMenu idMso="ContextMenuMultipleItems">
<menuSeparator id="MultipleItemsSeparator"/>
<button id="SendToJiraMultipleItems"
getImage = "GetImage"
label="Send til Jira"
onAction="ExplorerSendToJiraButtonClicked"/>
<dynamicMenu id="DynamicMenuMultiple" label= "Send til Jira som..." getImage="GetImage" getContent="GetContent" />
</contextMenu>
<contextMenu idMso="ContextMenuCalendarItem">
<menuSeparator id="AppointmentSeparator"/>
<button id="SendToJiraCalendarItem"
getImage = "GetImage"
label="Send til Jira"
onAction="ExplorerSendToJiraButtonClicked"/>
<dynamicMenu id="DynamicMenuAppointment" label= "Send til Jira som..." getImage="GetImage" getContent="GetContent" />
</contextMenu>
</contextMenus>
</customUI>
I'm sorry for sharing this amount of code with you, however reproducing the issue seems a futile task, and I am under time pressure as the Add-in, due to the extended features destroying the Add-in altogether, cannot be used by various entities at my workplace.
Thank you in advance to anyone who can bring insight as to what may be wrong! And especially why it works on development-involved machines and not others...
I found the problem.
The statement:
Debug.WriteLine(ribbonId);
made the whole app crash on client machines, but not on development machines (machines that have had the project open i Visual Studio).
Does anybody have any clue as to how this could be? Isn't the whole purpose of Debug.WriteLines that it only has an effect during debugging? It shouldn't be causing issues to VSTO after publishing the project... A ridiculous and quite difficult error to discover, as it doesn't really make any sense to me.
Thanks for the reply, #Maarten van Stam.
Make sure the RibbonXML is added to your project(s) as embedded resource. I've seen often that this little detail was omitted resulting in running without issues on the developer machines but failing on client end user machines.
If this already is done correctly (your text does not get into that detail) the only option is to strip down. The issue can be part of your RibbonXML definition or reading the RibbonXML file. Just start with a -very- simple XML, one button definition and see if that works on your machine and client end users machines. Same thing with the GetCustomUI, limit it to one line and check the results. From there start expanding until you find the failing source.
Related
I have made an addin (New Flux Ad Mail) for Outlook and would like to move it's position next to the "New" group - see picture.
Currently, I have this in my xml:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<ribbon startFromScratch="false">
<tabs>
<tab idMso="TabMail">
<group id="fluxAdMail" label="Flux Ad Mail">
<button id="btnNewFluxMail" label="New Flux Ad Mail" onAction="click" size="large" imageMso="NewMail"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
I noticed that there's something in the <group> section called insertAfterMso and I'm wondering if that's what I need to use set the position of my group. However, I have a hard time finding any information regarding this or what the different name/id is for the controls
Any help would be appreciated
You are on the right avenue - the insertAfterMso attribute specifies the identifier for the built-in control after which to position this control. You can can find the list of built-in control IDs at https://github.com/OfficeDev/office-fluent-ui-command-identifiers . Use the GroupMailNew idMso value for the insertAfterMso attribute in case of Explorer windows.
If you only need to find control names, you can discover them within Office applications by hovering over commands in the Customize Ribbon tab of the Options dialog and looking at the tooltip:
Using this Outlook 2013, I develop an addin in C#. My ribbon.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<contextMenus>
<!-- Move mail to -->
<contextMenu idMso="ContextMenuMailItem">
<button id="MoveMailTo_CM"
imageMso="CopyToFolder"
insertBeforeMso="Copy"
getLabel="MoveMailTo_GetLabel"
getVisible="MoveMailTo_GetVisible"
onAction="MoveMailTo_OnAction"/>
</contextMenu>
<!-- Manage holiday request -->
<contextMenu idMso="ContextMenuMailItem">
<button id="ManageHolidayRequest_CM"
imageMso="CopyToPersonalCalendar"
insertBeforeMso="Copy"
label="Copy to Calendar"
getVisible="ManageHolidayRequest_GetVisible"
onAction="ManageHolidayRequest_OnAction" />
</contextMenu>
</contextMenus>
</customUI>
When I launch my addin using Visual Studio and I right-click on an email item, only the first "getVisible" is called (the MoveMailTo_GetVisible) but not the other one.
If i switch both menu, only ManageHolidayRequest_GetVisible is called.
Can't we specify two different function in that case? Any workaround ?
Best regards,
Answer was : I had two <contextMenu idMso="ContextMenuMailItem"> (so for the same Mso). Just merged both button in context Menu and worked.
I'm writing an outlook Add-In in VS2017. I need a context menu to appear when 1 or more calendar events are selected. I can get a context menu to appear when a single calendar event is selected with the following XML:
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="GetImage">
<contextMenus>
<contextMenu idMso="ContextMenuCalendarItem">
<button id="MyContextMenuCalendarItem"
label="Copy To Google Calendar"
image="Google_Calendar_Logo.png"
onAction="CopyToGoogleCalendar_Click"/>
</contextMenu>
</contextMenus>
</customUI>
If I use the idMso "ContextMenuMultipleItems", the context menu will appear when multiple of any type (email, calendar, etc.) is selected. I can not figure out the correct idMso for context menu with multiple calendar events selected.
Any help would be greatly appreciated.
Turns out that using the "ContextMenuMultipleItems" idMso works with the added "getVisible" method. My XML now looks like:
<?xml version="1.0" encoding="utf-8"?>
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2009/07/customui" loadImage="GetImage">
<contextMenus>
<contextMenu idMso="ContextMenuCalendarItem">
<button id="MyContextMenuCalendarItem"
label="Copy To Google Calendar"
image="Google_Calendar_Logo.png"
onAction="CopyToGoogleCalendar_Click"/>
</contextMenu>
<contextMenu idMso="ContextMenuMultipleItems">
<button id="MyContextMenuMultipleItems"
label="Copy To Google Calendar"
image="Google_Calendar_Logo.png"
getVisible="ContextMenuMultipleItems_IsVisible"
onAction="CopyToGoogleCalendar_Click"/>
</contextMenu>
</contextMenus>
</customUI>
and the ContextMenuMultipleItems_IsVisible looks like:
public bool ContextMenuMultipleItems_IsVisible(Office.IRibbonControl control)
{
if (control.Context is Outlook.Selection)
{
Outlook.Selection selection = control.Context as Outlook.Selection;
if (selection[1] is Outlook.AppointmentItem)
return true;
}
return false;
}
Clicking on custom ribbon control causes outlook to crash.
The Event listener for the control never gets invoked.
Reproducible for all types of Ribbon controls - RibbonButton, RibbonCheckbox.
RibbonType - "Microsoft.Outlook.Mail.Read" reproducible for others too.
Problem specific to Outlook 2016, not reproducible for 2013.
Outlook version number: 16.0.7167.2040 (latest - part of Office 365)
Steps to reproduce:
Create New project - "Outlook 2013 and 2016 VSTO add-in".
Add New Ribbon using designer. (default type is mail read ribbon).
Add new button - "Important Button" and register listener.
Run -> Outlook -> Home -> Add-Ins -> click "Important Button"
Have checked offCat confing and live loggin - nothing there.
Any pointers on what I am missing here? Any pointers on how to find what exactly is going wrong.
Edit:
Found this in Event Log under Windows Logs -> Applications
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Application Error" />
<EventID Qualifiers="0">1000</EventID>
<Level>2</Level>
<Task>100</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2016-09-06T04:51:22.000000000Z" />
<EventRecordID>247449</EventRecordID>
<Channel>Application</Channel>
<Computer>USER</Computer>
<Security />
</System>
- <EventData>
<Data>OUTLOOK.EXE</Data>
<Data>16.0.7167.2040</Data>
<Data>57ad490b</Data>
<Data>mso40uiwin32client.dll</Data>
<Data>0.0.0.0</Data>
<Data>57ab7885</Data>
<Data>c0000005</Data>
<Data>000ce501</Data>
<Data>107c</Data>
<Data>01d207f98604f7ee</Data>
<Data>C:\Program Files (x86)\Microsoft Office\root\Office16\OUTLOOK.EXE</Data>
<Data>C:\Program Files (x86)\Common Files\Microsoft Shared\Office16\mso40uiwin32client.dll</Data>
<Data>8e19d2e5-73ed-11e6-8343-34e6d7290fdd</Data>
<Data />
<Data />
</EventData>
</Event>
I am agree with Shyam sundar shah.It will be better to use Ribbon(xml).
you can modify the ribbon.xml like this.
<?xml version="1.0" encoding="UTF-8"?>
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tab idMso="TabNewMailMessage">
<group id="ImportantGroup" label="Important Group" insertAfterMso="GroupIncludeMainTab">
<button id="ImportantButton" label="Important Button" onAction="ImportantButton_Click"/>
</group>
</tab>
</ribbon>
</customUI>
Using C#, I'm writing a program that has to use Excel only in order to edit some tabular data provided by my program. My program just creates an Excel application (the Microsoft.Office.Interop.Excel.Application object), creates within it a workbook, creates a worksheet, puts the data in Excel, and, after this, allows to a user to edit these data. The edited data can be easily read by my program. That's, in principal, all what I need from Excel.
This, therefore, means that a user of my program should not be able to format data in Excel, save an Excel file to the hard drive, open Excel files, and so on and so on. A user even does not need the Excel ribbon. Working with formulas is also does not required. Hotkeys (like "Ctrl + B" making the font bold, "Ctrl + S" saving the file, and so on) should be also not workable.
My question is: Is there a way to simply set such a minimalist interface for Excel? Or I should disable any aspect mentioned above by hand, step by step (disable the ribbon, switch off the hotkeys ans so on)?
When working within a VSTO project, you can disable most/all of the UI by using a custom ribbon XML file (there is a visual designer too but I doubt it would be sufficient for this).
To remove things, add a section for what you're removing, and set visible="false" or enabled="false" (users could still potentially add it back to the ribbon, but disabling it makes it grayed out).
e.g.:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<commands>
<command idMso="Cut" enabled="false" />
</commands>
<ribbon>
<tabs>
<tab idMso="TabHome" visible="false" />
</tabs>
</ribbon>
<contextualTabs>
<tabSet idMso="TabSetDrawingTools" visible="false" />
</contextualTabs>
<backstage>
<tab idMso="TabInfo" visible="false">
</backstage>
<contextMenus>
<contextMenu idMso="ContextMenuText">
<!-- you can't hide a context menu entirely, you have to hide each item -->
<button idMso="FontDialog" visible="false" />
</contextMenu>
</contextMenus>
</customUI>
This may also be possible if you're working with Office in the way that you seem to be, I don't really know.