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")]