我正在用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