Ich bin auf das Problem gestoßen, einen String, der mehrere Null-Terminierungen enthält, zu Lesen.
Die Funktion "GetPrivateProfileString" liefert solch einen String, deshalb habe ich hiermit ein Bsp. erstellt.
Der folgende Aufruf liefert die Sektionsnamen einer INI-Datei in der Form:
Sektion_1 Chr(0) Sektion_2 Chr(0) ... Sektion_n Chr(0) Chr(0)
In der dritten Variante gehe ich den Umweg über ein Byte-Array. Da kann ich die Null-Bytes sauber auslesen, ohne das danach abgebrochen wird.
Aber ist das tatsächlich der einzige Weg - oder sehe ich gerade den Wald vor lauter Bäumen nicht?
AutoIt
$sINI = "Eine *.ini"
; mit Sektion=Null werden alle Sektionsnamen hintereinander Null-terminiert ausgegeben. Nach dem letzten Element folgt eine zusätzliche Null.
_Ini_Read_1($sINI) ; korrekte Pufferlänge, aber nur erstes Element
ConsoleWrite(@CRLF)
_Ini_Read_2($sINI) ; korrekte Pufferlänge, aber nur erstes Element
ConsoleWrite(@CRLF)
; mit diesem Umweg klappt es
_Ini_Read_3($sINI) ; korrekte Pufferlänge, alle Elemente
Func _Ini_Read_1($lpFileName, $lpAppName=Null, $lpKeyName=Null, $lpDefault='')
Local $0 = Chr(0)
$lpAppName = $lpAppName = Null ? Null : $lpAppName & $0
$lpKeyName = $lpKeyName = Null ? Null : $lpKeyName & $0
$lpDefault = $lpDefault = '' ? '' : $lpDefault & $0
Local $nSize = 32767
Local $tString = DllStructCreate('char[' & $nSize & ']')
Local $aRes = DllCall('kernel32.dll', 'dword', 'GetPrivateProfileString', _
'str', $lpAppName, _ ; A null-terminated string that specifies the section containing the key name. If this parameter is NULL, the GetPrivateProfileString function copies all section names in the file to the supplied buffer.
'str', $lpKeyName, _ ; The null-terminated string containing the key name whose associated string is to be retrieved. If this parameter is NULL, all key names in the section specified by the lpAppName parameter are copied to the buffer specified by the lpReturnedString parameter.
'str', $lpDefault, _ ; A null-terminated default string. If the lpKeyName key cannot be found in the initialization file, GetPrivateProfileString copies the default string to the lpReturnedString buffer. This parameter cannot be NULL. Avoid specifying a default string with trailing blank characters. The function inserts a null character in the lpReturnedString buffer to strip any trailing blanks.
'struct*', $tString, _ ; Pointer to the buffer that receives the retrieved string.
'dword', $nSize, _ ; Specifies the size, in characters, of the buffer pointed to by the lpReturnedString parameter.
'str', $lpFileName & $0)
ConsoleWrite('Anzahl Zeichen im Puffer: ' & $aRes[0] & @CRLF)
ConsoleWrite('Inhalt Puffer: ' & DllStructGetData($tString, 1) & @CRLF)
EndFunc
Func _Ini_Read_2($lpFileName, $lpAppName=Null, $lpKeyName=Null, $lpDefault='')
Local $0 = Chr(0)
$lpAppName = $lpAppName = Null ? Null : $lpAppName & $0
$lpKeyName = $lpKeyName = Null ? Null : $lpKeyName & $0
$lpDefault = $lpDefault = '' ? '' : $lpDefault & $0
Local $nSize = 32767
Local $aRes = DllCall('kernel32.dll', 'dword', 'GetPrivateProfileString', _
'str', $lpAppName, _
'str', $lpKeyName, _
'str', $lpDefault, _
'str', '', _
'dword', $nSize, _
'str', $lpFileName & $0)
ConsoleWrite('Anzahl Zeichen im Puffer: ' & $aRes[0] & @CRLF)
ConsoleWrite('Inhalt Puffer: ' & $aRes[4] & @CRLF)
EndFunc
Func _Ini_Read_3($lpFileName, $lpAppName=Null, $lpKeyName=Null, $lpDefault='')
Local $0 = Chr(0)
$lpAppName = $lpAppName = Null ? Null : $lpAppName & $0
$lpKeyName = $lpKeyName = Null ? Null : $lpKeyName & $0
$lpDefault = $lpDefault = '' ? '' : $lpDefault & $0
Local $nSize = 32767
Local $tBuffer = DllStructCreate('byte[' & $nSize*2 & ']')
Local $lpReturnedString = DllStructGetPtr($tBuffer)
Local $aRes = DllCall('kernel32.dll', 'dword', 'GetPrivateProfileString', _
'str', $lpAppName, _
'str', $lpKeyName, _
'str', $lpDefault, _
'ptr', $lpReturnedString, _
'dword', $nSize, _
'str', $lpFileName & $0)
ConsoleWrite('Anzahl Zeichen im Puffer: ' & $aRes[0] & @CRLF)
ConsoleWrite('Inhalt Puffer: ' & __MultiStrBinaryToString(DllStructGetData($tBuffer, 1), '|') & @CRLF)
EndFunc
Func __MultiStrBinaryToString($_sBin, $_sDelim)
$_sBin = StringTrimLeft($_sBin, 2)
Local $sOut = '', $iChar, $iLast = ''
For $i = 1 To StringLen($_sBin) -2 Step 2
$iChar = StringMid($_sBin, $i, 2)
If $iChar = '00' Then
If $iLast = '00' Then ExitLoop
$iLast = '00'
$sOut &= $_sDelim
Else
$sOut &= Chr('0x' & $iChar)
$iLast = $iChar
EndIf
Next
$sOut = StringRegExpReplace($sOut, '\' & $_sDelim & '$', '')
Return $sOut
EndFunc
Alles anzeigen