 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
Posted: Tue Apr 04, 2006 9:02 pm Post subject: Simple Change to IniRead |
|
|
I think GetPrivateProfileString is used with IniRead and if we can mod the call to allow for a null Section parameter or a null Key parameter, then the call would return all section names or key names, respectively, from an INI file.
Reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getprivateprofilestring.asp
"lpAppName
[in] The name of 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.
lpKeyName
[in] The name of the key 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.".
Chris, can we get this implemented?
I already know about IniKeyGet, but this could be a better option in some cases... _________________ I am he of whom he speaks! |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Wed Apr 05, 2006 8:33 am Post subject: |
|
|
IniKeyGet? What is it? Even Google returned nothing on this word.
BTW, I spotted a typo in the IniRead page: Key | The key name in the in the .ini file.
(stupid BBCode that doesn't allow nesting of color tags...)
I don't know if INI files are so much used, nowadays, that such functionnality is to be implemented. If so, I suppose it could be made on the model of Loop (registry). Otherwise, perhaps a DllCall solution is to be implemented. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Wed Apr 05, 2006 10:45 am Post subject: |
|
|
| I'll add this to the to-do list; thanks. If you need it right away, hopefully it can be done with DllCall. |
|
| Back to top |
|
 |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
|
| Back to top |
|
 |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
Posted: Wed Apr 05, 2006 8:30 pm Post subject: |
|
|
I have the basic DllCall created and it works:
VarSetCapacity( buff, 10000 )
i:=10000
numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"Section",Str,"Key",Str,"Default",Str,buff,Int,i,Str,"C:\autokey\scripts\test.ini",Int)
msgbox, % buff
Now the issue is with my suggestion of retrieving all the section or key names. I can get it to work, and the buffer contains all key names, but they are nul char delimited. Any suggestions how I can split the buffer using a nul character as the delimiter?
Note that if you want to pass a section or key param as NULL with this call, use Int,0. _________________ I am he of whom he speaks! |
|
| Back to top |
|
 |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
Posted: Wed Apr 05, 2006 10:25 pm Post subject: |
|
|
Ok, got it working. I had to convert the binary string to hex, change the nuls to newlines and convert the hex string back to binary. I utilized the Bin2Hex and Hex2Bin functions written by Laszlo (thanks!) with a one line modification of Bin2Hex.
Here is my code:
| Code: |
VarSetCapacity( buff, 10000 )
i:=10000
; Normal - Return Value of Key
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"Section",Str,"Key",Str,"Default",Str,buff,Int,i,Str,"C:\a.ini",Int)
msgbox,% "Value: " . buff
; Return Key names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"Section",Int,0,Str,"Default",Str,buff,Int,i,Str,"C:\a.ini",Int)
Bin2Hex(knb,buff,numchars)
StringReplace, knb, knb,-00,0A, All
StringReplace, knb, knb,-,, All
Hex2Bin(knames,knb,numchars)
msgbox,% "Key Names: " . knames
; Return Section names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Int,0,Int,0,Str,"Default",Str,buff,Int,i,Str,"C:\a.ini",Int)
Bin2Hex(snb,buff,numchars)
StringReplace, snb, snb,-00,0A, All
StringReplace, snb, snb,-,, All
Hex2Bin(snames,snb,numchars)
msgbox,% "Section Names: ". snames
Return
Bin2Hex(ByRef h, ByRef b, n=0) ; n bytes binary data -> stream of 2-digit
;hex
{
; n = 0: all (SetCapacity can be larger than used!)
format = %A_FormatInteger% ; save original integer format
SetFormat Integer, Hex ; for converting bytes to hex
m := VarSetCapacity(b)
If (n < 1 or n > m)
n := m
Address := &b
h =
Loop %n%
{
x := *Address ; get byte in hex
StringTrimLeft x, x, 2 ; remove 0x
x = 0%x% ; pad left
StringRight x, x, 2 ; 2 hex digits
h = %h%-%x% ; modded for null character identification
Address++
}
SetFormat Integer, %format% ; restore original format
}
Hex2Bin(ByRef b, h, n=0) ; n hex digit-pairs -> binary data
{ ; n = 0: all. (Only ByRef can handle binaries)
m := Ceil(StrLen(h)/2)
If (n < 1 or n > m)
n := m
Granted := VarSetCapacity(b, n, 33)
IfLess Granted,%n%, {
ErrorLevel = Mem=%Granted%
Return
}
StringLeft b, b, n
Address := &b
Loop %n%
{
StringLeft x, h, 2
StringTrimLeft h, h, 2
x = 0x%x%
DllCall("RtlFillMemory", "UInt", Address, "UInt", 1, "UChar", x)
Address++
}
}
|
I threw this all together rather quickly so it may have an issue or three. _________________ I am he of whom he speaks! |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4012 Location: Pittsburgh
|
Posted: Wed Apr 05, 2006 11:41 pm Post subject: |
|
|
Try CharReplace(buff,0,13,numchars) with this function | Code: | CharReplace(ByRef Buf, Ch1, Ch2, Len=0) {
m := VarSetCapacity(Buf)
If (Len < 1 or Len > m)
Len = %m%
Loop %Len%
If (*(&Buf+A_Index-1) = Ch1)
DllCall("RtlFillMemory", UInt,&Buf+A_Index-1, UInt,1, UInt,Ch2)
} |
Edit: fixed typo: 1st param at call must be the buffer name.
Last edited by Laszlo on Thu Apr 06, 2006 3:47 am; edited 1 time in total |
|
| Back to top |
|
 |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
