diff --git a/Greenshot-OCR-Plugin/OCRPlugin.cs b/Greenshot-OCR-Plugin/OCRPlugin.cs
index 33d69e817..83d6d6bbc 100644
--- a/Greenshot-OCR-Plugin/OCRPlugin.cs
+++ b/Greenshot-OCR-Plugin/OCRPlugin.cs
@@ -29,17 +29,43 @@ using GreenshotPlugin.Controls;
using GreenshotPlugin.Core;
using Greenshot.IniFile;
using Greenshot.Interop;
+using System.Diagnostics;
//using Microsoft.Win32;
namespace GreenshotOCR {
+ // Needed for the drop down, available languages for OCR
+ public enum ModiLanguage {
+ CHINESE_SIMPLIFIED = 2052,
+ CHINESE_TRADITIONAL = 1028,
+ CZECH = 5,
+ DANISH = 6,
+ DUTCH = 19,
+ ENGLISH = 9,
+ FINNISH = 11,
+ FRENCH = 12,
+ GERMAN = 7,
+ GREEK = 8,
+ HUNGARIAN = 14,
+ ITALIAN = 16,
+ JAPANESE = 17,
+ KOREAN = 18,
+ NORWEGIAN = 20,
+ POLISH = 21,
+ PORTUGUESE = 22,
+ RUSSIAN = 25,
+ SPANISH = 10,
+ SWEDISH = 29,
+ TURKISH = 31,
+ SYSDEFAULT = 2048
+ }
///
/// OCR Plugin Greenshot
///
public class OcrPlugin : IGreenshotPlugin {
private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(OcrPlugin));
private const string CONFIG_FILENAME = "ocr-config.properties";
-
+ private const string OCR_COMMAND = "greenshotocrcommand.exe";
private static IGreenshotHost host;
private static OCRConfiguration config;
private PluginAttribute myAttributes;
@@ -175,15 +201,13 @@ namespace GreenshotOCR {
string text = "";
try {
- using (ModiDocu modiDocument = COMWrapper.GetOrCreateInstance()) {
- if (modiDocument != null) {
- modiDocument.Create(filePath);
- modiDocument.OCR((ModiLanguage)Enum.Parse(typeof(ModiLanguage), config.Language), config.Orientimage, config.StraightenImage);
- IImage modiImage = modiDocument.Images[0];
- ILayout layout = modiImage.Layout;
- text = layout.Text;
- modiDocument.Close(false);
- }
+ ProcessStartInfo processStartInfo = new ProcessStartInfo(OCR_COMMAND, "\"" + filePath + "\" " + config.Language + " " + config.Orientimage + " " + config.StraightenImage);
+ processStartInfo.CreateNoWindow = true;
+ processStartInfo.RedirectStandardOutput = true;
+ Process process = Process.Start(processStartInfo);
+ process.WaitForExit(30*1000);
+ if (process.ExitCode == 0) {
+ text = process.StandardOutput.ReadToEnd();
}
} catch (Exception e) {
LOG.Error("Error while calling Microsoft Office Document Imaging (MODI) to OCR: ", e);
@@ -210,12 +234,10 @@ namespace GreenshotOCR {
private bool HasMODI() {
try {
- using (ModiDocu modiDocument = COMWrapper.GetOrCreateInstance()) {
- if (modiDocument != null) {
- modiDocument.Close(false);
- return true;
- }
- }
+ Process process = Process.Start(OCR_COMMAND, "-c");
+ process.WaitForExit();
+ int errorCode = process.ExitCode;
+ return errorCode == 0;
} catch(Exception e) {
LOG.DebugFormat("Error trying to initiate MODI: {0}", e.Message);
}
diff --git a/GreenshotOCRCommand/COMWrapper.cs b/GreenshotOCRCommand/COMWrapper.cs
new file mode 100644
index 000000000..e0bc63b17
--- /dev/null
+++ b/GreenshotOCRCommand/COMWrapper.cs
@@ -0,0 +1,648 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Proxies;
+
+namespace Greenshot.Interop {
+ ///
+ /// Wraps a late-bound COM server.
+ ///
+ public sealed class COMWrapper : RealProxy, IDisposable, IRemotingTypeInfo {
+ private const int MK_E_UNAVAILABLE = -2147221021;
+ private const int CO_E_CLASSSTRING = -2147221005;
+
+ #region Private Data
+
+ ///
+ /// Holds reference to the actual COM object which is wrapped by this proxy
+ ///
+ private object _COMObject;
+
+ ///
+ /// Type of the COM object, set on constructor after getting the COM reference
+ ///
+ private Type _COMType;
+
+ ///
+ /// The type of which method calls are intercepted and executed on the COM object.
+ ///
+ private Type _InterceptType;
+
+ #endregion
+ [DllImport("ole32.dll")]
+ static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);
+
+ #region Construction
+
+ ///
+ /// Gets a COM object and returns the transparent proxy which intercepts all calls to the object
+ ///
+ /// Interface which defines the method and properties to intercept
+ /// Transparent proxy to the real proxy for the object
+ /// The must be an interface decorated with the attribute.
+ public static T GetInstance() {
+ Type type = typeof(T);
+ if (null == type) {
+ throw new ArgumentNullException("type");
+ }
+ if (!type.IsInterface) {
+ throw new ArgumentException("The specified type must be an interface.", "type");
+ }
+
+ ComProgIdAttribute progIDAttribute = ComProgIdAttribute.GetAttribute(type);
+ if (null == progIDAttribute || null == progIDAttribute.Value || 0 == progIDAttribute.Value.Length) {
+ throw new ArgumentException("The specified type must define a ComProgId attribute.", "type");
+ }
+ string progId = progIDAttribute.Value;
+
+ // Convert from clsid to Prog ID, if needed
+ if (progId.StartsWith("clsid:")) {
+ Guid guid = new Guid(progId.Substring(6));
+ int result = ProgIDFromCLSID(ref guid, out progId);
+ if (result != 0) {
+ //LOG.WarnFormat("Error {0} getting progId {1}", result, progIDAttribute.Value);
+ } else {
+ //LOG.InfoFormat("Mapped {0} to progId {1}", progIDAttribute.Value, progId);
+ }
+ }
+
+ object comObject = null;
+ try {
+ comObject = Marshal.GetActiveObject(progId);
+ } catch (COMException comE) {
+ if (comE.ErrorCode == MK_E_UNAVAILABLE) {
+ //LOG.DebugFormat("No current instance of {0} object available.", progId);
+ } else if (comE.ErrorCode == CO_E_CLASSSTRING) {
+ //LOG.WarnFormat("Unknown progId {0}", progId);
+ } else {
+ //LOG.Warn("Error getting active object for " + progId, comE);
+ }
+ } catch (Exception e) {
+ //LOG.Warn("Error getting active object for " + progId, e);
+ }
+
+ if (comObject != null) {
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return (T)wrapper.GetTransparentProxy();
+ }
+ return default(T);
+ }
+
+ ///
+ /// 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
+ /// The must be an interface decorated with the attribute.
+ public static T GetOrCreateInstance() {
+ Type type = typeof(T);
+ if (null == type) {
+ throw new ArgumentNullException("type");
+ }
+ if (!type.IsInterface) {
+ throw new ArgumentException("The specified type must be an interface.", "type");
+ }
+
+ ComProgIdAttribute progIDAttribute = ComProgIdAttribute.GetAttribute(type);
+ if (null == progIDAttribute || null == progIDAttribute.Value || 0 == progIDAttribute.Value.Length) {
+ throw new ArgumentException("The specified type must define a ComProgId attribute.", "type");
+ }
+
+ object comObject = null;
+ Type comType = null;
+ string progId = progIDAttribute.Value;
+
+ // Convert from clsid to Prog ID, if needed
+ if (progId.StartsWith("clsid:")) {
+ Guid guid = new Guid(progId.Substring(6));
+ int result = ProgIDFromCLSID(ref guid, out progId);
+ if (result != 0) {
+ //LOG.WarnFormat("Error {0} getting progId {1}", result, progIDAttribute.Value);
+ } else {
+ //LOG.InfoFormat("Mapped {0} to progId {1}", progIDAttribute.Value, progId);
+ }
+ }
+
+ try {
+ comObject = Marshal.GetActiveObject(progId);
+ } catch (COMException comE) {
+ if (comE.ErrorCode == MK_E_UNAVAILABLE) {
+ //LOG.DebugFormat("No current instance of {0} object available.", progId);
+ } else if (comE.ErrorCode == CO_E_CLASSSTRING) {
+ //LOG.WarnFormat("Unknown progId {0} (application not installed)", progId);
+ return default(T);
+ } else {
+ //LOG.Warn("Error getting active object for " + progId, comE);
+ }
+ } catch (Exception e) {
+ //LOG.Warn("Error getting active object for " + progId, e);
+ }
+ // Did we get the current instance? If not, try to create a new
+ if (comObject == null) {
+ try {
+ comType = Type.GetTypeFromProgID(progId, true);
+ } catch (Exception ex) {
+ //LOG.Warn("Error type for " + progId, ex);
+ }
+ if (comType != null) {
+ try {
+ comObject = Activator.CreateInstance(comType);
+ if (comObject != null) {
+ //LOG.DebugFormat("Created new instance of {0} object.", progId);
+ }
+ } catch (Exception e) {
+ //LOG.Warn("Error creating object for " + progId, e);
+ }
+ }
+ }
+ if (comObject != null) {
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return (T)wrapper.GetTransparentProxy();
+ }
+ return default(T);
+ }
+
+ ///
+ /// Wrap an object and return the transparent proxy which intercepts all calls to the object
+ ///
+ /// An object to intercept
+ /// Interface which defines the method and properties to intercept
+ /// Transparent proxy to the real proxy for the object
+ private static object Wrap(object comObject, Type type) {
+ if (null == comObject) {
+ throw new ArgumentNullException("comObject");
+ }
+ if (null == type) {
+ throw new ArgumentNullException("type");
+ }
+
+ COMWrapper wrapper = new COMWrapper(comObject, type);
+ return wrapper.GetTransparentProxy();
+ }
+
+ ///
+ /// Constructor
+ ///
+ ///
+ /// The COM object to wrap.
+ ///
+ ///
+ /// The interface type to impersonate.
+ ///
+ private COMWrapper(object comObject, Type type)
+ : base(type) {
+ this._COMObject = comObject;
+ this._COMType = comObject.GetType();
+ this._InterceptType = type;
+ }
+
+ #endregion
+
+ #region Clean up
+
+ ///
+ /// If is not called, we need to make
+ /// sure that the COM object is still cleaned up.
+ ///
+ ~COMWrapper() {
+ //LOG.DebugFormat("Finalize {0}", this._InterceptType.ToString());
+ this.Dispose(false);
+ }
+
+ ///
+ /// Cleans up the COM object.
+ ///
+ public void Dispose() {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Release the COM reference
+ ///
+ ///
+ /// if this was called from the
+ /// interface.
+ ///
+ private void Dispose(bool disposing) {
+ if (null != this._COMObject) {
+ //LOG.DebugFormat("Disposing {0}", this._InterceptType.ToString());
+ if (Marshal.IsComObject(this._COMObject)) {
+ try {
+ while (Marshal.ReleaseComObject(this._COMObject) > 0)
+ ;
+ } catch (Exception ex) {
+ //LOG.WarnFormat("Problem releasing {0}", _COMType);
+ //LOG.Warn("Error: ", ex);
+ }
+ }
+
+ this._COMObject = null;
+ }
+ }
+
+ #endregion
+
+ #region Object methods
+
+ ///
+ /// Returns a string representing the wrapped object.
+ ///
+ ///
+ /// The full name of the intercepted type.
+ ///
+ public override string ToString() {
+ return this._InterceptType.FullName;
+ }
+
+ ///
+ /// Returns the hash code of the wrapped object.
+ ///
+ ///
+ /// The hash code of the wrapped object.
+ ///
+ public override int GetHashCode() {
+ return this._COMObject.GetHashCode();
+ }
+
+ ///
+ /// Compares this object to another.
+ ///
+ ///
+ /// The value to compare to.
+ ///
+ ///
+ /// if the objects are equal.
+ ///
+ public override bool Equals(object value) {
+ if (null != value && RemotingServices.IsTransparentProxy(value)) {
+ COMWrapper wrapper = RemotingServices.GetRealProxy(value) as COMWrapper;
+ if (null != wrapper) {
+ return this._COMObject == wrapper._COMObject;
+ }
+ }
+
+ return base.Equals(value);
+ }
+
+ ///
+ /// Returns the base type for a reference type.
+ ///
+ ///
+ /// The reference type.
+ ///
+ ///
+ /// The base value type.
+ ///
+ ///
+ /// is .
+ ///
+ private static Type GetByValType(Type byRefType) {
+ if (null == byRefType) {
+ throw new ArgumentNullException("byRefType");
+ }
+
+ if (byRefType.IsByRef) {
+ string name = byRefType.FullName;
+ name = name.Substring(0, name.Length - 1);
+ byRefType = byRefType.Assembly.GetType(name, true);
+ }
+
+ return byRefType;
+ }
+
+ #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;
+ 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 GetUnderlyingTypeForWrapper(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;
+ }
+
+ ///
+ /// Return the Type of a IDispatch
+ ///
+ /// IDispatch to get the type object for
+ /// Type of the IDispatch
+ public static Type GetUnderlyingType(IDispatch dispatch) {
+ Type returnType = null;
+ 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 Type to the log, this uses reflection
+ ///
+ /// Type to inspect
+ public static void DumpTypeInfo(Type type) {
+ //LOG.InfoFormat("Type information for Type with name: {0}", type.Name);
+ try {
+ foreach (MemberInfo memberInfo in type.GetMembers()) {
+ //LOG.InfoFormat("Member: {0};", memberInfo.ToString());
+ }
+ } catch (Exception memberException) {
+ //LOG.Error(memberException);
+ }
+ try {
+ foreach (PropertyInfo propertyInfo in type.GetProperties()) {
+ //LOG.InfoFormat("Property: {0};", propertyInfo.ToString());
+ }
+ } catch (Exception propertyException) {
+ //LOG.Error(propertyException);
+ }
+ try {
+ foreach (FieldInfo fieldInfo in type.GetFields()) {
+ //LOG.InfoFormat("Field: {0};", fieldInfo.ToString());
+ }
+ } catch (Exception fieldException) {
+ //LOG.Error(fieldException);
+ }
+ //LOG.InfoFormat("Type information end.");
+ }
+
+ ///
+ /// Intercept method calls
+ ///
+ ///
+ /// Contains information about the method being called
+ ///
+ ///
+ /// A .
+ ///
+ public override IMessage Invoke(IMessage myMessage) {
+ IMethodCallMessage callMessage = myMessage as IMethodCallMessage;
+ if (null == callMessage) {
+ //LOG.DebugFormat("Message type not implemented: {0}", myMessage.GetType().ToString());
+ return null;
+ }
+
+ MethodInfo method = callMessage.MethodBase as MethodInfo;
+ if (null == method) {
+ //LOG.DebugFormat("Unrecognized Invoke call: {0}", callMessage.MethodBase.ToString());
+ return null;
+ }
+
+ object returnValue = null;
+ object[] outArgs = null;
+ int outArgsCount = 0;
+
+ string methodName = method.Name;
+ Type returnType = method.ReturnType;
+ BindingFlags flags = BindingFlags.InvokeMethod;
+ int argCount = callMessage.ArgCount;
+
+ object invokeObject;
+ Type invokeType;
+ Type byValType;
+
+ object[] args;
+ object arg;
+ COMWrapper[] originalArgs;
+ COMWrapper wrapper;
+
+ ParameterModifier[] argModifiers = null;
+ ParameterInfo[] parameters = null;
+ ParameterInfo parameter;
+
+ if ("Dispose" == methodName && 0 == argCount && typeof(void) == returnType) {
+ this.Dispose();
+ } else if ("ToString" == methodName && 0 == argCount && typeof(string) == returnType) {
+ returnValue = this.ToString();
+ } else if ("GetType" == methodName && 0 == argCount && typeof(System.Type) == returnType) {
+ returnValue = this._InterceptType;
+ } else if ("GetHashCode" == methodName && 0 == argCount && typeof(int) == returnType) {
+ returnValue = this.GetHashCode();
+ } else if ("Equals" == methodName && 1 == argCount && typeof(bool) == returnType) {
+ returnValue = this.Equals(callMessage.Args[0]);
+ } else if (1 == argCount && typeof(void) == returnType && (methodName.StartsWith("add_") || methodName.StartsWith("remove_"))) {
+ bool removeHandler = methodName.StartsWith("remove_");
+ methodName = methodName.Substring(removeHandler ? 7 : 4);
+
+ Delegate handler = callMessage.InArgs[0] as Delegate;
+ if (null == handler) {
+ return new ReturnMessage(new ArgumentNullException("handler"), callMessage);
+ }
+ } else {
+ invokeObject = this._COMObject;
+ invokeType = this._COMType;
+
+ if (methodName.StartsWith("get_")) {
+ // Property Get
+ methodName = methodName.Substring(4);
+ flags = BindingFlags.GetProperty;
+ args = callMessage.InArgs;
+ } else if (methodName.StartsWith("set_")) {
+ // Property Set
+ methodName = methodName.Substring(4);
+ flags = BindingFlags.SetProperty;
+ args = callMessage.InArgs;
+ } else {
+ args = callMessage.Args;
+ if (null != args && 0 != args.Length) {
+ // Modifiers for ref / out parameters
+ argModifiers = new ParameterModifier[1];
+ argModifiers[0] = new ParameterModifier(args.Length);
+
+ parameters = method.GetParameters();
+ for (int i = 0; i < parameters.Length; i++) {
+ parameter = parameters[i];
+ if (parameter.IsOut || parameter.ParameterType.IsByRef) {
+ argModifiers[0][i] = true;
+ outArgsCount++;
+ }
+ }
+
+ if (0 == outArgsCount) {
+ argModifiers = null;
+ }
+ }
+ }
+
+ // Un-wrap wrapped COM objects before passing to the method
+ if (null == args || 0 == args.Length) {
+ originalArgs = null;
+ } else {
+ originalArgs = new COMWrapper[args.Length];
+ for (int i = 0; i < args.Length; i++) {
+ if (null != args[i] && RemotingServices.IsTransparentProxy(args[i])) {
+ wrapper = RemotingServices.GetRealProxy(args[i]) as COMWrapper;
+ if (null != wrapper) {
+ originalArgs[i] = wrapper;
+ args[i] = wrapper._COMObject;
+ }
+ } else if (0 != outArgsCount && argModifiers[0][i]) {
+ byValType = GetByValType(parameters[i].ParameterType);
+ if (byValType.IsInterface) {
+ // If we're passing a COM object by reference, and
+ // the parameter is null, we need to pass a
+ // DispatchWrapper to avoid a type mismatch exception.
+ if (null == args[i]) {
+ args[i] = new DispatchWrapper(null);
+ }
+ } else if (typeof(Decimal) == byValType) {
+ // If we're passing a decimal value by reference,
+ // we need to pass a CurrencyWrapper to avoid a
+ // type mismatch exception.
+ // http://support.microsoft.com/?kbid=837378
+ args[i] = new CurrencyWrapper(args[i]);
+ }
+ }
+ }
+ }
+
+ try {
+ returnValue = invokeType.InvokeMember(methodName, flags, null, invokeObject, args, argModifiers, null, null);
+ } catch (Exception ex) {
+ return new ReturnMessage(ex, callMessage);
+ }
+
+ // Handle enum and interface return types
+ if (null != returnValue) {
+ if (returnType.IsInterface) {
+ // Wrap the returned value in an intercepting COM wrapper
+ if (Marshal.IsComObject(returnValue)) {
+ returnValue = COMWrapper.Wrap(returnValue, returnType);
+ }
+ } else if (returnType.IsEnum) {
+ // Convert to proper Enum type
+ returnValue = Enum.Parse(returnType, returnValue.ToString());
+ }
+ }
+
+ // Handle out args
+ if (0 != outArgsCount) {
+ outArgs = new object[args.Length];
+ for (int i = 0; i < parameters.Length; i++) {
+ if (!argModifiers[0][i]) {
+ continue;
+ }
+
+ arg = args[i];
+ if (null == arg) {
+ continue;
+ }
+
+ parameter = parameters[i];
+ wrapper = null;
+
+ byValType = GetByValType(parameter.ParameterType);
+ if (typeof(Decimal) == byValType) {
+ if (arg is CurrencyWrapper) {
+ arg = ((CurrencyWrapper)arg).WrappedObject;
+ }
+ } else if (byValType.IsEnum) {
+ arg = Enum.Parse(byValType, arg.ToString());
+ } else if (byValType.IsInterface) {
+ if (Marshal.IsComObject(arg)) {
+ wrapper = originalArgs[i];
+ if (null != wrapper && wrapper._COMObject != arg) {
+ wrapper.Dispose();
+ wrapper = null;
+ }
+
+ if (null == wrapper) {
+ wrapper = new COMWrapper(arg, byValType);
+ }
+ arg = wrapper.GetTransparentProxy();
+ }
+ }
+ outArgs[i] = arg;
+ }
+ }
+ }
+
+ 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/GreenshotOCRCommand/ComProgIdAttribute.cs b/GreenshotOCRCommand/ComProgIdAttribute.cs
new file mode 100644
index 000000000..4c938b063
--- /dev/null
+++ b/GreenshotOCRCommand/ComProgIdAttribute.cs
@@ -0,0 +1,83 @@
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+using System;
+
+namespace Greenshot.Interop {
+ ///
+ /// An attribute to specifiy the ProgID of the COM class to create. (As suggested by Kristen Wegner)
+ ///
+ [AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
+ public sealed class ComProgIdAttribute : Attribute {
+ private string _value;
+
+ ///
+ /// Extracts the attribute from the specified type.
+ ///
+ ///
+ /// The interface type.
+ ///
+ ///
+ /// The .
+ ///
+ ///
+ /// is .
+ ///
+ public static ComProgIdAttribute GetAttribute(Type interfaceType) {
+ if (null == interfaceType) {
+ throw new ArgumentNullException("interfaceType");
+ }
+
+ Type attributeType = typeof(ComProgIdAttribute);
+ object[] attributes = interfaceType.GetCustomAttributes(attributeType, false);
+
+ if (null == attributes || 0 == attributes.Length) {
+ Type[] interfaces = interfaceType.GetInterfaces();
+ for (int i = 0; i < interfaces.Length; i++) {
+ interfaceType = interfaces[i];
+ attributes = interfaceType.GetCustomAttributes(attributeType, false);
+ if (null != attributes && 0 != attributes.Length) {
+ break;
+ }
+ }
+ }
+
+ if (null == attributes || 0 == attributes.Length) {
+ return null;
+ }
+ return (ComProgIdAttribute)attributes[0];
+ }
+
+ /// Constructor
+ /// The COM ProgID.
+ public ComProgIdAttribute(string value) {
+ _value = value;
+ }
+
+ ///
+ /// Returns the COM ProgID
+ ///
+ public string Value {
+ get {
+ return _value;
+ }
+ }
+ }
+}
diff --git a/GreenshotOCRCommand/GreenshotOCRCommand.csproj b/GreenshotOCRCommand/GreenshotOCRCommand.csproj
new file mode 100644
index 000000000..846614509
--- /dev/null
+++ b/GreenshotOCRCommand/GreenshotOCRCommand.csproj
@@ -0,0 +1,59 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}
+ WinExe
+ Properties
+ GreenshotOCRCommand
+ GreenshotOCRCommand
+ v2.0
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ Off
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ GreenshotOCRCommand.Program
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GreenshotOCRCommand/IDispatch.cs b/GreenshotOCRCommand/IDispatch.cs
new file mode 100644
index 000000000..a9f53a6c0
--- /dev/null
+++ b/GreenshotOCRCommand/IDispatch.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.CustomMarshalers;
+
+namespace Greenshot.Interop {
+ [ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IDispatch {
+ void Reserved();
+ [PreserveSig]
+ int GetTypeInfo(uint nInfo, int lcid, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))] out Type typeInfo);
+ }
+}
diff --git a/Greenshot-OCR-Plugin/ModiInterop.cs b/GreenshotOCRCommand/ModiInterop.cs
similarity index 100%
rename from Greenshot-OCR-Plugin/ModiInterop.cs
rename to GreenshotOCRCommand/ModiInterop.cs
diff --git a/GreenshotOCRCommand/Program.cs b/GreenshotOCRCommand/Program.cs
new file mode 100644
index 000000000..d3ab67bc1
--- /dev/null
+++ b/GreenshotOCRCommand/Program.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using GreenshotOCR;
+using Greenshot.Interop;
+using System.IO;
+
+namespace GreenshotOCRCommand {
+ public class Program {
+ private const string USAGE = "<-c> | [language] [orientimage] [straightenImage]";
+ public static int Main(string[] args) {
+ // to test
+ //args = new string[] { @"C:\localdata\test.bmp"};
+ if (args.Length == 0) {
+ Console.WriteLine(USAGE);
+ return -1;
+ }
+ string filename = args[0];
+ ModiLanguage language = ModiLanguage.ENGLISH;
+ if (args.Length >= 2) {
+ language = (ModiLanguage)Enum.Parse(typeof(ModiLanguage), args[1]);
+ }
+ bool orientimage = true;
+ if (args.Length >= 3) {
+ orientimage = bool.Parse(args[2]);
+ }
+ bool straightenImage = true;
+ if (args.Length >= 4) {
+ straightenImage = bool.Parse(args[3]);
+ }
+ try {
+ if (File.Exists(filename) || "-c".Equals(filename)) {
+ using (ModiDocu modiDocument = COMWrapper.GetOrCreateInstance()) {
+ if (modiDocument == null) {
+ Console.WriteLine("MODI not installed");
+ return -2;
+ }
+ if ("-c".Equals(filename)) {
+ return 0;
+ }
+ modiDocument.Create(args[1]);
+ modiDocument.OCR(language, orientimage, straightenImage);
+ IImage modiImage = modiDocument.Images[0];
+ ILayout layout = modiImage.Layout;
+ Console.WriteLine(layout.Text);
+ modiDocument.Close(false);
+ return 0;
+ }
+ }
+ } catch (Exception ex) {
+ Console.WriteLine(ex.Message);
+ }
+ return -1;
+ }
+ }
+}
diff --git a/GreenshotOCRCommand/Properties/AssemblyInfo.cs b/GreenshotOCRCommand/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..ea3dbece7
--- /dev/null
+++ b/GreenshotOCRCommand/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("GreenshotOCRCommand")]
+[assembly: AssemblyDescription("A small executable to OCR a bitmap")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Greenshot")]
+[assembly: AssemblyProduct("GreenshotOCRCommand")]
+[assembly: AssemblyCopyright("Greenshot")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("d7668e7e-3018-4d27-9aa0-21b1afade1b8")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]