Multistrings (double null-terminated string of null-separated strings) are common in the Windows API. What's a good method for converting a multistring returned from an API to a C# string collection and vice versa?
I'm especially interested in proper handling of character encoding (Windows XP an later).
The following method seems to be okay for creating a multistring, but I don't have an example of decoding a multistring.
static string StringArrayToMultiString(
ICollection<string> stringArray
)
{
StringBuilder multiString = new StringBuilder();
if (stringArray != null)
{
foreach (string s in stringArray)
{
multiString.Append(s);
multiString.Append('\0');
}
}
return multiString.ToString();
}
This might be naïve, but how about:
static string[] MultiStringToArray(string multiString)
{
return multiString.TrimEnd('\0').Split('\0');
}
Also - aren't you missing the final And it might be easier to call if the array was a \0
(you state double-null-terminated) in StringArrayToMultiString
?params string[]
array - something like:
static string StringArrayToMultiString(params string[] values)
{
if (values == null) throw new ArgumentNullException("values");
StringBuilder multiString = new StringBuilder();
foreach (string s in values)
{
multiString.Append(s);
multiString.Append('\0');
}
return multiString.ToString();
}
[edited after clarification about final \0]
I've tested the StringArrayToMultiString method, using the ChangeServiceConfig() function to change the dependencies of a Windows service, and it works nicely for zero, one and many strings.
In the meantime, I've worked out a solution for decoding a multistring received from an API call. For example, the SCardListReaders() function returns a multistring of PC/SC reader names. I declared this as:
[DllImport("winscard.dll", CharSet = CharSet.Auto)]
static extern int SCardListReaders(
IntPtr context,
string groups,
char[] readers,
ref uint readersLen
);
Note that the readers parameter, which returns the multistring, is declared as char[]. The return value is easily parsed and converted into a collection of strings:
static string[] MultiStringToArray(
char[] multistring
)
{
List<string> stringList = new List<string>();
int i = 0;
while (i < multistring.Length)
{
int j = i;
if (multistring[j++] == '\0') break;
while (j < multistring.Length)
{
if (multistring[j++] == '\0')
{
stringList.Add(new string(multistring, i, j - i - 1));
i = j;
break;
}
}
}
return stringList.ToArray();
}
In the MSDN documentation for RegistryKey.SetValue() and RegistryKey.GetValue(), the examples simply pass in, or cast to, string[], respectively. Is there something wrong with that?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With