none
请教,C#下操作COM组件的几个问题 RRS feed

  • 问题

  • 最近正在学习MS Active Accessibility技术,本意是想做一个类似AccExplorer32这样的工具,在网络上找了一下相关的资料,发现了如下的页面:

    http://vckbase.com/index.php/wv/651 (MS Active Accessibility 接口技术编程尝试)

    根据这个教程给出的资料学习了一下,然后尝试以C#来写例子,发现一些问题,想请教一下各位大大:

    Native Code

    BOOL FindChild (IAccessible* paccParent,
                              LPSTR szName, LPSTR szRole,
                              LPSTR szClass,
                              IAccessible** paccChild,
                              VARIANT* pvarChild)
     {
     HRESULT hr;
     long numChildren;
     unsigned long numFetched;
     VARIANT varChild;
     int index;
     IAccessible* pCAcc = NULL;
     IEnumVARIANT* pEnum = NULL;
     IDispatch* pDisp = NULL;
     BOOL found = false;
     char szObjName[256], szObjRole[256], szObjClass[256], szObjState[256];

     //得到父亲支持的IEnumVARIANT接口
    hr = paccParent -> QueryInterface(IID_IEnumVARIANT, (PVOID*) & pEnum);

     if(pEnum)
     pEnum -> Reset();

     //取得父亲拥有的可访问的子的数目
    paccParent -> get_accChildCount(&numChildren);

     //搜索并比较每一个子ID,找到名字、角色、类与输入相一致的。
    for(index = 1; index <= numChildren && !found; index++)
     {
     pCAcc = NULL;
     // 如果支持IEnumVARIANT接口,得到下一个子ID
     //以及其对应的 IDispatch 接口
    if (pEnum)
     hr = pEnum -> Next(1, &varChild, &numFetched);
     else
     {

    ...

    }

    Managed Code

    private bool FindChild(object paccParent, string szName, string szRole, string szClass, ref Accessibility.IAccessible paccChild, ref object pvarChild)
            {
                int hr = 0;
                int numChildren = 0;
                IntPtr numFetched = default(IntPtr);
                object[] oChild = null;
                int index = 0;
                Accessibility.IAccessible pCAcc = null;
                IntPtr pUnk = default(IntPtr);
                IntPtr pInt = default(IntPtr);
                IEnumVARIANT pEnum = null;
                pUnk = Marshal.GetIUnknownForObject(paccParent);
                hr = Marshal.QueryInterface(pUnk, ref Headers.IEnum_GUID, out pInt);
                pEnum = (IEnumVARIANT)Marshal.GetObjectForIUnknown(pInt);
                Marshal.Release(pUnk);

                if (pEnum == null)
                {
                    pEnum.Reset();
                }

                numChildren = ((Accessibility.IAccessible)paccParent).accChildCount;

                for (index = 0; index <= numChildren; index++)
                {

                    if (pEnum != null)
                    {
                        hr = pEnum.Next(1, oChild, numFetched); <--调试时中断于此,错误提示为:“其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
                    }
                    else
                    {
                       ...... 

            }

    请问一下哪里有问题呢?

    另外就是C++中的VARIANT类型翻译成C#下的话根据MSDN提供的信息对应Object类型,但想了很久都没明白,望大大们不惜赐教。

    最后就是.NET下操作COM的书籍也请推荐一下,无论说VB还是C#的都可以。

    2015年4月21日 13:59

答案

  • C#一般用UIA(UI Automatic)至于MSAA一般不怎么用。

                object patObj;
                AutomationElement root = AutomationElement.FromHandle(base.Handle);
                AutomationElement edit = root.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
                if (edit.TryGetCurrentPattern(ValuePattern.Pattern, out patObj))
                {
                    ValuePattern vpEdit;
                    if ((vpEdit = patObj as ValuePattern) != null)
                        vpEdit.SetValue("hello worlds");
                }




    • 已编辑 sAcacia 2015年4月22日 1:16
    • 已标记为答案 xiaoluo18 2015年4月24日 1:53
    2015年4月22日 1:07

全部回复

  • C#一般用UIA(UI Automatic)至于MSAA一般不怎么用。

                object patObj;
                AutomationElement root = AutomationElement.FromHandle(base.Handle);
                AutomationElement edit = root.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
                if (edit.TryGetCurrentPattern(ValuePattern.Pattern, out patObj))
                {
                    ValuePattern vpEdit;
                    if ((vpEdit = patObj as ValuePattern) != null)
                        vpEdit.SetValue("hello worlds");
                }




    • 已编辑 sAcacia 2015年4月22日 1:16
    • 已标记为答案 xiaoluo18 2015年4月24日 1:53
    2015年4月22日 1:07
  • C#一般用UIA(UI Automatic)至于MSAA一般不怎么用。

                object patObj;
                AutomationElement root = AutomationElement.FromHandle(base.Handle);
                AutomationElement edit = root.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
                if (edit.TryGetCurrentPattern(ValuePattern.Pattern, out patObj))
                {
                    ValuePattern vpEdit;
                    if ((vpEdit = patObj as ValuePattern) != null)
                        vpEdit.SetValue("hello worlds");
                }




    非常感谢您的回答。

    UIA或许是.NET下最好的解决方法,但是我现在更想学习C#与COM的互操作,既然找不到解决的办法,那就算了。

    2015年4月24日 1:57