Enhancements to the interop functionality

git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1678 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
RKrom 2012-03-02 16:06:34 +00:00
commit a5295fb5a4
6 changed files with 155 additions and 15 deletions

View file

@ -22,6 +22,8 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>3</LangVersion>
<NoStdLib>false</NoStdLib>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -30,8 +32,12 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
<LangVersion>3</LangVersion>
<NoStdLib>false</NoStdLib>
</PropertyGroup>
<ItemGroup>
<Reference Include="CustomMarshalers" />
<Reference Include="log4net">
<HintPath>..\Greenshot\Lib\log4net.dll</HintPath>
</Reference>
@ -40,6 +46,8 @@
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<Compile Include="RemedyInterop\RemedyExporter.cs" />
<Compile Include="RemedyInterop\RemedyInterop.cs" />
<Compile Include="IEInterop\IHTMLBodyElement.cs" />
<Compile Include="IEInterop\IHTMLCurrentStyle.cs" />
<Compile Include="IEInterop\IHTMLDocument.cs" />
@ -61,6 +69,8 @@
<Compile Include="IEInterop\IHTMLWindow2.cs" />
<Compile Include="IEInterop\IHTMLWindow3.cs" />
<Compile Include="IEInterop\IHTMLWindow4.cs" />
<Compile Include="Interop\Base.cs" />
<Compile Include="Interop\IDispatch.cs" />
<Compile Include="Interop\IOleWindow.cs" />
<Compile Include="Interop\IServiceProvider.cs" />
<Compile Include="IEInterop\IWebBrowser2.cs" />

View file

