我正在用COM Interop写一个C++/CLI项目来公开VBA客户端的方法和对象。为什么RegAsm在某些方法签名上添加'W'?
到目前为止都很好,但是我遇到了一个奇怪的问题:某些方法会导出一个(不需要的)'W'后缀(例如GetUserNameW
)!
让我详细解释...
我有一个实用工具类,写这样的:
MyUtils.h
#pragma once
namespace MyApp {
[System::Runtime::InteropServices::ComVisible(true)]
[System::Runtime::InteropServices::Guid("...guid...")]
[System::Runtime::InteropServices::InterfaceType(System::Runtime::InteropServices::ComInterfaceType::InterfaceIsDual)]
public interface class IMyUtils
{
System::String^ CombinePaths(System::String^ path1, System::String^ path2);
System::String^ GetDocumentsDirectory();
System::String^ GetMachineName();
System::String^ GetSystemDirectory();
System::String^ GetUserName();
};
[System::Runtime::InteropServices::ComVisible(true)]
[System::Runtime::InteropServices::Guid("...another guid...")]
[System::Runtime::InteropServices::ClassInterface(System::Runtime::InteropServices::ClassInterfaceType::None)]
public ref class MyUtils : IMyUtils
{
public:
MyUtils();
virtual System::String^ CombinePaths(System::String^ path1, System::String^ path2);
virtual System::String^ GetDocumentsDirectory();
virtual System::String^ GetMachineName();
virtual System::String^ GetSystemDirectory();
virtual System::String^ GetUserName();
};
}
MyUtils.cpp
#include "stdafx.h"
#include "MyUtils.h"
using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Runtime::InteropServices;
namespace MyApp
{
MyUtils::MyUtils()
{
// Do nothing...
}
String^ MyUtils::CombinePaths(String^ path1, String^ path2)
{
return Path::Combine(path1, path2);
}
String^ MyUtils::GetDocumentsDirectory()
{
return Environment::GetFolderPath(Environment::SpecialFolder::MyDocuments);
}
String^ MyUtils::GetMachineName()
{
return Environment::MachineName;
}
String^ MyUtils::GetSystemDirectory()
{
return Environment::SystemDirectory;
}
String^ MyUtils::GetUserName()
{
return Environment::UserName;
}
}
这里没什么困难。
然后,我创建了TLB和使用此命令行注册程序集:
regasm MyLib.dll /codebase /tlb
现在,当我尝试使用对象的VBA客户端上,我有这样的:
Dim utils As New MWUtils
utils.CombinePaths "C:\Windows", "System32"
utils.GetDocumentsDirectory
utils.GetMachineName
utils.GetSystemDirectoryW '<== What?
utils.GetUserNameW '<== Again?
注意GetSystemDirectory
和GetUserName
方法上的'W'后缀!
中介问题:它从哪里来?
好吧,看看生成的IDL的接口:
[
uuid(...guid...),
dual,
oleautomation
]
interface IMyUtils : IDispatch {
[id(0x60020000)]
HRESULT CombinePaths(
[in] BSTR path1,
[in] BSTR path2,
[out, retval] BSTR* pRetVal
);
[id(0x60020001)]
HRESULT GetDocumentsDirectory([out, retval] BSTR* pRetVal);
[id(0x60020002)]
HRESULT GetMachineName([out, retval] BSTR* pRetVal);
[id(0x60020003)]
HRESULT GetSystemDirectoryW([out, retval] BSTR* pRetVal);
[id(0x60020004)]
HRESULT GetUserNameW([out, retval] BSTR* pRetVal);
};
很显然现在的RegAsm工具有改变的方法的签名,但为什么?
'W'后缀表示一个Unicode字符串,但这是我第一次看到这种改变!
最终问题#1:为什么RegAsm表示这两种方法的Unicode字符串?
最终问题#2:我该如何抑制这种“改变”?
非常微妙。 C#中不存在的另一个C++/CLI陷阱。因此,在添加stdafx.h之后,我添加了'#undef GetUserName'和'#undef GetSystemDirectory',但之前添加了MyUtils.h并且它可以正常工作!非常感谢你! – 2014-11-03 14:17:04