XML: MSXML Not Installed

15,591

Solution 1

On Windows, TXMLDocument uses MSXML by default, which uses COM objects. Your thread is not calling CoInitialize/Ex() before loading the XML, so COM is not able to instantiate any of the MSXML COM objects that IXMLDocument attempts to create internally (it attempts to create multiple COM objects to discover which version of MSXML is actually installed). The error message you are seeing means all of the MSXML COM objects failed to instantiate.

You MUST call CoInitialize/Ex() in every thread context that accesses COM objects, eg:

procedure My_Thread.Execute;
var
  ...
begin
  CoInitialize(nil);
  try
    ...
    XMLDoc := LoadXMLData(str);
    try
     ...
    finally
      // Since CoInitialize() and CoUninitialize() are being called in the same
      // method as local COM interface variables, it is very important to release
      // the COM interfaces before calling CoUninitialize(), do not just let them
      // release automatically when they go out of scope, as that will be too late...
      StartItemNode := nil;
      ANode := nil;
      XMLDoc := nil;
    end;
    ...
  finally
    CoUninitialize;
  end;
end;

UPDATE: If you don't want to rely on this: you can use a different XML library of your choosing, you don't have to use MSXML:

Using the Document Object Model

Selecting an XML Vendor

When you build an application, RAD Studio uses the default built-in XML vendor, MSXML.

If you do not specify a different XML vendor, your application does not have XML support on other platforms than Windows, and you see a run-time exception when you run your application in other platforms. For cross-platform applications, OmniXML is currently the best choice, as it shows much better performance than ADOM.

To choose a different XML vendor, add a reference to the unit of the vendor into the unit where you use the RTL XML features, such as the TXMLDocument class. If you add more than one XML vendor unit, the first unit referenced is used as XML vendor. If you need to override this behavior, change the value of the DefaultDOMVendor global variable to the global variable of the XML vendor that you want to use.

Note: You can look up the unit and the global variable of each XML vendor in the List of Built-in XML Vendors above.

When you use the TXMLDocument component, you can choose an XML vendor using its DOMVendor property. When you change the value of DOMVendor, the unit that uses the component is configured to use the specified XML vendor, so that you do not need to change unit references or the DefaultDOMVendor global variable manually.

Solution 2

MSXMLS needs to be installed before.. in servicePack2 for XP MSXML 4.0 Service Pack 2 (Microsoft XML Core Services) Microsoft Core XML Services (MSXML) 6.0 the same for windows 7.. Bye

Share:
15,591
Sky
Author by

Sky

I'm a person who loves programming ♥

Updated on June 04, 2022

Comments

  • Sky
    Sky almost 2 years

    Using this code to get rss of a site. This code works fine for my computer and many other computers. But in some computers (Windows XP or 7) I get this error: MSXML Not Installed

    How can I fix this problem? What is wrong?

    Here is the code:

    procedure My_Thread.Execute;
    var
      http                 : tidhttp;
      strm                 : tmemorystream;
      str,sTitle,  sDec ,er : string;
      StartItemNode        : IXMLNode;
      ANode                : IXMLNode;
      XMLDoc               : IXMLDocument;
    
    begin
      http := tidhttp.Create();
      strm := tmemorystream.Create;
        try
          http.Get('http://www.sample.com/rss.xml',strm);     //Download the RSS file
          SetString(str,PANSIChar(strm.Memory),strm.Size);
    
          XMLDoc :=  LoadXMLData(str);
    
          StartItemNode := XMLDoc.DocumentElement.ChildNodes.First.ChildNodes.FindNode('item');
          ANode         := StartItemNode;
    
          i := 0;
          repeat
            inc(i);
            sTitle    := ANode.ChildNodes['title'].Text;
            sDec       := ANode.ChildNodes['description'].Text;
            Synchronize(procedure begin            //Synchronize? I'm using threads
              case I of
                1: begin
                     main_frm.edit1.text := sTitle; //main_frm is my form
                     main_frm.edit2.text := sDec;
                   end;
                2: begin
                     main_frm.edit3.text := sTitle;
                     main_frm.edit4.text := sDec;
                   end;
                3: begin
                     main_frm.edit5.text := sTitle;
                     main_frm.edit6.text := sDec;
                   end;
              end;
              ANode := ANode.NextSibling;
            end);
          until ANode = nil;
    
          http.Free;
          strm.Free;
    
        except
          on E: Exception do
            begin
              er := e.Message;
              Synchronize(procedure begin
                ShowMessage(er);
              end);
            end;
        end;
    end;
    

    As you see I'm useing threads. So Synchronize was needed.

    • Rob Kennedy
      Rob Kennedy over 10 years
      You get that message from an exception, right? The debugger interrupts your program and tells you exactly where the exception came from, doesn't it? So debug it. At the very least, include the source of the exception in your question.
    • J...
      J... over 10 years
      This is a complete aside, but Dec is a function (in unit System) that is used to decrement an integer. Here you declare a string variable Dec, which hides that function. This is bad practice, especially for such a common function as dec - you should use a unique name for your variables.
    • Sky
      Sky over 10 years
      @J... Fixed that. Thanks
    • Sky
      Sky over 10 years
      @RobKennedy No. On my system the code works fine. I cannot debug it on another computer. So I used ShowMessage(er); But I think the error is because of XMLDoc := LoadXMLData(str);. I used TXMLDocument (added it on the main form) instead of XMLDoc : IXMLDocument; and also removed the thread. It worked on all computers. Don't know why.
    • Sertac Akyuz
      Sertac Akyuz over 10 years
      I'd think you'd need to call 'CoInitializeEx' in the thread before using MSXML. But working on some computers.., dunno..
    • Rob Kennedy
      Rob Kennedy over 10 years
      ShowMessage isn't a remote debugging tool. Use MadExcept to collect real exception information. Don't catch an exception unless you know how to resolve the problem that triggered it.
  • Sky
    Sky over 10 years
    But when I use TXMLDocument in form without using thread it works fine. Why?
  • Pericles
    Pericles over 10 years
    Maybe they are not threadsafe. You showld take care of that doing a critical section maybe.. Is it really need to use threads for that? I think you have the data in memory it is just need to put it into the form! bye
  • Sky
    Sky over 10 years
    I removed the thread. It worked. But I need to use it in threads :(
  • Newbi
    Newbi almost 7 years
    After that i saw a same problem again. The new problem happened when I call a procedure to save my xml file. Finally I solved that with this line: IdThreadComponent1.Synchronize(SaveXML);
  • Remy Lebeau
    Remy Lebeau over 5 years
    That is because you are creating the XMLDocument in the main UI thread, so only that thread can use it by default. MSXML's COM objects do not use a multi-threaded apartment model, so you would have to manually marshal its COM interface across thread boundaries. Best to just create the XMLDocument in the same thread that will be using it. Just make sure to initialize the COM library in that thread beforehand
  • Lucas Steffen
    Lucas Steffen about 5 years
    That comment about releasing the COM interfaces is really interesting. Does this also apply to interfaces generated by importing WSDL?
  • Remy Lebeau
    Remy Lebeau about 5 years
    @LucasSteffen It applies only to interfaces used with COM objects specifically. Delphi interfaces in general are not dependent on COM (though Delphi's IInterface is modeled after COM's IUnknown). AFAIK, Delphi's WSDL framework is not based on COM.
  • Jason L Wharton
    Jason L Wharton about 4 years
    Why doesn't anyone share the units required in the uses clause for what is in their code???