8

更新:簡単な例を機能させるために20時間以上費やした後、これは見た目ほど単純ではないことに気付きました。このような記事は「落とし穴」を明らかにします-そしてこれはWindows7の前に書かれました(マニフェストの扱いが異なります)。VSTOを介して.NETアセンブリをVBAに公開することに固執しています。


単純なCOM-Visible.NETアセンブリを作成し、ExcelVBAから呼び出そうとしています。.NETビルド中に「COM相互運用機能に登録」すると、VBAから正常に呼び出すことができます。

Sub VBA()    
    Dim obj As Object
    Set obj = actCtx.CreateObject("ComTest.Main")
    MsgBox obj.Test() '<-- Displays "Hello"
End Sub

ただし、登録なしでやりたいです。

ハンスからのアドバイスごとに更新:

[COM相互運用機能の登録]のチェックを外し、app.Manifestを次のように設定しました。

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly 
  manifestVersion="1.0" 
  xmlns="urn:schemas-microsoft-com:asm.v1" 
  xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
  xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <assemblyIdentity
    type="win32"
    version="1.0.0.0" 
    name="ComTest" 
    publicKeyToken="a36a7110110d7bd7" />

  <clrClass
      clsid="{975DC7E0-4596-4C42-9D0C-0601F86E3A1B}"
      progid="ComTest.Main"
      threadingModel="Both"
      name="ComTest.Main"
      runtimeVersion="v4.0.30319">
  </clrClass>

  <file name = "ComTest.dll"></file>   
</asmv1:assembly>

次のようなダミーの「client.manifest」を作成しました。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<asmv1:assembly 
  manifestVersion="1.0" 
  xmlns="urn:schemas-microsoft-com:asm.v1" 
  xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" 
  xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    manifestVersion="1.0" 
    xmlns="urn:schemas-microsoft-com:asm.v1" >
    <assemblyIdentity
        name="xxx"
        version="1.0.0.0" />
    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="ComTest" 
                version="1.0.0.0"
                publicKeyToken="a36a7110110d7bd7" />
        </dependentAssembly>            
    </dependency>
</asmv1:assembly>

オブジェクトの作成時にclient.manifestを使用するようにVBAを変更しました。

Sub VBA()    
    Dim actCtx As Object
    Set actCtx = CreateObject("Microsoft.Windows.ActCtx")
    actCtx.Manifest = "C:\Users\me\Desktop\COM Test\ComTest\ComTest\bin\Debug\client.manifest"

    Dim obj As Object
    Set obj = actCtx.CreateObject("ComTest.Main")  '<-- Fails here.
    MsgBox obj.Test()    
End Sub

CreateObjectで失敗し、役に立たないエラーが発生しますMethod 'CreateObject' of object 'IActCtx' failed

sxstraceは、client.manifestを読み取り、アクティベーションコンテキストを作成することを示しています。プロセスモニターは、ComTest.dllにアクセスし、レジストリでクラス975DC7E0-4596-4C42-9D0C-0601F86E3A1Bを検索することを示しています。

私は何が欠けていますか?


.NETコードは次のとおりです。

<ComVisible(True)>
<Guid("EB6AA207-ECC7-413B-9A9B-9D142FF2701D")>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface IMain
    Function Test() As String
End Interface

<ComVisible(True)>
<Guid("975DC7E0-4596-4C42-9D0C-0601F86E3A1B")>
<ProgId("ComTest.Main")>
<ClassInterface(ClassInterfaceType.None)>
<ComDefaultInterface(GetType(IMain))>
Public Class Main
    Implements IMain
    Public Function Test() As String Implements IMain.Test
        Return "HELLO"
    End Function
End Class

64ビットのWindows7を実行しています。

4

1 に答える 1

0

登録不要の COM を使用するには、サーバー (アセンブリ) とクライアントの両方が同じフォルダーにある必要があります。見る:

http://msdn.microsoft.com/en-us/magazine/cc188708.aspx

于 2013-03-19T15:25:20.743 に答える