Retrieve name of VB6 calling app via reflection from C# COM interf

Q

QSIDeveloper

I have a C# logging assembly with a static constructor and methods that is
called from another C# Assembly that is used as a COM interface for a VB6
Application. Ideally I need to build a file name based on the name of the
VB6 application. A second choice would be a file name based on the # COM
interface assembly. I have tried calling Assembly.GetCallingAssembly() but
this fails when I use the VB6 client. Is there a way to get this information
at runtime?
 
A

amdrit

What do you mean "fails"? Do you get an exception, or do you get and empty
string, or do you get a string that makes no sense?

It would seem to me that you are on the right track, and since the VB Client
is the ultimately the caller, is should come back with it's name if at all.
However, since you have the middle interface, why not require the caller to
name itself to the interface and just pass in App.Name there?
 
Q

QSIDeveloper

When I call GetCallingAssembly It does not fail (my bad) but I get the
Current assembly, in the prev description that would be the C# logging
assembly rather than the C# COM interface assembly as I had expected.

I also tried applying MethodImplAttribute attribute with
MethodImplOptions.NoInlining to the C# logging assembly constructor but it
had no affect.

I also tried GetEntryAssembly but that return null when run with a VB6
executable calling the COM interface.

I would like not to need an additional parameter for the name because this
will impact existing code. I would prefer a silent/automatic name creation.
 
S

Steven Cheng [MSFT]

Hi Amdrit,

As for the "GetCallingAssembly" method, it should return the immediate
caller of the current method. I'm not sure whether there is anything else
in your applicaiton/assmeblies that may cause the problem, but if what you
want to do is get reference to a certain assembly, you can consider using
the a type in the assembly to reference it. e.g.

"MyAssembly.MyType" is a known type defined in the target assemly I want
to get reference
================
Type tp =typeof(MyAssembly.MyType);

Assembly asm = tp.Assembly;

================

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.


--------------------
From: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= <[email protected]>
References: <[email protected]>
 
Q

QSIDeveloper

In the real app I don't know hat the calling assembly is nor do I know ablut
any types it contains.

Here is a simple example of the issue.
// Calling assembly
namespace ReflectionTest
{
class Program
{
static void Main(string[] args)
{
MyLogger.Logger.LogInfo("Hello");
}
}
}

// logger
namespace MyLogger
{
public class Logger
{
static string callingAssembly = string.Empty;
static Logger()
{

// This is where I need to know who called. The first call is
to LogInfo Below
// that causes this constructor to be called.
// What I need to know is the assembly that called LogInfo
string caller = Assembly.GetCallingAssembly().FullName; // this
returns 'Logger'
string s;
Assembly a = Assembly.GetEntryAssembly();
if (null != a)
s = a.FullName; // this gives me 'ReflectionTester', but
when called from VB6. a is null in that case
}

public static void LogInfo(string info)
{
if (callingAssembly.Equals(string.Empty))
callingAssembly = Assembly.GetCallingAssembly().FullName;
//This gives 'Logger' but it is too late by the time this is run

}
}
}
 
S

Steven Cheng [MSFT]

Thanks for your reply Amdrit,

Based on the complete code sample you provided, I've also tested it on my
side. I think the output is as expected.

In the static constructor of "Logger" class, the "GetCallingAssembly" will
return "MyLogger" assembly because the static constructor is called by .NET
runtime's internal code which is marked as the assembly itself(Rather than
the "ReflectionTest" app assembly).

And in the "LogInfo" method, the "GetCallingAssembly" will return
"ReflectionTest" because it is the immediate caller of the LogInfo method.
Also, if you call "GetEntryAssembly" it will return the assembly that
contains the Main entry point, that's the "ReflectionTest" app assembly
here. You can also see this chain correctly via the CallStack in
debugger's callstack window.

However, for unmanaged VB6 client, it is not a managed application, the
..NET runtime won't mark it as part of the calling assembly chain or entry
point, that's why you will not get it as Entry point assembly.

Why do you need to cache the calling AssemblyName in static constructor? I
think at runtime, it is possible that many different classes in different
assemblies may call "LogInfo" method and the "CallingAssmebly" may also
vary from time to time. It is reasonable to call "GetCallingAssembly" in
"LogInfo" method if you do need to get the assembly who invoke that method.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
Thread-Topic: Retrieve name of VB6 calling app via reflection from C# COM in
thread-index: Acie74kZBFIskDvWSkqeSsNJrp7vVQ==
Subject: Re: Retrieve name of VB6 calling app via reflection from C# COM in
Date: Tue, 15 Apr 2008 04:55:01 -0700
In the real app I don't know hat the calling assembly is nor do I know ablut
any types it contains.

