|
As a beginner, I'm always afraid of 'loosing' the variables allocated locally inside the functions.
So, I should have defined the variable 'RtnVal' as static.
Is it necessary for CStrings, or the compiler takes care of them?
Thanks in advance.
Lino Masoni, Turin, Italy
lmasoni@alice.it
|
|
|
|
|
So what is some smart-ass user moved your exec to another folder, and the .ini files are still in the original folder?? There are many ways to screw up a function if someone really wants to...
Why not just call _getcwd() in OnInitialUpdate() and store the app-path in the registry... BEFORE any dialogs are opened. Presumably, the app was installed with your installer, and is being run from your shortcuts...
Sure, someone could manually create a shortcut and mess with the "Start in Folder" setting to "trick" your app... but realistically?? If so, I have no problem showing them an alert.
|
|
|
|
|
I've had WAY too many people creating desktop shortcuts and leave off the "Start in Folder" field altogether.
If we find users moving the program, we let our tech-support team loose on them. (Those are NOT kind and gentle phone calls!!!)
Many of our customers don't allow their users have access to the registry either.
There are many methods for doing this, as well as many ways to corrupt it, but it's been working for us for about 7 years now!
Thanks for the comment though. It's always good to get another opinion.
|
|
|
|
|
Brad Bruce wrote:
I've had WAY too many people creating desktop shortcuts and leave off the "Start in Folder" field altogether.
That's interesting, because even using right click or SEND TO DESKTOP to create shortcuts, Windows automatically fills in the START IN field. So they would have to manually open the shortcut and delete this field. For what purpose?? To sabotage the app?? I would turn the tech-support team loose on these people too.
Brad Bruce wrote:
Many of our customers don't allow their users have access to the registry either.
What?? Sure, some segments of the registry are reserved only for administrators, but the app automatically has access to it's own keys. Or are you saying your customers demand that you write apps that don't use the registry at all. That would be a very strange request. What would be the point of that?
Brad Bruce wrote:
it's been working for us for about 7 years now!
Hey... if it ain't broke, don't fix it!!
|
|
|
|
|
|
There's a global variable _pgmptr (and _wpgmptr) that's intialised to this value.
From dev docs:
When a program is run from the command interpreter (CMD.EXE), _pgmptr is automatically initialized to the full path of the executable file. For example, if HELLO.EXE is in C:\BIN and C:\BIN is in the path, _pgmptr is set to C:\BIN\HELLO.EXE when you execute.
Or have I missed the point?
|
|
|
|
|
The point was to get the directory of the program. This could be used to locate files. I frequently use this when using .ini files from the program directory.
|
|
|
|
|
This is how i do it ....
CString GetAppPath( void )
{
// get the app path from the help path
CString sAppPath = AfxGetApp()->m_pszHelpFilePath;
int iPos = sAppPath.ReverseFind( '\\' );
sAppPath = sAppPath.Mid( 0, iPos );
return sAppPath;
}
i was tired of finding a way to get the exe path, as i needed to access config files from there, and i had not read this post here, so i hacked up this little trick, works fine for me ...
of course this will only work if the help file path has not been changed, which i dont .
------------------------
Gopal Raichur
|
|
|
|
|
what is the adventage of using GetModuleFileName(AfxGetInstanceHandle(), FileName, MAX_PATH) instead of GetModuleFileName(NULL, FileName, MAX_PATH)?
May anybody explain me?
Rgs,
Alex
|
|
|
|
|
|
Alex2002 wrote:
what is the adventage of using GetModuleFileName(AfxGetInstanceHandle(), FileName, MAX_PATH) instead of GetModuleFileName(NULL, FileName, MAX_PATH)?
In this case, there is no advantage and I suggest that you should use NULL so that we can avoid the extra call to AfxGetInstanceHandle. MSDN snip follows :-
hModule
[in] Handle to the module whose path is being requested.
If this parameter is NULL, GetModuleFileName retrieves
the path for the current module.
Regards,
Nish
Author of the romantic comedy
Summer Love and Some more Cricket [New Win]
Review by Shog9
Click here for review[NW]
|
|
|
|
|
The article has been moved to the tips area and the level changed to beginner
|
|
|
|
|
|
It was intermediate. I missed the field when I first posted.
Brad
|
|
|
|
|
...you want to display the directory path in a dialog or setting file but if you want to open a file in the same dir all you need to do is send the file name to the file open function.
Real World Coding:
POP& BuyAPop(Money ADollar){...};
|
|
|
|
|
FileOpen ... go to the current working directory (whereever that is), not necessarily the program directory.
The same with the GetPrivateProfile... functions.
|
|
|
|
|
Bruce is right. If you want to open a file in your executable's directory, NEVER assume the program was started from that directory.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
Sorry, I forgot about CreateProcess() and SetCurrentDir...()
Real World Coding:
POP& BuyAPop(Money ADollar){...};
|
|
|
|
|
FYI, you can use the OFN_NOCHANGEDIR flag when using the Windows file dialog to stop it from changing directories. This makes _getcwd() more attractive. (And it's more portable too!)
-Mat
|
|
|
|
|
#include "shlwapi.h"
#pragma comment (lib,"shlwapi.lib")
CString GetProgramDir()
{
// Allocate buffer
CString lModulePath ;
LPSTR lModuleBuffer = lModulePath . GetBufferSetLength ( MAX_PATH ) ;
// Get module filename path, use NULL so it get application path and
// not a dll
GetModuleFileName ( NULL, lModuleBuffer, MAX_PATH ) ;
// Use shell api to extract the path
PathRemoveFileSpec ( lModuleBuffer ) ;
PathAddBackslash ( lModuleBuffer ) ;
// Free extra
lModulePath .ReleaseBuffer () ;
return lModulePath ;
}
|
|
|
|
|
Yes but...
Windows NT/2000: Requires Windows 2000 (or Windows NT 4.0 with Internet Explorer 4.0 or later).
Windows 95/98/Me: Requires Windows 98 (or Windows 95 with Internet Explorer 4.0 or later).
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
Come now, Tim! Are you really expecting to find those non-IE4 configurations of there?
MK
|
|
|
|
|
From a standpoint of shipping software, yes.
You just can't assume everyone has installed what you want installed. Considering that a routine not based on those functions is so easy to write, I wouldn't use them.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
I appreciate this article. I think the reason it has gotten such low marks is 1) because it is so simple and 2) the implementation is not perfect.
This question gets asked often in the forums and someone needed to answer it in an article.
3suggestions, though:
1) Make it UNICODE compliant. Someone already posted code for this.
2) Use _splitpath to extract the directory. The reverse_find method probably works all of the time, but I always use _splitpath because I trust it.
3) I would recommend removing the dependence on MFC. The way I would do this is to have 2 functions, 1 which returns a CString and the other which takes a char* and len as input paramaters.
Just my 2 cents.
Matt Gullett
|
|
|
|
|
Not that this is a function that is in need of optimization, but since you've forgotten to make it UNICODE/TCHAR-compatible, I though it would be in order to present two alternatives.
1) You needn't use both a CString and a buffer. Instead, I think you should either use CString's GetBuffer(), or base it entirely on CRT-functions.
2) You should normally include the last backslash in a path (add one to ReverseFind's result).
// Fully based on CString
CString GetProgramDir()
{
CString csProgDir;
::GetModuleFileName(AfxGetInstanceHandle(), csProgDir.GetBuffer(MAX_PATH), MAX_PATH);
csProgDir.ReleaseBuffer();
// Return path, including the last backslash. If ReverseFind should not
// find a backslash, the result will be -1 + 1 = 0, and a zero-length
// CString will be returned.
return csProgDir.Left(csProgDir.ReverseFind(_T('\\')) + 1);
}
// Avoids unnecessary memory allocation by using a buffer until it returns
CString GetProgramDir()
{
TCHAR tszFileName[MAX_PATH];
::GetModuleFileName(AfxGetInstanceHandle(), tszFileName, MAX_PATH);
// Remove filename from path
LPTSTR tszSlash = _tcsrchr(tszFileName, static_cast<int>(_T('\\')));
if ( tszSlash )
*++tszSlash = _T('\0');
return CString(tszFileName);
}
Cheers!
|
|
|
|