为什么我的 C# DLL 中的方法丢失了?
Why are the methods from my C# DLL missing?
我正在尝试学习如何编写 C# DLL 并从 MFC 应用程序调用它。
这里是一些 DLL 代码:
using System;
using System.IO;
using System.Xml.Serialization;
namespace MSATools
{
public class MSAToolsLibrary
{
public MSAToolsLibrary()
{
_PublisherData = new PublisherData();
}
[XmlIgnore]
private string _strPathXML;
public void SetPathXML(String strPathXML)
{
_strPathXML = strPathXML;
}
[XmlIgnore]
private PublisherData _PublisherData;
public void SavePublisherData()
{
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamWriter writer = new StreamWriter(_strPathXML))
{
x.Serialize(writer, _PublisherData);
}
}
public void ReadPublisherData()
{
_PublisherData.Publishers.Clear(); // Reset
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamReader reader = new StreamReader(_strPathXML))
{
_PublisherData = (PublisherData)x.Deserialize(reader);
}
}
public void AddPublisherData()
{
_PublisherData.AddStudent("Andrew", "Andrew notes");
_PublisherData.AddStudent("Rachel", "Rachel notes");
_PublisherData.AddStudent("Joshua", "Joshua notes");
_PublisherData.AddStudent("Finlay", "Finlay notes");
}
}
}
我勾选了将其注册为互操作的选项,并且我有一个 TLB 文件。
然后我进入一个新的 MFC 项目并按照教程从 TLB 文件创建 class。但它所创建的只是:
// Machine generated IDispatch wrapper class(es) created with Add Class from Typelib Wizard
#import "D:\My Programs\2017\MSATools\MSATools\bin\Release\MSATools.tlb" no_namespace
// CMSAToolsLibrary wrapper class
class CMSAToolsLibrary : public COleDispatchDriver
{
public:
CMSAToolsLibrary() {} // Calls COleDispatchDriver default constructor
CMSAToolsLibrary(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
CMSAToolsLibrary(const CMSAToolsLibrary& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}
// Attributes
public:
// Operations
public:
// _MSAToolsLibrary methods
public:
// _MSAToolsLibrary properties
public:
};
我显然在这里遗漏了一些东西。我期待看到我的 public 方法:
SetPathXML
ReadPublisherData
SavePublisherData
AddPublisherData
我错过了什么?
这是 classes 在 IDE(MSATools DLL 项目)中的样子:
更新
我试图向我的 C# 库添加一个接口,我一定是做错了什么:
using System;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.InteropServices;
namespace MSATools
{
[Guid("xxxxxx")]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface iInterface
{
void SetPathXML(String strPathXML);
void SavePublisherData();
void ReadPublisherData();
void AddPublisherData();
}
[Guid("xxxx")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class MSAToolsLibrary
{
#region iInterface Members
public MSAToolsLibrary()
{
_PublisherData = new PublisherData();
}
[XmlIgnore]
private string _strPathXML;
public void SetPathXML(String strPathXML)
{
_strPathXML = strPathXML;
}
[XmlIgnore]
private PublisherData _PublisherData;
public void SavePublisherData()
{
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamWriter writer = new StreamWriter(_strPathXML))
{
x.Serialize(writer, _PublisherData);
}
}
public void ReadPublisherData()
{
_PublisherData.Publishers.Clear(); // Reset
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamReader reader = new StreamReader(_strPathXML))
{
_PublisherData = (PublisherData)x.Deserialize(reader);
}
}
public void AddPublisherData()
{
_PublisherData.AddStudent("Andrew", "Andrew notes");
_PublisherData.AddStudent("Rachel", "Rachel notes");
_PublisherData.AddStudent("Joshua", "Joshua notes");
_PublisherData.AddStudent("Finlay", "Finlay notes");
}
#endregion
}
}
编译成功。但是当我转到 Visual C++ MFC 并从 TypeLib 添加一个 class 并选择此 TLB 文件时 列表中没有任何内容 显示可用。
困惑。
更新 2
我决定尝试创建自己的 class 作为包装器:
#pragma once
#import "D:\My Programs\2017\MSATools\MSATools\bin\Release\MSATools.tlb" raw_interfaces_only named_guids
class CMSATools
{
public:
CMSATools();
~CMSATools();
void SetPathXML(CString strPath);
void Test();
};
并且:
#include "stdafx.h"
#include "MSATools.h"
CMSATools::CMSATools()
{
}
CMSATools::~CMSATools()
{
}
void CMSATools::SetPathXML(CString strPath)
{
MSATools::iInterfacePtr pInterface = NULL;
HRESULT hr;
hr = pInterface.CreateInstance(__uuidof(MSATools::MSAToolsLibrary));
if (SUCCEEDED(hr))
{
CComBSTR bstrText = strPath.AllocSysString();
pInterface->SetPathXML(bstrText);
}
}
void CMSATools::Test()
{
MSATools::iInterfacePtr pInterface = NULL;
HRESULT hr;
hr = pInterface.CreateInstance(__uuidof(MSATools::MSAToolsLibrary));
if (SUCCEEDED(hr))
{
CComBSTR bstrText(_T("d:\TestStudents.XML"));
pInterface->SetPathXML(bstrText);
pInterface->AddPublisherData();
pInterface->SavePublisherData();
}
}
它编译了,我可以看到 VisualAssist 的方法:
但是由于某些原因,hr
没有通过 SUCCEEDED
调用。
更新 3
如果我将 DLL 重建为 x64 并将 MFC EXE 重建为 x64,则会出现异常:
更新 4
我必须添加到我的 MFC 应用程序中 InitInstance
:
::Coinitialize(true);
在ExitInstance
中:
::CoUnitialize();
然后异常消失了。
试试这个修改,用VS生成一个新的guid,因为我不记得它是否自动写入另一个文件。
using System.Runtime.InteropServices;
...
[ComVisibleAttribute(true)]
[Guid("xxx-xxx-xxx-xxx-xxx")]
[ProgId("MSAToolsLibraryClass")]
public class MSAToolsLibrary
{
...
编辑
确保您的 Assembly.cs 有这样一行:
[程序集:Guid("xxx-xxx-xxx-xxx-xxx")]
我正在尝试学习如何编写 C# DLL 并从 MFC 应用程序调用它。
这里是一些 DLL 代码:
using System;
using System.IO;
using System.Xml.Serialization;
namespace MSATools
{
public class MSAToolsLibrary
{
public MSAToolsLibrary()
{
_PublisherData = new PublisherData();
}
[XmlIgnore]
private string _strPathXML;
public void SetPathXML(String strPathXML)
{
_strPathXML = strPathXML;
}
[XmlIgnore]
private PublisherData _PublisherData;
public void SavePublisherData()
{
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamWriter writer = new StreamWriter(_strPathXML))
{
x.Serialize(writer, _PublisherData);
}
}
public void ReadPublisherData()
{
_PublisherData.Publishers.Clear(); // Reset
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamReader reader = new StreamReader(_strPathXML))
{
_PublisherData = (PublisherData)x.Deserialize(reader);
}
}
public void AddPublisherData()
{
_PublisherData.AddStudent("Andrew", "Andrew notes");
_PublisherData.AddStudent("Rachel", "Rachel notes");
_PublisherData.AddStudent("Joshua", "Joshua notes");
_PublisherData.AddStudent("Finlay", "Finlay notes");
}
}
}
我勾选了将其注册为互操作的选项,并且我有一个 TLB 文件。
然后我进入一个新的 MFC 项目并按照教程从 TLB 文件创建 class。但它所创建的只是:
// Machine generated IDispatch wrapper class(es) created with Add Class from Typelib Wizard
#import "D:\My Programs\2017\MSATools\MSATools\bin\Release\MSATools.tlb" no_namespace
// CMSAToolsLibrary wrapper class
class CMSAToolsLibrary : public COleDispatchDriver
{
public:
CMSAToolsLibrary() {} // Calls COleDispatchDriver default constructor
CMSAToolsLibrary(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
CMSAToolsLibrary(const CMSAToolsLibrary& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}
// Attributes
public:
// Operations
public:
// _MSAToolsLibrary methods
public:
// _MSAToolsLibrary properties
public:
};
我显然在这里遗漏了一些东西。我期待看到我的 public 方法:
SetPathXML
ReadPublisherData
SavePublisherData
AddPublisherData
我错过了什么?
这是 classes 在 IDE(MSATools DLL 项目)中的样子:
更新
我试图向我的 C# 库添加一个接口,我一定是做错了什么:
using System;
using System.IO;
using System.Xml.Serialization;
using System.Runtime.InteropServices;
namespace MSATools
{
[Guid("xxxxxx")]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface iInterface
{
void SetPathXML(String strPathXML);
void SavePublisherData();
void ReadPublisherData();
void AddPublisherData();
}
[Guid("xxxx")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class MSAToolsLibrary
{
#region iInterface Members
public MSAToolsLibrary()
{
_PublisherData = new PublisherData();
}
[XmlIgnore]
private string _strPathXML;
public void SetPathXML(String strPathXML)
{
_strPathXML = strPathXML;
}
[XmlIgnore]
private PublisherData _PublisherData;
public void SavePublisherData()
{
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamWriter writer = new StreamWriter(_strPathXML))
{
x.Serialize(writer, _PublisherData);
}
}
public void ReadPublisherData()
{
_PublisherData.Publishers.Clear(); // Reset
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamReader reader = new StreamReader(_strPathXML))
{
_PublisherData = (PublisherData)x.Deserialize(reader);
}
}
public void AddPublisherData()
{
_PublisherData.AddStudent("Andrew", "Andrew notes");
_PublisherData.AddStudent("Rachel", "Rachel notes");
_PublisherData.AddStudent("Joshua", "Joshua notes");
_PublisherData.AddStudent("Finlay", "Finlay notes");
}
#endregion
}
}
编译成功。但是当我转到 Visual C++ MFC 并从 TypeLib 添加一个 class 并选择此 TLB 文件时 列表中没有任何内容 显示可用。
困惑。
更新 2
我决定尝试创建自己的 class 作为包装器:
#pragma once
#import "D:\My Programs\2017\MSATools\MSATools\bin\Release\MSATools.tlb" raw_interfaces_only named_guids
class CMSATools
{
public:
CMSATools();
~CMSATools();
void SetPathXML(CString strPath);
void Test();
};
并且:
#include "stdafx.h"
#include "MSATools.h"
CMSATools::CMSATools()
{
}
CMSATools::~CMSATools()
{
}
void CMSATools::SetPathXML(CString strPath)
{
MSATools::iInterfacePtr pInterface = NULL;
HRESULT hr;
hr = pInterface.CreateInstance(__uuidof(MSATools::MSAToolsLibrary));
if (SUCCEEDED(hr))
{
CComBSTR bstrText = strPath.AllocSysString();
pInterface->SetPathXML(bstrText);
}
}
void CMSATools::Test()
{
MSATools::iInterfacePtr pInterface = NULL;
HRESULT hr;
hr = pInterface.CreateInstance(__uuidof(MSATools::MSAToolsLibrary));
if (SUCCEEDED(hr))
{
CComBSTR bstrText(_T("d:\TestStudents.XML"));
pInterface->SetPathXML(bstrText);
pInterface->AddPublisherData();
pInterface->SavePublisherData();
}
}
它编译了,我可以看到 VisualAssist 的方法:
但是由于某些原因,hr
没有通过 SUCCEEDED
调用。
更新 3
如果我将 DLL 重建为 x64 并将 MFC EXE 重建为 x64,则会出现异常:
更新 4
我必须添加到我的 MFC 应用程序中 InitInstance
:
::Coinitialize(true);
在ExitInstance
中:
::CoUnitialize();
然后异常消失了。
试试这个修改,用VS生成一个新的guid,因为我不记得它是否自动写入另一个文件。
using System.Runtime.InteropServices;
...
[ComVisibleAttribute(true)]
[Guid("xxx-xxx-xxx-xxx-xxx")]
[ProgId("MSAToolsLibraryClass")]
public class MSAToolsLibrary
{
...
编辑
确保您的 Assembly.cs 有这样一行:
[程序集:Guid("xxx-xxx-xxx-xxx-xxx")]