By
Sahir Shah
20 - October - 2007
Office Automation using a reference to an Office application's object library is not guaranteed to work with all versions of MS Office. Every time users migrate to a new version of office, someone will have to make some adjustments to all applications which interact with Excel, Word, Outlook etc. and re-deploy them. In a corporate environment, migrating to a new version of Office can be a long drawn out process with hundreds of compatibility issues. The office automation issue will simply add another dimension of pain to the process. To eliminate this office automation should ideally be done using late binding. This makes the automation code version agnostic and also enables better exception handling if MS Office is not installed on the target machine or the installation has been damaged.
Late binding in a CLR application can be done with the help of the Type class. Here is an example using Outlook automation to add a new appointment item to the calendar.
using namespace System;
using namespace System::Reflection;
int main(array<System::String ^> ^args) {
try {
Type^ type = Type::GetTypeFromProgID("Outlook.Application");
Object^ olApp = Activator::CreateInstance(type);
array <Object^>^ params = gcnew array <Object^> (1);
params[0] = gcnew Object();
params[0] = 1; // olAppointmentItem
Object^ appointment = type->InvokeMember("CreateItem" ,
BindingFlags::InvokeMethod,
Type::DefaultBinder,
olApp, params);
DateTime^ dt = DateTime::Now;
dt = dt->AddHours(72);
params[0] = gcnew Object();
params[0] = dt;
type = appointment->GetType();
type->InvokeMember("Start",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
params[0] = gcnew Object();
params[0] = "appointment's subject line 2";
type->InvokeMember("Subject",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
params[0] = "body text of appointment ";
type->InvokeMember("Body",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
params[0] = gcnew Object();
params[0] = 60;
type->InvokeMember("Duration",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
params[0] = 20;
type->InvokeMember("ReminderMinutesBeforeStart",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
params[0] = gcnew Object();
params[0] = true;
type->InvokeMember("ReminderSet",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
type->InvokeMember("ReminderSet",
BindingFlags::SetProperty,
Type::DefaultBinder,
appointment, params);
type->InvokeMember("Save" ,
BindingFlags::InvokeMethod,
Type::DefaultBinder,
appointment, nullptr);
}
catch(Exception^ ex) {
Console::Write(ex->Message);
}
Console::WriteLine("ok. done");
Console::ReadLine();
return 0;
}