Sign in to follow this  
Super Llama

C++ equivalent to Application.StartupPath?

Recommended Posts

Okay, with GetModuleFileName, what do I pass as the hModule? I've never used that type before... also what is argv[0]? I'm kind of new to C++, I understand it well but I don't know all the functions yet (switched from VB and C#)

EDIT: Nevermind, I googled it and found out it should be NULL. Thanks for telling me about the function [smile]

EDIT AGAIN:
I've implemented it successfully, thanks for the help. It took me a while to figure out the LPCH buffer and Size but that's what MSDN is for :D

Share this post


Link to post
Share on other sites
Quote:
Original post by Super Llama
also what is argv[0]?
In a standard C++ application, your main function should look something like this:
#include <iostream>

int main(int argc, char **argv) {
std::cout << argv[0] << '\n'; // This will print the application's launch path
}



The first item in the argv array (i.e. argv[0]) is your program's launch path. However, if you are using WinMain instead of main, things will be a little different.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
The first item in the argv array (i.e. argv[0]) is your program's launch path.

That's not guaranteed. According to the C++ standard (section 3.6.1 paragraph 2), argv[0] is "the name used to invoke the program". This may or may not include the path to the application, and in fact is allowed to be an empty string.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by swiftcoder
The first item in the argv array (i.e. argv[0]) is your program's launch path.

That's not guaranteed. According to the C++ standard (section 3.6.1 paragraph 2), argv[0] is "the name used to invoke the program". This may or may not include the path to the application, and in fact is allowed to be an empty string.
Fair enough, but in all the command line environments I have encountered, it has given exactly the (expanded) string I typed to launch the application, which is the relative path from the working directory.

It doesn't work so often in GUI environments - in particular, it is always the root directory for a Mac GUI application. However, a GUI application probably shouldn't be messing around in the application's install location - there are well defined directories on each platform reserved for program data ('~/Library/Application Support' on Mac, 'Documents & Settings' on Windows...).

Share this post


Link to post
Share on other sites
What argv[0] contains is not just dependent on command line environment, but also dependent on compiler and standard library implementation. For example compiling this program

#include <iostream>
int main (int, char ** argv) {
std::cout << argv[0] << std::endl;
}

with gcc 3.4.4 in cygwin to the executable a.exe and running it from Vista's command prompt produces the output "a". No path included or even any path delimiters. It's not even the full name of the executable.

Share this post


Link to post
Share on other sites
I'm trying to load bitmaps from a folder in the application's install folder, so SiCrane's method worked perfectly for me. I'm using WinMain instead of just Main, so there is no argv parameter.

This is my first GUI application in Native C++, EasilyConfused taught me how to use GDI+ in a different help topic yesterday, now I'm trying to load a bitmap from the same folder.

GetModuleFileName() works nicely. Now I just need to figure out how to chop off the end of it... I'm addicted to the VBA String class XD

Share this post


Link to post
Share on other sites
You can use std::string (or std::wstring if compiling for Unicode) for this like so:

char module_name[MAX_PATH];
GetModuleFileName(0, module_name, MAX_PATH);
std::string path(module_name);
path.erase(path.find_last_of('\\'), std::string::npos);

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
with gcc 3.4.4 in cygwin to the executable a.exe and running it from Vista's command prompt produces the output "a". No path included or even any path delimiters. It's not even the full name of the executable.
Did you provide a full path on the command line, or did you run it from its own directory? Either way, it is good to know that one shouldn't rely on the behaviour.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
I ran it from the executable's directory.
Then you would expect to get a relative path, i.e. 'a.exe'. On the other hand, since Windows does not require you to type the .exe extension, you may well have typed just 'a' to launch the program, in which case I would expect you to get exactly that in argv[0]. Note that the program inherits the users working directory, so passing that argv[0] to exec() (or whatever the equivalent is), will launch the program itself, so you do in fact have a complete path.

I don't have cygwin installed here, but I would be interested to see what happens if you specify a full path on the command line.

Share this post


Link to post
Share on other sites
As SiCrane has pointed out there is not a defined answer as to what argv[0] 's value will be.
http://www.faqs.org/faqs/unix-faq/programmer/faq/
Quote:

1.14 How can I find a process' executable file?
===============================================

This would be a good candidate for a list of `Frequently Unanswered
Questions', because the fact of asking the question usually means that the
design of the program is flawed. :-)

You can make a `best guess' by looking at the value of `argv[0]'. If this
contains a `/', then it is probably the absolute or relative (to the
current directory at program start) path of the executable. If it does
not, then you can mimic the shell's search of the `PATH' variable, looking
for the program. However, success is not guaranteed, since it is possible
to invoke programs with arbitrary values of `argv[0]', and in any case the
executable may have been renamed or deleted since it was started.

If all you want is to be able to print an appropriate invocation name with
error messages, then the best approach is to have `main()' save the value
of `argv[0]' in a global variable for use by the entire program. While
there is no guarantee whatsoever that the value in `argv[0]' will be
meaningful, it is the best option available in most circumstances.

The most common reason people ask this question is in order to locate
configuration files with their program. This is considered to be bad form;
directories containing executables should contain *nothing* except
executables, and administrative requirements often make it desirable for
configuration files to be located on different filesystems to executables.

A less common, but more legitimate, reason to do this is to allow the
program to call `exec()' *on itself*; this is a method used (e.g. by some
versions of `sendmail') to completely reinitialise the process (e.g. if a
daemon receives a `SIGHUP').


If you are using a system which has /proc/self/ then see HKO's post here

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Quote:
Original post by SiCrane
I ran it from the executable's directory.
Then you would expect to get a relative path, i.e. 'a.exe'. On the other hand, since Windows does not require you to type the .exe extension, you may well have typed just 'a' to launch the program, in which case I would expect you to get exactly that in argv[0]. Note that the program inherits the users working directory, so passing that argv[0] to exec() (or whatever the equivalent is), will launch the program itself, so you do in fact have a complete path.

In other words, the behavior is unpredictable and dependent on user invocation. On the other hand, Application.StartupPath and GetModuleFileName are independent of user action. ie, you can't rely on argv[0].

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Note that the program inherits the users working directory, so passing that argv[0] to exec() (or whatever the equivalent is), will launch the program itself, so you do in fact have a complete path.

Actually, it gives the same result if I dump it somewhere on the PATH and run it from a random directory. Which means that you've got absolutely no information about the path of the executable from argv[0].

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by swiftcoder
Note that the program inherits the users working directory, so passing that argv[0] to exec() (or whatever the equivalent is), will launch the program itself, so you do in fact have a complete path.
Actually, it gives the same result if I dump it somewhere on the PATH and run it from a random directory. Which means that you've got absolutely no information about the path of the executable from argv[0].
Right - I forgot about PATH. Yeah, it should give you a valid path to launch the application, not necessarily the application's own path.

Share this post


Link to post
Share on other sites
Ah, thanks, I didn't notice that ;)

I'm not compiling for Unicode but the Image::FromFile method requires a WCHAR for some reason XD

EDIT: YESSS!!! It worked, converted successfully, and loaded and displayed the bitmap :)

Thanks for all the help [smile]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this