locked
MSXMLl 6.0 XmlDOMNodeList fails when is invoked GetEnumerator RRS feed

  • Question

  • Our project uses MSXML 6.0 com object for working with XML through ComImport attribute. Below com Class which provides access to existing MSXML COM(I left only SelectNodes for clarify problem )

    [ComImport]
    [ComSourceInterfaces("MSXML2.XMLDOMDocumentEvents")]
    [TypeLibType(TypeLibTypeFlags.FCanCreate)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("88d96a06-f192-11d4-a65f-0040963251e5")]
    public class FreeThreadedDOMDocumentClass : IXMLDOMDocument2
    {
        [return: MarshalAs(UnmanagedType.Interface)]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(0x1d)]
        public extern object SelectNodes([In, MarshalAs(UnmanagedType.BStr)] string queryString);
    
    }
    
    [ComImport, Guid("2933BF95-7B36-11D2-B20E-00C04F983E60"), TypeLibType((short)0x10c0)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IXMLDOMDocument2
    {
        [return: MarshalAs(UnmanagedType.Interface)]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(0x1d)]
        object SelectNodes([In, MarshalAs(UnmanagedType.BStr)] string queryString);
    }
    
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix"), ComImport]
    [Guid("2933BF82-7B36-11D2-B20E-00C04F983E60")]
    [TypeLibType(TypeLibTypeFlags.FDispatchable)]//(short) 0x10c0
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IXMLDOMNodeList: IEnumerable
    {
    
        [DispId(0)]
        IXMLDOMNode this[int index]
        {
          [return: MarshalAs(UnmanagedType.Interface)]
          [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0)]
          get;
        }
    
    
        [DispId(0x4a)]
        int Count
        {
          [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0x4a)]
          get;
        }
    }

    And We have problem with some parts of code. Example :

    string xmlText = "<Item> <Element></Element></Item>";
    IXMLDOMDocument2 domDocument = new FreeThreadedDOMDocumentClass();
    domDocument.LoadXml(xmlText);
    string xPath = "//Item";
    IXMLDOMNodeList resultQuery = domDocument.SelectNodes(xPath) as IXMLDOMNodeList;
    resultQuery.GetEnumerator()

    Obtained object resultQuery as result of execution of SelectNodes has problem with GetEnumerator depending on some outside factors:

    1. In windows 7 or more early systems (system without support of WinRT technology)

      • obtained object resultQuery has type System.__ComObject
      • resultQuery.GetEnumerator() executes without any problem and provide working Enumerator
    2. In windows 8 or more later systems (system with support of WinRT technology)

      • obtained object resultQuery has type Windows.Data.Xml.Dom.XmlNodeList. This is WinRt type.
      • resultQuery.GetEnumerator() throws exception:System.ArgumentException: The object's type must not be a Windows Runtime type. I figured out that source of exception is Marshal.GetComObjectData. It means that our Marshalling process fails
    3. In windows 8 or more later systems with version of imported com MSXML 3.0 :

      • obtained object resultQuery has type System.__ComObject
      • resultQuery.GetEnumerator() executes without any problem and provide working Enumerator

    At this moment I found three workarounds for point 2 (using msxml on windows with WinRT) but not the solutions for us (It can be helpful for developers with the same issue):

    1. Do not use foreach and GetEnumerator. it's clear :)
    2. Create custom marshalling for SelectNodes with using ICustomMarshaler which will create wrapper over WinRT type and provide custom GetEnumerator through for.
    3. Change version of msxml from 6 to 3.

    I need help to find source of problem in point 2 and understand how to fix it. Thanks






    MS

    Monday, March 6, 2017 2:04 PM

Answers

All replies

  • Could you give a small demo to show your issue?

    It is not 100% clear what your scenario is.

    Wednesday, March 8, 2017 5:00 AM
  • >Could you give a small demo to show your issue?

    >It is not 100% clear what your scenario is.

    Sure,

    In this place  I catch  System.ArgumentException: The object's type must not be a Windows Runtime type

    and as result I canot use foreach statement with resultQuery collection. It happens only in windows 8-10. That is my problem.

    resultQuery.GetEnumerator()


    MS




    • Edited by Che097 Thursday, March 9, 2017 6:56 AM
    Thursday, March 9, 2017 6:40 AM
  • Hi Che097,

    What's your application project? I wonder if it is an UWP project. If yes, I will suggest you repost this issue in Windows and Windows phone apps   Developing Universal Windows apps forum for better support.

    By the way, based on your code, if U want to obtain the COM object, you should wrap the specified COM object in an object of the specified type in windows runtime.

    https://msdn.microsoft.com/en-us/library/9tx5ztzt(v=vs.110).aspx

    Best regards,

    Kristin


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, March 10, 2017 2:08 AM
  • Hello Kristin Xie,

    Project type is desktop. It is not UWP. That is the biggest problem  - I want to obtain com object but I receives winRt object which fails.


    MS

    Friday, March 10, 2017 6:04 AM
    • Marked as answer by Che097 Monday, March 13, 2017 12:43 PM
    Monday, March 13, 2017 12:43 PM