MSXML2.ServerXMLHTTP
/ MSXML2.XMLHTTP.3.0
我的行为非常奇怪
问题出在send
方法上。可接受BSTR
/ SAFEARRAY
/ XMLDOC
对象/ IStream
此代码正常工作很好并且工作多年(FServiceUrl, FReqXML
命名的用法是有意的):
procedure PostRequest(const FServiceUrl, FReqXML: WideString);
var
xmlHttp: OleVariant;
begin
xmlHttp := CreateOleObject('MSXML2.ServerXMLHTTP.6.0');
xmlHttp.Open('POST', FServiceUrl, False);
// VarType(FReqXML) -> BSTR
xmlHttp.send(FReqXML);
end;
现在我需要将这个过程包装成一个简单的类:
type
TXMLHttpNet = class
private
FServiceUrl: WideString;
FReqXML: WideString;
public
constructor Create(const AServiceUrl, AReqXML: WideString);
procedure PostRequest;
end;
constructor TXMLHttpNet.Create(const AServiceUrl, AReqXML: WideString);
begin
FServiceUrl := AServiceUrl;
FReqXML := AReqXML;
end;
procedure TXMLHttpNet.PostRequest; // Problem is in this call
var
xmlHttp: OleVariant;
begin
xmlHttp := CreateOleObject('MSXML2.ServerXMLHTTP.6.0');
xmlHttp.Open('POST', FServiceUrl, False);
// VarType(FReqXML) -> BSTR
xmlHttp.send(FReqXML); // EOleException: "the parameter is incorrect"
end;
奇怪的是,上面一行xmlHttp.send(FReqXML);
引发了一个异常:
EOleException:“参数不正确”
请注意FReqXML
类型在两种情况下都相同(WideString/BSTR
)
一个简单的测试:
uses ComObj;
procedure TForm1.Button1Click(Sender: TObject);
var
Request: TXMLHttpNet;
begin
// simple procedure
PostRequest('http://www.gmail.com', 'foo'); // OK!
// via object method
Request := TXMLHttpNet.Create('http://www.gmail.com', 'foo');
Request.PostRequest; // EOleException: "the parameter is incorrect"
Request.Free;
end;
我根本无法理解为什么会发生这种异常!
如果我在FReqXML
中使用WideString
明确地将VarToWideStr
“转换为TXMLHttpNet.PostRequest
,那就可以了:
xmlHttp.send(VarToWideStr(FReqXML));
甚至奇怪地喜欢这个(!):
xmlHttp.send((FReqXML)); // note the double Brackets
问题:这里发生了什么?
我可以告诉FReqXML
在两种情况下都是 WideString/BSTR
为什么FReqXML
参数在两种情况下表现不同?
答案 0 :(得分:1)
你是对的,FReqXML
在两种情况下属于同一类型,但在后一种情况下,其内存是根据对象的内存(堆)分配的。根据Delphi版本和编译器设置,这可能会导致用于字符串的内存的行为不同于仅限本地使用(堆栈)。这就是VarToWideStr
确实起作用的原因(而且显然还有一些奇怪的额外括号)。
除此之外,我强烈建议导入MSXML2类型库并使用它。它使用早期绑定,这不仅提高了性能,还在代码编辑器中启用了代码完成。
您可以使用类型库导入程序生成它,或使用我拥有here的副本。
然后,请勿使用OleVariant
和CreateOleObject
(导致后期绑定),但请使用CoServerXMLHTTP.Create
和XMLHTTP
接口类型。