Here is a simple example of the issue.
// Calling assembly
namespace ReflectionTest
{
class Program
{
static void Main(string[] args)
{
MyLogger.Logger.LogInfo("Hello");
}
}
}

// logger
namespace MyLogger
{
public class Logger
{
static string callingAssembly = string.Empty;
static Logger()
{

// This is where I need to know who called. The first call is
to LogInfo Below
// that causes this constructor to be called.
// What I need to know is the assembly that called LogInfo
string caller = Assembly.GetCallingAssembly().FullName; // this
returns 'Logger'
string s;
Assembly a = Assembly.GetEntryAssembly();
if (null != a)
s = a.FullName; // this gives me 'ReflectionTester', but
when called from VB6. a is null in that case
}

public static void LogInfo(string info)
{
if (callingAssembly.Equals(string.Empty))
callingAssembly = Assembly.GetCallingAssembly().FullName;
//This gives 'Logger' but it is too late by the time this is run

}
}
}

Steven Cheng said:
Hi Amdrit,

As for the "GetCallingAssembly" method, it should return the immediate
caller of the current method. I'm not sure whether there is anything else
in your applicaiton/assmeblies that may cause the problem, but if what you
want to do is get reference to a certain assembly, you can consider using
the a type in the assembly to reference it. e.g.

"MyAssembly.MyType" is a known type defined in the target assemly I want
to get reference
================
Type tp =typeof(MyAssembly.MyType);

Assembly asm = tp.Assembly;

================

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.


--------------------

at
all. caller
to that
is a
VB6 of
the #
COM
 
Q

QSIDeveloper

Thank you for looking at this, I had hoped I had overlooked something.
In most cases the logger is consumed by a .NET executable. In that case the
config information is found in the app.config file. In this case the main
executable is a VB6 application we that will eventually be replaced. New
feature are being added using .NET via COM. So as you know normally the
config file name is related to the exe as assembly.exe.config. In the case
of the VB6 EXE, the COM interface will be the only consumer of the logger so
I am looking for a way to build a config file name based on the assembly name
of the COM interface assembly rather than the usual exe. I was hoping there
was some way through reflection to get the assembly name (GetCallingAssembly
of CallingAssembly ) in case we need to have another similar situation with
another interface to legacy code rather than hard coding or passing in a
name.

Is there some way at run time to get the stack information?
If not thanks for you help.


Steven Cheng said:
Thanks for your reply Amdrit,

Based on the complete code sample you provided, I've also tested it on my
side. I think the output is as expected.

In the static constructor of "Logger" class, the "GetCallingAssembly" will
return "MyLogger" assembly because the static constructor is called by .NET
runtime's internal code which is marked as the assembly itself(Rather than
the "ReflectionTest" app assembly).

And in the "LogInfo" method, the "GetCallingAssembly" will return
"ReflectionTest" because it is the immediate caller of the LogInfo method.
Also, if you call "GetEntryAssembly" it will return the assembly that
contains the Main entry point, that's the "ReflectionTest" app assembly
here. You can also see this chain correctly via the CallStack in
debugger's callstack window.

However, for unmanaged VB6 client, it is not a managed application, the
.NET runtime won't mark it as part of the calling assembly chain or entry
point, that's why you will not get it as Entry point assembly.

Why do you need to cache the calling AssemblyName in static constructor? I
think at runtime, it is possible that many different classes in different
assemblies may call "LogInfo" method and the "CallingAssmebly" may also
vary from time to time. It is reasonable to call "GetCallingAssembly" in
"LogInfo" method if you do need to get the assembly who invoke that method.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
Thread-Topic: Retrieve name of VB6 calling app via reflection from C# COM in
thread-index: Acie74kZBFIskDvWSkqeSsNJrp7vVQ==
Subject: Re: Retrieve name of VB6 calling app via reflection from C# COM in
Date: Tue, 15 Apr 2008 04:55:01 -0700
In the real app I don't know hat the calling assembly is nor do I know ablut
any types it contains.

Here is a simple example of the issue.
// Calling assembly
namespace ReflectionTest
{
class Program
{
static void Main(string[] args)
{
MyLogger.Logger.LogInfo("Hello");
}
}
}

