diff --git a/GreenshotInterop/GreenshotInterop.csproj b/GreenshotInterop/GreenshotInterop.csproj index d29125004..775330ba1 100644 --- a/GreenshotInterop/GreenshotInterop.csproj +++ b/GreenshotInterop/GreenshotInterop.csproj @@ -22,6 +22,8 @@ DEBUG;TRACE prompt 4 + 3 + false pdbonly @@ -30,8 +32,12 @@ TRACE prompt 4 + Off + 3 + false + ..\Greenshot\Lib\log4net.dll @@ -40,6 +46,8 @@ + + @@ -61,6 +69,8 @@ + + diff --git a/GreenshotInterop/Interop/COMWrapper.cs b/GreenshotInterop/Interop/COMWrapper.cs index 1b9b83c49..9f03448f3 100644 --- a/GreenshotInterop/Interop/COMWrapper.cs +++ b/GreenshotInterop/Interop/COMWrapper.cs @@ -29,7 +29,7 @@ namespace Greenshot.Interop { /// /// Wraps a late-bound COM server. /// - 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 { } /// - /// 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:" /// /// Interface which defines the method and properties to intercept /// Transparent proxy to the real proxy for the object @@ -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 + /// + /// 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 + /// + /// the type you want to cast to + /// The wrapper interface, e.g. something you got back from calling GetItem + /// A new wrapper proxy for the specified type public static T Cast(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)); + } + + /// + /// Returns the "com" type of the wrapperproxy, making it possible to perform reflection on it. + /// + /// wrapperProxy to get the type from + /// Type + 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; + } + + /// + /// Dump the Type-Information for the COM type to the log, this uses reflection + /// + /// wrapperProxy to inspect + 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."); } /// @@ -497,5 +573,29 @@ namespace Greenshot.Interop { return new ReturnMessage(returnValue, outArgs, outArgsCount, callMessage.LogicalCallContext, callMessage); } + + /// + /// Implementation for the interface IRemotingTypeInfo + /// This makes it possible to cast the COMWrapper + /// + /// Type to cast to + /// object to cast + /// + public bool CanCastTo(Type toType, object o) { + bool returnValue = _InterceptType.IsAssignableFrom(toType); + return returnValue; + } + + /// + /// Implementation for the interface IRemotingTypeInfo + /// + public string TypeName { + get { + throw new NotImplementedException(); + } + set { + throw new NotImplementedException(); + } + } } } diff --git a/GreenshotInterop/OfficeExport/OutlookEmailExporter.cs b/GreenshotInterop/OfficeExport/OutlookEmailExporter.cs index 5292aa3c5..0741c7b9a 100644 --- a/GreenshotInterop/OfficeExport/OutlookEmailExporter.cs +++ b/GreenshotInterop/OfficeExport/OutlookEmailExporter.cs @@ -89,12 +89,15 @@ namespace Greenshot.Interop.Office { if (currentItem != null) { OlObjectClass currentItemClass = currentItem.Class; if (OlObjectClass.olMail.Equals(currentItemClass)) { - MailItem mailItem = COMWrapper.Cast(currentItem); + MailItem mailItem = (MailItem)currentItem; + //MailItem mailItem = COMWrapper.Cast(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(currentItem); + //AppointmentItem appointmentItem = COMWrapper.Cast(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(currentItem); + //mailItem = COMWrapper.Cast(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(newItem); + //MailItem newMail = COMWrapper.Cast(newItem); + MailItem newMail = (MailItem)newItem; newMail.Subject = subject; newMail.BodyFormat = OlBodyFormat.olFormatHTML; string bodyString = null; diff --git a/GreenshotInterop/OfficeInterop/ExcelInterop.cs b/GreenshotInterop/OfficeInterop/ExcelInterop.cs index 7d44e4756..391abdb49 100644 --- a/GreenshotInterop/OfficeInterop/ExcelInterop.cs +++ b/GreenshotInterop/OfficeInterop/ExcelInterop.cs @@ -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); } } diff --git a/GreenshotInterop/OfficeInterop/OfficeInterop.cs b/GreenshotInterop/OfficeInterop/OfficeInterop.cs index 4e379daa6..545832238 100644 --- a/GreenshotInterop/OfficeInterop/OfficeInterop.cs +++ b/GreenshotInterop/OfficeInterop/OfficeInterop.cs @@ -23,11 +23,8 @@ using System.Collections; namespace Greenshot.Interop.Office { /// - /// Common properties that has appreared in almost all objects + /// If the "type" this[object index] { get; } is implemented, use index + 1!!! (starts at 1) /// - 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 diff --git a/GreenshotInterop/OfficeInterop/OutlookInterop.cs b/GreenshotInterop/OfficeInterop/OutlookInterop.cs index b46667ba2..d7ba6bc47 100644 --- a/GreenshotInterop/OfficeInterop/OutlookInterop.cs +++ b/GreenshotInterop/OfficeInterop/OutlookInterop.cs @@ -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; } }