1

I call GetModuleFileName function, in order to retrieve the fully qualified path of a specified module, in order to call another .exe in the same file, via Process::Start method.

However, .exe cannot be called when the path contains other than Latin characters (in my case Greek characters).

Is there any way I can fix this?

Code:

    TCHAR path[1000];
    GetModuleFileName(NULL, path, 1000) ; // Retrieves the fully qualified path for the file that
                                          // contains the specified module.

    PathRemoveFileSpec(path); // Removes the trailing file name and backslash from a path (TCHAR).

    CHAR mypath[1000];
    // Convert TCHAR to CHAR.
    wcstombs(mypath, path, wcslen(path) + 1);

    // Formatting the string: constructing a string by substituting computed values at various 
    // places in a constant string.
    CHAR mypath2[1000];
    sprintf_s(mypath2, "%s\\Client_JoypadCodesApplication.exe", mypath);

    String^ result;
    result = marshal_as<String^>(mypath2);

    Process::Start(result);
dempap
  • 352
  • 1
  • 9
  • 21
  • [`GetModuleFileName`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms683197.aspx) - like pretty much any other string related API - has Unicode and ANSI implementations (`GetModuleFileNameW` and `GetModuleFileNameA`). The error is in the code you haven't posted. – IInspectable May 16 '14 at 12:45
  • 1
    "Convert TCHAR to CHAR." This conversion is lossy. That is where you are losing the non-Latin characters. @IInspectable This code is built UNICODE as evidenced by the call to wcstombs. OP got the path just fine. They just handled the answer incorrectly. – Raymond Chen May 16 '14 at 13:49
  • @Raymond Chen If i understood `GetModuleFileName`, `PathRemoveFileSpec` store characters in Unicode by default and then `wcstombs` turns Unicode to ANSI? – dempap May 16 '14 at 14:21
  • They store in the character set you request. Your project is defined as a UNICODE project, so you get Unicode. You then convert this to ANSI, which loses the non-Latin characters. You got the path just fine. You just mishandled it afterwards. – Raymond Chen May 16 '14 at 14:45
  • 1
    Windows API calls without a `W` or `A` suffix are mapped to either Unicode or ANSI version, depending on whether `UNICODE` is defined. As @Raymond pointed out, your project is set to use Unicode characters. Your conversion to MBCS (`wcstombs`) is where things fall apart. Keep using Unicode throughout and things will be just fine. – IInspectable May 16 '14 at 14:47

2 Answers2

1

You must use GetModuleFileNameW and store the result in a wchar_t string.

Most Win32 API functions have a "Unicode" variant, which takes/gives UTF-16 strings. Using the ANSI versions is highly discouraged.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
1

Strings in .NET are encoded in UTF-16. The fact that you are calling wcstombs() means your app is compiled for Unicode and TCHAR maps to WCHAR, which is what Windows uses for UTF-16. So there is no need to call wcstombs() at all. Retrieve and format the path as UTF-16, then marshal it as UTF-16. Stop using TCHAR altogether (unless you need to compile for Windows 9x/ME):

WCHAR path[1000];
GetModuleFileNameW(NULL, path, 1000);

PathRemoveFileSpecW(path);

WCHAR mypath[1000];
swprintf_s(mypath, 1000, L"%s\\Client_JoypadCodesApplication.exe", path);

String^ result;
result = marshal_as<String^>(mypath);

Process::Start(result);

A better option would be to use a native .NET solution instead (untested):

String^ path = Path::DirectoryName(Application->StartupPath); // uses GetModuleFileName() internally
// or:
//String^ path = Path::DirectoryName(Process::GetCurrentProcess()->MainModule->FileName);

Process::Start(path + L"\\Client_JoypadCodesApplication.exe");
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770