// logger
namespace MyLogger
{
public class Logger
{
static string callingAssembly = string.Empty;
static Logger()
{

// This is where I need to know who called. The first call is
to LogInfo Below
// that causes this constructor to be called.
// What I need to know is the assembly that called LogInfo
string caller = Assembly.GetCallingAssembly().FullName; // this
returns 'Logger'
string s;
Assembly a = Assembly.GetEntryAssembly();
if (null != a)
s = a.FullName; // this gives me 'ReflectionTester', but
when called from VB6. a is null in that case
}

public static void LogInfo(string info)
{
if (callingAssembly.Equals(string.Empty))
callingAssembly = Assembly.GetCallingAssembly().FullName;
//This gives 'Logger' but it is too late by the time this is run

}
}
}

Steven Cheng said:
Hi Amdrit,

As for the "GetCallingAssembly" method, it should return the immediate
caller of the current method. I'm not sure whether there is anything else
in your applicaiton/assmeblies that may cause the problem, but if what you
want to do is get reference to a certain assembly, you can consider using
the a type in the assembly to reference it. e.g.

"MyAssembly.MyType" is a known type defined in the target assemly I want
to get reference
================
Type tp =typeof(MyAssembly.MyType);

Assembly asm = tp.Assembly;

================

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.


--------------------
From: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= <[email protected]>
References: <[email protected]>
<[email protected]>
Subject: Re: Retrieve name of VB6 calling app via reflection from C# COM in
Date: Mon, 14 Apr 2008 10:43:14 -0700


When I call GetCallingAssembly It does not fail (my bad) but I get the
Current assembly, in the prev description that would be the C# logging
assembly rather than the C# COM interface assembly as I had expected.

I also tried applying MethodImplAttribute attribute with
MethodImplOptions.NoInlining to the C# logging assembly constructor but it
had no affect.

I also tried GetEntryAssembly but that return null when run with a VB6
executable calling the COM interface.

I would like not to need an additional parameter for the name because this
will impact existing code. I would prefer a silent/automatic name
creation.


:

What do you mean "fails"? Do you get an exception, or do you get and
empty
string, or do you get a string that makes no sense?

It would seem to me that you are on the right track, and since the VB
Client
is the ultimately the caller, is should come back with it's name if at
all.
However, since you have the middle interface, why not require the caller
to
name itself to the interface and just pass in App.Name there?


I have a C# logging assembly with a static constructor and methods that
is
called from another C# Assembly that is used as a COM interface for a
VB6
Application. Ideally I need to build a file name based on the name of
the
VB6 application. A second choice would be a file name based on the #
COM
interface assembly. I have tried calling
Assembly.GetCallingAssembly()
but
this fails when I use the VB6 client. Is there a way to get this
information
at runtime?
 
S

Steven Cheng [MSFT]

Thanks for your reply Amdrit,

There does exist a StackTrace class under "System.Diagnositcs" namespace
which can help capture the callstack(for managed code) of the current
thread.

#StackTrace Class
http://msdn2.microsoft.com/en-us/library/system.diagnostics.stacktrace(VS.71
).aspx

BTW, for unmanaged application(use COM interop to call .net component),it
can also have a exe.config file and you can store some simple data such as
<appSettings> items in it. Not sure whether this will be helpful?

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

--------------------
Thread-Topic: Retrieve name of VB6 calling app via reflection from C# COM i
From: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= <[email protected]>
References: <[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
Subject: Re: Retrieve name of VB6 calling app via reflection from C# COM in
Date: Wed, 16 Apr 2008 04:18:00 -0700
Thank you for looking at this, I had hoped I had overlooked something.
In most cases the logger is consumed by a .NET executable. In that case the
config information is found in the app.config file. In this case the main
executable is a VB6 application we that will eventually be replaced. New
feature are being added using .NET via COM. So as you know normally the
config file name is related to the exe as assembly.exe.config. In the case
of the VB6 EXE, the COM interface will be the only consumer of the logger so
I am looking for a way to build a config file name based on the assembly name
of the COM interface assembly rather than the usual exe. I was hoping there
was some way through reflection to get the assembly name (GetCallingAssembly
of CallingAssembly ) in case we need to have another similar situation with
another interface to legacy code rather than hard coding or passing in a
name.

Is there some way at run time to get the stack information?
If not thanks for you help.


Steven Cheng said:
Thanks for your reply Amdrit,

Based on the complete code sample you provided, I've also tested it on my
side. I think the output is as expected.

In the static constructor of "Logger" class, the "GetCallingAssembly" will
return "MyLogger" assembly because the static constructor is called by ..NET
runtime's internal code which is marked as the assembly itself(Rather than
the "ReflectionTest" app assembly).

