Do pre-processor directives protect server code from the client? - c#

I'm developing a client-server library. Some of the classes can be used by either the client or the server but are executed differently and yield slightly different results for each. As well, the server code may contain additional methods that will not be called from the client build.
A class may look like this:
public class StuffDoer {
public void DoStuff(object msg)
{
ServerDoStuff(msg);
ClientDoStuff(msg);
}
[Conditional("SERVER")]
private void ServerDoStuff(object msg)
{
// Do secret server stuff...
}
[Conditional("CLIENT")]
private void ClientDoStuff(object msg)
{
// Do client sutff...
}
[Conditional("SERVER")]
public void DoCoolStuff(object msg)
{
// server does cool stuff...
}
}
I've read that the Conditional attribute still compiles the code and would therefore be in the build, unlike pre-processor directives which would completely remove the code and not even compile it.
I'm concerned that a dishonest client may hack the product by unobfuscating the source code and figure out how the server works.
Are my fears unfounded or would I need to place pre-processor directives in order to hide the source code?

According to the documentation:
Applying ConditionalAttribute to a method indicates to compilers that
a call to the method should not be compiled into Microsoft
intermediate language (MSIL) unless the conditional compilation symbol
that is associated with ConditionalAttribute is defined.
When you compile with CLIENT defined, the code to call a method marked with SERVER will not be present in the final assembly. But the code for the method will be present. You cannot achieve what you need in this way.

When "SERVER" is not defined, The method be marked as "SERVER" will always compile to the final assembly but all of callings to the method will be removed.
This is code
This is decompiled result

Related

StackTrace.GetFrame throws NullReferenceException in Release build but works in Debug build

