使用此代码获取站点的 rss。此代码适用于我的计算机和许多其他计算机。但在某些计算机(Windows XP 或 7)中,我收到此错误: MSXML 未安装

我该如何解决这个问题?怎么了?

这是代码:

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;

如您所见,我正在使用线程。所以需要 Synchronize

最佳答案

在 Windows 上,TXMLDocument 默认使用 MSXML,它使用 COM 对象。您的线程在加载 XML 之前没有调用 CoInitialize/Ex(),因此 COM 无法实例化 IXMLDocument 尝试在内部创建的任何 MSXML COM 对象(它尝试创建多个 COM 对象以发现实际安装了哪个版本的 MSXML)。您看到的错误消息意味着所有 MSXML COM 对象都无法实例化。

您必须在访问 COM 对象的每个线程上下文中调用 CoInitialize/Ex(),例如:

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 :如果你不想依赖这个:你可以使用你选择的不同的 XML 库,你不必使用 MSXML:

Using the Document Object Model

关于XML:未安装 MSXML,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20478739/

10-13 09:47