Extract multiple IClass values from a registry key - c++

I am trying to get the IClass values from registry key using RegQueryVaueEx and convert them to GUID for my application. I could do that for REG_SZ size, however, I am trying to figure out a way to do the same for IClass values with REG_MULTI_SZ that have more than one IClass. It doesn't seem to be straightforward as characters between the values are not consistent. Sometimes, each value is delimited by a COMMA, sometimes the IClass value is equated to %b. Is there a simple way to achieve what I am looking for? Please suggest.

Looks like the best way to achieve this is to open the registry key of the driver with RegOpenKeyEx and use RegEnumValue to get the IClass values (by passing IClass value name as parameter) in a loop (do-while) until RegEnumValue fails.
Thanks all for the comments and suggestions.

Searching my WinXP/64 registry, I find no "IClass" value.
MSDN says that MULTI_SZ is a list of nul-terminated strings with a size value; and that page has example code that "walks a REG_MULTI_SZ string."

Related

Save Column Width and Order Info to Registry (MFC)

For saving column order, I was thinking of using the CSettingsStore class to save and restore arrays of integers to and from the registry (arrays that I would use CListCtrl::GetColumnOrderArray() and CListCtrl::SetColumnOrderArray() to generate and set). But I have no idea if that's realistically possible, or what registry data type to use (DWORD? Stuff the ints into a string array and use multi-string?). Also, CSettingsStore requires a string path to open up keys, while GetAppRegistryKey() returns an HKEY, so I'm not sure how to even use CSettingsStore with my app.
I have 3 questions.
Will this approach be feasible for loading and saving of column information? Or is there an obviously simpler solution?
What data types should I use to store the column order arrays in the registry?
How can I convert an HKEY value to a CString? Or should I just look up my app's registry key and hardcode it?
My recommendation would be to format the column-count and the index values as a string delimited by comma (like 5, 1, 3, 4, 2, 0, the first number is column-count) and store it in the registry as REG_SZ with something like
AfxGetApp()->WriteProfileString(_T("Settings\\<ListControlName>"), _T("ColumnOrder"), sFormattedString);
You can load the string using GetProfileString() and use either CStringT::Tokenize() or the straight API strtok_s() functions to retrieve the values.
I used "Settings\\<ListControlName>" in case you need to store more values for each ListControl, like sort-order, for example. Otherwise, you could have just one registry section called "Settings\\ColumnOrder" and use <ListControlName> as the value-name.

MFC treeview control : looking for a foolproof way to deal with data

Maybe I am doing something wrong here. I am using a treeview control , which I populate with data. The data (integers mainly) are transformed to CStrings for that matter. When the user clicks on an item, I can read the CString, but then have to parse it in order to get the data .
Several times I have changed the way the data appears on the screen ,and then everything breaks, and I need to rewrite the parsing function. I wonder if there is a better way to do this...
EDIT : The treeview is being populated with items from a std::vector. If I could get the treeview to return an index in the vector instead of a CString , this would fit me perfectly.
You can use CTreeCtrl::SetItemData to associate an arbitrary data value with a tree item, and CTreeCtrl::GetItemData to retrieve this value. Typically you use SetItemData to store a pointer to an object, but in your case you could use this to store the integer values directly.
I hope this helps!
If you change the way you set/get your data in the tree, then you will have to change the way you format and and parse it.
Normally, you should only have 2 functions, the setter and the parser, so it should not be a big issue
I don't think there is a way to make it really faster or cleaner.

How to get constraint errors from OCIErrorGet?

Our C++ program is using Oracle and OCI to do its database work. Occasionally, the user will trigger a constraint violation, which we detect and then show an error message from OCIErrorGet. OCIErrorGet returns strings like this:
ORA-02292: integrity constraint (MYSCHEMA.CC_MYCONSTRAINT) violated - child record found
ORA-06512: at line 5
I am looking for the cleanest way to extract "MYSCHEMA.CC_MYCONSTRAINT" from the Oracle error. Knowing the name of the constraint, I could show a better error message (our code could look up a very meaningful error message if it had access to the constraint name).
I could use a regex or something and assume that the Oracle message will never change, but this seems a little fragile to me. Or I could look for specific ORA codes and then grab whatever text falls between the parentheses. But I was hoping OCI had a cleaner/more robust way, if a constraint fails, to figure out the actual name of the failed constraint without resorting to hardcoded string manipulation.
Any ideas?
According to the Oracle Docs, a string search is exactly what you need to do:
Recognizing Variable Text in Messages
To help you find and fix errors, Oracle embeds object names, numbers,
and character strings in some messages. These embedded variables are
represented by string, number, or character, as appropriate. For
example:
ORA-00020: maximum number of processes (number) exceeded
The preceding message might actually appear as follows:
ORA-00020: maximum number of processes (50) exceeded
Oracle makes a big point in their docs of saying the strings will be kept up to date in their section on "Message Accuracy." It's a pretty strong suggestion that they intend you to do a string search.
Also, according to this website, the Oracle Error structure also pretty strongly implies that they intend you to do a string search, because the data structure lacks anything else for you to get:
array(4) {
["code"]=>int(942)
["message"]=>string(40) "ORA-00942: table or view does not exist"
["offset"]=>int(14)
["sqltext"]=>string(32) "select * from non_existing_table"
}
This output reveals the following information:
The variable $erris an array with four elements.
The first element is accessible by the key ‘code’ and its value is number 942.
The second value is accessible by the key ‘message’ and the value is string “ORA-00942: table or view does not exist”.
The third value is accessible by the key ‘offset’, and its value is the number 14. This is the character before the name of the
non-existing table.
The fourth member is the problematic SQL message causing the error in the first place.
I agree with you; it would be great if there were a better way to get the constraint name you're violating, but string-matching seems to be the intended way.

How to determine the "(default)" value of a key

I want to know how can I get the default value of a registry key using C++.
I already tried sending NULL or an empty string in the key param in RegQueryValueEx() function.
Tried to check another key and I get it right. I just can't get the default.
The function returns "" instead of the value.
What do you mean by "key param?" You should be passing NULL or "" as the lpValueName parameter. If that's not working for you then it's a bug in your code. Post your code and perhaps we can provide further assistance.

Determining actual args an Excel UDF was called with

I'm adding a user defined function to Excel with varargs-based signature in C++:
LPXLOPER MyFunction(...);
When Excel calls MyFunction, it passes it 30 arguments regardless of how many the user entered in the sheet. The extraneous ones are blank strings.
MyFunction, however, is designed to accept empty string arguments. As a result, I cannot tell valid empty strings apart from the extraneous ones sent by Excel.
A solution could be to obtain the contents of the actual cell where the user entered the function. However, I can't find a way of doing that from within the implementation of my function.
Could someone please suggest a way out?
I've found a simple way to get hold of the caller cell.
Use excelApp->get_Caller();