Search code examples
c++winapivisual-c++getmodulefilename

Can I retrieve a path, containing other than Latin characters?


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);

Solution

  • 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");