1

ここでは非常によく似たトピックが議論されているようですが、これまでのところ誰もが私の問題を解決しています。

私はこの割り当てを持っています:

  1. コマンドで実行する.exe(32ビット)ユーティリティがあります
  2. このユーティリティは、64ビットプラットフォームのWindowsサービスで開始されます

これは64ビットプロセスで32ビットアプリを実行する可能性がないことを私は知っています。それ以外の場合は、COMIPC通信による回避策を見つけました。

だから私の解決策があります:

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();
      }      
    }
  }
}

コードはエラーや警告なしでビルドされます。次に、COMとして登録されたregAsm.exeによって。

今、私は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. 参照の追加ウィザードを使用してVSのプロジェクトにCOM参照を追加できません。エラーダイアログウィンドウで終了します:「'assemblyName'への参照を追加できませんでした。ActiveXタイプライブラリ'ライブラリパス'は.netアセンブリからエクスポートされたため、できません。参照として追加されます。代わりに、.netアセンブリへの参照を追加してください。」

私はたくさんの解決策を試しましたが、失敗しました...助けてくれてありがとう。

4

1 に答える 1

3

64ビットプロセスから32ビットを実行できないというのは事実ではありません。64ビットプロセスで32ビットDLLまたはCOM-Controlを使用することはできませんが、Process.Start任意のプロセスを開始するために使用できます。

あなたの場合、あなたが説明している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 に答える