Updating .config XML in InstallScript
I am attempting to write a short install script to update a value in an XML file (myplatforinfo.config).
I shamefully stole the code from [this post on a similar task]{http://stackoverflow.com/questions/4129633/how-to-update-attributes-in-an-xml-file-with-installscript}, but have hacked it for my needs.
/// <summary>
/// This function reads in the fddId.config and alters the number associated
/// with the serial number fo the installed package.
/// <summary>
function UpdateDeviceFirmwareVers开发者_运维技巧ion(hMSI)
OBJECT oDoc;
STRING sConfigFilePath;
BOOL successfulLoad;
NUMBER retVal;
begin
sConfigFilePath = "C:\\myplatforinfo.config";
retVal = 0;
if (Is(FILE_EXISTS, sConfigFilePath)) = FALSE then
MessageBox("Could not find fddId file.", 0);
retVal = -1;
endif;
// get values from public properties
set oDoc = CreateObject("Msxml2.DOMDocument.4.0");
if (!IsObject(oDoc)) then
MessageBox("Could not create XML Document", 0);
retVal = -1;
endif;
oDoc.async = FALSE;
oDoc.setProperty("SelectionLanguage", "XPath");
successfulLoad = oDoc.load(sConfigFilePath);
if (successfulLoad < 0) then
MessageBox("Could not load the fddId as an xml file", SEVERE);
retVal = -1;
endif;
if (retVal = -1) then
return retVal;
abort;
endif;
ReplaceValueOf(oDoc, "//platformID/SerialNumber/version", "1");
oDoc.save(sConfigFilePath);
set oDoc = NOTHING;
end;
function ReplaceValueOf(oDoc, xPath, valueToPutIn)
OBJECT oNode;
begin
set oNode = oDoc.selectNodes(xPath)(0);
try
oNode.attributes.getNamedItem("value").value = valueToPutIn;
catch
MessageBox("Could not set '" + xPath + "' with '" + valueToPutIn + "'", SEVERE);
endcatch;
end;
It is however falling over on the load method, need help!:
successfulLoad = oDoc.load(sConfigFilePath);
if (successfulLoad < 0) then
MessageBox("Could not load the fddId as an xml file", SEVERE);
retVal = -1;
endif;
I am not sure why. This file is a valid XML file and it handled ok by the .Net code that uses it. Below I have included a simplified version of the XML config file. Just the header and the tags that are used, but the structure is identical. It has comments in it, could this effect the InstallShield parser?
<?xml version="1.0" encoding="utf-8"?>
<platformIDxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<type>35</type>
<manufacturer>14</manufacturer>
<SerialNumber>
<version>2</version>
</SerialNumber>
</platformID>
I have only been battling with InstallShield 2011 for a short time, but I am fast learning to love it's power and hate it's development support and lack of a clear UI. Any help welcome :) .
EDIT: As Michael Urman has kindly pointed out I wasn't correctly handling the boolean return from my XML Document load. I have made this edit and my script is now getting as far as the 'getNamedItem' and set the value.
Is this possibly because the field I wish to set is not the named "value" attribute? My elements don't have any attributes, but I suspected the value for the element was an attribute named 'value', lol. Have I presumed wrong?
Further EDIT!! Nope it's not the above then... I have tried the node.Value and the named element route, both ways the debugger crashes on the 'setter' line for the new value. Think I might just have to use the inbuilt function.
I think your load check is incorrect. The return value of the DOMDocument.load method is boolean, not hresult. Thus instead of negative values being failures, only a zero value is a failure. If you compare your highlighted code excerpt with the code on the question you reference, you'll see the other code uses if !successfulLoad
instead.
But let's also clarify a few things. When you go through operations on an object from a CreateObject call, you're really fighting with COM instead of InstallScript, unless it's the language side that's preventing you from doing something.
Secondly, if the single ReplaceValueOf call is the only change you need to make to this file, and you know where the file is (or will be), it would probably be much easier to use the built-in XML file changes support. Set up its XPath to refer to //platformID/SerialNumber/version
by creating three hierarchical elements with those names, and set the version
element's node text to 1
.
Recent versions of InstallShield handle small changes like this pretty well, only having problems with ordering and similar on large wholesale changes. If indentation and other such changes are causing a problem, you can disable that as well.
Above code is working for me if I changed code to set xml element text in function ReplaceValueOf
to oNode.text = valueToPutIn;
I needed also changed create object to use 6.0 version:
CreateObject("Msxml2.DOMDocument.6.0");
精彩评论