CString::Replace not working with values from registry
I'm trying to implement something where I need to change values in the registry where what I'm removing and what I'm adding is only decided at run time.
my test code:
CString test_string, change_from, change_to;
test_string.Format(_T("Communications Port (COM1)"));
change_from.Format(_T("COM1"));
change_to.Format(_T("COM2"));
test_string.Replace(change_from, change_to);
MessageBox(test_string, _T("Test"), MB_OK);
works as expected.
but when test_string and change_from are populated from the registry it does not.
CRegKey serenum_key;
serenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\services\Serenum\Enum"), KEY_READ);
CRegKey sysenum_key;
sysenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\Enum"), KEY_READ);
DWORD count = 0;
serenum_key.QueryDWORDValue(_T("Count"), count);
CString keyname, keypath, friendlyname, portname;
const ULONG max_len = 256;
ULONG len;
keypath.Preallocate(max_len);
friendlyname.Preallocate(max_len);
portname.Preallocate(max_len);
for (DWORD i = 0; i < count; i++)
keyname.Format(_T("%d"), i);
len = max_len;
serenum_key.QueryStringValue(keyname, keypath.GetBuffer(), &len);
CRegKey dev_key;
dev_key.Open(sysenum_key, keypath.GetBuffer(), KEY_READ);
len = max_len;
dev_key.QueryStringValue(_T("FriendlyName"), friendlyname.GetBuffer(), &len);
CRegKey devparams_key;
devparams_key.Open(dev_key, _T("Device Parameters"), KEY_READ);
len = max_len;
devparams_key.QueryStringValue(_T("PortName"), portname.GetBuffer(), &len);
ATLTRACE(friendlyname);
ATLTRACE(portname);
CString newname;
newname.Format(_T("COM%d"), 50);
ATLTRACE(newname);
friendlyname.Replace(portname, newname);
ATLTRACE(friendlyname);
devparams_key.Close();
dev_key.Close();
sysenum_key.Close();
serenum_key.Close();
}
the traces I'm getting show what I expect to see coming from the registry key, and the new name, but the friendly name remains unchanged:
Communications Port (COM1)
COM1
COM50
Communications Port (COM1)
why does Replace
work in the first instance but not with the registry key values?
for note I'm working with visual studio community 2017, platform toolset v141, Unicode, x64
visual-c++ mfc
add a comment |
I'm trying to implement something where I need to change values in the registry where what I'm removing and what I'm adding is only decided at run time.
my test code:
CString test_string, change_from, change_to;
test_string.Format(_T("Communications Port (COM1)"));
change_from.Format(_T("COM1"));
change_to.Format(_T("COM2"));
test_string.Replace(change_from, change_to);
MessageBox(test_string, _T("Test"), MB_OK);
works as expected.
but when test_string and change_from are populated from the registry it does not.
CRegKey serenum_key;
serenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\services\Serenum\Enum"), KEY_READ);
CRegKey sysenum_key;
sysenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\Enum"), KEY_READ);
DWORD count = 0;
serenum_key.QueryDWORDValue(_T("Count"), count);
CString keyname, keypath, friendlyname, portname;
const ULONG max_len = 256;
ULONG len;
keypath.Preallocate(max_len);
friendlyname.Preallocate(max_len);
portname.Preallocate(max_len);
for (DWORD i = 0; i < count; i++)
keyname.Format(_T("%d"), i);
len = max_len;
serenum_key.QueryStringValue(keyname, keypath.GetBuffer(), &len);
CRegKey dev_key;
dev_key.Open(sysenum_key, keypath.GetBuffer(), KEY_READ);
len = max_len;
dev_key.QueryStringValue(_T("FriendlyName"), friendlyname.GetBuffer(), &len);
CRegKey devparams_key;
devparams_key.Open(dev_key, _T("Device Parameters"), KEY_READ);
len = max_len;
devparams_key.QueryStringValue(_T("PortName"), portname.GetBuffer(), &len);
ATLTRACE(friendlyname);
ATLTRACE(portname);
CString newname;
newname.Format(_T("COM%d"), 50);
ATLTRACE(newname);
friendlyname.Replace(portname, newname);
ATLTRACE(friendlyname);
devparams_key.Close();
dev_key.Close();
sysenum_key.Close();
serenum_key.Close();
}
the traces I'm getting show what I expect to see coming from the registry key, and the new name, but the friendly name remains unchanged:
Communications Port (COM1)
COM1
COM50
Communications Port (COM1)
why does Replace
work in the first instance but not with the registry key values?
for note I'm working with visual studio community 2017, platform toolset v141, Unicode, x64
visual-c++ mfc
Try to step into MFC'sReplace
method. You'll see what happens.
– Jabberwocky
Nov 13 '18 at 10:24
still getting to grips with using a debugger, tried that and found that it was not able to see the new or old strings for replacement, I tried changing them to useGetBuffer()
on those two arguments which replaced something, but unfortunately with gibberish.
– James Kent
Nov 13 '18 at 10:46
2
You are missingCString::ReleaseBuffer()
calls, so the string length won't be set to the actual length of the strings read from the registry.
– zett42
Nov 13 '18 at 11:47
thank you. this was the hint I needed.
– James Kent
Nov 13 '18 at 11:58
add a comment |
I'm trying to implement something where I need to change values in the registry where what I'm removing and what I'm adding is only decided at run time.
my test code:
CString test_string, change_from, change_to;
test_string.Format(_T("Communications Port (COM1)"));
change_from.Format(_T("COM1"));
change_to.Format(_T("COM2"));
test_string.Replace(change_from, change_to);
MessageBox(test_string, _T("Test"), MB_OK);
works as expected.
but when test_string and change_from are populated from the registry it does not.
CRegKey serenum_key;
serenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\services\Serenum\Enum"), KEY_READ);
CRegKey sysenum_key;
sysenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\Enum"), KEY_READ);
DWORD count = 0;
serenum_key.QueryDWORDValue(_T("Count"), count);
CString keyname, keypath, friendlyname, portname;
const ULONG max_len = 256;
ULONG len;
keypath.Preallocate(max_len);
friendlyname.Preallocate(max_len);
portname.Preallocate(max_len);
for (DWORD i = 0; i < count; i++)
keyname.Format(_T("%d"), i);
len = max_len;
serenum_key.QueryStringValue(keyname, keypath.GetBuffer(), &len);
CRegKey dev_key;
dev_key.Open(sysenum_key, keypath.GetBuffer(), KEY_READ);
len = max_len;
dev_key.QueryStringValue(_T("FriendlyName"), friendlyname.GetBuffer(), &len);
CRegKey devparams_key;
devparams_key.Open(dev_key, _T("Device Parameters"), KEY_READ);
len = max_len;
devparams_key.QueryStringValue(_T("PortName"), portname.GetBuffer(), &len);
ATLTRACE(friendlyname);
ATLTRACE(portname);
CString newname;
newname.Format(_T("COM%d"), 50);
ATLTRACE(newname);
friendlyname.Replace(portname, newname);
ATLTRACE(friendlyname);
devparams_key.Close();
dev_key.Close();
sysenum_key.Close();
serenum_key.Close();
}
the traces I'm getting show what I expect to see coming from the registry key, and the new name, but the friendly name remains unchanged:
Communications Port (COM1)
COM1
COM50
Communications Port (COM1)
why does Replace
work in the first instance but not with the registry key values?
for note I'm working with visual studio community 2017, platform toolset v141, Unicode, x64
visual-c++ mfc
I'm trying to implement something where I need to change values in the registry where what I'm removing and what I'm adding is only decided at run time.
my test code:
CString test_string, change_from, change_to;
test_string.Format(_T("Communications Port (COM1)"));
change_from.Format(_T("COM1"));
change_to.Format(_T("COM2"));
test_string.Replace(change_from, change_to);
MessageBox(test_string, _T("Test"), MB_OK);
works as expected.
but when test_string and change_from are populated from the registry it does not.
CRegKey serenum_key;
serenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\services\Serenum\Enum"), KEY_READ);
CRegKey sysenum_key;
sysenum_key.Open(HKEY_LOCAL_MACHINE, _T("System\CurrentControlSet\Enum"), KEY_READ);
DWORD count = 0;
serenum_key.QueryDWORDValue(_T("Count"), count);
CString keyname, keypath, friendlyname, portname;
const ULONG max_len = 256;
ULONG len;
keypath.Preallocate(max_len);
friendlyname.Preallocate(max_len);
portname.Preallocate(max_len);
for (DWORD i = 0; i < count; i++)
keyname.Format(_T("%d"), i);
len = max_len;
serenum_key.QueryStringValue(keyname, keypath.GetBuffer(), &len);
CRegKey dev_key;
dev_key.Open(sysenum_key, keypath.GetBuffer(), KEY_READ);
len = max_len;
dev_key.QueryStringValue(_T("FriendlyName"), friendlyname.GetBuffer(), &len);
CRegKey devparams_key;
devparams_key.Open(dev_key, _T("Device Parameters"), KEY_READ);
len = max_len;
devparams_key.QueryStringValue(_T("PortName"), portname.GetBuffer(), &len);
ATLTRACE(friendlyname);
ATLTRACE(portname);
CString newname;
newname.Format(_T("COM%d"), 50);
ATLTRACE(newname);
friendlyname.Replace(portname, newname);
ATLTRACE(friendlyname);
devparams_key.Close();
dev_key.Close();
sysenum_key.Close();
serenum_key.Close();
}
the traces I'm getting show what I expect to see coming from the registry key, and the new name, but the friendly name remains unchanged:
Communications Port (COM1)
COM1
COM50
Communications Port (COM1)
why does Replace
work in the first instance but not with the registry key values?
for note I'm working with visual studio community 2017, platform toolset v141, Unicode, x64
visual-c++ mfc
visual-c++ mfc
edited Nov 13 '18 at 10:25
Jabberwocky
26.6k93770
26.6k93770
asked Nov 13 '18 at 10:03
James KentJames Kent
3,715831
3,715831
Try to step into MFC'sReplace
method. You'll see what happens.
– Jabberwocky
Nov 13 '18 at 10:24
still getting to grips with using a debugger, tried that and found that it was not able to see the new or old strings for replacement, I tried changing them to useGetBuffer()
on those two arguments which replaced something, but unfortunately with gibberish.
– James Kent
Nov 13 '18 at 10:46
2
You are missingCString::ReleaseBuffer()
calls, so the string length won't be set to the actual length of the strings read from the registry.
– zett42
Nov 13 '18 at 11:47
thank you. this was the hint I needed.
– James Kent
Nov 13 '18 at 11:58
add a comment |
Try to step into MFC'sReplace
method. You'll see what happens.
– Jabberwocky
Nov 13 '18 at 10:24
still getting to grips with using a debugger, tried that and found that it was not able to see the new or old strings for replacement, I tried changing them to useGetBuffer()
on those two arguments which replaced something, but unfortunately with gibberish.
– James Kent
Nov 13 '18 at 10:46
2
You are missingCString::ReleaseBuffer()
calls, so the string length won't be set to the actual length of the strings read from the registry.
– zett42
Nov 13 '18 at 11:47
thank you. this was the hint I needed.
– James Kent
Nov 13 '18 at 11:58
Try to step into MFC's
Replace
method. You'll see what happens.– Jabberwocky
Nov 13 '18 at 10:24
Try to step into MFC's
Replace
method. You'll see what happens.– Jabberwocky
Nov 13 '18 at 10:24
still getting to grips with using a debugger, tried that and found that it was not able to see the new or old strings for replacement, I tried changing them to use
GetBuffer()
on those two arguments which replaced something, but unfortunately with gibberish.– James Kent
Nov 13 '18 at 10:46
still getting to grips with using a debugger, tried that and found that it was not able to see the new or old strings for replacement, I tried changing them to use
GetBuffer()
on those two arguments which replaced something, but unfortunately with gibberish.– James Kent
Nov 13 '18 at 10:46
2
2
You are missing
CString::ReleaseBuffer()
calls, so the string length won't be set to the actual length of the strings read from the registry.– zett42
Nov 13 '18 at 11:47
You are missing
CString::ReleaseBuffer()
calls, so the string length won't be set to the actual length of the strings read from the registry.– zett42
Nov 13 '18 at 11:47
thank you. this was the hint I needed.
– James Kent
Nov 13 '18 at 11:58
thank you. this was the hint I needed.
– James Kent
Nov 13 '18 at 11:58
add a comment |
1 Answer
1
active
oldest
votes
The documentation on CString::GetBuffer explains, how to use this class member:
If you use the pointer returned by
GetBuffer
to change the string contents, you must call ReleaseBuffer before you use any otherCSimpleStringT
member methods.
If you don't, the internal state of the CString
object is not valid. The GetBuffer
/ReleaseBuffer
family of class members are useful, when you need to attach non-CString
string data to CString
instances. The former temporarily disable class invariants, where the latter re-establishes them, so they always need to be called in tandem.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53278437%2fcstringreplace-not-working-with-values-from-registry%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The documentation on CString::GetBuffer explains, how to use this class member:
If you use the pointer returned by
GetBuffer
to change the string contents, you must call ReleaseBuffer before you use any otherCSimpleStringT
member methods.
If you don't, the internal state of the CString
object is not valid. The GetBuffer
/ReleaseBuffer
family of class members are useful, when you need to attach non-CString
string data to CString
instances. The former temporarily disable class invariants, where the latter re-establishes them, so they always need to be called in tandem.
add a comment |
The documentation on CString::GetBuffer explains, how to use this class member:
If you use the pointer returned by
GetBuffer
to change the string contents, you must call ReleaseBuffer before you use any otherCSimpleStringT
member methods.
If you don't, the internal state of the CString
object is not valid. The GetBuffer
/ReleaseBuffer
family of class members are useful, when you need to attach non-CString
string data to CString
instances. The former temporarily disable class invariants, where the latter re-establishes them, so they always need to be called in tandem.
add a comment |
The documentation on CString::GetBuffer explains, how to use this class member:
If you use the pointer returned by
GetBuffer
to change the string contents, you must call ReleaseBuffer before you use any otherCSimpleStringT
member methods.
If you don't, the internal state of the CString
object is not valid. The GetBuffer
/ReleaseBuffer
family of class members are useful, when you need to attach non-CString
string data to CString
instances. The former temporarily disable class invariants, where the latter re-establishes them, so they always need to be called in tandem.
The documentation on CString::GetBuffer explains, how to use this class member:
If you use the pointer returned by
GetBuffer
to change the string contents, you must call ReleaseBuffer before you use any otherCSimpleStringT
member methods.
If you don't, the internal state of the CString
object is not valid. The GetBuffer
/ReleaseBuffer
family of class members are useful, when you need to attach non-CString
string data to CString
instances. The former temporarily disable class invariants, where the latter re-establishes them, so they always need to be called in tandem.
answered Nov 13 '18 at 12:29
IInspectableIInspectable
26k54396
26k54396
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53278437%2fcstringreplace-not-working-with-values-from-registry%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Try to step into MFC's
Replace
method. You'll see what happens.– Jabberwocky
Nov 13 '18 at 10:24
still getting to grips with using a debugger, tried that and found that it was not able to see the new or old strings for replacement, I tried changing them to use
GetBuffer()
on those two arguments which replaced something, but unfortunately with gibberish.– James Kent
Nov 13 '18 at 10:46
2
You are missing
CString::ReleaseBuffer()
calls, so the string length won't be set to the actual length of the strings read from the registry.– zett42
Nov 13 '18 at 11:47
thank you. this was the hint I needed.
– James Kent
Nov 13 '18 at 11:58