fbpx
Welcome, Guest
Username: Password: Remember me
Hier wird Deutsch gesprochen
  • Page:
  • 1

TOPIC: GetPrivateProfileString

GetPrivateProfileString 09 Jan 2020 13:26 #12515

  • lagraf's Avatar

  • lagraf

  • Topic Author


  • Posts: 121
  • Ich lese einen String aus einer INI-Datei mit:
    METHOD GetString(cSection, cEntry) 
    LOCAL ptrBuffer AS PTR
    LOCAL cValue AS STRING
    	
    ptrBuffer := MemAlloc(INI_STRING_LEN)
    GetPrivateProfileString(String2Psz(cSection), String2Psz(cEntry), String2Psz(" "), PSZ( _CAST, ptrBuffer ), INI_STRING_LEN, String2Psz(SELF:fullPath))
    cValue := Psz2String(PSZ(_CAST, ptrBuffer))
    MemFree(ptrBuffer)
    RETURN cValue

    Die gesamte Section wäre demnach
    METHOD GetSection(cSection) CLASS IniFile
    LOCAL cBuffer AS STRING
    LOCAL ptrBuffer AS PTR
    LOCAL nLen AS DWORD
    	
    ptrBuffer := MemAlloc(INI_STRING_LEN)
    nLen := GetPrivateProfileString(String2Psz(cSection), NULL_PSZ, String2Psz(" "), PSZ(_CAST, ptrBuffer), INI_STRING_LEN, String2Psz(SELF:FullPath))
    cBuffer := Psz2String(PSZ(_CAST, ptrBuffer))
    MemFree(ptrBuffer)
    RETURN IIF(nLen<=0, {}, String2Array(Left(cBuffer, nLen-1), _CHR(0)))

    Ich erhalte aber immer nur das erste Element, hat sich da etwas seit VO geändert?
    LG Franz

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 09 Jan 2020 16:35 #12519

  • wriedmann's Avatar

  • wriedmann


  • Posts: 2232
  • Hallo Franz,
    da hat sich nichts geändert.... Das Problem ist, dass dieser Buffer Null-terminierte Strings enthält, und unter X# ist alles Unicode....
    Versuchs mal damit:
    public virtual method GetSection( cSection as string ) as array
    	local aReturn		as array
    	local pszBuffer		as byte[]
    	local aEntries		as string[]
    	local nPos			as int
    	local nMaxLen		as int
    
    	aReturn				:= {}
    	nMaxLen			:= 65767
    	pszBuffer			:= byte[]{ nMaxLen }
    	if IniFile.GetSection( cSection, pszBuffer, nMaxLen, _cFileName )
    		aEntries			:= Encoding.ASCII:GetString( pszBuffer ):Trim( '\0' ):Split( '\0' )
    		foreach cEntry as string in aEntries
    			AAdd( aReturn, cEntry )
    		next
    	endif
    
    	return aReturn
    [DllImport("kernel32.dll",CharSet:=CharSet.Ansi,EntryPoint:="GetPrivateProfileSection")];
    static method GetSection(lpAppName as string, lpszReturnBuffer as byte[], nSize as int, lpFileName as string) as logic pascal

    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 09 Jan 2020 18:15 #12522

  • Karl-Heinz's Avatar

  • Karl-Heinz


  • Posts: 550
  • Hallo Franz,

    >> Ich erhalte aber immer nur das erste Element, hat sich da etwas seit VO geändert?

    Ich kann mir nicht vorstellen, dass Deine GetSection() Methode - so wie gepostet - mit VO funktioniert. Da ptrBuffer mit chr(0) separierte Strings enthält bewirkt ein

    cBuffer := Psz2String(PSZ(_CAST, ptrBuffer))

    dass cBuffer immer nur den ersten string beinhaltet.

    wäre der Inhalt von ptrBuffer:

    "eins" + CHR (0) + "zwei" + CHR (0) + "Drei" + CHR (0) + CHR ( 0 )

    wäre der Inhalt von cBuffer also immer "eins".

    So sollte es mit VO und X# funktionieren. Den besseren net Weg hat ja Wolfgang gepostet.
    METHOD GetSection(cSection) CLASS IniFile
    LOCAL ptrBuffer AS PTR
    LOCAL nLen AS DWORD
    local aValues := {} as array 
    
    ptrBuffer := MemAlloc(INI_STRING_LEN)
    
    nLen := GetPrivateProfileString(String2Psz(cSection), NULL_PSZ, String2Psz(" "), PSZ(_CAST, ptrBuffer), INI_STRING_LEN, String2Psz(SELF:FullPath))
    
    if nLen > 0 
    
       aValues := Psz2Array ( ptrBuffer )
    
    endif 
    
    MemFree(ptrBuffer)
    
    RETURN aValues 
    FUNCTION Psz2Array ( ptrEnv AS PTR ) AS ARRAY PASCAL
    LOCAL ptrTemp AS BYTE PTR
    LOCAL cString AS STRING
    LOCAL aRet := {} AS ARRAY
    
    	ptrTemp := ptrEnv
    
    	cString := Psz2String ( ptrTemp )
    
    	WHILE cString != NULL_STRING
    	
    		AAdd ( aRet , cString  )
    	
    		ptrTemp +=  SLen ( cString ) + 1
    	
    		cString := Psz2String ( ptrTemp )
    	
    	ENDDO
    
    	RETURN  aRet
    

    Gruß
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 09 Jan 2020 19:20 #12524

  • lagraf's Avatar

  • lagraf

  • Topic Author


  • Posts: 121
  • Hallo Karl-Heinz,
    dein Code funktioniert! Mein Code in VO war noch etwas einfacher, ich hatte ihn schon so angepaßt, dass X# keine Fehler mehr gemeldet hat, das Original war:
    METHOD GetSection(cSection) CLASS IniFile
    LOCAL cBuffer AS STRING
    LOCAL nLen AS DWORD
    	
    cBuffer := Buffer(4096)
    nLen := GetPrivateProfileString(PSZ(cSection), NULL_PTR, PSZ(" "), PSZ(cBuffer), 4096, PSZ(SELF:FullPath))
    RETURN IIF(nLen<=0, {}, String2Array(Left(cBuffer, nLen-1), _CHR(0)))

    Hallo Wolfgang,
    [DllImport("kernel32.dll" ...
    habe ich entfernt, da jede Menge Fehler. Danach bleiben 2 Fehler übrig:
    error XS0120: An object reference is required for the non-static field, method, or property 'IniFile.GetSection(params XSharp.__Usual[])'
    error XS0103: The name 'Encoding' does not exist in the current context

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 09 Jan 2020 19:29 #12525

  • wriedmann's Avatar

  • wriedmann


  • Posts: 2232
  • Hallo Franz,
    auf den DLLImport kannst Du nicht verzichten, ggf. solltest Du den Namen anpassen, z.B. auf
    [DllImport("kernel32.dll",CharSet:=CharSet.Ansi,EntryPoint:="GetPrivateProfileSection")];
    static method GetSectionX(lpAppName as string, lpszReturnBuffer as byte[], nSize as int, lpFileName as string) as logic pascal
    und dann den Aufruf entsprechend anpassen.
    Den Fehler mit dem Encoding kannst Du durch ein
    using System.Text
    im Kopf der Datei beheben, bzw. durch volle Qualifizierung:
    System.Text.Encoding.ASCII:GetString( pszBuffer )
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 07:57 #12530

  • lagraf's Avatar

  • lagraf

  • Topic Author


  • Posts: 121
  • Hallo Wolfgang,
    PUBLIC VIRTUAL METHOD GetSection( cSection AS STRING ) AS ARRAY
    ...
    IF IniFile.GetSectionX( cSection, pszBuffer, nMaxLen, "C:\WINAPPS\PDFMAIL\PDFMAIL.INI" )
    ...
    [DllImport("kernel32.dll",CharSet:=CharSet.Ansi,EntryPoint:="GetPrivateProfileSection")];
    STATIC METHOD GetSectionX(lpAppName AS STRING, lpszReturnBuffer AS BYTE[], nSize AS INT, lpFileName AS STRING) AS LOGIC PASCAL

    bringt die Fehler
    error XS0246: The type or namespace name 'DllImportAttribute' could not be found (are you missing a using directive or an assembly reference?)
    error XS0246: The type or namespace name 'DllImport' could not be found (are you missing a using directive or an assembly reference?)
    error XS0246: The type or namespace name 'CharSet' could not be found (are you missing a using directive or an assembly reference?)
    error XS0103: The name 'CharSet' does not exist in the current context
    error XS0246: The type or namespace name 'EntryPoint' could not be found (are you missing a using directive or an assembly reference?)

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 08:19 #12531

  • wriedmann's Avatar

  • wriedmann


  • Posts: 2232
  • Hallo Franz,

    bitte ergänze oben in der PRG-Datei
    using System.Runtime.InteropServices
    .NET organisiert die Klassen und Methoden in sogenannten Namespaces. Dadurch kommt es nicht mehr zu Überschneidungen zwischen verschiedenen Klassen, die in verschiedenen Assemblies mit demselben Namen vorliegen können.
    Und die Klassen und Attribute für die Einbindung sind im Namespace System.Runtime.Interop definiert.
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 08:35 #12532

  • lagraf's Avatar

  • lagraf

  • Topic Author


  • Posts: 121
  • Hallo Wolfgang,
    damit bleibt nun noch zwei identische Meldungen bei der Zeile System.Text.Encoding.ASCII:
    error XS1503: Argument 1: cannot convert from 'string' to 'char'

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 09:18 #12533

  • wriedmann's Avatar

  • wriedmann


  • Posts: 2232
  • Hallo Franz,

    sorry, im VO-Dialekt muss man bei den einfachen Hochkommas definieren, dass die als Char zu interpretieren sind:
    aEntries := Encoding.ASCII:GetString( pszBuffer ):Trim( c'\0' ):Split( c'\0' )
    Mein Code ist nämlich im Core-Dialekt und gibt ein Dictionary zurück:
    public virtual method GetSection( cSection as string ) as Dictionary<string,string>
    	local oReturn		as Dictionary<string,string>
    	local pszBuffer		as byte[]
    	local aEntries		as string[]
    	local cKey			as string
    	local cValue		as string
    	local nPos			as int
    	local nMaxLen		as int
    
    	oReturn				:= Dictionary<string,string>{}
    	nMaxLen				:= 65767
    	pszBuffer			:= byte[]{ nMaxLen }
    	if IniFile.GetSection( cSection, pszBuffer, nMaxLen, _cFileName )
    		aEntries			:= Encoding.ASCII:GetString( pszBuffer ):Trim( '\0' ):Split( '\0' )
    		foreach cEntry as string in aEntries
    			nPos				:= cEntry:IndexOf( "=" )
    			if nPos > 0
    				cKey				:= cEntry:SubStr( 0, nPos )
    				cValue				:= cEntry:SubStr( nPos + 1 )
    				oReturn:Add( cKey, cValue )
    			endif
    		next
    	endif
    
    	return oReturn

    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 09:42 #12534

  • lagraf's Avatar

  • lagraf

  • Topic Author


  • Posts: 121
  • Hallo Wolfgang,
    das sind dann die Feinheiten! Die Methode bringt im Gegensatz zum VO-Code nicht nur die Schlüsselworte, sondern auch gleich den Wert dazu. Danke, so funktionierts jetzt!

    Eine Frage: Ich sehe immer wieder, dass du versuchst, soviel wie möglich mit .NET zu lösen. Beziehst du dein Wissen über .NET aus dem Netz oder aus einem Buch? Wie geht man da am Besten vor um sich zu informieren oder eine Lösung für eine Problemstellung zu finden?

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 09:52 #12536

  • wriedmann's Avatar

  • wriedmann


  • Posts: 2232
  • Hallo Franz,
    auch meine VO-Version liefert Schlüsselworte und Werte zurück, in einem zweidimensionalen Array.

    Was die Lösung über .NET betrifft: ich probiere das meistens über .NET zu lösen, weil die Lösung da fast immer wesentlich einfacher und leistungsfähiger ist. Für manche Dinge braucht es in VO viel eigenen Code, und in .NET ist es eine Zeile.
    Ein gutes Beispiel ist z.B. die Methode Split() der String-Klasse. Die zerlegt einen String in Teile:
    docs.microsoft.com/en-us/dotnet/api/syst...iew=netframework-4.8
    Sowas habe ich zwar in VO, aber wesentlich weniger leistungsfähig und fehleranfälliger, und zudem nicht Unicode-fähig.
    Was die Suche betrifft: Google ist der beste Freund, vielleicht kombiniert mit dem Zusatzwort C#. StackOverflow bietet sehr oft gute Lösungen, aber auch die Microsoft-Seiten selber.
    Und der Rest ist viel Probieren....
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 10:39 #12538

  • lumberjack's Avatar

  • lumberjack


  • Posts: 680
  • Hi Franz,

    lagraf wrote: Ich lese einen String aus einer INI-Datei mit:

    I wrote a .INI file reader in the Vulcan days that does not require the Win32 API calls. Not sure if you have it, otherwise please let me know and I can submit it.
    ______________________
    Johan Nel
    George, South Africa

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 10:58 #12540

  • wriedmann's Avatar

  • wriedmann


  • Posts: 2232
  • Hi Johan,
    yes, I know your code (and I have similar code from my Clipper times <g>).
    But I do prefer using the Windows API to be 100% compatible with VO and other applications that access Ini files.
    Wolfgang
    Wolfgang Riedmann
    Meran, South Tyrol, Italy

    www.riedmann.it - docs.xsharp.it

    Please Log in or Create an account to join the conversation.

    GetPrivateProfileString 10 Jan 2020 14:16 #12544

  • lagraf's Avatar

  • lagraf

  • Topic Author


  • Posts: 121
  • Hi Johan,
    thank you for your offer, but I use GetPrivateProfileString in my INI reader in all my apps for years and with the code of Karl-Heinz it also does well in X#! If M$ deletes this call in the future I would come back to you!
    Franz

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1
    Moderators: wriedmann