Thread: Working Directory and Links

  1. #1
    Registered User
    Join Date
    Mar 2007
    Posts
    416

    Working Directory and Links

    I am trying to deploy an application, and I ran in to this weird problem. When I install my program it works as it should, but only when I got to the Program File folder and click on the *.exe file itself. When I launch the file from the start menu, which uses a link, it will not find the external files needed to run (such as data files, ini, whatever files I need). If I put these needed files in with the link where the start menu folder is, then it works correctly. I have printed off the working directories for both ways of launching and they have always returned the same C:\Program Files\blah blah blah which is what I want, but the link seems to be ignoring this.

    So, is there something i am not aware of with the way links work, and the current working directory?

    edit: I should mention that I am using the current working directory path, plus the names of the files to get absolute paths and it is still giving me this problem.
    Last edited by scwizzo; 08-06-2010 at 09:27 PM.

  2. #2
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    To debug this, try printing the result of GetCurrentDirectory, build your path from that and print what you are trying to load. You'll probably find that you're missing a backslash or something.

  3. #3
    Registered User
    Join Date
    Mar 2007
    Posts
    416
    Here's something interesting.

    When I use getcwd() I get the the correct path, but it still won't open my files. When I use GetCurrentDirectory() I get the C:\Windows\system\ path. So both return different things, yet neither will open my file despite one of them being correct.

    edit: nevermind, I just ran it through another test. It is returning the C:\Windows\system path every time it is launched from the link. Does anyone know of a way to make it be what I want, without hard coding it, and without sticking an .ini file in the start menu folder? I prefer to keep only links in the start menu folder, and keep all program files in the folder under Program Files.

    The reason I don't want to hard code it is cause some systems are x86 with only Program Files folder, and other are x64 with both Program Files and Program Files (x86) folders. Also, the user may change the path on install.

  4. #4
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    The usual way to do it is to assemble it yourself using the path of the exe returned from GetModuleFileName(NULL, ...) as a starting point. I use this:

    Code:
    #include <windows.h>
    #include <string>
    #include <cassert>
    
    typedef std::basic_string<TCHAR> tstring;
    
    enum GMPP_Flag
    {
        GMPP_FULL_PATH,
        GMPP_DIRECTORY_ONLY,
        GMPP_FILE_ONLY
    };
    
    tstring GetModulePathPart(HMODULE hMod, GMPP_Flag op)
    {
        DWORD bufferSize = MAX_PATH;
        tstring filePath(bufferSize, 0);
        DWORD writtenSize = 0;
        for(;;)
        {
            writtenSize = GetModuleFileName(hMod, &filePath[0], bufferSize);
            if(writtenSize == bufferSize)
            {
                filePath.resize(bufferSize *= 2);
            }
            else if(!writtenSize)
            {
                return tstring();
            }
            else break;
        }
        filePath.resize(writtenSize);
        if(op != GMPP_FULL_PATH)
        {
            tstring::size_type where = filePath.find_last_of(TEXT("\\/"));
            if(where == tstring::npos)
            {
                where = 0;
            }
            // skip over the slash as we want it on the dir name, but not on the file name
            else ++where;
            if(op == GMPP_FILE_ONLY)
            {
                filePath = filePath.substr(where);
            }
            else
            {
                filePath.erase(where);
            }   
        }
        return filePath;
    }
    
    tstring BuildAbsolutePath(LPCTSTR addendum)
    {
        tstring appDir(GetModulePathPart(NULL, GMPP_DIRECTORY_ONLY));
        assert(!appDir.empty());
        return appDir + addendum;
    }

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by scwizzo View Post
    Here's something interesting.

    When I use getcwd() I get the the correct path, but it still won't open my files. When I use GetCurrentDirectory() I get the C:\Windows\system\ path. So both return different things, yet neither will open my file despite one of them being correct.

    edit: nevermind, I just ran it through another test. It is returning the C:\Windows\system path every time it is launched from the link. Does anyone know of a way to make it be what I want, without hard coding it, and without sticking an .ini file in the start menu folder? I prefer to keep only links in the start menu folder, and keep all program files in the folder under Program Files.

    The reason I don't want to hard code it is cause some systems are x86 with only Program Files folder, and other are x64 with both Program Files and Program Files (x86) folders. Also, the user may change the path on install.
    Extract the full path from argv[ 0 ]. If it isn't empty, use it to set the current directory. Something like this should work:

    Code:
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    char* extract_program_path( const char* nam, char* buf, size_t max )
    {
        char* end = strrchr( nam, '\\' );
        if( end == NULL )
            return getcwd( buf, max );
        size_t len = end - nam;
        if( max <= len )
            return NULL;
        strncpy( buf, nam, len );
        buf[ len ] = 0;
        return buf;
    }
    
    // Example:
    
    int main( int argc, char** argv )
    {
        char dir[ MAX_PATH ];
        if( extract_program_path( argv[ 0 ], dir, MAX_PATH ) )
        {
            chdir( dir );
        }
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Mar 2007
    Posts
    416
    Thanks guys. Using GetModuleFileName() worked out and now I can get the working directory of the .exe regardless of being a link, or even if it's launched through Visual Studios. Thanks again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. version of ls -l bug, only takes cwd :(
    By chl12 in forum C Programming
    Replies: 2
    Last Post: 06-12-2007, 02:44 AM
  2. Help Required!!!!!
    By bobthebullet990 in forum C Programming
    Replies: 14
    Last Post: 11-27-2005, 03:56 PM
  3. copy directory in C
    By Dbyte in forum C Programming
    Replies: 3
    Last Post: 06-14-2003, 12:00 PM
  4. Directory reading!
    By Unregistered in forum Linux Programming
    Replies: 0
    Last Post: 03-10-2002, 09:47 AM