And in the "LogInfo" method, the "GetCallingAssembly" will return
"ReflectionTest" because it is the immediate caller of the LogInfo method.
Also, if you call "GetEntryAssembly" it will return the assembly that
contains the Main entry point, that's the "ReflectionTest" app assembly
here. You can also see this chain correctly via the CallStack in
debugger's callstack window.

However, for unmanaged VB6 client, it is not a managed application, the
.NET runtime won't mark it as part of the calling assembly chain or entry
point, that's why you will not get it as Entry point assembly.

Why do you need to cache the calling AssemblyName in static constructor? I
think at runtime, it is possible that many different classes in different
assemblies may call "LogInfo" method and the "CallingAssmebly" may also
vary from time to time. It is reasonable to call "GetCallingAssembly" in
"LogInfo" method if you do need to get the assembly who invoke that method.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
Thread-Topic: Retrieve name of VB6 calling app via reflection from C#
COM
in
thread-index: Acie74kZBFIskDvWSkqeSsNJrp7vVQ==
Subject: Re: Retrieve name of VB6 calling app via reflection from C# COM in
Date: Tue, 15 Apr 2008 04:55:01 -0700
In the real app I don't know hat the calling assembly is nor do I know ablut
any types it contains.

Here is a simple example of the issue.
// Calling assembly
namespace ReflectionTest
{
class Program
{
static void Main(string[] args)
{
MyLogger.Logger.LogInfo("Hello");
}
}
}

// logger
namespace MyLogger
{
public class Logger
{
static string callingAssembly = string.Empty;
static Logger()
{

// This is where I need to know who called. The first call is
to LogInfo Below
// that causes this constructor to be called.
// What I need to know is the assembly that called LogInfo
string caller = Assembly.GetCallingAssembly().FullName; // this
returns 'Logger'
string s;
Assembly a = Assembly.GetEntryAssembly();
if (null != a)
s = a.FullName; // this gives me 'ReflectionTester', but
when called from VB6. a is null in that case
}

public static void LogInfo(string info)
{
if (callingAssembly.Equals(string.Empty))
callingAssembly = Assembly.GetCallingAssembly().FullName;
//This gives 'Logger' but it is too late by the time this is run

}
}
}

:

Hi Amdrit,

As for the "GetCallingAssembly" method, it should return the immediate
caller of the current method. I'm not sure whether there is anything else
in your applicaiton/assmeblies that may cause the problem, but if
what
you
want to do is get reference to a certain assembly, you can consider using
the a type in the assembly to reference it. e.g.

"MyAssembly.MyType" is a known type defined in the target assemly I want
to get reference
================
Type tp =typeof(MyAssembly.MyType);

Assembly asm = tp.Assembly;

================

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.


--------------------
From: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= <[email protected]>
References: <[email protected]>
<[email protected]>
Subject: Re: Retrieve name of VB6 calling app via reflection from C# COM in
Date: Mon, 14 Apr 2008 10:43:14 -0700


When I call GetCallingAssembly It does not fail (my bad) but I get the
Current assembly, in the prev description that would be the C# logging
assembly rather than the C# COM interface assembly as I had expected.

I also tried applying MethodImplAttribute attribute with
MethodImplOptions.NoInlining to the C# logging assembly constructor
but
it
had no affect.

I also tried GetEntryAssembly but that return null when run with a VB6
executable calling the COM interface.

I would like not to need an additional parameter for the name
because
this
will impact existing code. I would prefer a silent/automatic name
creation.


:

What do you mean "fails"? Do you get an exception, or do you get and
empty
string, or do you get a string that makes no sense?

It would seem to me that you are on the right track, and since the VB
Client
is the ultimately the caller, is should come back with it's name
if
at
all.
However, since you have the middle interface, why not require the caller
to
name itself to the interface and just pass in App.Name there?


I have a C# logging assembly with a static constructor and
methods
that
is
called from another C# Assembly that is used as a COM interface
for
a
VB6
Application. Ideally I need to build a file name based on the
name
of
the
VB6 application. A second choice would be a file name based on
the
#
COM
interface assembly. I have tried calling
Assembly.GetCallingAssembly()
but
this fails when I use the VB6 client. Is there a way to get this
information
at runtime?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top