11-23-2010 10:41 AM
Hello. In Programmer Box - 3 functions to get data from registry.
If parameter register is string - no problem. But if type is Reg_Expand_SZ - all functions don't work.
What i need to do to get this registry entry? If don't difficult - with example.
OS - Win XP.
Tree: '\HKEY LOCAL MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup
Parameter: DriverCachePath
Value: %SystemRoot%\Driver Cache
Type: REG_EXPAND_SZ
Value after save in .REG file:
"DriverCachePath"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,\
6f,00,74,00,25,00,5c,00,44,00,72,00,69,00,76,00,65,00,72,00,20,00,43,00,61,\
00,63,00,68,00,65,00,00,00
Thanks.
11-23-2010 11:09 AM
Hello -
You might be able to try the Win32 API function ExpandEnvironmentStrings. I think it should do what you're looking for. Here's a simple example:
NickB
National Instruments
11-23-2010 11:19 AM - edited 11-23-2010 11:22 AM
As REG_EXPAND_SZ keys are no other than strings one could expect that RegReadString succeeded in getting these values. However, as you may see by looking at toolbox code, this function is forced to read only REG_SZ keys and returns an error for a different key type.
I suppose the easiest method for reading these type of values is to copy actual code for RegReadString in your code and modify it adding the correspondent key type to the code; next rename the function and use it as the original one (you will need to include windows.h in your code if you aren't already doing so).
By modifying the check line to
if (keyType != REG_SZ && keyType != REG_EXPAND_SZ) {
you should be able to read those types of keys. I was able to do it by copying the relevant code in the Interactive window and commenting out that line: the result was no error and correct value read.
Edit: I just noted Nick answer, written while I was writing mine one. I made my checks with CVI 8.5: it is possible that this behaviour has been fixed in more recent CVI releases so Nick hasn't got the error in RegReadString.
11-23-2010 11:51 AM - edited 11-23-2010 11:55 AM
Roberto -
Yes, this was a change that was made in CVI 2009. We now allow REG_EXPAND_SZ strings to be read from the registry.
I just assumed the problem was expanding the string, but if the problem is indeed that RegReadString is returning an error for REG_EXPAND_SZ types, Roberto's suggestion is best.
NickB
National Instruments
11-24-2010 10:19 AM
No. No one of solutions don't work. Try write porblem with more details.
CVI - version 9.0.0 (348).
Function - RegReadString (REGKEY_HKLM, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup","DriverCachePath", tempchar, 2000, &temp_int);
Let value to read - "abvgde".
Function don't cry "ERROR!"; temp_int after her indicate lenght of "abvgde", and = 6. But tempchar = "", not "abvgde"!
Tried gaming with type tempchar - no effect: char *tempchar, char tempchar[260]="", with malloc tried too.
...Novel N. G. Chernishevsky: "What to do?.."...
11-24-2010 03:37 PM - edited 11-24-2010 03:38 PM
Hi Sergey!
Does RegReadString return any error? As far as I can understand it should return value -5069, that is wrong key value type (it can be decoded by passing it to GetGeneralErrorString function).
I am attaching a sample project with the modified toolbox function that permits to read REG_EXPAND_SZ keys: please test it on your system and let us know if it works. In case of errors, please report us the error value returned by either version. Knowing which CVI distribution you are using (either base or professional) can be useful too.
11-27-2010 03:17 AM
Your project is work.
About me: finded file "toolbox.c" from adress C:\Program Files (x86)\National Instruments\CVI90\toolslib\toolbox.
Replace string № 13732: if (keyType != REG_SZ) to if (keyType != REG_SZ && keyType != REG_EXPAND_SZ).
Restart CVI - no effects.
About error#: return error -5069. String here:
temp_int2=RegReadString (REGKEY_HKLM, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup","DriverCachePath", tempchar, 2000, &temp_int);
static int temp_int=0, temp_int2=0;
static char tempchar[2000]="";
temp_int=26 after execute - length 25 + 1; tempchar="".
11-27-2010 05:37 AM
Hi Sergey,
what you are seeing is the expected behaviour. Let me explain.
Error -5069 does mean "Incorrect type for Registry Value". You can get this explanation by using string = GetGeneralErrorString (-5069); as I told you. This is expected as you have CVI 9.0 and Nick told us that the modification to those functions in the toolbox was introduced in CVI2009 (actually CVI 9.1). I guess this is not a free update.
As per the Programmer's Toolbox, when you integrate it in your projects you are actually using a library created out of the code; modifications to the source code have no effect until you recreate the library. This normally implies appropriate documentation in case you need to port it to an updated system.
However, I personally discourage you from doing so, as the Programmer's toolbox is part of CVI system and it can be overwritten without notfication in case of an update to the CVI environment. What you may want to do is get a copy of the complete toolbox, modify it and recreate the library and the .fp with a different name. This is needed in case the modification to toolbox code relies on use of internal toolbox functions, which is not the case we are discussing.
In this case, I would better copy the code I posted in one of your actual project source files, leaving the toolbox unchanged.
Hope all this is clear enough: feel free to post some questions in case of doubt.
11-27-2010 06:11 AM
Thanks for all; theme is closed. I include in my project Roberto's with rename the function; that is correct solution: don't use RegReadString, use that func:
char key[512], value[256], raw[MAX_PATHNAME_LEN], expanded[MAX_PATHNAME_LEN];
int temp_int;
int error;
error = RegReadStringEx (REGKEY_HKLM, key, value, raw, 2000, &temp_int);
int CVIFUNC RegReadStringEx (unsigned int userRootKey, const char* userSubKeyName, const char* userValName,
unsigned char* userString, unsigned int userStringSize, unsigned int* prealStringSize)
{
int retVal = 0;
DWORD sdkErr;
DWORD keyType;
HKEY huserKey = NULL;
Assert(userSubKeyName);
Assert(prealStringSize);
if ((sdkErr = RegOpenKeyEx ((HKEY)userRootKey, userSubKeyName, 0, KEY_QUERY_VALUE, &huserKey))
!= ERROR_SUCCESS)
{
retVal = (sdkErr == ERROR_FILE_NOT_FOUND) ? ToolErr_MissingKey : ToolErr_CantOpenKey;
goto Error;
}
if ((sdkErr = RegQueryValueEx (huserKey, userValName, NULL, &keyType, NULL, prealStringSize))
!= ERROR_SUCCESS)
{
retVal = (sdkErr == ERROR_FILE_NOT_FOUND) ? ToolErr_MissingKeyValue
: ToolErr_CantAccessKeyValue;
goto Error;
}
if (keyType != REG_SZ && keyType != REG_EXPAND_SZ)
{
retVal = ToolErr_WrongKeyValueType;
goto Error;
}
if (userString)
{
if (*prealStringSize > userStringSize)
// User buffer's not big enough, return an error (the output size parameter will tell
// them how big the buffer needs to be)
retVal = UIEBufTooSmall;
else
{
if (RegQueryValueEx (huserKey, userValName, NULL, NULL, userString, prealStringSize)
!= ERROR_SUCCESS)
retVal = ToolErr_CantAccessKeyValue;
}
}
Error:
if (huserKey)
RegCloseKey (huserKey);
return retVal;
}