C# IVsDropdownBarClient和GetEntryText:文本缓冲区存在问题
在我的VisualStudio扩展中,我将阅读导航栏中的文本。因此,我监听窗口创建的事件,并从IVsCodeWindow对象中获取IVsDropdownBar以获取下拉栏中的当前选择。这个很好用。然后,我使用以下代码片段提取当前选择的文本:C# IVsDropdownBarClient和GetEntryText:文本缓冲区存在问题,c#,visual-studio-2013,visual-studio-extensions,C#,Visual Studio 2013,Visual Studio Extensions,在我的VisualStudio扩展中,我将阅读导航栏中的文本。因此,我监听窗口创建的事件,并从IVsCodeWindow对象中获取IVsDropdownBar以获取下拉栏中的当前选择。这个很好用。然后,我使用以下代码片段提取当前选择的文本: string text; barClient.GetEntryText(MembersDropdown, curSelection, out text); if (hr == VSConstants.S_OK) { Debug.WriteLi
string text;
barClient.GetEntryText(MembersDropdown, curSelection, out text);
if (hr == VSConstants.S_OK)
{
Debug.WriteLine("Text: " + text);
} else {
Debug.WriteLine("No text found!");
}
然而,这是行不通的。我的扩展崩溃,代码段第二行出现未处理的异常。我阅读了文档,发现以下注释:
ppszText中返回的文本缓冲区通常由
IVsDropdownBarClient对象和缓冲区必须终身保留
IVsDropdownBarClient对象的。如果您正在实施此功能
接口,您需要处理该字符串
由调用者在上实现ivscotaskmemfreeystrings接口
IVsDropdownBarClient接口
我假设这是我的问题的一部分,但我不能真正理解我必须在代码中修改什么才能让它工作。有什么提示吗?我现在非常确定Visual Studio SDK Interop DLL具有错误的IVsDropDownbarClient.GetEntryText封送信息,并且无法使用该接口调用该方法 到目前为止,我发现最好的解决方法是: 使用tlbimp工具为textmgr生成备用互操作DLL。您可以安全地忽略几十个警告,包括关于GetExtentry的警告 tlbimp c:\Program Files x86\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Inc\textmgr.tlb 如果使用源代码管理,则可能需要将生成的文件textmanagernal.dll复制到扩展项目的子目录中,并将其作为外部依赖项检入 在Visual Studio扩展项目中,添加对文件textmanagernal.dll的引用 添加应正确处理字符串编组的以下方法
static public string HackHackGetEntryText(IVsDropdownBarClient client, int iCombo, int iIndex)
{
TextManagerInternal.IVsDropdownBarClient hackHackClient = (TextManagerInternal.IVsDropdownBarClient) client;
string szText = null;
IntPtr ppszText = IntPtr.Zero;
try
{
ppszText = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
if(ppszText == IntPtr.Zero)
throw new Exception("Unable to allocate memory for IVsDropDownBarClient.GetTextEntry string marshalling.");
hackHackClient.GetEntryText(iCombo, iIndex, ppszText);
IntPtr pszText = Marshal.ReadIntPtr(ppszText);
szText = Marshal.PtrToStringUni(pszText);
}
finally
{
if(ppszText != IntPtr.Zero)
Marshal.FreeCoTaskMem(ppszText);
}
return szText;
}
}