locked
Stack Frame Different in .Net4.0/Win7 to .NET1.1/XP, No Assembly/Module Information for Event Handlers RRS feed

  • Question

  • Hi,

    I am currently porting a .NET1.1 application that runs on XP, to .NET4.0 to be run on Windows 7. I am experiencing a problem with some of the logging functions that work in .NET1.1/XP but exhibit different behaviour under .NET4.0/Win7.

    The logging code can be called from any module by use of a logger object, which directs its output to a log file who's path is constructed by concatenation of a configurable path, the current date, and the assembly that the object owning the logger belongs to. Also, each module has its logging level configured in a config file, and when logging, a threshold is passed in (Trace, Debug, Info...etc) that the logger uses to determine whether or not to log the accompanying text, by comparing it to the configured level for that module.

    Inside the logger a stack frame is constructed using:

    stackFrame = new System.Diagnostics.StackFrame(stackLevel, true); // Stack level is 3 typically, but can be lowered if a valid stack frame isn't constructed.

    The logging level for the calling module is found by using the following as an index into the config array:

    stackFrame.GetMethod().DeclaringType.Assembly.GetName().FullName

    The assembly name, for use in the log file, is found from:

    stackFrame.GetMethod().DeclaringType.Assembly.GetName().Name

    The problem occurs when logging from within event handlers. In .NET1.1/XP, FullName and Name return values that are modules and assemblies within the application, in the same manner as regular (non event handler) methods do.

    However, in .NET4.0/Win7 these values, for event handlers only (non event handlers are unaffected by this problem) are not specific to my application. These are their values for an event handler:

    StackFrame.GetMethod().DeclaringType.FullName = System.Runtime.Remoting.Messaging.StackBuilderSink
    stackFrame.GetMethod().DeclaringType.Assembly.GetName().Name = mscorlib

    Since System.Runtime.Remoting.Messaging.StackBuilderSink is not a recognised module, the logger fails to find the logging level and can proceed no further. If allowed to, all event handler output, for all modules, will be written to the same file.

    If I change the Release build settings in VS2010, to turn off optimisation, and set Debug output to 'full' (in Advanced properties on the build tab of the properties page) FullName and Name then return the 'correct' values, that are meaningful to my application. This may be a viable workaround, but I am concerned about the possibility of someone reverse engineering the released code. Is this a valid concern?

    Ideally I'd like to get an optimised Release build, with no debug output, to function under .NET4.0/Win7 in the same manner as it does under .NET1.1/XP. Is this possible?  Also, is this difference in behaviour attributable to the different .NET version, or the different version of Windows, and what exactly has changed to change the behaviour?

    Thanks in advance for any help,

    Jon

    Thursday, April 18, 2013 4:31 PM

Answers

  • Your concerns are not valid for the release build.  I can get a dump of any .NET source code minus the comments by using any # of reflection tools available like Reflector or JustDecompile.  Whether it is a debug or release build is irrelevant.  You do however want to ship release code for the optimizations.

    However your logging behavior is somewhat flawed because a release mode app won't have full stack information necessarily.  You shouldn't rely on it existing as any # of things can cause intermediate code to be placed between code you've written and code that is being called.  Your logging infrastructure should be smart enough to walk the stack frames until it gets to an identifiable piece of code it can handle or it gets to native code where it should probably stop processing.

    While there are changes between versions of the framework AFAIK the stack frame behavior hasn't changed at all.  It has always been true that a release build will generate different stack frame information than debug (if for no other reason than methods can be inlined).  But you may see different stack frames between different versions as optimizations are made and code is rewritten.  Irrelevant your logging infrastructure should be resilient to that sort of thing.  If it isn't then it is limiting its usefulness.  If you were to take a look at the TraceSource stuff starting with .NET 2.0 you can see it implements a lot of this same logic where you can filter things by where they came from (type is most common) and whatnot.  One key property of all good logging infrastructures is that they just work even when faced with potentially bad data because, after all, the times you want logging is when things go wrong.

    Michael Taylor
    http://msmvps.com/blogs/p3net

    • Proposed as answer by Mike Feng Friday, April 19, 2013 2:14 PM
    • Marked as answer by Jon S Hill Tuesday, April 23, 2013 9:36 AM
    Thursday, April 18, 2013 10:11 PM

All replies

  • Your concerns are not valid for the release build.  I can get a dump of any .NET source code minus the comments by using any # of reflection tools available like Reflector or JustDecompile.  Whether it is a debug or release build is irrelevant.  You do however want to ship release code for the optimizations.

    However your logging behavior is somewhat flawed because a release mode app won't have full stack information necessarily.  You shouldn't rely on it existing as any # of things can cause intermediate code to be placed between code you've written and code that is being called.  Your logging infrastructure should be smart enough to walk the stack frames until it gets to an identifiable piece of code it can handle or it gets to native code where it should probably stop processing.

    While there are changes between versions of the framework AFAIK the stack frame behavior hasn't changed at all.  It has always been true that a release build will generate different stack frame information than debug (if for no other reason than methods can be inlined).  But you may see different stack frames between different versions as optimizations are made and code is rewritten.  Irrelevant your logging infrastructure should be resilient to that sort of thing.  If it isn't then it is limiting its usefulness.  If you were to take a look at the TraceSource stuff starting with .NET 2.0 you can see it implements a lot of this same logic where you can filter things by where they came from (type is most common) and whatnot.  One key property of all good logging infrastructures is that they just work even when faced with potentially bad data because, after all, the times you want logging is when things go wrong.

    Michael Taylor
    http://msmvps.com/blogs/p3net

    • Proposed as answer by Mike Feng Friday, April 19, 2013 2:14 PM
    • Marked as answer by Jon S Hill Tuesday, April 23, 2013 9:36 AM
    Thursday, April 18, 2013 10:11 PM
  • Thank you for your input Michael, I will take it on board.

    Jon

    Tuesday, April 23, 2013 9:36 AM