Is there a way to use .NET reflection to capture the values of all parameters/local variables?
You could get at this information using the CLR debugging API though it won't be a simple couple of lines to extract it.
Reflection is not used to capture information from the stack. It reads the Assembly.
You might want to take a look at StackTrace
http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx
Good article here:
http://www.codeproject.com/KB/trace/customtracelistener.aspx
Reflection will tell you the type of parameters that a method has but it won't help discover their values during any particular invocation. Reflection doesn't tell you anything about local variables at all.
You need the sort of APIs that the debugger uses to access this sort of info.
I dont think this is possible, you can get the method and its parameters by looking at the StackTrace.
System.Diagnostics.StackTrace sTrace = new System.Diagnostics.StackTrace(true);
for (Int32 frameCount = 0; frameCount < sTrace.FrameCount; frameCount++){
System.Diagnostics.StackFrame sFrame = sTrace.GetFrame(frameCount);
System.Reflection.MethodBase thisMethod = sFrame.GetMethod();
if (thisMethod == currentMethod){
if (frameCount + 1 <= sTrace.FrameCount){
System.Diagnostics.StackFrame prevFrame = sTrace.GetFrame(frameCount + 1);
System.Reflection.MethodBase prevMethod = prevFrame.GetMethod();
}
}
}
I don't know how it's possible using reflection, but look at using weaving. SpringFramework.Net allows you to define pointcuts that can intercept method calls. Others probably do it as well.
Here's a link to the "BeforeAdvice" interceptor
http://www.springframework.net/docs/1.2.0-M1/reference/html/aop.html#d0e8139
The folks at secondlife suspend scripts and move them between servers. That implies that they have to capture the state of a running script, including the values of variables on the call stack.
Their scripting language runs on mono, an open source implementation of the .NET runtime. I doubt that their solution applies to the regular .NET runtime, but the video of the presentation on how they did it (skip to second half) might still be interesting.
Related
Are there any ways to find all code that invokes IO operations like File.WriteAllText, Request.Files["filename"].SaveAs("out"), etc?
For now I can just grep for all possible common ways to read/write files with something like that for example:
grep 'SaveAs' -I -r . -l | grep "\.cs"
This is not satisfactory because I can't think of all possible ways files can be read and written. Maybe it could be done via reflection somehow or through analysis of system calls in compiled binaries? Any ideas?
EDIT:
If method A calls method B and method B calls method C, and method C does a file operation it would be good to have that code identified as well. However, just to simplify the problem finding direct calls to IO would be sufficient.
If you're planning to develop this tool, you can start here.
The article describes ways to detect assembly and method dependencies, so you could find all methods that calls IO primitives, such as FileStream.Write.
So on a whim I decided to try this using Mono.Cecil.
It's pretty simple to recursively get a list of all the methods that a method calls:
static IEnumerable<MethodDefinition> GetMethodsCalledInMethod(MethodDefinition md)
{
if (md.Body == null)
{
return Enumerable.Empty<MethodDefinition>();
}
return md.Body.Instructions
.Select(i => i.Operand)
.OfType<MethodReference>()
.Select(mr => mr.Resolve())
.Where(mr => mr != null);
}
You can get all the methods in an assembly you want to inspect:
var ad = AssemblyDefinition.ReadAssembly(typeof(ATypeInTheAssembly).Assembly.Location);
var allMethodsInAssembly = ad.Modules
.SelectMany(m => m.Types)
.SelectMany(t => t.Methods));
You can then recurse through this tree of method calls until you find a method call which looks like an IO call.
Func<MethodDefinition, bool> isFileOperation = md =>
md.DeclaringType.Name == "FileStream";
Is this sufficient? I don't know. File.WriteAllText uses a FileStream. The SaveAs example you gave does too. But does every file access go through a FileStream? I can't say.
This approach also has issues:
You need to look out for recursive calls, because otherwise your recursion will turn into an infinite loop and you'll blow your stack.
This is sloooow. When I analysed a simple console application that called File.WriteAllLines I got a result immediately, but when I tried to analyse the analyser itself it got lost in the tree.
If you run into an interface - or even a virtual method - you can't know for sure what the implementation is going to be, so you can't know whether it'll perform an IO operation or not!
It depends on how much do you want to do in depth analysis.If you're really serious about catching all 'System.IO' method calls I would suggest using NRefactory. It's a front-end C# parser which can parse C# code and generated syntax tree and code resolver.
There's good tutorial about using it in code project that can help you to get started. Also in code project tutorial sample there's auxiliary classes that let you to load the whole solution, and provide you with code resolver.
If you need more sample you can find some in my blog.
PS : I'll try to extend this answer with code sample in a few hours.
What would be the easiest way to do instrumentation of C# code? By instrumentation I mean inserting my own pieces of the code to gather some dynamic information during the execution.
For example (star represents some unimportant piece of code):
for (int i=0; i<s.Length-2; ++i) {
if (*)
s = s.Substring(1, s.Length-2);
}
I would like to catch 0 being assigned to i, i incremented and assignment and call to a Substring. By catching a method call, I mean that I have information what method it is and values of the arguments or similar.
I tried to do it with the Roslyn by wrapping method calls with my own wrappers which could a) intercept values and store them (for example), b) call actual method and c) return this result. Only problem is that this approach is really error-prone and difficult (because there are many different cases to cover).
I wonder if there is already some library for this purpose or someone knows easier way of doing it. Thank you!
You could use tools like :
- Cecil
- ReFrameworker
- MBEL
- RAIL
I would like (in an ELEGANT way) to use some custom method attribute which will give me this:
When I call such a method foo(), in some attribute I'll have the elapsed time (how long the method call lasted).
How can I do it in C#? Reflections?
Thank you in advance.
James
C# doesn't offer this out of the box. You have a few choices:
Use some external profiler (I think higher editions of VS have one integrated)
Use an AOP framework. For example Postsharp rewrites your IL in an after build step to introduce prolog/epilog code based on attributes.
What's wrong with the StopWatch class? I use it regularly for profiling general timings in critical code. If that's not enough, I'll switch to ANTS (or dotTrace).
Action<Action> elegantBenchmark = (body) =>
{
var startTime = DateTime.Now;
body();
Console.WriteLine(DateTime.Now - startTime);
};
elegantBenchmark(DoWork);
P.S.
PostSharp will do the work as you want it to be done.
There is no way to intercept a plain old method call in C#. You would have to post(pre)-process your C# code (like with PostSharp) to really achieve this.
Alternatively, you could write a benchmarking method that takes a lambda to time a chunk of code, but this is obviously not a true decorator.
I am building a logging control for a C# project and would like to be able to call it with the name of the current source code File, Line, Class, Function, etc. PHP uses "magic constants" that have all of this info: http://php.net/manual/en/language.constants.predefined.php but I don't see anything like that in the C# compiler language.
Am I looking for something that doesn't exist?
Using the StackTrace/StackFrame classes, you can have your control find out where it's been called from, rather than passing it that information:
private static StringBuilder ListStack(out string sType)
{
StringBuilder sb = new StringBuilder();
sType = "";
StackTrace st = new StackTrace(true);
foreach (StackFrame f in st.GetFrames())
{
MethodBase m = f.GetMethod();
if (f.GetFileName() != null)
{
sb.AppendLine(string.Format("{0}:{1} {2}.{3}",
f.GetFileName(), f.GetFileLineNumber(),
m.DeclaringType.FullName, m.Name));
if (!string.IsNullOrEmpty(m.DeclaringType.Name))
sType = m.DeclaringType.Name;
}
}
return sb;
}
(I used this code to get the call stack of the currently executed method, so it does more than you asked for)
The StackTrace/StackFrame classes will give you quite a bit of this, though they can be quite expensive to construct.
You can ask the system for a stack trace, and you can use reflection. Details are coming.
__LINE__
__FILE__
__DIR__
__FUNCTION__ (does not really exist in C#)
__CLASS__
__METHOD__
__NAMESPACE__
This is a start:
http://www.csharp-examples.net/reflection-callstack/
http://www.csharp-examples.net/reflection-calling-method-name/
Assembly.GetExecutingAssembly().FullName
System.Reflection.MethodBase.GetCurrentMethod().Name
You will get better information in Debug (non-optimized) build. PhP might always have access to all that stuff, but it ain't the fastest gun on this planet. Play with it and let me know what is missing.
There are methods to get this type of data. It depends on what data you want.
__CLASS__ : If you want the current classname you'll need to use reflection.
__LINE__ : I'm not sure what "The current line number of the file" means, I'll take a guess and say it's how many lines in the file. That can be done by opening the file and doing a line count. This can be done via the File class, the FileInfo class may also work.
__DIR__ :Getting the directory of the file is done by using the DirectoryInfo class.
__FUNCTION__ and __METHOD__: Function name (method name), this can be retrieved via reflection.
__NAMESPACE__ :Namespace an be retrieved via reflection
Using Type, the best you can really do is get information about the current class. There is no means to get the file (though you should generally stick to one class per file), nor line number, nor function using Type.
Getting a type is simple, for example, this.getType(), or typeof(MyClass).
You can get the more specific details by generating a StackTrace object and retrieving a StackFrame from it, but doing so repeatedly is a bad idea.
I think a more important question is perhaps: why do you need them? For trace debugging, your output is supposedly temporary, so whether it reflects an accurate line number or not shouldn't matter (in fact, I rarely ever include a line number in trace debugging). Visual Studio is also very useful as a true step debugger. What do you really need File, Class, Function, and Line Number for?
Edit: For error checking, use exceptions like they're meant to be used: for exceptional (wrong) cases. The exception will generate a stack trace pointing you right at the problem.
Many of the previous responders have provided excellent information; however, I just wanted to point out that accessing the StackFrame is exorbitantly expensive and probably shouldn't be done except for special cases. Those cases being an extremely chatty verbose mode for debugging corner cases or error logging and for an error you probably already have an Exception instance which provides the StackTrace. Your best performance will be as Bring S suggested by using Type. Also as another design consideration logging to the console can slow your application down by several orders of magnitude depending on the volume of data to display. So if there is a console sink having the writer operating on a worker thread helps tremendously.
Question
I'm writing some code that needs to be able to get the values of the parameters from the method that called into the class. I know how to get all the way to the ParameterInfo[] array, but I don't know how to then get the values. Is this even possible?
If it is, I think it has something to do with using the MethodBody property from the MethodInfo object, which allows you to inspect the IL stream, including properties, but I don't know how to do it, and I haven't found applicable code on Google.
Code
// Finds calling method from class that called into this one
public class SomeClass
{
public static void FindMethod()
{
for (int i = 1; i < frameCount; i++)
{
var frame = new StackFrame(i);
var methodInfo = frame.GetMethod();
if (methodInfo.DeclaringType != this.GetType())
{
string methodName = frame.GetMethod().Name;
var paramInfos = methodInfo.GetParameters();
// Now what?? How do I get the values from the paramInfos
break;
}
else if (i == frameCount - 1)
{
throw new TransportException("Couldn't find method name");
}
}
}
}
You cannot do it without introspecting the stack yourself (and this is fragile since many optimizations may mean the stack frame is not what you expect, or even that the parameter passed is not in fact what the method signature would suggest (it is perfectly possible for an optimizing JIT compiler to spot that you are only using a sub field of an object/struct and pass that instead).
The ParameterInfo simply tells you the signature of the method as compiled, not the values that were passed.
The only realistic way to achieve this automatically is via code injection (via something like AOP) to create the data and do what you want with it based on analysing the IL.
This is generally not a good idea, if you need to debug something use a debugger, if you need to log something be explicit about what you are logging.
To be clear simple reflective techniques cannot achieve what you desire with full generality
Jonathan Keljo at Microsoft says, in this news group post, :
Unfortunately, the only easy way to get argument information from a
callstack today is with a debugger. If you're trying to do this as part of
error logging in an application and you plan to send the error log back to
your support department, we're hoping to have you use minidumps for that
purpose in the future. (Today, using a minidump with managed code is a
little problematic as it does not include enough information to even get a
stack trace by default. A minidump with heap is better, but not so "mini"
if you know what I mean.)
A purist would say that allowing people to write code that can get
arguments from functions elsewhere on the callstack would encourage them to
break encapsulation and create code that's very fragile in the face of
change. (Your scenario does not have this particular problem, but I've
heard other requests for this feature that would. Anyway most of those
requests can be solved in other ways, like using thread stores.) However,
more importantly there would be security implications of this--applications
that allow plugins would be at risk of those plugins scraping the stack for
sensitive information. We could certainly mark the function as requiring
full-trust, but that would make it unusable for pretty much every scenario
I've heard of.
Jonathan
So... I guess the short answer is "I can't." That sucks.
Yes, you can do this.
What you need to do is use an IL disassembler (which is achievable within the System.Reflection.Emit namespace) to find the Operand that contains the parameter value you're looking for.
Start with this SO question: C# reflection and finding all references
Then use the class mentioned in the answers (from Mono.Reflection) to do your inspection. Something like this:
var instructions = method.GetInstructions();
foreach (var instruction in instructions)
{
var methodInfo = instruction.Operand as MethodInfo;
if(methodInfo == null)
{
continue;
}
if (instruction.OpCode.Name.Equals("call") && methodInfo.Name.Equals("YourMethodHere"))
{
var value = (CastToMyType)instruction.Previous.Operand;
// Now you have the value...
}
}
You can't do it with either StackFrame or StackTrace. You can, however, employ some interception framework (such as AOP stuff from Spring.NET) so that you can get hold of parameter values.
See here:
Can you get a list of variables on the stack in C#?
I don't think it's possbile, based on all the comments on my answer there. The PropertyInfo class does have a GetValue method, but that requires you to have an actual object of which you want to get the value from.
Not sure if this counts as a solution, but worked for a specific case that i had,
i wanted to log each time a float was modified with minimal code changes,
Reading the file on the stack trace line to figure out the params
public static Score operator +(Score x,float y) {
var st = new StackTrace(true);
var sf = st.GetFrame(1);
string paramName = File.ReadLines(sf.GetFileName()).ElementAtOrDefault(sf.GetFileLineNumber()-1).Split(new[] { "+=" }, StringSplitOptions.None)[1];
x.DebugString += (paramName+" "+y);
x.DebugString += System.Environment.NewLine;
x.val += y;
return x;
}
void Main(){
Score score = new Score();
float firstScore = 2;
float secondScore = -13;
score+=firstScore;
score+=secondScore;
Console.WriteLine(score.DebugString);
}
Output :
firstscore 2
secondScore -13