Notre projet utilise MSXML 6.0
objet com pour travailler avec XML
grâce à l'attribut ComImport
. Ci-dessous la classe com qui fournit un accès à MSXML COM
existant (j'ai quitté seulement SelectNodes pour clarifier le problème).MSXMLl 6.0 XmlDOMNodeList échoue quand est appelé GetEnumerator
[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;
}
}
Et nous avons des problèmes avec certaines parties du code. Exemple:
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()
objet obtenu resultQuery
à la suite de l'exécution de SelectNodes
a un problème avec GetEnumerator en fonction de certains facteurs extérieurs:
Dans Windows 7 ou systèmes plus tôt (système sans le soutien de la technologie WinRT)
- objet obtenu
resultQuery
System.__ComObject
est de type - resultQuery.GetEnumerator() exécute sans problème et fournir de travail recenseur
- objet obtenu
Dans Windows 8 ou plus systèmes ultérieurs (système avec le soutien de la technologie WinRT)
- objet obtenu
resultQuery
est de typeWindows.Data.Xml.Dom.XmlNodeList
. C'est un type WinRt. - resultQuery.GetEnumerator() déclenche une exception:
System.ArgumentException: The object's type must not be a Windows Runtime type
. J'ai compris que cette source d'exception estMarshal.GetComObjectData
. Cela signifie que notre processus de sérialisation échoue
- objet obtenu
Dans Windows 8 ou plusieurs systèmes plus tard avec la version des produits importés com
MSXML 3.0
:- objet obtenu
resultQuery
est de typeSystem.__ComObject
- resultQuery.GetEnumerator() est parcouru sans tout problème et fournir recenseur travail
- objet obtenu
En ce moment, j'ai trouvé trois solutions de contournement pour le point 2 (en utilisant MSXML sur les fenêtres avec WinRT) mais pas les solutions pour nous (Il peut être utile pour les développeurs avec le même numéro):
- Ne pas utiliser foreach et GetEnumerator. il est clair :)
- Créer un regroupement personnalisé pour
SelectNodes
en utilisant ICustomMarshaler qui va créer un wrapper sur le type WinRT et fournir GetEnumerator personnalisé viafor
. - version Changement de MSXML de 6 à 3.
je besoin d'aide pour trouver la source de problèmes au point 2 et comprendre comment y remédier. Merci
Artsiom vous remercie de l'avoir fait. J'essaie de faire exactement la même chose, en utilisant MSXML 6 (il n'est pas possible pour moi de reculer à MSXML 3). Moi aussi j'essaie de parcourir un ensemble de nœuds récupérés. Votre réponse n'est pas très claire, j'espère que je ne devrais pas aller déconstruire les DLL, ajouter à IXMLDOMNodeList. Cela semble beaucoup plus profond que prévu, pour éviter un problème dans une version MSXML actuelle. Avez-vous découvert d'autres approches pour coder cela? J'utilise VBScript dans le framework .NET. Je vous remercie. – Dave