creating a LPCTSTR pointer to a string in VS2010 - c++

I have to feed a LPCTSTR in to CreateProcess.
The short question is how do I convert a std::string into a LPCTSTR?
( LPCTSTR lpApplicationName = (LPCTSTR)FilePath.c_str(); does not work, CreateProcess simply ignores it, I know the path etc. I'm using is right because it works perfectly if I put in LPCTSTR lpApplicationName = L"a//test//path//and//file";).
The long question (why I need to do this) is: This LPCTSTR has to contain the path to, and name of, a file I wish to run.
The process is:
To get the path into the right format for CreateProcess I am having
to perform character replace (replacing single \ with double \ ) on
the output from GetModuleFileName. This output starts off as a
WCHAR buffer and I then convert into a std::string.
I then also need to concatenate this string with the final file name
which could be in any variable type (I define it in the program).
The finished string goes into the CreateProcess LPCTSTR.
I have tried using other sorts of string, but so far I haven't found any that the concatenate and character replace will work on.
Every solution I have seen does not work in Visual Studio 2010, which is what I'm using. All advice gratefully received.

LPCTSTR is a pointer to a const TCHAR*, not a const char*. Depending on your UNICODE and _UNICODE settings you will need either a std::wstring or a std::string. If you are stuck with std::string then you need to convert the char* returned by c_str() to a wchar_t* string (or not depending on UNICODE).
To make life a little easier on yourself I recommend:
#ifdef _UNICODE
typedef std::wstring tstring;
#else
typedef std::string tstring;
#endif

Related

Proper way crossplatfom convert from std::string to 'const TCHAR *'

I'm working for crossplatrofm project in c++ and I have variable with type std::string and need convert it to const TCHAR * - what is proper way, may be functions from some library ?
UPD 1: - as I see in function definition there is split windows and non-Windows implementations:
#if defined _MSC_VER || defined __MINGW32__
#define _tinydir_char_t TCHAR
#else
#define _tinydir_char_t char
#endif
- so is it a really no way for non spliting realization for send parameter from std::string ?
Proper way crossplatfom convert from std::string to 'const TCHAR *'
TCHAR should not be used in cross platform programs at all; Except of course, when interacting with windows API calls, but those need to be abstracted away from the rest of the program or else it won't be cross-platform. So, you only need to convert between TCHAR strings and char strings in windows specific code.
The rest of the program should use char, and preferably assume that it contains UTF-8 encoded strings. If user input, or system calls return strings that are in a different encoding, you need to figure out what that encoding is, and convert accordingly.
Character encoding conversion functionality of the C++ standard library is rather weak, so that is not of much use. You can implement the conversion according the encoding specification or you can use a third party implementation, as always.
may be functions from some library ?
I recommend this.
as I see in function definition there is split windows and non-Windows implementations
The library that you use doesn't provide a uniform API to different platforms, so it cannot be used in a truly cross-platform way. You can write a wrapper library with uniform function declarations that handles the character encoding conversion on platforms that need it.
Or, you can use another library, which provides a uniform API and converts the encoding transparently.
TCHAR are Windows type and it defined in this way:
#ifdef UNICODE
typedef wchar_t TCHAR, *PTCHAR;
#else
typedef char TCHAR, *PTCHAR;
#endif
UNICODE macro is typically defined in project settings (in case when your use Visual Studio project on Windows).
You can get the const TCHAR* from std::string (which is ASCII or UTF8 in most cases) in this way:
std::string s("hello world");
const TCHAR* pstring = nullptr;
#ifdef UNICODE
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wstr = converter.from_bytes(s);
pstring = wstr.data();
#else
pstring = s.data();
#endif
pstring will be the result.
But it's highly not recommended to use the TCHAR on other platforms. It's better to use the UTF8 strings (char*) within std::string
I came across boost.nowide the other day. I think it will do exactly what you want.
http://cppcms.com/files/nowide/html/
As others have pointed out, you should not be using TCHAR except in code that interfaces with the Windows API (or libraries modeled after the Windows API).
Another alternative is to use the character conversion classes/macros defined in atlconv.h. CA2T will convert an 8-bit character string to a TCHAR string. CA2CT will convert to a const TCHAR string (LPCTSTR). Assuming your 8-bit strings are UTF-8, you should specify CP_UTF8 as the code page for the conversion.
If you want to declare a variable containing a TCHAR copy of a std::string:
CA2T tstr(stdstr.c_str(), CP_UTF8);
If you want to call a function that takes an LPCTSTR:
FunctionThatTakesString(CA2CT(stdsr.c_str(), CP_UTF8));
If you want to construct a std::string from a TCHAR string:
std::string mystdstring(CT2CA(tstr, CP_UTF8));
If you want to call a function that takes an LPTSTR then maybe you should not be using these conversion classes. (But you can if you know that the function you are calling does not modify the string outside its current length.)

Variable type with MoveFile() in VC++

So I am trying to move a file that the user specifies by using cin and MoveFile(). But the thing is MoveFile() parameters take LPCTSTR variables but cin doesnt take those variable types can anyone help me with a conversion from a char myChars[] table to a LPCTSTR variable? Any help is appreciated.
LPCTSTR is a typedef. It's actually another type: It's a long pointer to a const TCHAR string. Or, in other words, it's a const TCHAR*.
A TCHAR is also a typedef, but it's either a char or a wide character, depending on whether your project is using Unicode or ASCII. They usually default to Unicode.
You can use MoveFileA to force ASCII. Then, a LPCTSTR is literally a const char*.

Is MFC CString a wide char string

I'm working on a win32 project with CStrings (console application), and I noticed something odd when I want to pass to a function (like strtok_s for example) a LPSTR pointer from a CString with the method GetBuffer(), this last one instead of giving me a LPSTR, it gave me a LPWSTR (a pointer to a wide string)... CString is supposed to store 8 bit chars isn't it ?
I'm obliged in some cases to use CStringA for example to be able for example to use the method Find() because with a CString my input string must be a wide one. But in other another project (windowed program), I don't have this problem, i'm suspecting the headers (when I use afxstr.h "Find" works with a normal string, but not with afxcoll.h...)
Usually I work with std::string that's why I'm lost.
CString is a typdef, declared as (afxstr.h):
typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;
// Or, when using the MFC DLL
typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
Depending on what TCHAR is, a CString stores either an ANSI (MBCS) or Unicode string. There are also explicit instantiations of the CStringT template: CStringW and CStringA.
Either type has a conversion constructor, taking a constant pointer to the respective other character encoding. In other words: You can construct a CStringW from an ANSI (MBCS) string, as well as a CStringA from a UTF-16LE-encoded Unicode string.
If you need to be explicit about the character encoding, use either CStringW or CStringA.
Full documentation for CString is available at CStringT Class.

How to use a variable inside a _T wrapper?

I want to make the hostname part of this string to be variable..
Currently, it is only fix to this URL:
_T(" --url=http://www.myurl.com/ --out=c:\\current.png");
I want to make something like this, so the URL is changeable..
_T(" --url=http://www." + myurl + "/ --out=c:\\current.png");
update. Below is my latest attempt:
CString one = _T(" --url=http://www.");
CString two(url->bstrVal);
CString three = _T("/ --out=c:\\current.png");
CString full = one + two + three;
ShellExecute(0,
_T("open"), // Operation to perform
_T("c:\\IECapt"), // Application name
_T(full),// Additional parameters
0, // Default directory
SW_HIDE);
The error is : Error 1 error C2065: 'Lfull' : undeclared identifier c:\test.cpp
It doesn't work because the _T() macro works only with constant string literals. The definition for _T() looks something like this:
#ifdef UNICODE
#define _T(str) L##str
#else
#define _T(str) str
Since you're apparently compiling in Unicode mode, _T(full) expands to Lfull, which is obviously not what you want.
In your case, just pass in full without the _T() macro since CString defines a conversion operator to a const wchar_t* in Unicode mode, and const char* in non-Unicode mode.
ShellExecute(0, _T("open"), _T("c:\\IECapt"), full, 0, SW_HIDE);
Note that standard C++ also provides a std::string type and a std::wstring type which does pretty much what CString does, so MFC isn't actually required for string manipulation. std::string does not provide a conversion operator, but does provide access to the underlying C-style string via c_str().
Your latest attempt will work if you lose _T() from around "full" in the call to ShellExecute. The CString will return the correct pointer. Job done.
In addition though... You should just lose the _T() stuff completely. If you're going to do things like reference url->bstrVal directly (which is Unicode, no matter what you're compiling for) then your code will only work as Unicode.
There's very little reason anymore to compile the same project for both Unicode and ANSI these days. The _T() stuff was created to address both modes "easily". But unless you're targeting Win95/98/ME, you can just go Unicode and clean up your code. Unicode is faster too, because the Windows API and the Kernel is Unicode internally. All ANSI APIs start by converting string parameters to Unicode first, and then calling their wide-char counterpart.
So no _T, TCHAR, etc. Use things like this instead:
PWSTR psz = L"my unicode string";
CString s = L"my other string, yay!";
In addition to what In silico said, CString::Format makes this code a lot more readable:
CString full;
full.Format(_T(" --url=http://www.%s/ --out=c:\\current.png"), url->bstrVal));

