Luke Vo
Luke Vo

Reputation: 20658

From a .NET library, how to check if the RUNNING assembly/app is in Debug build (without Debugger attached)?

I am making a class library Foo (Xamarin Android Library if relevant but I prefer a general .NET solution if possible), and I need something like this:

if (builtInDebugConfig) 
{
    this.DoSomething();
}

Now Foo.dll will certainly be compiled in Release mode when the above code is called. Therefore #if is not possible for sure, Conditional should not work also (correct me if I am wrong, I've read it's a compiler attribute too) (the answer of the question and my test confirms Conditional works). The closest I could think of is Debugger.IsAttached, however most of the time we test apps without a debugger attached.

Is there a way to detect if the calling assembly is compiled with DEBUG symbol/config? If possible I don't want the calling (app) code to have something like this in every app because it defeats the purpose:

#if DEBUG
    Foo.IsDebug = true;
#endif

UPDATE: Clarification for why I want that: I want to enable Debug codes (i.e enable WebView debug signal) if the calling app is in in development and don't want such code to exist in final view. That's why I am interested in a solution that prevent such code leaking to Release build.

Upvotes: 1

Views: 1301

Answers (2)

Luke Vo
Luke Vo

Reputation: 20658

Thanks to the comments and answers, I've found two working solutions, both are great but I think I will use Conditional in my final project. IsExecutingDebug checks if DebuggableAttribute is present in the Entry assembly, while Conditional is explained in Jon Skeet's answer.

namespace ClassLibrary1
{
    public class Class1
    {

        public bool IsExecutingDebug()
        {
#if DEBUG
            Console.WriteLine("Debug in lib");
#endif

            return Assembly.GetExecutingAssembly().IsInDebug();
        }

        [Conditional("DEBUG")]
        public void ExecuteInDebugOnly()
        {
            Console.WriteLine("Hi!");
        }

    }
}

namespace System
{

    public static class MyExtensions
    {
        public static bool IsInDebug(this Assembly assembly)
        {
            return assembly.GetCustomAttributes<DebuggableAttribute>().Any();
        }
    }

}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500385

You can use Conditional in Foo to decorate a method - any calls to that method will depend on whether the calling code defines the relevant symbol. So something like:

[Conditional("DEBUG")]
public void MaybeSetDebugMode()
{
    // Remember the decision
}

Then the calling code can unconditionally write code calling MaybeSetDebugMode, and the call will only actually be compiled in if DEBUG is defined when the calling code is compiled. The method in Foo itself will be compiled into Foo.dll regardless of the symbols defined when you compile it.

That's not the same as #if, which does depend on the symbols when you're compiling your code.

Note that this is how Debug.WriteLine etc work.

One downside of this: this code absolutely will exist in the "final build" unless you take more action. It has to, given that the existence of code in Foo.dll can't change depending on what calls it.

So you may actually want to use #if instead, for example:

#if FINAL_BUILD
public void MaybeSetDebugMode()
{
    // This method exists so that the calling code will still build
    // with the final DLL, but there won't be any "interesting" code
    // for anyone to find.
}

#else

public void MaybeSetDebugMode()
{
    // Interesting code goes here. This code won't be included in the final build,
    // but callers can call it unconditionally, because there'll be an empty
    // method in the final build.
}
#endif

Upvotes: 4

Related Questions