【发布时间】:2014-12-30 04:17:45
【问题描述】:
我正在编写一个带有 COM Interop 的 C++/CLI 项目,以便为 VBA 客户端公开方法和对象。
到目前为止一切都很好,但我遇到了一个奇怪的问题:某些方法以(不需要的)“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:我怎样才能抑制这种“改变”?
【问题讨论】:
标签: .net visual-studio-2010 com c++-cli com-interop