1

我看到这里已经讨论了非常相似的主题,但到目前为止有人已经解决了我的问题。

我有这个任务:

  1. 我有 .exe(32 位)实用程序可以使用命令运行
  2. 此实用程序将在 64 位平台上使用 windows 服务启动

我知道这不可能在 64 位进程上运行 32 位应用程序。否则,我通过 COM IPC 通信找到了解决方法。

所以有我的解决方案:

COM库的接口声明:

namespace Win32ConsoleAppWrapper
{
  [GuidAttribute("5a6ab402-aa68-4d58-875c-fe26dea9c1cd"), ComVisible(true),
  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  interface IKDUCompessor
  {
    event ProcessStarted processStarted;
    void RunKDUCompress(string comm);
  }
}

实现接口的类:

namespace Win32ConsoleAppWrapper
{

  [GuidAttribute("a1f4eb1a-b276-4272-90e0-0eb26e4273e0"), ComVisible(true),
  ClassInterface(ClassInterfaceType.None)]
  public class KDUCompessor : IKDUCompessor
  {
    public static readonly string KDU_COMPRESS_LIBRARY_NAME = "kdu_compress.exe";

    public event ProcessStarted processStarted;

    public KDUCompessor() { }

    public void RunKDUCompress(string comm)
    {
      if(!File.Exists(KDU_COMPRESS_LIBRARY_NAME))
      {
        throw new FileNotFoundException(String.Format("File {0} could not be found. Please check the bin directory.", KDU_COMPRESS_LIBRARY_NAME));
      }

      ProcessStartInfo info = new ProcessStartInfo();
      info.CreateNoWindow = false;
      info.UseShellExecute = true;
      info.FileName = String.Concat(KDU_COMPRESS_LIBRARY_NAME);
      info.WindowStyle = ProcessWindowStyle.Hidden;
      info.Arguments = comm;

      // Start the process with the info we specified.
      // Call WaitForExit and then the using statement will close.
      using(Process exeProcess = Process.Start(info))
      {
        exeProcess.WaitForExit();
      }      
    }
  }
}

代码构建没有错误,也没有警告。然后通过regAsm.exe注册为COM。

现在我正在尝试访问 COM 并调用该方法:

public class MyClass
{

#region COM Interface and class declaration

[
  ComImport(),
  Guid("5a6ab402-aa68-4d58-875c-fe26dea9c1cd"),
  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
public interface IKDUCompessor
{
  [PreserveSig]
  void RunKDUCompress(string comm);   

}

[
  ComImport,
  Guid("a1f4eb1a-b276-4272-90e0-0eb26e4273e0")
]
public class KDUCompessor { }

#endregion

protected void CallCOM(_command)
{
  if (IsCommandValid(_command))
  {
    // instance
    Type type = Type.GetTypeFromCLSID(new Guid("a1f4eb1a-b276-4272-90e0-0eb26e4273e0"));
    object o = Activator.CreateInstance(type);
    IKDUCompessor t = (IKDUCompessor)o;
    t.RunKDUCompress(_command);

  }
}

我遇到了一个问题:

  1. 执行以异常结束:未处理 System.Runtime.InteropServices.COMException,未注册类 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)),当 regasm.exe 注册程序集时没有错误
  2. 我无法通过添加引用向导将 COM 引用添加到 VS 中的项目,它以错误对话框窗口结束:“无法添加对‘assemblyName’的引用。ActiveX 类型库‘libary path’是从 .net 程序集中导出的,不能被添加为引用。改为添加对 .net 程序集的引用。”

我尝试了很多解决方案,但没有成功……感谢您的帮助。

4

1 回答 1

3

不能从 64 位进程运行32 位是不正确的。您不能在 64 位进程中使用Process.Start32 位 DLL 或 COM-Control,但您可以使用它来启动您想要的任何进程。

在您的情况下,听起来您甚至不必使用您描述的 COM 控件(这甚至会导致更多问题)。只需在您的服务中执行以下操作(无论是 32 位还是 64 位),就可以了:

if(!File.Exists(KDU_COMPRESS_LIBRARY_NAME))
{
    throw new FileNotFoundException(String.Format("File {0} could not be found. Please check the bin directory.", KDU_COMPRESS_LIBRARY_NAME));
}

ProcessStartInfo info = new ProcessStartInfo();
info.CreateNoWindow = false;
info.UseShellExecute = true;
info.FileName = String.Concat(KDU_COMPRESS_LIBRARY_NAME);
info.WindowStyle = ProcessWindowStyle.Hidden;
info.Arguments = comm;

// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using(Process exeProcess = Process.Start(info))
{
    exeProcess.WaitForExit();
}    
于 2012-12-03T12:23:12.940 回答