jglouie
jglouie

Reputation: 12880

.NET String [] operator returns different stuff from ToString()

I have a .NET Custom Action (DTF) executing from InstallShield.

In the .NET CA, I'm pulling an MSI property whose value is "[CommonAppDataFolder]abc\def.txt".

The property is accessed as follows:

string val = session["MY_PROPERTY"]; // Microsoft.Deployment.WindowsInstaller.Session

When I print this variable out to a log file, I get: C:\ProgramData\abc\def.txt. This is what I expect.

However, when I use the [] operator to look character-by-character, I get characters from the unsubstituted value: [CommonAppDataFolder]... for example, val[0] is '[' instead of 'C'.

How in the world is this possible?

Also, the ==, string.compare(), !=, etc. are all not giving expected results (I'd imagine these use the [] operator underneath the hood).

EDIT:

This is how I'm logging: session.Log("File name: {0}", val);

This is how I'm printing character-by-character:

for (int i = 0; i < val.Length; i++) 
{ 
    session.Log(val[i].ToString());
}

Upvotes: 3

Views: 128

Answers (1)

Eddy
Eddy

Reputation: 5360

The string val does still contain the unsubstituted version so the for loop works fine.
The Log() method in the session uses 'val' as a formatstring (and not as a literal) which replaces any placeholders with the actual values before writing the result.

If you download the debug symbols (output is probably not legal to post here) you can see this happening.

In short Log() calls Message() and that calls MsiProcessMessage() in that msdn page it refers to MsiFormatRecord(). At the end of that document it explains the substitutions that take place automatically. Most notably for this case:

  • If a substring of the form [propertyname] is encountered, it is replaced by the value of the property.
  • If a substring of the form [%environmentvariable] is found, the value of the environment variable is substituted.

Try the following code to get your expected results

string formattedVal = session.Format(val)
for (int i = 0; i < formattedVal.Length; i++)  
{  
    session.Log(formattedVal[i].ToString()); 
} 

Upvotes: 4

Related Questions