Testing whether to launch debugger based on build & command line arguments
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
1
down vote
favorite
I have a C# application that may be spawned by another process using Shell
or its equivalent. As such, it is not trivial to simply F5 into a breakpoint nor launching an external program will work since a brand new process get spawned. Thus it is problematic especially when doing integration tests or diagnosing unusual problem that requires the same context than the one provided by automated tests.
I thought of passing in a debug flag but I don't want it to be accepted in a release build. I adapted the code from this SO thread by making it a complete function that returns a private struct
. The important part is the check within the Main
procedure where we inspect whether a -debug
flag has been passed via the command line argument and if so, confirm this is a debug build, not a release build. This seems to work well enough; but I want to know if this is reasonably good way to enable debugging on demand without exposing too much. Thus, the review is to see if this could be improved upon:
Note: I don't currently use all the member of the struct in the code; I don't know if there may be other use yet and didn't bother eliminating the unused members.
Note #2: I belatedly realized that I could have wrapped the check and the supporting function inside a #if DEBUG
block, which would also prevent the code from ever being included in a release build. However, it got me thinking if there might be legitimate scenario to launch debugger on a release build (even though the debug information will be sparse due to optimizations), so we can leave the question with the expectation that it could be used in release. Would it be an acceptable way or are there better ways?
internal class Program
[STAThread]
private static int Main(string args)
if (args.Any(a => a == "--debug") && GetDebugData().BuildType.ToLowerInvariant() == "debug")
Debugger.Launch();
// do something interesting....
private struct AssemblyDebugData
internal bool HasDebuggableAttribute;
internal bool IsJITOptimized;
internal string BuildType;
internal string DebugOutput;
private static AssemblyDebugData GetDebugData()
AssemblyDebugData result = new AssemblyDebugData();
object attribs = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
// If the 'DebuggableAttribute' is not found then it is definitely an OPTIMIZED build
if (attribs.Length > 0)
// Just because the 'DebuggableAttribute' is found doesn't necessarily mean
// it's a DEBUG build; we have to check the JIT Optimization flag
// i.e. it could have the "generate PDB" checked but have JIT Optimization enabled
DebuggableAttribute debuggableAttribute = attribs[0] as DebuggableAttribute;
if (debuggableAttribute != null)
result.HasDebuggableAttribute = true;
result.IsJITOptimized = !debuggableAttribute.IsJITOptimizerDisabled;
result.BuildType = debuggableAttribute.IsJITOptimizerDisabled ? "Debug" : "Release";
// check for Debug Output "full" or "pdb-only"
result.DebugOutput = (debuggableAttribute.DebuggingFlags &
DebuggableAttribute.DebuggingModes.Default) !=
DebuggableAttribute.DebuggingModes.None
? "Full" : "pdb-only";
else
result.IsJITOptimized = true;
result.BuildType = "Release";
return result;
c#
add a comment |Â
up vote
1
down vote
favorite
I have a C# application that may be spawned by another process using Shell
or its equivalent. As such, it is not trivial to simply F5 into a breakpoint nor launching an external program will work since a brand new process get spawned. Thus it is problematic especially when doing integration tests or diagnosing unusual problem that requires the same context than the one provided by automated tests.
I thought of passing in a debug flag but I don't want it to be accepted in a release build. I adapted the code from this SO thread by making it a complete function that returns a private struct
. The important part is the check within the Main
procedure where we inspect whether a -debug
flag has been passed via the command line argument and if so, confirm this is a debug build, not a release build. This seems to work well enough; but I want to know if this is reasonably good way to enable debugging on demand without exposing too much. Thus, the review is to see if this could be improved upon:
Note: I don't currently use all the member of the struct in the code; I don't know if there may be other use yet and didn't bother eliminating the unused members.
Note #2: I belatedly realized that I could have wrapped the check and the supporting function inside a #if DEBUG
block, which would also prevent the code from ever being included in a release build. However, it got me thinking if there might be legitimate scenario to launch debugger on a release build (even though the debug information will be sparse due to optimizations), so we can leave the question with the expectation that it could be used in release. Would it be an acceptable way or are there better ways?
internal class Program
[STAThread]
private static int Main(string args)
if (args.Any(a => a == "--debug") && GetDebugData().BuildType.ToLowerInvariant() == "debug")
Debugger.Launch();
// do something interesting....
private struct AssemblyDebugData
internal bool HasDebuggableAttribute;
internal bool IsJITOptimized;
internal string BuildType;
internal string DebugOutput;
private static AssemblyDebugData GetDebugData()
AssemblyDebugData result = new AssemblyDebugData();
object attribs = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
// If the 'DebuggableAttribute' is not found then it is definitely an OPTIMIZED build
if (attribs.Length > 0)
// Just because the 'DebuggableAttribute' is found doesn't necessarily mean
// it's a DEBUG build; we have to check the JIT Optimization flag
// i.e. it could have the "generate PDB" checked but have JIT Optimization enabled
DebuggableAttribute debuggableAttribute = attribs[0] as DebuggableAttribute;
if (debuggableAttribute != null)
result.HasDebuggableAttribute = true;
result.IsJITOptimized = !debuggableAttribute.IsJITOptimizerDisabled;
result.BuildType = debuggableAttribute.IsJITOptimizerDisabled ? "Debug" : "Release";
// check for Debug Output "full" or "pdb-only"
result.DebugOutput = (debuggableAttribute.DebuggingFlags &
DebuggableAttribute.DebuggingModes.Default) !=
DebuggableAttribute.DebuggingModes.None
? "Full" : "pdb-only";
else
result.IsJITOptimized = true;
result.BuildType = "Release";
return result;
c#
add a comment |Â
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have a C# application that may be spawned by another process using Shell
or its equivalent. As such, it is not trivial to simply F5 into a breakpoint nor launching an external program will work since a brand new process get spawned. Thus it is problematic especially when doing integration tests or diagnosing unusual problem that requires the same context than the one provided by automated tests.
I thought of passing in a debug flag but I don't want it to be accepted in a release build. I adapted the code from this SO thread by making it a complete function that returns a private struct
. The important part is the check within the Main
procedure where we inspect whether a -debug
flag has been passed via the command line argument and if so, confirm this is a debug build, not a release build. This seems to work well enough; but I want to know if this is reasonably good way to enable debugging on demand without exposing too much. Thus, the review is to see if this could be improved upon:
Note: I don't currently use all the member of the struct in the code; I don't know if there may be other use yet and didn't bother eliminating the unused members.
Note #2: I belatedly realized that I could have wrapped the check and the supporting function inside a #if DEBUG
block, which would also prevent the code from ever being included in a release build. However, it got me thinking if there might be legitimate scenario to launch debugger on a release build (even though the debug information will be sparse due to optimizations), so we can leave the question with the expectation that it could be used in release. Would it be an acceptable way or are there better ways?
internal class Program
[STAThread]
private static int Main(string args)
if (args.Any(a => a == "--debug") && GetDebugData().BuildType.ToLowerInvariant() == "debug")
Debugger.Launch();
// do something interesting....
private struct AssemblyDebugData
internal bool HasDebuggableAttribute;
internal bool IsJITOptimized;
internal string BuildType;
internal string DebugOutput;
private static AssemblyDebugData GetDebugData()
AssemblyDebugData result = new AssemblyDebugData();
object attribs = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
// If the 'DebuggableAttribute' is not found then it is definitely an OPTIMIZED build
if (attribs.Length > 0)
// Just because the 'DebuggableAttribute' is found doesn't necessarily mean
// it's a DEBUG build; we have to check the JIT Optimization flag
// i.e. it could have the "generate PDB" checked but have JIT Optimization enabled
DebuggableAttribute debuggableAttribute = attribs[0] as DebuggableAttribute;
if (debuggableAttribute != null)
result.HasDebuggableAttribute = true;
result.IsJITOptimized = !debuggableAttribute.IsJITOptimizerDisabled;
result.BuildType = debuggableAttribute.IsJITOptimizerDisabled ? "Debug" : "Release";
// check for Debug Output "full" or "pdb-only"
result.DebugOutput = (debuggableAttribute.DebuggingFlags &
DebuggableAttribute.DebuggingModes.Default) !=
DebuggableAttribute.DebuggingModes.None
? "Full" : "pdb-only";
else
result.IsJITOptimized = true;
result.BuildType = "Release";
return result;
c#
I have a C# application that may be spawned by another process using Shell
or its equivalent. As such, it is not trivial to simply F5 into a breakpoint nor launching an external program will work since a brand new process get spawned. Thus it is problematic especially when doing integration tests or diagnosing unusual problem that requires the same context than the one provided by automated tests.
I thought of passing in a debug flag but I don't want it to be accepted in a release build. I adapted the code from this SO thread by making it a complete function that returns a private struct
. The important part is the check within the Main
procedure where we inspect whether a -debug
flag has been passed via the command line argument and if so, confirm this is a debug build, not a release build. This seems to work well enough; but I want to know if this is reasonably good way to enable debugging on demand without exposing too much. Thus, the review is to see if this could be improved upon:
Note: I don't currently use all the member of the struct in the code; I don't know if there may be other use yet and didn't bother eliminating the unused members.
Note #2: I belatedly realized that I could have wrapped the check and the supporting function inside a #if DEBUG
block, which would also prevent the code from ever being included in a release build. However, it got me thinking if there might be legitimate scenario to launch debugger on a release build (even though the debug information will be sparse due to optimizations), so we can leave the question with the expectation that it could be used in release. Would it be an acceptable way or are there better ways?
internal class Program
[STAThread]
private static int Main(string args)
if (args.Any(a => a == "--debug") && GetDebugData().BuildType.ToLowerInvariant() == "debug")
Debugger.Launch();
// do something interesting....
private struct AssemblyDebugData
internal bool HasDebuggableAttribute;
internal bool IsJITOptimized;
internal string BuildType;
internal string DebugOutput;
private static AssemblyDebugData GetDebugData()
AssemblyDebugData result = new AssemblyDebugData();
object attribs = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(DebuggableAttribute), false);
// If the 'DebuggableAttribute' is not found then it is definitely an OPTIMIZED build
if (attribs.Length > 0)
// Just because the 'DebuggableAttribute' is found doesn't necessarily mean
// it's a DEBUG build; we have to check the JIT Optimization flag
// i.e. it could have the "generate PDB" checked but have JIT Optimization enabled
DebuggableAttribute debuggableAttribute = attribs[0] as DebuggableAttribute;
if (debuggableAttribute != null)
result.HasDebuggableAttribute = true;
result.IsJITOptimized = !debuggableAttribute.IsJITOptimizerDisabled;
result.BuildType = debuggableAttribute.IsJITOptimizerDisabled ? "Debug" : "Release";
// check for Debug Output "full" or "pdb-only"
result.DebugOutput = (debuggableAttribute.DebuggingFlags &
DebuggableAttribute.DebuggingModes.Default) !=
DebuggableAttribute.DebuggingModes.None
? "Full" : "pdb-only";
else
result.IsJITOptimized = true;
result.BuildType = "Release";
return result;
c#
edited Mar 21 at 1:54
Hosch250
16.9k561153
16.9k561153
asked Mar 20 at 2:35
this
1,232317
1,232317
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Use
#if Debug
. It will be a lot more expected to have to remove/disable that than to change the if and remember to remove the then-deadGetDebugData
method. (Principle of Least Astonishment, right?)Don't specify
STAThread
. It's just useless. First, it would be extremely surprising if someone tries to use multithreading 10 years down the road and it failed. Second, it doesn't provide any significant overhead (if any at all) to not use this. Finally, console apps run single-threaded by default. There is no excuse to disable multi-threading in the whole app. There is excuse to disable multi-threading in parts that can't be multi-threaded because of whatever (maybe it calls into code running on a STA thread), but those instances can be handled on a case-by-case basis with explanation in comments.
Now, assuming for some reason I haven't comprehended, you absolutely have to use this.
- You are defining whether a build is a "debug" or "release" based on whether the code is optimized. That has nothing to do with Visual Studio's definition (and therefore the standard definition) of what a "debug" or "release" build is. That and the output paths are the only changes I can think of off-hand between the default "debug" and "release" candidates. However, you could define a "debug" build as one compiled against C# 7.2 and a "release" build as one compiled against C# 6 and leave optimization on or off in both for whatever reason. I wouldn't use the terminology "debug" vs. "release" here; I'd just check whether debug symbols were enabled when I determined whether to kick off the debugger.
- If you change what I suggest above, I'd recommend renaming
DebugOutput
to justOutput
and assigning it whether the code is optimized or not. I can compile as None, Full, Pdb-Only, Portable, or Embedded with JIT-optimization enabled anyway.
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Use
#if Debug
. It will be a lot more expected to have to remove/disable that than to change the if and remember to remove the then-deadGetDebugData
method. (Principle of Least Astonishment, right?)Don't specify
STAThread
. It's just useless. First, it would be extremely surprising if someone tries to use multithreading 10 years down the road and it failed. Second, it doesn't provide any significant overhead (if any at all) to not use this. Finally, console apps run single-threaded by default. There is no excuse to disable multi-threading in the whole app. There is excuse to disable multi-threading in parts that can't be multi-threaded because of whatever (maybe it calls into code running on a STA thread), but those instances can be handled on a case-by-case basis with explanation in comments.
Now, assuming for some reason I haven't comprehended, you absolutely have to use this.
- You are defining whether a build is a "debug" or "release" based on whether the code is optimized. That has nothing to do with Visual Studio's definition (and therefore the standard definition) of what a "debug" or "release" build is. That and the output paths are the only changes I can think of off-hand between the default "debug" and "release" candidates. However, you could define a "debug" build as one compiled against C# 7.2 and a "release" build as one compiled against C# 6 and leave optimization on or off in both for whatever reason. I wouldn't use the terminology "debug" vs. "release" here; I'd just check whether debug symbols were enabled when I determined whether to kick off the debugger.
- If you change what I suggest above, I'd recommend renaming
DebugOutput
to justOutput
and assigning it whether the code is optimized or not. I can compile as None, Full, Pdb-Only, Portable, or Embedded with JIT-optimization enabled anyway.
add a comment |Â
up vote
2
down vote
accepted
Use
#if Debug
. It will be a lot more expected to have to remove/disable that than to change the if and remember to remove the then-deadGetDebugData
method. (Principle of Least Astonishment, right?)Don't specify
STAThread
. It's just useless. First, it would be extremely surprising if someone tries to use multithreading 10 years down the road and it failed. Second, it doesn't provide any significant overhead (if any at all) to not use this. Finally, console apps run single-threaded by default. There is no excuse to disable multi-threading in the whole app. There is excuse to disable multi-threading in parts that can't be multi-threaded because of whatever (maybe it calls into code running on a STA thread), but those instances can be handled on a case-by-case basis with explanation in comments.
Now, assuming for some reason I haven't comprehended, you absolutely have to use this.
- You are defining whether a build is a "debug" or "release" based on whether the code is optimized. That has nothing to do with Visual Studio's definition (and therefore the standard definition) of what a "debug" or "release" build is. That and the output paths are the only changes I can think of off-hand between the default "debug" and "release" candidates. However, you could define a "debug" build as one compiled against C# 7.2 and a "release" build as one compiled against C# 6 and leave optimization on or off in both for whatever reason. I wouldn't use the terminology "debug" vs. "release" here; I'd just check whether debug symbols were enabled when I determined whether to kick off the debugger.
- If you change what I suggest above, I'd recommend renaming
DebugOutput
to justOutput
and assigning it whether the code is optimized or not. I can compile as None, Full, Pdb-Only, Portable, or Embedded with JIT-optimization enabled anyway.
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Use
#if Debug
. It will be a lot more expected to have to remove/disable that than to change the if and remember to remove the then-deadGetDebugData
method. (Principle of Least Astonishment, right?)Don't specify
STAThread
. It's just useless. First, it would be extremely surprising if someone tries to use multithreading 10 years down the road and it failed. Second, it doesn't provide any significant overhead (if any at all) to not use this. Finally, console apps run single-threaded by default. There is no excuse to disable multi-threading in the whole app. There is excuse to disable multi-threading in parts that can't be multi-threaded because of whatever (maybe it calls into code running on a STA thread), but those instances can be handled on a case-by-case basis with explanation in comments.
Now, assuming for some reason I haven't comprehended, you absolutely have to use this.
- You are defining whether a build is a "debug" or "release" based on whether the code is optimized. That has nothing to do with Visual Studio's definition (and therefore the standard definition) of what a "debug" or "release" build is. That and the output paths are the only changes I can think of off-hand between the default "debug" and "release" candidates. However, you could define a "debug" build as one compiled against C# 7.2 and a "release" build as one compiled against C# 6 and leave optimization on or off in both for whatever reason. I wouldn't use the terminology "debug" vs. "release" here; I'd just check whether debug symbols were enabled when I determined whether to kick off the debugger.
- If you change what I suggest above, I'd recommend renaming
DebugOutput
to justOutput
and assigning it whether the code is optimized or not. I can compile as None, Full, Pdb-Only, Portable, or Embedded with JIT-optimization enabled anyway.
Use
#if Debug
. It will be a lot more expected to have to remove/disable that than to change the if and remember to remove the then-deadGetDebugData
method. (Principle of Least Astonishment, right?)Don't specify
STAThread
. It's just useless. First, it would be extremely surprising if someone tries to use multithreading 10 years down the road and it failed. Second, it doesn't provide any significant overhead (if any at all) to not use this. Finally, console apps run single-threaded by default. There is no excuse to disable multi-threading in the whole app. There is excuse to disable multi-threading in parts that can't be multi-threaded because of whatever (maybe it calls into code running on a STA thread), but those instances can be handled on a case-by-case basis with explanation in comments.
Now, assuming for some reason I haven't comprehended, you absolutely have to use this.
- You are defining whether a build is a "debug" or "release" based on whether the code is optimized. That has nothing to do with Visual Studio's definition (and therefore the standard definition) of what a "debug" or "release" build is. That and the output paths are the only changes I can think of off-hand between the default "debug" and "release" candidates. However, you could define a "debug" build as one compiled against C# 7.2 and a "release" build as one compiled against C# 6 and leave optimization on or off in both for whatever reason. I wouldn't use the terminology "debug" vs. "release" here; I'd just check whether debug symbols were enabled when I determined whether to kick off the debugger.
- If you change what I suggest above, I'd recommend renaming
DebugOutput
to justOutput
and assigning it whether the code is optimized or not. I can compile as None, Full, Pdb-Only, Portable, or Embedded with JIT-optimization enabled anyway.
answered Mar 21 at 1:52
Hosch250
16.9k561153
16.9k561153
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f189992%2ftesting-whether-to-launch-debugger-based-on-build-command-line-arguments%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password