Something like IniFile=Application.ExecutablePath in Visual C++?

  • Thread starter Thread starter Harry Whitehouse
  • Start date Start date
H

Harry Whitehouse

I'm trying to obtain the load directory for my application, as well as the
Windows directory on the machine, but I don't know how this is accomplished
in VC++ .NET. In C# there is an Application object which provides this type
of information:

IniFile=Application.ExecutablePath;

Is there something comparable in VC?

TIA

Harry
 
Harry Whitehouse said:
I'm trying to obtain the load directory for my application,
GetModuleFileName().

as well as the Windows directory on the machine,

GetWindowsDirectory().

Regards,
Will
 
Hi Will!

When I try this:
Form1(void)

{

InitializeComponent();

TCHAR WinPath[_MAX_PATH+1]="";

GetWindowsDirectory(WinPath,_MAX_PATH);



}

I get these compiler errors:

c:\junkfuck\Form1.h(51): error C3861: 'GetWindowsDirectory': identifier not
found, even with argument-dependent lookup
c:\junkfuck\Form1.h(270): error C2065: 'WindowsDir' : undeclared identifier


I've used this API call in straight windows before many times, but I can't
get it recognized in the .NET environment!

Best

Harry
 
Harry Whitehouse said:
Hi Will!
Hello.

When I try this:
Form1(void)

{

InitializeComponent();

TCHAR WinPath[_MAX_PATH+1]="";

GetWindowsDirectory(WinPath,_MAX_PATH);



}

I get these compiler errors:

c:\junkfuck\Form1.h(51): error C3861: 'GetWindowsDirectory': identifier
not found, even with argument-dependent lookup
c:\junkfuck\Form1.h(270): error C2065: 'WindowsDir' : undeclared
identifier


I've used this API call in straight windows before many times, but I can't
get it recognized in the .NET environment!

Right. That's because in the .Net environment, an application is expected to
use the framwork. You can "drop down" to the level of the API but it is some
work to do so. It wouldn't surprise me if there is a class in .Net with a
method to get what you want. I don't have time now to do the research.

As for using the API, you have two choices. One is Platform Invoke aka
P/Invoke. This is an example

#include "stdafx.h"
#using <mscorlib.dll>

using namespace System;
using namespace System::Runtime::InteropServices;

[ DllImport("Kernel32.dll", EntryPoint="GetWindowsDirectoryW",
CallingConvention=CallingConvention::StdCall) ]
extern "C" int GetWindowsDirectory(wchar_t *, unsigned int);

int _tmain()
{
wchar_t wszDir[260];

GetWindowsDirectory(wszDir, sizeof(wszDir));

return 0;
}

Note that I hardcoded the size of the string. That's bad and only done here
as an expedient.

Another option is to use "it just works". IJW lets you have a managed caller
call into an unmanaged function. To do that, I'd suggest putting the native
API call in a module which does not use the framework and which is not
compiled with the /CLR option.

Regards,
Will
 
Harry said:
I'm trying to obtain the load directory for my application, as well
as the Windows directory on the machine, but I don't know how this is
accomplished in VC++ .NET. In C# there is an Application object
which provides this type of information:

IniFile=Application.ExecutablePath;

Is there something comparable in VC?

It's available in MC++ too:

System::String^ iniFile =
System::Windows::Forms::Application::ExecutablePath;

Can't remember off the top of my head how to get the Windows directory in
..NET, but if you can do in C#, you can use the same method in MC++. See also
Will's post on interop.
 
Bill -- That did it!

I had tried that with some C# syntax for the DLL call and it was crashing.
I see you need to add more verbage on the declaration and then it works!

Thanks so much!

Best

Harry
 
Harry Whitehouse said:
I had tried that with some C# syntax for the DLL call and it was crashing.
I see you need to add more verbage on the declaration and then it works!

You don't say what verbage. Here are a couple of tips. Virtually all of the
Win32 API uses the "standard" calling convention. C and C++ applications
tend to use a different one by default. So it is a good idea to specify the
calling convention, very nearly always
CallingConvention=CallingConvention::StdCall

In addition, Win32 API functions that take or return strings very nearly
always come in two variants - one whose name ends in 'A' and which takes and
returns ANSI characters and one whose name ends in 'W' and uses UNICODE. As
the .Net framework is all UNICODE, you are generally better off with the 'W'
variant.

Finally, go slow on the interoperability front. If you can find a .Net way
to do the same thing as a Win32 function as easily, prefer it instead.
Thanks so much!

You are welcome.

Regards,
Will
 
Hello William DePalo [MVP VC++],