How to do type conversion for the following Scenario?

I am using
TCHAR buffer[MAX_SIZE];
after some set of steps i am gettig the relative path of folder say for ex:
c:\Microsoft.NET\Framework\v1.0.037\
Since the above path is in buffer of type TCHAR and i am trying to concatenate"RegAsm.exe"
After Appending i need to convert the path to the LPCTSTR since i need to pass it to
CreateProcess() which takes LPCTSTR type as argument
then the compiler giving error.I have tried but vexed.
can any one help me in this aspect....
_tcscat_s
is the related method for TCHAR. It depends like TCHAR on the _UNICODE & _MBCS preprocessor swithch and will be resolved to strcat_s or wcscat_s.
TCHAR buffer[MAX_SIZE] = _T("c:\Microsoft.NET\Framework\v1.0.037\");
_tcscat_s(buffer, MAX_SIZE, _T("RegAsm.exe"));
but this is very good old C style. So while you are using TCHAR I would suggest that
you also use MFC stuff. So using CString which also is affected by _UNICODE & _MBCS would also solve your issue.
CString buffer;
buffer = _T("c:\Microsoft.NET\Framework\v1.0.037\");
buffer += _T("RegAsm.exe");
CreateProcess(buffer, ..
std::string or std::wstring will not help because they do not change their behavior related to the preprocessor switched but if you use CreateProcessA or CreateProcessW you can also use std::string or std::wstring.
The problem is TCHAR and CreateProcess are macros that expand differently depending on whether you compile for Unicode or not. The caveat is that GetCORSystemDirectory() will only accept a Unicode buffer. To get rid of these ANSI/Unicode problems write this code part explicitly for Unicode.
Instead of TCHAR use WCHAR for the buffer. Instead of CreateProcess() use CreateProcessW() - it will happily accept the Unicode buffer. Use wcscat() for strings concatenation.
Something like this (error handling omitted):
WCHAR buffer[MAX_PATH + 1];
DWORD realLength;
GetCORSystemDirectory( buffer, MAX_PATH, &realLength );
*( buffer + realLength ) = 0;// Don't forget to null-terminate the string
wcscat( buffer, L"regasm.exe" );
CreateProcessW( /*pass buffer here*/ );
I assume from the fact that you get an error that you're working with Unicode... In which case you may want to look at the mbstowcs and wcstombs functions.
More information is really needed to be able to answer properly.
If you want to make your life easier I would always suggest using std::string, then when calling the CreateProcess() function just do:
std::string myPath = "somePath";
LPCTSTR lpBuf = reinterpret_cast<LPCTSTR>(myPath.c_str());
Not tested but that should probably work, if you are still getting an error, well posting the code would be beneficial.
Note that it may be more complicated if you are using Unicode.
When you do buffer + "RegAsm.exe", it will be like adding two pointers (as arrays decay into pointers and "RegAsm.exe" will be const TCHAR*) hence you get the compiler error. What you want is string concatanation. Use _tcscat or or the secure version (as claimed in MSDN) _tcscat_s function for doing the concatanation.