Getting AppData Directory Path
-
Ok guys... i've been working on this section of code for about a week now and i'm giving up...can someone help me? I've got the basics down, but the code won't compile: Argument of type LPWSTR* is incompatible with parameter type of LPWSTR
//read in hotkey settings
// String buffer for holding the path. LPWSTR strPath\[ MAX\_PATH \]; // Get the special folder path. SHGetSpecialFolderPath( 0, // Hwnd strPath, // String buffer. CSIDL\_APPDATA, // CSLID of folder FALSE ); // Create if doesn't exists? LPWSTR appDataPath = \*strPath; \_tcscat(appDataPath, L"\\\\SSST\\Settings.ini"); MessageBox(NULL,(LPCTSTR)appDataPath, NULL, NULL);
-
Ok guys... i've been working on this section of code for about a week now and i'm giving up...can someone help me? I've got the basics down, but the code won't compile: Argument of type LPWSTR* is incompatible with parameter type of LPWSTR
//read in hotkey settings
// String buffer for holding the path. LPWSTR strPath\[ MAX\_PATH \]; // Get the special folder path. SHGetSpecialFolderPath( 0, // Hwnd strPath, // String buffer. CSIDL\_APPDATA, // CSLID of folder FALSE ); // Create if doesn't exists? LPWSTR appDataPath = \*strPath; \_tcscat(appDataPath, L"\\\\SSST\\Settings.ini"); MessageBox(NULL,(LPCTSTR)appDataPath, NULL, NULL);
The problem with your code is as follows:
LPWSTR strPath[ MAX_PATH ];
The "LP" in "LPWSTR" stands for Long Pointer. So the above code declares an array of pointers, NOT an array of WCHARs. You need to declare it as:
WCHAR strPath[ MAX_PATH ];
Also, this code is wrong:
LPWSTR appDataPath = *strPath;
_tcscat(appDataPath, L"\\SSST\Settings.ini");You haven't allocated any memory for the appDataPath string. So you must make it something like:
LPWSTR appDataPath = new WCHAR[ 400 ];
I chose 400 arbitrarily to make it big enough. And be sure to deallocate appDataPath when you are done with it by saying:
delete [] appDataPath;
The difficult we do right away... ...the impossible takes slightly longer.
-
The problem with your code is as follows:
LPWSTR strPath[ MAX_PATH ];
The "LP" in "LPWSTR" stands for Long Pointer. So the above code declares an array of pointers, NOT an array of WCHARs. You need to declare it as:
WCHAR strPath[ MAX_PATH ];
Also, this code is wrong:
LPWSTR appDataPath = *strPath;
_tcscat(appDataPath, L"\\SSST\Settings.ini");You haven't allocated any memory for the appDataPath string. So you must make it something like:
LPWSTR appDataPath = new WCHAR[ 400 ];
I chose 400 arbitrarily to make it big enough. And be sure to deallocate appDataPath when you are done with it by saying:
delete [] appDataPath;
The difficult we do right away... ...the impossible takes slightly longer.
Great! that works perfect, the only issue is that now the MessageboxA shows a ton of chinese/gibberish characters at the front.. i'm assuming that these are the buffer characters? i'm new to C++ (in fact this is only my second attempt at C++)... counting "Hello World!"
-
Great! that works perfect, the only issue is that now the MessageboxA shows a ton of chinese/gibberish characters at the front.. i'm assuming that these are the buffer characters? i'm new to C++ (in fact this is only my second attempt at C++)... counting "Hello World!"
I should have mentioned that you should zero out the buffer before using it:
LPWSTR appDataPath = new WCHAR[ 400 ];
ZeroMemory( appDataPath, sizeof( WCHAR ) * 400 );The difficult we do right away... ...the impossible takes slightly longer.
-
Ok guys... i've been working on this section of code for about a week now and i'm giving up...can someone help me? I've got the basics down, but the code won't compile: Argument of type LPWSTR* is incompatible with parameter type of LPWSTR
//read in hotkey settings
// String buffer for holding the path. LPWSTR strPath\[ MAX\_PATH \]; // Get the special folder path. SHGetSpecialFolderPath( 0, // Hwnd strPath, // String buffer. CSIDL\_APPDATA, // CSLID of folder FALSE ); // Create if doesn't exists? LPWSTR appDataPath = \*strPath; \_tcscat(appDataPath, L"\\\\SSST\\Settings.ini"); MessageBox(NULL,(LPCTSTR)appDataPath, NULL, NULL);
Though what the other poster said is correct, you need to make a few extra modifications. First I'll give you the working 'proper' code, and then I'll explain:
// String buffer for holding the path and filename TCHAR strPath\[ MAX\_PATH + 50 \]; // Get the special folder path. SHGetSpecialFolderPath( 0, // Hwnd strPath, // String buffer. CSIDL\_APPDATA, // CSLID of folder FALSE ); // Create if doesn't exists? \_tcscat(strPath, \_T("\\\\SSST\\\\Settings.ini")); MessageBox(NULL, strPath, NULL, MB\_OK);
First of all, you were mixing WCHAR definitions with TCHAR functions (such as _tcscat, MessageBox). Depending on whether you compile for Unicode or not, the TCHAR definition changed from a char to a wchar_t, and so do all the tchar.h routines, as well as the Windows API functions (which switch to their wide variants). To fix this, use TCHAR and LPTSTR's in your program. For string literals, enclose them in a _T macro as shown, which automatically adds the L prefix if needed and omits it if not unicode. Then a simplification: you can just strcat (_tcscat) in strPath, no need to add extra variables and certainly no need to use new, which adds the overhead of extra memory management and can lead to memory leaks if you forget to clean it up. And finally, the last argument of the MessageBox is a UINT flag, and not a pointer, so you shouldn't pass NULL to it, but rather one of the predefined constants. Hope this helps.
-
Though what the other poster said is correct, you need to make a few extra modifications. First I'll give you the working 'proper' code, and then I'll explain:
// String buffer for holding the path and filename TCHAR strPath\[ MAX\_PATH + 50 \]; // Get the special folder path. SHGetSpecialFolderPath( 0, // Hwnd strPath, // String buffer. CSIDL\_APPDATA, // CSLID of folder FALSE ); // Create if doesn't exists? \_tcscat(strPath, \_T("\\\\SSST\\\\Settings.ini")); MessageBox(NULL, strPath, NULL, MB\_OK);
First of all, you were mixing WCHAR definitions with TCHAR functions (such as _tcscat, MessageBox). Depending on whether you compile for Unicode or not, the TCHAR definition changed from a char to a wchar_t, and so do all the tchar.h routines, as well as the Windows API functions (which switch to their wide variants). To fix this, use TCHAR and LPTSTR's in your program. For string literals, enclose them in a _T macro as shown, which automatically adds the L prefix if needed and omits it if not unicode. Then a simplification: you can just strcat (_tcscat) in strPath, no need to add extra variables and certainly no need to use new, which adds the overhead of extra memory management and can lead to memory leaks if you forget to clean it up. And finally, the last argument of the MessageBox is a UINT flag, and not a pointer, so you shouldn't pass NULL to it, but rather one of the predefined constants. Hope this helps.
it did help significantly, i appreciate the explanation rather than a code dump... I'm still a bit confused about the TCHAR and WCHAR definitions... they seem to convert themselves... i guess these are one of those "C++ Macros" that i've been reading about? i figured i could just strcat() the strings in the same line, but i'm still trying to figure out C++ i've made the changes stated above, but i am now getting a "Debug Assertion Error" on my line:
delete [] strPath
i've figured out that an assertion error is similar to a conditioned break point... i've found the line of code in one of the C++ files: dbgdel.cpp
void operator delete(
void *pUserData
)
{
_CrtMemBlockHeader * pHead;RTCCALLBACK(\_RTC\_Free\_hook, (pUserData, 0)); if (pUserData == NULL) return; \_mlock(\_HEAP\_LOCK); /\* block other threads \*/ \_\_TRY /\* get a pointer to memory block header \*/ pHead = pHdr(pUserData); /\* verify block type \*/ \_ASSERTE(\_BLOCK\_TYPE\_IS\_VALID(pHead->nBlockUse)); \_free\_dbg( pUserData, pHead->nBlockUse ); \_\_FINALLY \_munlock(\_HEAP\_LOCK); /\* release other threads \*/ \_\_END\_TRY\_FINALLY return;
}
#endif /* _DEBUG */
the code looks like i've passed an invalid param to the delete function... should i not be disposing of this variable, it is not used anywhere else in my code as of yet? or is there another method for disposing of this var?
-
it did help significantly, i appreciate the explanation rather than a code dump... I'm still a bit confused about the TCHAR and WCHAR definitions... they seem to convert themselves... i guess these are one of those "C++ Macros" that i've been reading about? i figured i could just strcat() the strings in the same line, but i'm still trying to figure out C++ i've made the changes stated above, but i am now getting a "Debug Assertion Error" on my line:
delete [] strPath
i've figured out that an assertion error is similar to a conditioned break point... i've found the line of code in one of the C++ files: dbgdel.cpp
void operator delete(
void *pUserData
)
{
_CrtMemBlockHeader * pHead;RTCCALLBACK(\_RTC\_Free\_hook, (pUserData, 0)); if (pUserData == NULL) return; \_mlock(\_HEAP\_LOCK); /\* block other threads \*/ \_\_TRY /\* get a pointer to memory block header \*/ pHead = pHdr(pUserData); /\* verify block type \*/ \_ASSERTE(\_BLOCK\_TYPE\_IS\_VALID(pHead->nBlockUse)); \_free\_dbg( pUserData, pHead->nBlockUse ); \_\_FINALLY \_munlock(\_HEAP\_LOCK); /\* release other threads \*/ \_\_END\_TRY\_FINALLY return;
}
#endif /* _DEBUG */
the code looks like i've passed an invalid param to the delete function... should i not be disposing of this variable, it is not used anywhere else in my code as of yet? or is there another method for disposing of this var?
jwalker343 wrote:
I'm still a bit confused about the TCHAR and WCHAR definitions... they seem to convert themselves... i guess these are one of those "C++ Macros" that i've been reading about?
These are indeed macro's. The definition of TCHAR sort of goes like:
#ifdef _UNICODE
#define TCHAR WCHAR // Unicode is on -> Wide character type
#else
#define TCHAR CHAR // Unicode is off -> Normal character type
#endifjwalker343 wrote:
i figured i could just strcat() the strings in the same line, but i'm still trying to figure out C++
The thing with TCHARs is that they work very nicely in allowing your code to compile and work both when compiling for Ansi and for Unicode (Wide) character sets. But, there is a catch. You need to make sure all your string function follow the t-pattern. That's why, in tchar.h there are a lot of macro's that switch definition based on whether _UNICODE is true or not. These are the _txyz macro's, such as _tcscat for strcat/wcscat, or _tcslen for strlen or wcslen. If you define all your strings as TCHAR and use the associated _txyz routines, then your code will compile for all character sets without having to change. This does require a slight awareness though. Code like sizeof() can work differently. sizeof always gives the size in 'char', and that's equal to strlen for ansi, but equal to twice the wcslen for unicode (as wcslen gives the amount of wide characters, and each character is 2 bytes (chars) in size). There is a lot of intricacies to C++, certainly when targeting a specific platform, such as Windows. One of those intricacies is tchar.h and all its facets ;) At any rate, you were right in your assumption: you can just use strcat the way you wanted to.
jwalker343 wrote:
i've made the changes stated above, but i am now getting a "Debug Assertion Error" on my line:
Now, to the problem at hand: I think you are mixing two bits of code. The one I gave and the one given by the other poster. You posted a piece of code in the beginning. If you replace exactly that code with the code I posted (and add/remove nothing) then it should work. I think you added a
delete[] strPath
to the snippet I gave, as per the other posters code. delete[] is necessary when you allocate memory using new[]. However, in this snippet the strPath is a fixed size array (MAX_PATH + 5 -
jwalker343 wrote:
I'm still a bit confused about the TCHAR and WCHAR definitions... they seem to convert themselves... i guess these are one of those "C++ Macros" that i've been reading about?
These are indeed macro's. The definition of TCHAR sort of goes like:
#ifdef _UNICODE
#define TCHAR WCHAR // Unicode is on -> Wide character type
#else
#define TCHAR CHAR // Unicode is off -> Normal character type
#endifjwalker343 wrote:
i figured i could just strcat() the strings in the same line, but i'm still trying to figure out C++
The thing with TCHARs is that they work very nicely in allowing your code to compile and work both when compiling for Ansi and for Unicode (Wide) character sets. But, there is a catch. You need to make sure all your string function follow the t-pattern. That's why, in tchar.h there are a lot of macro's that switch definition based on whether _UNICODE is true or not. These are the _txyz macro's, such as _tcscat for strcat/wcscat, or _tcslen for strlen or wcslen. If you define all your strings as TCHAR and use the associated _txyz routines, then your code will compile for all character sets without having to change. This does require a slight awareness though. Code like sizeof() can work differently. sizeof always gives the size in 'char', and that's equal to strlen for ansi, but equal to twice the wcslen for unicode (as wcslen gives the amount of wide characters, and each character is 2 bytes (chars) in size). There is a lot of intricacies to C++, certainly when targeting a specific platform, such as Windows. One of those intricacies is tchar.h and all its facets ;) At any rate, you were right in your assumption: you can just use strcat the way you wanted to.
jwalker343 wrote:
i've made the changes stated above, but i am now getting a "Debug Assertion Error" on my line:
Now, to the problem at hand: I think you are mixing two bits of code. The one I gave and the one given by the other poster. You posted a piece of code in the beginning. If you replace exactly that code with the code I posted (and add/remove nothing) then it should work. I think you added a
delete[] strPath
to the snippet I gave, as per the other posters code. delete[] is necessary when you allocate memory using new[]. However, in this snippet the strPath is a fixed size array (MAX_PATH + 5wow, very helpful... explains why C++ is such a powerful language... it's almost as if the entire language can change pretty quickly depending on all of your own settings... that's crazy!! and the memory allocation seems understandable as well now that you explain it like that... basically if you specifically ask for new memory, you've got to deal with it yourself... Thanks a bunch MicroVirus... i'm looking to release my first CodeProject Article on this project in the coming months... i'll be sure to mention your help!