Wouldn't you recommend IJW, and handling the marshling (via Marshal::XXX
methods) manually versus DllImport style ? I would think IJW performs better,
no ?

Thanks, RBischoff

W> W>W> Hello.
W>
When I try this:
Form1(void)
{

InitializeComponent();

TCHAR WinPath[_MAX_PATH+1]="";

GetWindowsDirectory(WinPath,_MAX_PATH);

}

I get these compiler errors:

c:\junkfuck\Form1.h(51): error C3861: 'GetWindowsDirectory':
identifier
not found, even with argument-dependent lookup
c:\junkfuck\Form1.h(270): error C2065: 'WindowsDir' : undeclared
identifier
I've used this API call in straight windows before many times, but I
can't get it recognized in the .NET environment!
W> Right. That's because in the .Net environment, an application is
W> expected to use the framwork. You can "drop down" to the level of the
W> API but it is some work to do so. It wouldn't surprise me if there is
W> a class in .Net with a method to get what you want. I don't have time
W> now to do the research.
W>
W> As for using the API, you have two choices. One is Platform Invoke
W> aka P/Invoke. This is an example
W>
W> #include "stdafx.h"
W> #using <mscorlib.dll>
W> using namespace System;
W> using namespace System::Runtime::InteropServices;
W> [ DllImport("Kernel32.dll", EntryPoint="GetWindowsDirectoryW",
W> CallingConvention=CallingConvention::StdCall) ]
W> extern "C" int GetWindowsDirectory(wchar_t *, unsigned int);
W> int _tmain()
W> {
W> wchar_t wszDir[260];
W> GetWindowsDirectory(wszDir, sizeof(wszDir));
W>
W> return 0;
W> }
W> Note that I hardcoded the size of the string. That's bad and only
W> done here as an expedient.
W>
W> Another option is to use "it just works". IJW lets you have a managed
W> caller call into an unmanaged function. To do that, I'd suggest
W> putting the native API call in a module which does not use the
W> framework and which is not compiled with the /CLR option.
W>
W> Regards,
W> Will
 
RBischoff said:
Wouldn't you recommend IJW, and handling the marshling (via Marshal::XXX
methods) manually versus DllImport style ? I would think IJW performs
better, no ?

Premature optimization is the root of much evil.

If the OP is going to call the function to get the Windows' directory once,
then I wouldn't worry _at all_ about which method is more performant.

If the OP is going to call some other unmanaged function alot, then I'd be
inclined to do the profiling rather than go off half-cocked in one directon
or other.

In fact, I'd be more inclined to investigate the possibility of minimizing
the transitions and of trying to do as much as possible per transition.

Regards,
Will
 
Hi Will!
If the OP is going to call some other unmanaged function alot, then I'd be
inclined to do the profiling rather than go off half-cocked in one
directon or other.

In fact, I'd be more inclined to investigate the possibility of minimizing
the transitions and of trying to do as much as possible per transition.

This is an excellent (indeed the best) suggestion. You definitely need to
think about how your code is going to be transitioning between managed and
unmanaged code, and preferably, design with this in mind to ensure it does
so in the best possible manners (this will not only help your performance,
it will make your debugging and development easier).

As for the original question, yes, IJW might be faster in many
circumstances, but it also comes with more work sometimes, as there pretty
much no safeguards and almost no automatic conversions of types, like
P/Invoke does.
 
Hello Tomas,

You and Will make good points and I can cetrainly understand that IJW has
the possibility of a lot more work.
As someone mentioned previously the analogy of round trips to the database,
the same as trips from managed to unmanaged ;)

RBischoff
-----------------------------------------
http://msdn.microsoft.com/visualc/ (VC++ HOME)
http://www.mvps.org/vcfaq/ (C++ FAQ)
http://www.winterdom.com/mcppfaq/ (MC++ FAQ)
http://msdn.microsoft.com/visualc/whidbey/ (CLI)

TR> Hi Will!
TR>TR> This is an excellent (indeed the best) suggestion. You definitely
TR> need to think about how your code is going to be transitioning
TR> between managed and unmanaged code, and preferably, design with this
TR> in mind to ensure it does so in the best possible manners (this will
TR> not only help your performance, it will make your debugging and
TR> development easier).
TR>
TR> As for the original question, yes, IJW might be faster in many
TR> circumstances, but it also comes with more work sometimes, as there
TR> pretty much no safeguards and almost no automatic conversions of
TR> types, like P/Invoke does.
TR>
 
Tim -- Good call! I figured there was something analogous!

Thanks to all for the help here!!

Best

Harry
 
Back
Top