Posted: Thu Apr 06, 2006 1:01 am Post subject: |
|
|
I tried it with CharReplace(buff,0,13,numchars) and it seemed to choke when it got to the first nul character in the string. In other words, it returned the first key name and then a garbage char, then nothing... Does it work for you? If so, please post INI and example code. Thx _________________ I am he of whom he speaks! |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4012 Location: Pittsburgh
|
Posted: Thu Apr 06, 2006 3:42 am Post subject: |
|
|
Sorry, the 1st parameter has to be "buff", of course, as you noticed. It works for me (Win XP, SP2, AHK 1.0.43.04): | Code: | i = 10000
VarSetCapacity( buff, i )
; Return Key names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"HotKeys"
,Int,0,Str,"???",Str,buff,Int,i,Str,"c:\t\AutoHotKey\SKey.ini",Int)
CharReplace(buff, 0, 13, numchars)
MsgBox %buff%
CharReplace(ByRef Buf, Ch1, Ch2, Len=0) { ; In Buf all char Ch1 is replaced with Ch2 (NUL:0->`n:13)
m := VarSetCapacity(Buf)
If (Len < 1 or Len > m)
Len = %m%
Loop %Len%
If (*(&Buf+A_Index-1) = Ch1)
DllCall("RtlFillMemory", UInt,&Buf+A_Index-1, UInt,1, UInt,Ch2)
} | My ini file looks like | Code: | [ProcessDefaults]
ANSI =Mew32.exe,sbrowser.exe,pdexplo.exe
Unicode =WinWord.exe,PowerPnt.exe,WordPad.exe,Notepad.exe,IEXPLORE.EXE,nlnotes.exe,WINWORD.EXE
OFF =MathKernel.exe,Matlab.exe,Calc.exe
[HotKeys]
ForwardKey = CapsLock
BackwardKey = CapsLock & LShift
SymbolUpKey = CapsLock & Tab
SymbolDnKey = CapsLock & q
ReplaceKey = CapsLock & r
GuiWindKey = !CapsLock
[ANSIcodeRings]
… | ...and the MsgBox shows | Code: | ---------------------------
w.ahk
---------------------------
ForwardKey
BackwardKey
SymbolUpKey
SymbolDnKey
ReplaceKey
GuiWindKey
---------------------------
OK
--------------------------- |
|
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2397
|
Posted: Thu Apr 06, 2006 6:36 am Post subject: |
|
|
| Code: | IniReadEx(IFile, ISect="", IKey="", Delim=124, buffsz=10000)
{
IfNotExist, %IFile%
Return, "Error: File not found"
VarSetCapacity( buff, buffsz )
If ISect=
numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Int,0,Int,0,Int,0,Str,buff,Int,buffsz,Str,IFile,Int)
Else If IKey=
numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Str,ISect,Int,0,Int,0,Str,buff,Int,buffsz,Str,IFile,Int)
Else
numchar:=DllCall("kernel32.dll\GetPrivateProfileString",Str,ISect,Str,IKey,Int,0,Str,buff,Int,buffsz,Str,IFile,Int)
If (numchar > 1) {
Loop {
ahklen := StrLen(buff)
If (ahklen < (numchar -1))
DllCall("RtlFillMemory", UInt,(&buff+ahklen), UInt,1, UChar,Delim)
Else
break
}
}
Return, buff
} |
|
|
| Back to top |
|
 |
Atomhrt
Joined: 02 Sep 2004 Posts: 128 Location: Sunnyvale
|
Posted: Thu Apr 06, 2006 3:37 pm Post subject: |
|
|
This is what I was using: msgbox,% "Key Names: " . buff
...which does not work...
msgbox,Key Names: %buff%
... works fine...
Do we have a bug here? _________________ I am he of whom he speaks! |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4012 Location: Pittsburgh
|
Posted: Thu Apr 06, 2006 4:36 pm Post subject: |
|
|
| Add "StringReplace buff, buff, `n, `r`n, All". It looks like in expressions `n is not enough for a new line. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4012 Location: Pittsburgh
|
Posted: Thu Apr 06, 2006 4:50 pm Post subject: |
|
|
You can use the CharChange function below, which is slower, but can replace a char with an arbitrary string. | Code: | i = 10000
VarSetCapacity( buff, i )
; Return Key names
numchars:=DllCall("kernel32.dll\GetPrivateProfileString",Str,"HotKeys"
,Int,0,Str,"???",Str,buff,Int,i,Str,"c:\t\AutoHotKey\SKey.ini",Int)
msgbox % "Key Names: " CharChange(buff, 0, "`r`n", numchars)
CharChange(ByRef Buf, Ch, Str, Len=0) { ; In Buf all char of code Ch is replaced with Str
m := VarSetCapacity(Buf) ; Buf := CharChange(Buf, 0, "`r`n"): Nul -> new line
If (Len < 1 or Len > m)
Len = %m%
Loop %Len%
If (*(&Buf+A_Index-1) = Ch)
out = %out%%Str%
Else out:= out Chr(*(&Buf+A_Index-1))
Return out
} |
Last edited by Laszlo on Thu Apr 06, 2006 5:08 pm; edited 1 time in total |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2397
|
Posted: Thu Apr 06, 2006 5:00 pm Post subject: |
|
|
Using the function I posted above:
| Code: |
MsgBox, % IniReadEx("C:\a.ini", "HotKeys" )
|
or change the file name, section, etc... for the file you are using... |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4012 Location: Pittsburgh
|
Posted: Thu Apr 06, 2006 5:21 pm Post subject: |
|
|
| @corrupt: Your specialized version of StringReplace suffers from the same problem: if you set the delimiter character code to 13 (`n), it won't always be recognized as new line. With your default pipe "|" the problem remains hidden, everything is in one line. If some of your key names contain pipe characters, you are out of luck. `n is safer, because it cannot be part of a key name or value. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|