@ -29,7 +29,7 @@ namespace Greenshot.Interop {
/// <summary>
/// Wraps a late-bound COM server.
/// </summary>
public sealed class COMWrapper : RealProxy, IDisposable {
public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo {
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(COMWrapper));
private const int MK_E_UNAVAILABLE = -2147221021;
#region Private Data
@ -95,8 +95,8 @@ namespace Greenshot.Interop {
}
/// <summary>
/// Gets or creates a COM object and returns the transparent proxy
/// which intercepts all calls to the object
/// Gets or creates a COM object and returns the transparent proxy which intercepts all calls to the object
/// The ComProgId can be a normal ComProgId or a GUID prefixed with "clsid:"
/// </summary>
/// <param name="type">Interface which defines the method and properties to intercept</param>
/// <returns>Transparent proxy to the real proxy for the object</returns>
@ -116,7 +116,13 @@ namespace Greenshot.Interop {
}
object comObject = null;
Type comType = Type.GetTypeFromProgID(progID.Value, true);
Type comType = null;
if (progID.Value.StartsWith("clsid:")) {
Guid guid = new Guid(progID.Value.Substring(6));
comType = Type.GetTypeFromCLSID(guid, true);
} else {
comType = Type.GetTypeFromProgID(progID.Value, true);
}
try {
comObject = Marshal.GetActiveObject(progID.Value);
} catch (COMException comE) {
@ -294,14 +300,84 @@ namespace Greenshot.Interop {
#endregion
/// <summary>
/// Use this static method to cast a wrapped proxy to a new wrapper proxy of the supplied type.
/// In English, use this to cast you base "COM" interface to a specialized interface.
/// E.G. Outlook Item -> MailItem
/// </summary>
/// <typeparam name="T">the type you want to cast to</typeparam>
/// <param name="wrapperProxy">The wrapper interface, e.g. something you got back from calling GetItem</param>
/// <returns>A new wrapper proxy for the specified type</returns>
public static T Cast<T>(object wrapperProxy) {
if (wrapperProxy == null) {
return default(T);
}
Type newType = typeof(T);
COMWrapper oldWrapper = RemotingServices.GetRealProxy(wrapperProxy) as COMWrapper;
COMWrapper newWrapper = new COMWrapper(oldWrapper._COMObject, newType);
return (T)newWrapper.GetTransparentProxy();
if (oldWrapper == null) {
throw new ArgumentException("wrapper proxy was no COMWrapper");
}
if (oldWrapper._InterceptType.IsAssignableFrom(newType)) {
COMWrapper newWrapper = new COMWrapper(oldWrapper._COMObject, newType);
return (T)newWrapper.GetTransparentProxy();
}
throw new InvalidCastException(string.Format("{0} is not assignable from {1}", oldWrapper._InterceptType, newType));
}
/// <summary>
/// Returns the "com" type of the wrapperproxy, making it possible to perform reflection on it.
/// </summary>
/// <param name="wrapperProxy">wrapperProxy to get the type from</param>
/// <returns>Type</returns>
public static Type GetUnderlyingType(object wrapperProxy) {
Type returnType = null;
COMWrapper wrapper = RemotingServices.GetRealProxy(wrapperProxy) as COMWrapper;
if (wrapper != null) {
IDispatch dispatch = wrapper._COMObject as IDispatch;
if (dispatch != null) {
int result = dispatch.GetTypeInfo(0, 0, out returnType);
if (result != 0) {
LOG.DebugFormat("GetTypeInfo : 0x{0} ({1})", result.ToString("X"), result);
}
}
}
return returnType;
}
/// <summary>
/// Dump the Type-Information for the COM type to the log, this uses reflection
/// </summary>
/// <param name="wrapperProxy">wrapperProxy to inspect</param>
public static void DumpTypeInfo(object wrapperProxy) {
Type comType = COMWrapper.GetUnderlyingType(wrapperProxy);
if (comType == null) {
LOG.InfoFormat("Can't get Typeinformation");
return;
}
LOG.InfoFormat("Type information for COM object with name: {0}", comType.Name);
try {
foreach (MemberInfo memberInfo in comType.GetMembers()) {
LOG.InfoFormat("Member: {0};", memberInfo.ToString());
}
} catch (Exception memberException) {
LOG.Error(memberException);
}
try {
foreach (PropertyInfo propertyInfo in comType.GetProperties()) {
LOG.InfoFormat("Property: {0};", propertyInfo.ToString());
}
} catch (Exception propertyException) {
LOG.Error(propertyException);
}
try {
foreach (FieldInfo fieldInfo in comType.GetFields()) {
LOG.InfoFormat("Field: {0};", fieldInfo.ToString());
}
} catch (Exception fieldException) {
LOG.Error(fieldException);
}
LOG.InfoFormat("Type information end.");
}
/// <summary>
@ -497,5 +573,29 @@ namespace Greenshot.Interop {
return new ReturnMessage(returnValue, outArgs, outArgsCount, callMessage.LogicalCallContext, callMessage);
}
/// <summary>
/// Implementation for the interface IRemotingTypeInfo
/// This makes it possible to cast the COMWrapper
/// </summary>
/// <param name="toType">Type to cast to</param>
/// <param name="o">object to cast</param>
/// <returns></returns>
public bool CanCastTo(Type toType, object o) {
bool returnValue = _InterceptType.IsAssignableFrom(toType);
return returnValue;
}
/// <summary>
/// Implementation for the interface IRemotingTypeInfo
/// </summary>
public string TypeName {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
}

View file

@ -89,12 +89,15 @@ namespace Greenshot.Interop.Office {
if (currentItem != null) {
OlObjectClass currentItemClass = currentItem.Class;
if (OlObjectClass.olMail.Equals(currentItemClass)) {
MailItem mailItem = COMWrapper.Cast<MailItem>(currentItem);
MailItem mailItem = (MailItem)currentItem;
//MailItem mailItem = COMWrapper.Cast<MailItem>(currentItem);
LOG.DebugFormat("Mail sent: {0}", mailItem.Sent);
if (!mailItem.Sent) {
return true;
}
} else if (outlookVersion.Major >= 12 && allowMeetingAsTarget && OlObjectClass.olAppointment.Equals(currentItemClass)) {
AppointmentItem appointmentItem = COMWrapper.Cast<AppointmentItem>(currentItem);
//AppointmentItem appointmentItem = COMWrapper.Cast<AppointmentItem>(currentItem);
AppointmentItem appointmentItem = (AppointmentItem)currentItem;
if (string.IsNullOrEmpty(appointmentItem.Organizer) || (currentUser == null && currentUser.Equals(appointmentItem.Organizer))) {
return true;
} else {
@ -166,7 +169,8 @@ namespace Greenshot.Interop.Office {
MailItem mailItem = null;
try {
if (isMail) {
mailItem = COMWrapper.Cast<MailItem>(currentItem);
//mailItem = COMWrapper.Cast<MailItem>(currentItem);
mailItem = (MailItem)currentItem;
if (mailItem.Sent) {
LOG.WarnFormat("Item already sent, can't export to {0}", currentItem.Subject);
return false;
@ -271,7 +275,8 @@ namespace Greenshot.Interop.Office {
if (newItem == null) {
return;
}
MailItem newMail = COMWrapper.Cast<MailItem>(newItem);
//MailItem newMail = COMWrapper.Cast<MailItem>(newItem);
MailItem newMail = (MailItem)newItem;
newMail.Subject = subject;
newMail.BodyFormat = OlBodyFormat.olFormatHTML;
string bodyString = null;

View file

@ -36,6 +36,7 @@ namespace Greenshot.Interop.Office {
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.workbooks.aspx
public interface IWorkbooks : Common, Collection {
IWorkbook Add(object template);
// Use index + 1!!
IWorkbook this[object Index] { get; }
}
@ -55,10 +56,13 @@ namespace Greenshot.Interop.Office {
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.iworksheets_members.aspx
public interface IWorksheets : Common, Collection {
Object this[object Index] { get; }
// Use index + 1!!
IWorksheet this[object Index] { get; }
}
public interface IPictures : Common, Collection {
// Use index + 1!!
//IPicture this[object Index] { get; }
void Insert(string file);
}
}

View file

@ -23,11 +23,8 @@ using System.Collections;
namespace Greenshot.Interop.Office {
/// <summary>
/// Common properties that has appreared in almost all objects
/// If the "type" this[object index] { get; } is implemented, use index + 1!!! (starts at 1)
/// </summary>
public interface Common : IDisposable {
}
public interface Collection : Common, IEnumerable {
int Count { get; }
void Remove(int index);
@ -81,6 +78,7 @@ namespace Greenshot.Interop.Office {
}
// See: http://msdn.microsoft.com/en-us/library/ff861252.aspx
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.mailitem.aspx
public interface MailItem : Item, Common {
bool Sent { get; }
object MAPIOBJECT { get; }
@ -93,6 +91,7 @@ namespace Greenshot.Interop.Office {
}
// See: http://msdn.microsoft.com/en-us/library/ff869026.aspx
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.appointmentitem.aspx
public interface AppointmentItem : Item, Common {
string Organizer { get; set; }
string SendUsingAccount { get; }
@ -102,8 +101,28 @@ namespace Greenshot.Interop.Office {
OlReoccurenceState RecurrenceState { get; }
}
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.contactitem.aspx
public interface ContactItem : Item, Common {
bool HasPicture {
get;
}
void SaveBusinessCardImage(string path);
void AddPicture(string path);
void RemovePicture();
string FirstName {
get;
set;
}
string LastName {
get;
set;
}
}
public interface Attachments : Collection {
Attachment Add(object source, object type, object position, object displayName);
// Use index+1!!!!
Attachment this[object index] { get; }
}
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.attachment_members.aspx
@ -113,6 +132,7 @@ namespace Greenshot.Interop.Office {
OlAttachmentType Type { get; }
PropertyAccessor PropertyAccessor { get; }
object MAPIOBJECT { get; }
void SaveAsFile(string path);
}
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook.propertyaccessor_members.aspx

View file

@ -86,6 +86,7 @@ namespace Greenshot.Interop.Office {
// See: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.outlook._application.inspectors.aspx
public interface Inspectors : Common, Collection, IEnumerable {
// Use index + 1!!
Inspector this[Object Index] { get; }
}