I was looking for a way to write Unicode characters to an INI file. I stumbled upon some solutions which were not satisfactory: they involved ANSI/UTF-8 files. So here is a workaround, including a small sample project.
Module INI
Private Declare Ansi Function WritePrivateProfileString _
Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As String, _
ByVal lpKeyName As String, ByVal lpString As String, _
ByVal lpFileName As String) As Integer
Private Declare Auto Function GetPrivateProfileString Lib "kernel32" (ByVal lpAppName As String, _
ByVal lpKeyName As String, _
ByVal lpDefault As String, _
ByVal lpReturnedString As StringBuilder, _
ByVal nSize As Integer, _
ByVal lpFileName As String) As Integer
Private Const EscapeChar As String = "#"
Public Sub WritePrivateProfileStringUnicode(ApplicationName As String, KeyName As String, Value As String, FileName As String)
Dim ValueUnicode As String = EncodeUnicodeString(Value)
WritePrivateProfileString(ApplicationName, KeyName, ValueUnicode, FileName)
End Sub
Public Function GetPrivateProfileStringUnicode(ApplicationName As String, KeyName As String, FileName As String) As String
Dim sb As New StringBuilder(500)
GetPrivateProfileString(ApplicationName, KeyName, "", sb, sb.Capacity, FileName)
Return DecodeUnicodeString(sb.ToString())
End Function
Public Function EncodeUnicodeString(value As String) As String
Dim NewValue As String = Replace(value, EscapeChar, EscapeChar & Asc(EscapeChar) & EscapeChar)
If IsUnicode(NewValue) Then
Dim i As Integer
Dim ValueUnicode As String = ""
For i = 1 To Len(NewValue)
Dim strChar As String = Mid(NewValue, i, 1)
If AscW(strChar) > 255 Or AscW(strChar) < 0 Then
strChar = EscapeChar & AscW(strChar) & EscapeChar
End If
ValueUnicode = ValueUnicode & strChar
Next
Return ValueUnicode
Else
Return NewValue
End If
End Function
Public Function DecodeUnicodeString(value As String) As String
If InStr(Value, EscapeChar) = 0 Then
Return Value
Else
Dim i As Integer
Dim Parts() As String = Split(Value, EscapeChar) For i = 1 To UBound(Parts) Step 2 Parts(i) = Trim(ChrW(CInt(Parts(i))))
Next
Return Join(Parts, "") End If
End Function
Private Function IsUnicode(input As String) As Boolean
Dim asciiBytesCount = Encoding.ASCII.GetByteCount(input)
Dim unicodBytesCount = Encoding.UTF8.GetByteCount(input)
Return asciiBytesCount <> unicodBytesCount
End Function
End Module