Why would outlook.Version
display error CS1061: 'Application' does not contain a definition for 'Version'
when the value is clearly 16.0.0.14326
?
Building on this question: Outlook Interop - 'Class' does not contain a definition for 'Property'
I think I've zeroed in on what the issue is here. Printing the outlook
instance in the immediate window yields this:
{Microsoft.Office.Interop.Outlook.ApplicationClass}
AnswerWizard: '((Microsoft.Office.Interop.Outlook.ApplicationClass)outlook).AnswerWizard' threw an exception of type 'System.Runtime.InteropServices.COMException'
Application: {Microsoft.Office.Interop.Outlook.ApplicationClass}
Assistance: {System.__ComObject}
Assistant: {System.__ComObject}
COMAddIns: {System.__ComObject}
Class: olApplication
DefaultProfileName: "Outlook"
Explorers: {Microsoft.Office.Interop.Outlook.ExplorersClass}
FeatureInstall: msoFeatureInstallOnDemand
Inspectors: {Microsoft.Office.Interop.Outlook.InspectorsClass}
IsTrusted: false
LanguageSettings: {System.__ComObject}
Name: "Outlook"
Parent: null
PickerDialog: {System.__ComObject}
Reminders: {Microsoft.Office.Interop.Outlook.RemindersClass}
Session: {Microsoft.Office.Interop.Outlook.NameSpaceClass}
TimeZones: {Microsoft.Office.Interop.Outlook.TimeZonesClass}
Version: "16.0.0.14326"
But trying to print literally any property of the outlook
instance, even ones that should seemingly give straightforward values like outlook.Version
, gives me does not contain a definition for
errors. Intellisense happily autofills these properties and at least some of them clearly have values. What's going on?
Update, following @SimonMourier's suggestion to use:
dynamic outlook = Activator.CreateInstance(Type.GetTypeFromProgID("Outlook.Application"));
works, and I'd love to understand more about why it does. For example, it returns exactly the same values when the instance is printed:
{Microsoft.Office.Interop.Outlook.ApplicationClass}
AnswerWizard: '((Microsoft.Office.Interop.Outlook.ApplicationClass)outlook).AnswerWizard' threw an exception of type 'System.Runtime.InteropServices.COMException'
Application: {Microsoft.Office.Interop.Outlook.ApplicationClass}
Assistance: {System.__ComObject}
Assistant: {System.__ComObject}
COMAddIns: {System.__ComObject}
Class: olApplication
DefaultProfileName: "Outlook"
Explorers: {Microsoft.Office.Interop.Outlook.ExplorersClass}
FeatureInstall: msoFeatureInstallOnDemand
Inspectors: {Microsoft.Office.Interop.Outlook.InspectorsClass}
IsTrusted: false
LanguageSettings: {System.__ComObject}
Name: "Outlook"
Parent: null
PickerDialog: {System.__ComObject}
Reminders: {Microsoft.Office.Interop.Outlook.RemindersClass}
Session: {Microsoft.Office.Interop.Outlook.NameSpaceClass}
TimeZones: {Microsoft.Office.Interop.Outlook.TimeZonesClass}
Version: "16.0.0.14326"
So why do they not return property values in the same way? Why do I get definition errors with new Outlook.Application()
but no definition errors with Activator.CreateInstance()
?
In making an MVC example for @SimonMourier, I performed the following steps:
New C# .NET Framework 4.7.2 console desktop app project
Add Reference --> COM --> Outlook 16.0 Object Library
Added the below code to Main():
dynamic outlook2 = Activator.CreateInstance(Type.GetTypeFromProgID("Outlook.Application")); var outlook = new Microsoft.Office.Interop.Outlook.Application(); Console.WriteLine(outlook.Version); outlook2.Quit(); outlook.Quit();
Break on
outlook2.Quit();
As written, outlook.Version properly returns "16.0.0.14326"
When commenting out
Console.WriteLine(outlook.Version);
, outlook.Version returnserror CS1061: 'Application' does not contain a definition for 'Version'
outlook2.Version always properly returns "16.0.0.14326"
Why does writing a value to the console affect the ability to properly return a property?
CodePudding user response:
I actually cannot reproduce the problem in the question, but another way of calling COM object that support COM Automation (IDispatch interface, typelibs, etc.) such as Microsoft Office Applications is to use the C# dynamic keyword that was introduced with C# 4.
So, in the Outlook example, you can just create the Outlook Application object with this code (without creating any reference or using any PIA, you just need Outlook to be installed correctly):
dynamic outlook = Activator.CreateInstance(Type.GetTypeFromProgID("Outlook.Application"));
And then call any method or property just as you would if autocompletion did not exist:
Console.WriteLine(outlook.Version); // C# will dynamically call for a property named "Version"
Notes: name resolution happens at runtime, and the main drawback is you don't have autocompletion, so, with big models hierarchies like Outlook, it can be difficult to work with.