Correct usage of Variant type in Inno Setup function

65 views Asked by At

How do I correctly use the Variant type (Here: msxml MSXML2.DOMDocument.6.0)?

Consider those two functions. The second one fails with an access violation exception if called twice:

function CreateElementWorking(xmlDocument: Variant; name : String) : Variant;
var
    xmlNewElement : Variant;
begin
    Result := xmlDocument.createElement(name);
    xmlNewElement := Result;

    // Do sth. with the newly created element
    AddAttributes(xmlDocument, xmlNewElement);
end;

function CreateElementFailing(xmlDocument: Variant; name : String) : Variant;
var
    xmlNewElement : Variant;
begin
    xmlNewElement := xmlDocument.createElement(name);
    
    // Do sth. with the newly created element
    AddAttributes(xmlDocument, xmlNewElement);
    
    // When the function runs for the 2nd time, "Result" is no longer uninitialized.
    // Pascal scripting preserves the old value.
    // The assignment results in an access violation exception
    Result := xmlNewElement;
end;

Possible reason for the fail on second run is that Result already has a value. Pascal scripting somehow preserves the value from the first run.

The workaround in the first function does what I expect it does, although I don't know why it works. That always leaves a strange feeling...

Is there a way to reset Result prior to call Result := xmlNewElement; or is my Variant handling completely wrong?

Failing minimal example:

function AddAttributes(xmlDocument, xmlElement: Variant) : Variant;
begin
end;

function DoTest() : Boolean;
var
    xmlDocument    : Variant;
    xmlElement     : Variant;
    xmlRootElement : Variant;
begin
    xmlDocument       := CreateOleObject('MSXML2.DOMDocument.6.0');
    xmlDocument.async := False;
    xmlDocument.setProperty('SelectionLanguage', 'XPath');

    xmlRootElement := xmlDocument.selectSingleNode('/');

    xmlElement := CreateElementFailing(xmlDocument, 'Test');
    xmlRootElement.appendChild(xmlElement);
    xmlRootElement := xmlDocument.selectSingleNode('/Test');

    xmlElement := CreateElementFailing(xmlDocument, 'Test');  // This fails
    xmlRootElement.appendChild(xmlElement);
    
    // Result should be
    // <Test><Test/></Test>
end;    
0

There are 0 answers