从 C# 动态调用非托管 VB COM dll 时遇到问题?

发布于 2024-08-11 23:38:50 字数 2386 浏览 1 评论 0 原文

我在从 C# 调用非托管 VB COM dll 时遇到问题。这是使用 loadLibrary 和 GetProcAddress 的动态调用。

我可以使用 loadLibrary 成功加载 dll,但 GetProcAddress 始终返回 0。它没有记录任何错误消息,也没有记录任何内容。它只返回 0。

下面是示例代码

VB COM

VERSION 1.0 CLASS
BEGIN
    MultiUse = -1 
    Persistable = 0  
    DataBindingBehavior = 0  
    DataSourceBehavior  = 0 
    MTSTransactionMode  = 0  
END

Attribute VB_Name = "Sample"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True

Option Explicit

Private Attribute1 As String
Private Sub Class_Initialize()
    Attribute1 = "test"
End Sub

Public Sub TestSub()

End Sub

Public Function testFunction() As String
    testFunction = "default.html"
End Function

Public Function SetData(XML As String) As String
    SetData = Date + Time
End Function

c# 代码

static class UnManagedInvoker
{
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string dllToLoad);

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procedureName);

    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate string MethodToInvoke(string sdata);

    public static string InvokeUnmanagedDll(string dllPath, string methodName)
    {
        IntPtr DIedDll = LoadLibrary(dllPath);

        IntPtr AddressOfFunction = GetProcAddress(DIedDll, methodName);

        MethodToInvoke MI = (MethodToInvoke)Marshal.GetDelegateForFunctionPointer(AddressOfFunction, typeof(MethodToInvoke));

        string data = MI("ssdasda");

        FreeLibrary(DIedDll);
        return data;

    }
}

和调用代码

 string res = UnManagedInvoker.InvokeUnmanagedDll("xx.dll","SetData");

有人可以帮我吗..

更新:

如果组件已注册,我可以成功调用方法。 如果dll未注册,使用下面的代码

Type Med = Type.GetTypeFromCLSID(new Guid("089DD8B0-E12B-439B-B52C-007CA72C93D0"));
object MedObj = Activator.CreateInstance(Med);
object[] parameter = new object[1];
parameter[0] = "asdasd";
var ss = Med.InvokeMember("SetData", System.Reflection.BindingFlags.InvokeMethod, null, MedObj, parameter);

有没有办法?

I have a problem calling unmanaged VB COM dll from c#. This is dynamic invocation using loadLibrary and GetProcAddress.

I can successfully loaded the dll using loadLibrary , but the GetProcAddress always return 0. It wasnt log any error msg and nothing. it just returns 0.

below the sample code

VB COM

VERSION 1.0 CLASS
BEGIN
    MultiUse = -1 
    Persistable = 0  
    DataBindingBehavior = 0  
    DataSourceBehavior  = 0 
    MTSTransactionMode  = 0  
END

Attribute VB_Name = "Sample"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = True

Option Explicit

Private Attribute1 As String
Private Sub Class_Initialize()
    Attribute1 = "test"
End Sub

Public Sub TestSub()

End Sub

Public Function testFunction() As String
    testFunction = "default.html"
End Function

Public Function SetData(XML As String) As String
    SetData = Date + Time
End Function

c# code

static class UnManagedInvoker
{
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string dllToLoad);

    [DllImport("kernel32.dll")]
    private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procedureName);

    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate string MethodToInvoke(string sdata);

    public static string InvokeUnmanagedDll(string dllPath, string methodName)
    {
        IntPtr DIedDll = LoadLibrary(dllPath);

        IntPtr AddressOfFunction = GetProcAddress(DIedDll, methodName);

        MethodToInvoke MI = (MethodToInvoke)Marshal.GetDelegateForFunctionPointer(AddressOfFunction, typeof(MethodToInvoke));

        string data = MI("ssdasda");

        FreeLibrary(DIedDll);
        return data;

    }
}

And the calling code

 string res = UnManagedInvoker.InvokeUnmanagedDll("xx.dll","SetData");

Can someone help me out..

Update:

I can successfully call the methods if the component is registered. using the below code

Type Med = Type.GetTypeFromCLSID(new Guid("089DD8B0-E12B-439B-B52C-007CA72C93D0"));
object MedObj = Activator.CreateInstance(Med);
object[] parameter = new object[1];
parameter[0] = "asdasd";
var ss = Med.InvokeMember("SetData", System.Reflection.BindingFlags.InvokeMethod, null, MedObj, parameter);

is there a way if the dll not registered.?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

恍梦境° 2024-08-18 23:38:50

请注意,GetProcAddress 和 COM 对象的概念是完全不同的技术。 VB6 旨在构建 COM 对象,并且(据我所知)无法通过 GetProcAddress API 导出代码。

另外,根据设计,COM 对象需要在某处注册,但是可以将此信息放入清单文件而不是注册表中。这意味着您可以仅为您的应用程序注册 VB6 COM 类,而无需使用全局注册表。 (请注意,清单也可以嵌入到 .exe 中而不是作为文件。)

有关搜索“免注册 COM”的更多信息,这里有一个指向相应的 MSDN 文章

Note that the concept of GetProcAddress and COM objects are completely different technologies. VB6 is designed to build COM objects and (to my knowledge) is not able to export code via the GetProcAddress API.

Also by design COM objects need to be registered somewhere, it is however possible to put this information in a manifest file instead of the registry. This means you can register your VB6 COM classes only for your application without using the global registry. (Note that a manifest could also embedded into the .exe instead of being a file.)

For more information search for "Registration free COM", here's a link to the corresponding MSDN article.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文