cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
armyedsp
Level 4

XML element attribute change

My project is an InstallScript MSI project. I am trying to change the port attribute value in a channel element in a config file. Our applicatin is a .NET remoring server. The app.exe.config has
. In the XML File Change I have selected this element in XML view and in the General tab, I have set a value [PORT] for the post attribute and a fixed value of "tcp" for the ref attribute. I have also created an MSI property PORT - being all caps this is a public property. I have created a custom action named ConfigurePort(hMSI) in Installscript for immediate execution before InstallValidate (after SetODBCFolders. In the CA I am calling MsiSetProperty(hMSI, "[PORT]", svPort) where svPort is a user supplied port value (I have also tried hard coding to 9999). In the log file (SETUP.EXE /Verbose"path/test.log") I see this MsiProperty is properly being initialized to 9999 or any user supplied value. However the XML file retains the value that is set in the DirectEditor Msi Properties table for the PORT property. I have it set to 1234 there. I see the XML changes in the log file farther down following my successful MSI property [PORT] being set:
InstallShield 17:13:34: Processing XPath '//system.runtime.remoting/application[@name="EDSPV2"]/channels/channel[@port="33" and @ref="tcp"]'
InstallShield 17:13:34: Node name: 'channel' --> Attribute name = 'port', Current Value = '33', Operation = '1'
InstallShield 17:13:34: Node name: 'channel' - Attribute name = 'port', Old Value = '33', New value = '1234', Actual New Value = '1234'
InstallShield 17:13:34: Node name: 'channel' --> Attribute name = 'ref', Current Value = 'tcp', Operation = '1'
InstallShield 17:13:34: Node name: 'channel' - Attribute name = 'ref', Old Value = 'tcp', New value = 'tcp', Actual New Value = 'tcp'
InstallShield 17:13:34: Saving XML file 'C:\Program Files\SEC-Belvoir\EDSP MS Exchange Service V2\EDSP_Service.exe.config'

Any ideas what I am doing wrong? I am using InstallShield 2009 Professional.

Thanks in advance.
Labels (1)
0 Kudos
(8) Replies
Cne9999
Level 5

Can you run the MSI through the InstallShield debugger and see what the property values are at the various stages? This will tell you at least if it is populating the [PORT] property correctly, passing it off correctly, etc...

Let me know what you find.

Thank you,
Bill V.
0 Kudos
armyedsp
Level 4

Thanks for your response Bill.

In the Custom Action where I set the [PORT] to 9999, the same CA does verify the property is set to correct value by immediately calling MsiGetProperty. Further the log file confirms the value as well. The log file spews out all property values toward end of success report. I see the PORT set to 9999 there too. The strange thing I notice is the following:
I see the PORT in the PropertyManager and not in the DirectEditor! I believe DirectEditor represents the Msi properties that can be changed via MsiSetProperty while PropertyManager represents strings that cannot be changed. It seems what you enter in the Advanced tab of XML File Change View to change entire element goes in to DirectEditor while what you enter in the General tab of XML File Change view to change just the attribute goes in to PropertyManager. I am setting the attribute port value to [PORT] in the General tab. This results in the PORT showing up in the PropertyManager. The really weird thing is in the PropertyManager, the Name is listed as PORT and the Value is listed as {ID_STRING19}1234. This is the 1234 value that is populated in the XML file!

I am going to experiment with the Advanced Tab and attempt to change the entire element from CA as this will be truly a Msi proerty that can be changed. All this time, I believe I have simply been creating new Msi property named PORT at run time! Does that make sense?
0 Kudos
Cne9999
Level 5

“I see the PORT in the PropertyManager and not in the DirectEditor!”

Do you mean that you see the PORT property with declared value in the Property Manager but not in the Property table in the direct editor?

In InstallShield the Property Manager is a direct representation of the Property Table which can be seen in the Direct Editor. So if this is what you are saying this is peculiar.

However putting a property in the XML view anywhere that has not already been declared in the Property Manager only makes the MSI look for the value of that property at run time but does not set its value. I hope I am reading this right from your second post.

“The really weird thing is in the PropertyManager, the Name is listed as PORT and the Value is listed as {ID_STRING19}1234. This is the 1234 value that is populated in the XML file!”

This is normal. First, the ID_STRING19 is only telling you that the string ‘1234’ is localizable. You can ignore that but if possible I would make it NOT Localizable by recreating it and doing so a a regular property. Second, since the Property Manager has declared this value for the port, ‘1234’ that is what appears to be used during runtime. So there isn’t a change. If it does change maybe there is a scheduling issue with the Custom Action.

If possible can you send a couple screen shots of the CA, the XML config, and the Property table from the Direct Editor? Or better yet attach the ISM zipped if there is no sensitive info in it.

Thanks,
Bill V.
0 Kudos
TheTraveler
Level 8

Hello,

Since you have the ability to use Install Shield (IS) scripts, I may have an option for you. In this link, I posted an example on how to search and replace elements in an XML encoded file using the COM interface to XML functions. In the link above, I use these COM functions to look for a key, SQLConnection, and change the value to the database connection string the web site will use.

	




I have used this code for a couple of years now and it is pretty solid.

I hope this helps.
0 Kudos
armyedsp
Level 4

Thanks Bill. The scheduling of the CA may be the issue. Attached is a zip containing various screen shots.

Here is the CA code:
function SetPort(hMSI)
STRING svPort1;
STRING svPort2;
NUMBER nvSize;
begin
MessageBox("Entering SetPort() Custom Action", INFORMATION);

nvSize = 256;
svPort2 = "";
MsiGetProperty(hMSI, "[PORT]", svPort2, nvSize);
MessageBox("Initial PORT value is " + svPort2, INFORMATION);
svPort1 = "9999";//This is the port attribute value we want to set in the config file element: . In production, this will be supplied by user.
MessageBox("About to set Windows Installer property PORT to " + svPort1, INFORMATION);
MsiSetProperty(hMSI, "[PORT]", svPort1);
nvSize = 256;
svPort2 = "";
MsiGetProperty(hMSI, "[PORT]", svPort2, nvSize);
MessageBox("PORT value changed to " + svPort2, INFORMATION); // This successfully shows 9999
end;

Here is snippet from the log:

...
InstallShield 12:25:56: Setting script cmdline...
InstallShield 12:25:56: ProductCode is {6C95BEDC-328B-4FF3-9521-532C84070F0A}
InstallShield 12:25:56: Initializing Engine
InstallShield 12:25:57: Done Initializing...
InstallShield 12:25:57: Registering Msi Server...
MSI (s) (1C!E4) [12:26:10:290]: PROPERTY CHANGE: Adding [PORT] property. Its value is '9999'.
InstallShield 12:25:57: Invoking script function SetPort
InstallShield 12:26:11: CallScriptFunctionFromMsiCA() ends
MSI (s) (1C:F8) [12:26:11:853]: Doing action: InstallValidate
Action ended 12:26:11: ConfigPort. Return value 1.
Action start 12:26:11: InstallValidate.
MSI (s) (1C:F8) [12:26:11:853]: Feature: DefaultFeature; Installed: Absent; Request: Local; Action: Local
MSI (s) (1C:F8) [12:26:11:853]: Component: __MSXML4_Unicode.2E8D8EBB_CC16_45E1_BBCA_C65; Installed: Null; Request: Local; Action: Null
MSI (s) (1C:F8) [12:26:11:853]: Component: __MSXML4_Parser.2E8D8EBB_CC16_45E1_BBCA_CB65; Installed: Null; Request: Local; Action: Null
MSI (s) (1C:F8) [12:26:11:853]: Component: __ADTree.exe65; Installed: Null; Request: Local; Action: Local

.....
MSI (s) (1C:F8) [12:26:13:181]: Executing op: FileCopy(SourceName=EDSP_S~1.CON|EDSP_Service.exe.config,SourceCabKey=edsp_service.exe.config,DestName=EDSP_Service.exe.config,Attributes=16384,FileSize=626,PerTick=32768,,VerifyMedia=1,,,,,CheckCRC=0,,,InstallMode=58982400,HashOptions=0,HashPart1=-62670174,HashPart2=-94058478,HashPart3=1050048444,HashPart4=-26869178,,)
MSI (s) (1C:F8) [12:26:13:181]: File: C:\Program Files\SEC-Belvoir\EDSP MS Exchange Service V2\EDSP_Service.exe.config; To be installed; Won't patch; No existing file
MSI (s) (1C:F8) [12:26:13:181]: Source for file 'edsp_service.exe.config' is compressed
MSI (s) (1C:F8) [12:26:13:181]: Note: 1: 2318 2: C:\Program Files\SEC-Belvoir\EDSP MS Exchange Service V2\EDSP_Service.exe.config
MSI (s) (1C:F8) [12:26:13:181]: Executing op: CacheSizeFlush(,)
MSI (s) (1C:F8) [12:26:13:181]: Executing op: InstallProtectedFiles(AllowUI=0)
MSI (s) (1C:F8) [12:26:13:181]: Executing op: ActionStart(Name=ISNetApiInstall,,)
MSI (s) (1C:F8) [12:26:13:197]: Executing op: CustomActionSchedule(Action=ISNetApiInstall,ActionType=3073,Source=BinaryData,Target=ISNetApiInstall,)
MSI (s) (1C:F4) [12:26:13:197]: Invoking remote custom action. DLL: C:\WINDOWS\Installer\MSI56.tmp, Entrypoint: ISNetApiInstall
MSI (s) (1C:F8) [12:26:13:290]: Executing op: ActionStart(Name=ISXmlInstall,,)
MSI (s) (1C:F8) [12:26:13:290]: Executing op: CustomActionSchedule(Action=ISXmlInstall,ActionType=3073,Source=BinaryData,Target=ISXmlInstall,CustomActionData=C:\DOCUME~1\ganesh\LOCALS~1\Temp\XML1E0.tmp)
MSI (s) (1C:10) [12:26:13:306]: Invoking remote custom action. DLL: C:\WINDOWS\Installer\MSI57.tmp, Entrypoint: ISXmlInstall
InstallShield 12:26:13: Installing 1 XML component(s)
InstallShield 12:26:13: Installing XML Component 'EDSP_Service.exe.config'
InstallShield 12:26:13: Installing XML file 'C:\Program Files\SEC-Belvoir\EDSP MS Exchange Service V2\EDSP_Service.exe.config'
InstallShield 12:26:13: Using MSXML version 6
InstallShield 12:26:13: Processing XPath '//system.runtime.remoting/application[@name="EDSPV2"]'
InstallShield 12:26:13: Node name: 'application' --> Attribute name = 'name', Current Value = 'EDSPV2', Operation = '1'
InstallShield 12:26:13: Node name: 'application' - Attribute name = 'name', Old Value = 'EDSPV2', New value = 'EDSPV2', Actual New Value = 'EDSPV2'
InstallShield 12:26:13: Processing XPath '//system.runtime.remoting/application[@name="EDSPV2"]/channels/channel[@port="33" and @ref="tcp"]'
InstallShield 12:26:13: Node name: 'channel' --> Attribute name = 'port', Current Value = '33', Operation = '1'
InstallShield 12:26:13: Node name: 'channel' - Attribute name = 'port', Old Value = '33', New value = '1234', Actual New Value = '1234'
InstallShield 12:26:13: Node name: 'channel' --> Attribute name = 'ref', Current Value = 'tcp', Operation = '1'
InstallShield 12:26:13: Node name: 'channel' - Attribute name = 'ref', Old Value = 'tcp', New value = 'tcp', Actual New Value = 'tcp'
InstallShield 12:26:13: Saving XML file 'C:\Program Files\SEC-Belvoir\EDSP MS Exchange Service V2\EDSP_Service.exe.config'
InstallShield 12:26:13: Formatting XML document
InstallShield 12:26:13: Using MSXML version 6
0 Kudos
Cne9999
Level 5

OK. I see one thing that may be the issue. Look at this then let me know.

The Custom Action is scheduled as an immediate action for In Script Execution but is also scheduled under the Execute sequence.

Try moving it to the Install UI Sequence anytime after Cost Initialize.

Do this for both Custom Actions and let me know what happens.

Thanks,
Bill V.
0 Kudos
armyedsp
Level 4

Thanks Bill. No, that did not work either. I have the CA in both Install UI and Install Exec sequence set to fire after Cost Initialize. Our initial config file as installed has a port="33". It gets modified to port="1234", not port="9999". In other words, the behavior is same as before.
0 Kudos
armyedsp
Level 4

Just an update. I have worked around the problem by parsing the port directly in the config file and writing the updated value back to the file. I wrote a CA in InstallScript using ReadBytes(), WriteBytes() functions. I know our remoting config file is less than 1K, so I am using a large enough buffer of 2K to read the entire file in to memory and update the port= value and write it back to the file. This CA is inserted after InstallFiles in the InstallExec sequence for deferred execution. It works fine now. Thanks for all the help. I appreciate it.
0 Kudos