That makes sense now. The entire value of the environment variable was being passed as a file name, which obviously doesn't exist. Fortunately, you shouldn't need those options on CMD.EXE's command line. /e controls command interpreter extensions, which are on by default. /f control file directory and file name completion (very useful), which is off by default, but you can control both through registry settings.palahoot wrote:
the problem with the shell commmand is fixed, it appears that the comspec ev was set to: c:\windows\system32\cmd.exe /f:on /e:on so i reverted it to: c:\windows\system32\cmd.exe with no parameters, rebooted and now its working on my windows xp box.
How to get and display registry entries
Why do you need "Shell" at all?
It's easier and faster not to call external programs for every task^^
registry.bi
example.bas
Best regards,
Cherry
It's easier and faster not to call external programs for every task^^
registry.bi
Code: Select all
#Include Once "win/winreg.bi"
#Define REG_KEY_NOT_EXIST "REG_KEY_NOT_EXIST"
#Define REG_KEY_INVALID "REG_KEY_INVALID"
Type RegLib
Declare Constructor(root As HKEY, Key As String, create As Boolean = FALSE)
Declare Destructor()
Declare Function createMe() As Boolean
Declare Function deleteMe() As Boolean
Declare Function getValue(v As String) As String
Declare Function setValue(v As String, s As String) As Boolean
Declare Function getDwValue(v As String, errcheck As Boolean = FALSE) As Integer
Declare Function setDwValue(v As String, s As Integer) As Boolean
Declare Property default() As String
Declare Property default(s As String)
exists As Boolean
root As HKEY
key As String
Private:
rkey As HKEY
End Type
Constructor RegLib(root As HKEY, key As String, create As Boolean = FALSE)
this.root = root
this.key = key
If RegOpenKeyEx(root, StrPtr(key), 0, KEY_ALL_ACCESS, @this.rkey) <> ERROR_SUCCESS Then
If create Then
createMe()
Else
exists = FALSE
EndIf
Else
exists = TRUE
EndIf
End Constructor
Destructor RegLib()
RegCloseKey(rkey)
End Destructor
Function RegLib.createMe() As Boolean
If RegCreateKeyEx(root, StrPtr(key), 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, @rkey, 0) = ERROR_SUCCESS Then
exists = TRUE
Else
exists = FALSE
EndIf
Return exists
End Function
Function RegLib.deleteMe() As Boolean
If RegDeleteKey(root, StrPtr(key)) = ERROR_SUCCESS Then
exists = FALSE
Return TRUE
Else
exists = TRUE
Return FALSE
End If
End Function
Function RegLib.getValue(v As String) As String
If exists = FALSE Then Return REG_KEY_NOT_EXIST
Dim out_ As ZString * 1024
Dim l As DWORD = 512
Dim t As DWORD
If RegQueryValueEx(rkey, StrPtr(v), NULL, @t, @out_, @l) <> ERROR_SUCCESS OrElse (t <> REG_SZ AndAlso t <> REG_EXPAND_SZ) Then
Return REG_KEY_INVALID
EndIf
out_[512 - 1] = 0
Return out_
End Function
Function RegLib.setValue(v As String, s As String) As Boolean
If exists = FALSE Then Return FALSE
Return RegSetValueEx(rkey, StrPtr(v), 0, REG_SZ, StrPtr(s), Len(s) + 1) = ERROR_SUCCESS
End Function
Function RegLib.getDwValue(v As String, errcheck As Boolean = FALSE) As Integer
If exists = FALSE Then Return IIf(errcheck, -1, 0)
Dim out_ As Integer
Dim l As DWORD = 4
Dim t As DWORD
If RegQueryValueEx(rkey, StrPtr(v), NULL, @t, @out_, @l) <> ERROR_SUCCESS OrElse (t <> REG_DWORD) Then
Return IIf(errcheck, -1, 0)
EndIf
Return out_
End Function
Function RegLib.setDwValue(v As String, s As Integer) As Boolean
If exists = FALSE Then Return FALSE
Return RegSetValueEx(rkey, StrPtr(v), 0, REG_DWORD, @s, 4) = ERROR_SUCCESS
End Function
Property RegLib.default() As String
Return getValue("")
End Property
Property RegLib.default(s As String)
setValue("", s)
End Property
Type RegKey As RegLib
Code: Select all
#Include "registry.bi"
Var reg = RegKey(HKEY_CURRENT_USER, "Control Panel\Desktop")
Print reg.getValue("Wallpaper")
Sleep
Cherry
Re: How to get and display registry entries
Hey Cherry,
Many thanks. but im getting error's when i do the quick compile as well as the command line compile Here is the output:
i cheked this path and the library exists there: C:\Program Files\FreeBASIC\inc\win\winreg.bi
any thoughts?
Many thanks. but im getting error's when i do the quick compile as well as the command line compile Here is the output:
Code: Select all
C:\Program Files\FreeBASIC\fbc -s console "FbTemp.bas"
C:\Program Files\FreeBASIC\inc\win\winreg.bi(47) error 14: Expected identifier, found 'LPSTR' in 've_valuename as LPSTR'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(48) error 14: Expected identifier, found 'DWORD' in 've_valuelen as DWORD'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(49) error 14: Expected identifier, found 'DWORD' in 've_valueptr as DWORD'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(50) error 14: Expected identifier, found 'DWORD' in 've_type as DWORD'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(57) error 14: Expected identifier, found 'LPWSTR' in 've_valuename as LPWSTR'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(58) error 14: Expected identifier, found 'DWORD' in 've_valuelen as DWORD'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(59) error 14: Expected identifier, found 'DWORD' in 've_valueptr as DWORD'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(60) error 14: Expected identifier, found 'DWORD' in 've_type as DWORD'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(66) error 56: Illegal specification, at parameter 1 of RegCloseKey() in 'declare function RegCloseKey alias "RegCloseKey" (byval as HKEY) as LONG'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(67) error 56: Illegal specification, at parameter 1 of RegFlushKey() in 'declare function RegFlushKey alias "RegFlushKey" (byval as HKEY) as LONG'
C:\Program Files\FreeBASIC\inc\win\winreg.bi(67) error 123: Too many errors, exiting
any thoughts?
Re: How to get and display registry entries
winreg.bi depends on type definitions declared in windef.bi.palahoot wrote:Hey Cherry,
Many thanks. but im getting error's when i do the quick compile as well as the command line compile
i cheked this path and the library exists there: C:\Program Files\FreeBASIC\inc\win\winreg.bi
any thoughts?
Change "win\Winregbi" to "windows.bi".
Windows.bi includes almost all the header files usually required to work with the Win32 API.
Cherry's example works if Windows.bi is included prior to including his registy.bi. I assume he only included winreg.bi to cut down compile time.
See http://msdn.microsoft.com/en-us/library ... S.85).aspx for a list of data types used by the Win32 API.
Re: How to get and display registry entries
and indeed that does make the error's go away, many thanks for that fix. So now when i make the change to his program like so:codeFoil wrote: winreg.bi depends on type definitions declared in windef.bi.
Change "win\Winregbi" to "windows.bi".
Windows.bi includes almost all the header files usually required to work with the Win32 API.
Cherry's example works if Windows.bi is included prior to including his registy.bi. I assume he only included winreg.bi to cut down compile time.
See http://msdn.microsoft.com/en-us/library ... S.85).aspx for a list of data types used by the Win32 API.
Code: Select all
#Include "registry.bi"
Var reg = RegKey(HKEY_CURRENT_USER, "Software\SPAR")
Print reg.getValue("Return1")
Sleep
The reg key value type is REG_SZ and as you can see, it is just a standard string. what changes do i have to make to the program above to get it to accept the type as a REG_SZ
Re: How to get and display registry entries
First, make certain that your registry value actually exists. Check the spelling and the case.palahoot wrote: the path HKCU\Software\SPAR\Return1 does exist in the registry (i can get to the value with other methods) but when i run the new program, then i get the following error: REG_KEY_INVALID
The reg key value type is REG_SZ and as you can see, it is just a standard string. what changes do i have to make to the program above to get it to accept the type as a REG_SZ
Second, double check the registry value type.
From what I can see, Cherry's object method returns REG_KEY_INVALID if the underlying call to RegQueryValueEx returns anything other than ERROR_SUCCESS, or the value in the registry is not of type REG_SZ or REG_EXPAND_SZ. RegQueryValueEx may be returning an error code.
If your value does indeed exist, and it is of type REG_SZ, then the most likely reason that the call might fail is that the size of the string is larger than the size specified in the API call. Cherry's code specifies a maximum of 512 bytes, and declares a 1024 byte buffer to hold the returned string.
I have modified Cherry's code to output the return value of RegQueryValueEx and the byte count of the buffer required as reported by the API.
I have NOT tested this code.
Code: Select all
'****Cherry's original function modified for testing
Function RegLib.getValue(v As String) As String
If exists = FALSE Then Return REG_KEY_NOT_EXIST
Dim out_ As ZString * 1024
Dim l As DWORD = 512
Dim t As DWORD
'*** CHANGES BEGIN HERE
Dim as Long returnStatus = RegQueryValueEx( rkey ,_
StrPtr(v),_
NULL ,_
@t ,_
@out_ ,_
@l )
If returnStatus <> ERROR_SUCCESS _
OrElse (t <> REG_SZ AndAlso t <> REG_EXPAND_SZ) _
Then
Print returnStatus 'These lines are for debugging,
Print l 'and may be removed.
'*** CHANGES END HERE
Return REG_KEY_INVALID
EndIf
out_[512 - 1] = 0 'This statement forces a null termination in one did not exist
Return out_
End Function
See http://msdn.microsoft.com/en-us/library ... S.85).aspx for details on RegQueryValueEx. You might notice a detail that I have not.
Re: How to get and display registry entries
well that new piece of code (thanks codefoil) seems to have returned the following values:
234, followed by
2048 and then
reg_Key_invalid
and i can verify the type and value of the regkey by running regedit, amongst other programs... the key is valid and the type is reg_sz.
so based on the code that you added, then the return value of regqueryvalueex is 234 and the buffer is 2048, yes? so the first value is the error code (see below), but the second value is twice the size of the buffer. so i changed this line: Dim out_ As ZString * 2048 but i still have the same error.
what changes do i have to make to get this to not error out?
edit: i did check the links you suggested, is this the correct error output?
ERROR_MORE_DATA
234 (0xEA) More data is available
If the lpData buffer is too small to receive the data, the function returns ERROR_MORE_DATA.
234, followed by
2048 and then
reg_Key_invalid
and i can verify the type and value of the regkey by running regedit, amongst other programs... the key is valid and the type is reg_sz.
so based on the code that you added, then the return value of regqueryvalueex is 234 and the buffer is 2048, yes? so the first value is the error code (see below), but the second value is twice the size of the buffer. so i changed this line: Dim out_ As ZString * 2048 but i still have the same error.
what changes do i have to make to get this to not error out?
edit: i did check the links you suggested, is this the correct error output?
ERROR_MORE_DATA
234 (0xEA) More data is available
If the lpData buffer is too small to receive the data, the function returns ERROR_MORE_DATA.
Re: How to get and display registry entries
You almost nailed it. You've allocated a buffer large enough, but the RegQueryValueEx routine has no way of determining this. The last parameter specifies the largest count of bytes you are prepared to receive. When that value is less than the size of the registry value data, RegQueryValueEx returns ERROR_MORE_DATA. You need to initialize the variable l (terrible variable name) to a large enough value. You also need to change the statement just before the function return so that it does not truncate the data returned.palahoot wrote:well that new piece of code (thanks codefoil) seems to have returned the following values:
234, followed by
2048 and then
reg_Key_invalid
and i can verify the type and value of the regkey by running regedit, amongst other programs... the key is valid and the type is reg_sz.
so based on the code that you added, then the return value of regqueryvalueex is 234 and the buffer is 2048, yes? so the first value is the error code (see below), but the second value is twice the size of the buffer. so i changed this line: Dim out_ As ZString * 2048 but i still have the same error.
what changes do i have to make to get this to not error out?
edit: i did check the links you suggested, is this the correct error output?
ERROR_MORE_DATA
234 (0xEA) More data is available
If the lpData buffer is too small to receive the data, the function returns ERROR_MORE_DATA.
However, unless you know the maximum size of the data that is going to be stored in your registry key value, I don't advise using this code. It was a good example, but it is not structured for general purpose use. The example code on the MSDN page for ReqQueryValueEx illustrates a different method. (also not ideal, but more flexible)
If you have a lot of time invested in your shelling technique, I wouldn't get bogged down right now with learning the API calls. If you do have the time, go for it.
By the way, the buffer size that is being requested might not necessarily be the size of the data in your registry value. It seems like quite a coincidence that the value that came back is exactly 2 kilobytes. This may simply be the minimum size that the API routine is willing to work with in this case. On the other hand, 2 kilobytes is the largest byte count that the SDK documentation recommends storing in a registry key value. Above that limit, it is recommended that the data be stored in a file, and a file name stored in the registry.
Re: How to get and display registry entries
so should i change all of the dim l as dword =2048 then? and should it still be a dword? and what to change in the function so that it doesn't truncate?
yes the max size is 8096 according to the spec's for SET, but i cant image a "path" that is longer that 2048 characters so i think that i can safely set the max size to 2k.
no on the too much time in shelling, just unsure of the "best" way to implement. i can already save to disk, so that part is not an issue. just is it best to save it to: 1) registry? 2) file? 3) environment table. i like the envvar cause you can do "dir %return1%" or any other command that looks at directories or files (like copy filename.ext %return2% ).
so it depends on whether its best to use file vs registry or use all three to their best practice.
thoughts?
yes the max size is 8096 according to the spec's for SET, but i cant image a "path" that is longer that 2048 characters so i think that i can safely set the max size to 2k.
no on the too much time in shelling, just unsure of the "best" way to implement. i can already save to disk, so that part is not an issue. just is it best to save it to: 1) registry? 2) file? 3) environment table. i like the envvar cause you can do "dir %return1%" or any other command that looks at directories or files (like copy filename.ext %return2% ).
so it depends on whether its best to use file vs registry or use all three to their best practice.
thoughts?