I wrote a class which is intended to provide robust logging messages. One of the features I want to include is to include the class and method from which a call to generate a log message originated.
The problem I'm having is that StackTrace.GetFrame behaves inconsistently between debug and release builds. As far as I can tell, it behaves as expected when I execute programs from VS in debug. When I execute a release build deliverable, StackTrace.GetFrame throws a NullReferenceException.
Here's a simplified example of my code:
using Logging;
namespace MyApp
{
class Program
{
public static void Main(string[] args)
{
Logger Log = new Log(Level.INFO);
Log.Info(#"Hello, world!");
}
}
}
namespace Logging
{
class Logger
{
//Assume a constructor
public void Info(string message)
{
//We will need to go 3 method calls back from StandardEntry()
//to get the name of the method which called Log.Info
StandardEntry(text, Level.INFO, 3);
}
//This method is called by Logger.Info, Logger.Error, etc
private void StandardEntry(string message, Level entryLevel, int frameCount)
{
if (entryLevel >= this.level)
{
string message = $"[{CallingMethod(frameCount)}] {<entryLevel.ToString()>} {message}\r\n";
File.AppendText(this.LogPath, message);
}
}
private string CallingMethod()
{
string retVal;
StackTrace st = new StackTrace();
StackFrame sf = st.GetFrame(frameCount);
MethodBase callingMethod = sf.GetMethod();
return $"{callingMethod.ReflectedType.Name}.{callingMethod.Name}";
}
}
}
I've tried playing around with the value I'm passing in for frameCount, but a lower number returns a method call that is still within the Logger class. I need the method that actually called Log.Info
When running a release deliverable, Log.Info() in Program.Main throws a NullReferenceException, which leads me to believe that it's trying to access a stack frame index that is beyond the scope of the invoked executable.
When I debug in Visual Studio, there is no exception and CallingMethod() returns the expected expression.
In release builds, one of the optimizations the JIT compiler performs is inlining methods, i.e. inserting the code of a called method directly into the method calling it. This means that some methods may simply disappear from the stack trace you're seeing.
What you can do instead is add parameters to the Info method together with the caller information attributes which are made for scenarios like this. The C# compiler will automatically fill in the information for those parameters at compile time, so they're not affected by runtime optimizations.
It seems that class CallerMemberNameAttribute is what you actually needs.

Conditionally call a private method based on caller's debug configuration

My current code situation is that I have in assembly A the following code:
public class Foo
{
public Foo()
{
CreateDebugMessage();
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
private void CreateDebugMessage()
{
AddMessageType(MessageType.Debug, "Debug",
"/Company.App.Class;component/Images/image.png", Brushes.Green, false);
}
}
Some extra information is that I am using MEF and this method is called from the constructor. I have an assembly B (where I am importing assembly A) which depending on whether I am on DEBUG or RELEASE mode I want the Debug message to be created when I instantiate the class:
var foo = new Foo();
If I am on Debug mode I want the debug message to be created.
If I am on Release mode I DO NOT want the debug message to be created.
I thought the Conditional attribute would be better than the #iF DEBUG statement. This question showed me how WRONG I was! Since on runtime the method is never reached.
At this point I understand that the "#iF Debug" and "[Conditional("DEBUG")]" statements won't cut it for what I want to achieve.
Therefore my question is, how to make this scenario work?
The attribute works as it should, see Conditional Compilation in Referenced Assemblies. The attribute depends on the compilation symbols of the calling assembly. I tested and confirmed this: a method in an assembly with [Conditional("DEBUG")], compiled on Release, will only get called if the calling assembly is compiled in Debug. If this isn't the case for you, your code does not match your description.
The relevant part in your question is of course "This method is called from the constructor.". The attribute works for the direct caller, which in your case is the constructor of the containing class, which is Release.
You'll have to make it public and explicitly call the method:
public class Foo
{
public Foo()
{
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void CreateDebugMessage()
{
AddMessageType(MessageType.Debug, "Debug",
"/Company.App.Class;component/Images/image.png", Brushes.Green, false);
}
}
var foo = new Foo();
foo.CreateDebugMessage();

How do I add support for typed calls to a remote COM+ application

I am in the process of replacing a COM+ hosted application with a .Net variant.
The steps I took are roughly:
Generate an Interop assembly of the old dll
Create a new class in C# .Net that derives from ServicedComponent and implements the IMyClass interface from the interop.
I have annotated the class with a [Guid("...")] and a [ProgId("...")] attribute to match the class in the old dll
The end result looks like this:
[ProgId("MyComponent")]
[Guid("...")]
public class MyClass : ServicedComponent, IMyClass
{
public MyClass()
{
}
public object Open(string arg1, string arg2)
{
/* trace arguments*/
}
public object Run()
{
/* implementation here */
}
public void Close()
{
return;
}
}
This assembly is installed on a remote machine using regsvcs.exe
Now most clients use code similar to this unittest code:
Type typeFromProgID = Type.GetTypeFromProgID("MyComponent", "remoteMachine", true);
dynamic comInstance = Activator.CreateInstance(typeFromProgID);
comInstance.Open(string.Empty, string.Empty);
comInstance.Run();
comInstance.Close();
This works perfectly, the .Net tracing on the remote machine tells me everything is working as it should. Other clients use code similar to this:
Type typeFromProgID = Type.GetTypeFromProgID("MyComponent", "remoteMachine", true);
MyClass comInstance = (MyClass)Activator.CreateInstance(typeFromProgID);
comInstance.Open(string.Empty, string.Empty);
comInstance.Run();
comInstance.Close();
The first line is the same and seems to work fine, the rest acts weird. The VS debugger shows the lines are being executed. The remoteMachine shows that no methods are being executed.
The last call to Close(), which actually just returns, throws an exception:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Result StackTrace:
at Interop.MyComponent.IMyClass.Close()
at UnitTestProject1.UnitTest1.temp()
What have I missed in my implementation to support this last (typed) scenario?
This sounds like mismatched metadata, e.g. marshaling is different between the one that happens with the original type library and the one that happens with your server registered .NET assembly.
My guess is that the untyped case runs well because it depends solely on IDispatch, which .NET implements quite well, but the typed test fails (and I'm surprised it doesn't fail earlier) because of this mismatch.

Debug Log mess up my code

I am trying to add debug log to my C#.net code.
But it messes up my code, it looks like a hell.
Is there anything that log every code with its values automatically ?
Now it looks like this
#if DEBUG
debuglogger("The functionstarted");
#endif
someCode1();
#if DEBUG
debuglogger("SomeCode1 Finished");
#endif
someCode2();
#if DEBUG
debuglogger("SomeCode2 Finished");
#endif
someCode3();
#if DEBUG
debuglogger("SomeCode3 Finished");
#endif
#if DEBUG
debuglogger("Function End");
#endif
You should use the ConditionalAttribute. It allows you to define conditional methods that will be removed at build time if the condition doesn't match:
[Conditional("DEBUG")]
void DebugLog(string message)
{
// Do some logging...
}
calls to this method will be stripped out in builds without DEBUG defined. Just like
#if DEBUG
DebugLog("Testing...");
#endif
This has the added benefit of not cluttering up the stack traces as opposed to moving the #if inside the method.
Pretty late answer but I leave for future reference. In my opinion you should consider Aspect Oriented Programming for tasks like this. That said if you don't need to add such complexity for a small task you may move preprocessor conditions to your log method:
public static void Log(string message)
{
#if DEBUG
// Do logging
#endif
}
Do not worry to leave an empty method, JIT will optimize it away and it won't even be called. It's almost equivalent to:
[Condition("DEBUG")]
public static void Log(string message)
Warning: I say almost because with a method with [Condition] attribute arguments won't even be evaluated then given this code in release:
Log(String.Format("Index: {0}", index++));
index variable won't ever be incremented, because JIT compiler won't emit call to Log and even its arguments won't be evaluated. This is not true if you keep your method body empty with #if directive inside it. Call won't be emitted (because of empty body) but its arguments will be evaluated.
Problem of this solution is that it'll clutter your normal program flow. With log calls, parameters dumping and stuff like that. What can you do?
Refactor your log
If you call SomeCode1() method many times you shouldn't log at each call site, much better is to move logging inside called method. Log only at beginning and end of each function, log will still be in your code but it'll be spanned across multiple functions.
void SomeCode1() {
Log("Starting SomeCode1");
// Do something
Log("SomeCode1 completed");
}
Your calling site will then be clean:
SomeCode1();
SomeCode2();
SomeCode3();
Expressions
If performance aren't an issue (measure, don't guess) you may use Expressions to do the trick for you. You can log parameters too (or fields, object status, diagnostic informations, invariants and whatever else you may need), everything controlled by diagnostic switches (to enable them only when required). No logging code in your LOB classes but price to pay is execution speed (and LoggedOperation function complexity).
This code is (to be polite with myself) very naive, a decent implementation will be much more complex so just think about it as an idea more than an implementation.
static void LoggedOperation(Expression<Action> expression)
{
MethodCallExpression methodCall = expression.Body as MethodCallExpression;
if (methodCall != null)
Log("Calling {0}", methodCall.Method.Name);
expression.Compile()();
if (methodCall != null)
Log("{0} completed", methodCall.Method.Name);
}
It'll be then used like this:
LoggedOperation(() => SomeCode1());
LoggedOperation(() => SomeCode2());
LoggedOperation(() => SomeCode3());
You'll get:
Calling SomeCode1
SomeCode1 completed
Calling SomeCode2
SomeCode2 completed
Calling SomeCode3
SomeCode3 completed
AOP will give you a much cleaner code but this may be enough in many situations.
You can either move the preprocessor directives to the debuglogger function, or use a configurable logging framework that lets you configure when to log rather than relying on preprocessor statements at build time. That way you can "turn on" logging without having to rebuild the application.
You can use AOP for this, although I've not tried it myself.
Alternatively there are a number of things you can do to help improve the readability of your code such as using the Conditional attribute
Marking the debuglogger method with the Conditional attribute removes the need for the #if DEBUG code
[Conditional("DEBUG")]
public void debuglogger(string message)
{
// Logging code goes here
}
debuglogger("The functionstarted");
someCode1();
debuglogger("SomeCode1 Finished");
someCode2();
debuglogger("SomeCode2 Finished");
someCode3();
debuglogger("SomeCode3 Finished");
debuglogger("Function End");
Personally I would also have the someCodeN methods log the "SomeCodeN Finished" messages, which further simplifies your code
debuglogger("The functionstarted");
someCode1();
someCode2();
someCode3();
debuglogger("Function End");
public void someCode1()
{
// Do something
debuglogger("someCode1 Finished");
}
Mark Gravell recently posted an interesting idea utilizing partial classes. Link to his plog post
Project structure:
-Foo.cs
-Foo.debug.cs
And here the classes:
// Foo.debug.cs
#if DEBUG
partial class Foo
{
partial void Trace(string value)
{
Console.WriteLine("The value is: {0}", value);
}
}
#endif
// Foo.cs
partial class Foo
{
partial void Trace(string value);
public void MethodWithTracing()
{
Trace("This is traced");
}
}
Debug / Trace logic is separated from the normal code and when changing build options, it won't be compiled.

Compilter Directives - Suggestion - Run code in Debug mode only

I need to Log messages only when application is running in debug mode. I have found 2 ways:
First: Need to write 3 lines everywhere when logging is needed. But, Logger statement is disabled at compile time only which is exactly I need. Logger.Log will not be executed at all.
#if DEV_ENV
Logger.Log("Application started !"); // This line is grayed. Perfect !
#endif
public static void Log(string message)
{
Debug.WriteLine(message);
}
Second: Very neat. Only one line of code wherever logging is required. Not sure, whether Logger.Log statement is executed or not. If function call is removed at compile time only (same as first approach. But, now sure as line of code is not greyed out), I want to go with this.
Logger.Log("Application started !"); // This line is not grayed out. But, function is not called. So, confused whether its removed at compile time.
[Conditional("DEV_ENV")]
public static void Log(string message)
{
Debug.WriteLine(message);
}
I am concerned about the performance differences.
From the MSDN page for the ConditionalAttribute:
Applying ConditionalAttribute to a
method indicates to compilers that a
call to the method should not be
compiled into Microsoft intermediate
language (MSIL) unless the conditional
compilation symbol that is associated
with ConditionalAttribute is defined.
So, as it says, the method call is removed at compile time, same as the #if.
Depending on your compile settings, you could use:
if (System.Diagnostics.Debugger.IsAttached)
Logger.Log("Application started !");
or,
#if DEBUG
Logger.Log("Application started !");
#endif
As George points out, the method call will not be compiled if the Conditional attribute is applied. This also means (as with removing the code directly using #If DEV_ENV) that any side effects included in the method call will also not occur - as always, the warning about having side effects in logging code are well founded:
public static void Main(String[] args)
{
int i = 92;
Log(string.Format("{0} became {1}", i++, i));
Console.WriteLine(i);
Console.ReadLine();
}
[Conditional("SKIP")]
private static void Log(string msg)
{
Console.WriteLine(msg);
}
If SKIP is not defined, this code prints out 92. If SKIP is defined, it prints 92 became 93 and 93.

Categories