3

我正在尝试创建一个 Visual Studio 扩展,它可以在文本编辑器中记录按键并重播它们。

我有一个IVsTextViewCreationListener调用AddCommandFilter()来向正在创建的任何新文本编辑器添加命令过滤器:

public class VsTextViewCreationListener : IVsTextViewCreationListener
{
    public void VsTextViewCreated(IVsTextView textViewAdapter)
    {
        var filter = new MyCommandFilter();

        IOleCommandTarget next;
        if (ErrorHandler.Succeeded(textViewAdapter.AddCommandFilter(filter, out next)))
            filter.Next = next;
    }
}

命令过滤器如下所示:

public class MyCommandFilter : IOleCommandTarget
{
    public IOleCommandTarget Next { get; set; }

    public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
    {
        if (nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
        {
            // Save values of pguidCmdGroup, nCmdID, nCmdexecopt and GetTypedChar(pvaIn)
            // ...
        }

        return Next.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
    }

    public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return Next.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }

    public void Playback()
    {
        // Resend the values
        var pvaIn = Marshal.AllocCoTaskMem(4);
        Marshal.GetNativeVariantForObject((ushort)savedChar, pvaIn);
        Next.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, IntPtr.Zero);
    }

    private static char GetTypedChar(IntPtr pvaIn)
    {
        return (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
    }
}

(我已经剪掉了将值保存在列表中的代码部分)

它的工作原理是它捕获并重放按键,但是在经常(并非总是)重放它之后,Visual Studio 崩溃,并且崩溃发生在本机代码中,所以我没有太多关于错误的数据。

我以前从未写过任何 VS 扩展,而且我所做的肯定是粗略的……

(我可能应该释放分配的内存AllocCoTaskMem()- 我已经尝试过了,但它仍然崩溃,我认为此时不释放它不会有坏处)。

将不胜感激任何想法。

4

1 回答 1

2

MSDN 论坛得到答案:

VARIANT 的正确大小是 16 字节,而不是 4:

Marshal.AllocCoTaskMem(16);
于 2012-10-26T01:58:30.597 回答