How to programmatically obtain the value of switch in code? [duplicate] - c#

In my web.config I have:
<system.diagnostics>
<switches>
<add name="logLevelSwitch" value="1" />
</switches>
</system.diagnostics>
Is there a way that I could call, for example:
System.Diagnostics.TraceSwitch["logLevelSwitch"]to get the current value?

Once you've defined the switch value in your web.config file, it's easy to get this value from your application by creating a TraceSwitch with the same name:
private static TraceSwitch logSwitch = new TraceSwitch("logLevelSwitch",
"This is your logLevelSwitch in the config file");
public static void Main(string[] args)
{
// you can get its properties value then:
Console.WriteLine("Trace switch {0} is configured as {1}",
logSwitch.DisplayName,
logSwitch.Level.ToString());
// and you can use it like this:
if (logSwitch.TraceError)
Trace.WriteLine("This is an error");
// or like this also:
Trace.WriteLineIf(logSwitch.TraceWarning, "This is a warning");
}
Moreover, for this to work, according to the documentation:
You must enable tracing or debugging to use a switch. The following
syntax is compiler specific. If you use compilers other than C# or
Visual Basic, refer to the documentation for your compiler.
To enabledebugging in C#, add the /d:DEBUG flag to the compiler command line
when you compile your code, or you can add #define DEBUG to the top of
your file. In Visual Basic, add the /d:DEBUG=True flag to the compiler
command line.
To enable tracing using in C#, add the /d:TRACE flag to
the compiler command line when you compile your code, or add #define TRACE to the top of your file. In Visual Basic, add the /d:TRACE=True
flag to the compiler command line.

Related

How to force Visual Studio 2022 create console projects with namespaces and classes (like in old good days)?

Just switched to VS2022, created new project and see this:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Where is all other stuff? Why is that by default now?
Click the link. It redirects to https://learn.microsoft.com/nl-nl/dotnet/core/tutorials/top-level-templates. It has a paragraph stating:
If you want to use the old templates, see the Use the old program style section.
That section mentions that this is the new default. To circumvent it, create a .NET 5-targeting application, and modify your project file:
- <TargetFramework>net5.0</TargetFramework>
+ <TargetFramework>net6.0</TargetFramework>
A workaround I guess would be to create a custom project template.
If you are using Visual Studio, you can install the Classic Console Template
https://marketplace.visualstudio.com/items?itemName=Doomdied.ClassicConsole1
It add old classic console back, then you can forgot the new one.
You can access the args through a special variable with that name in a top level statement class file:
if (args.Length > 0)
{
foreach (var arg in args)
{
Console.WriteLine($"Argument={arg}");
}
}
else
{
Console.WriteLine("No arguments");
}
Similarly, you just return an int to set the exit code:
string? s = Console.ReadLine();
int returnValue = int.Parse(s ?? "-1");
return returnValue;
See:
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements
As to why, there has been a push to clean up the source files from needless whitespace, masses of curly braces, long lists of imports at the top of each file and the explicit namespace declaration, where most everyone syncs the namespaces with the assembly name and solution folder anyway.
It's been a thorn in the eye of many that simple things in c# need 10s of lines of code where they are a single line in node or python or ruby. It's just not productive. Same for Razor templates and Razor files. You just need an IDE to do she right thing. With these changes it should become much easier to be productive from the GitHub, even if you're not using Visual Studio.
Visual Studio 2022 with .NET 6 uses a new template when creating a C# console app. The new template reduces the amount of boilerplate code necessary to write a simple C# program. I believe this change was meant to benefit beginning programmers and those who are new to C#.
New style:
Statements in Program.cs that appear outside of any function are automatically placed in Main().
Function declarations are moved outside Main() and made static.
A number of using statements are implicitly added for common namespaces like System, System.IO, System.Linq, etc.
Example:
// New style
Console.WriteLine("Code in Main()");
Test();
void Test()
{
Console.WriteLine("Test");
}
is roughly equivalent to:
// Old style
using System;
namespace MyApp
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Code in Main()");
Test();
}
static void Test()
{
Console.WriteLine("Test");
}
}
}
There is nothing stopping you from using the old style. You can copy and paste the old-style code above into Program.cs, and it will run just fine.
There is an option now, to disable top-level statements:
I just tried it and it produces an old-style project. :-)
You also don't loose file-scoped namespaces, they still work.
The "other stuff" is all there; it's just a new convention. It isn't obvious as you might use to get things in C# but this is the new way. And of course, you can use the old style with Main(string args) by selecting Do no use top-level statements checkbox when creating the project in Visual Studio or employ the --use-program-main option on the command line, like this:
dotnet new console --use-program-main
As for the magic of accessing the command line arguments with this new style, see my answer here.

Custom user configuration in C# application

Let's say I have a command line application that needs to reference some form of a user configuration file. Furthermore, the values contained within this file are to only be updated by the user manually -- there won't be any ways of updating the configuration file within the application, nor will the application seek out any inputs once started. If a configuration listing is missing from the configuration file, a default value should be used instead.
I understand that Visual Studio / .NET Framework offer tools for creating such constructs (i.e. Settings and App.configs), but I'm not sure I'm using them correctly -- or if I should be using them at all.
I created a Settings file and threw in a couple of default settings (e.g. SomeBooleanFlag is a bool with a default value of 'False'). This addition of course was reflected within my App.config. However, here is where the dilemma lies: how should I read from the App.config?
Currently, I've created a class to abstract away the configuration manager / settings stuff:
class AppSettings
{
public static bool SomeBooleanFlag
{
get
{
try
{
string rawValue = ConfigurationManager.AppSettings["SomeBooleanFlag"];
bool userSetSomeBooleanFlag;
bool userValueParsed = bool.TryParse(rawValue, out userSetSomeBooleanFlag);
return (userValueParsed) ? userSetSomeBooleanFlag : Settings.Default.SomeBooleanFlag;
}
catch
{
return Settings.Default.SomeBooleanFlag;
}
}
}
}
Which then gives me the ability to write:
if (AppSettings.SomeBooleanFlag)
{
/* Do Something... */
}
However, this does not seem like a clean way to approach the problem I stated above. Any help would be greatly appreciated!
Instead of coding your own Application Settings wrapper, you can reuse the functionality built into Visual Studio to generate this wrapper for you. See How to: Add or Remove Application Settings and How To: Read Settings at Run Time With C#. In addition to specifying the type of the setting you can also indicate the scope (User or Application).
Following the steps in the aforementioned articles, it will add the settings to your App.config file, below is an example:
<configuration>
...
<applicationSettings>
<ConsoleApplication1.Properties.Settings>
<setting name="TestKey" serializeAs="String">
<value>TestValue</value>
</setting>
</ConsoleApplication1.Properties.Settings>
</applicationSettings>
...
</configuration>
And you can access these settings as follows:
string s = Properties.Settings.Default.TestKey;

Generate an exe with predefinied settings

I do apologise if i didn't asked correctly in the title.. i don't know how to ask or what to call for what i need.
-
Let's say that i have a simple Application called "TestApp" written in C#.
Inside that application, i have the next variables:
int clientid = 123;
string apiurl = "http://somesite/TestApp/api.php";
When i have a new client, i need to create a new special TestApp.exe just for him, changing the 'clientid' variable inside the code.
It's possible to automate this process? To change that variable automatically and export an exe without for me to interfere with the process?
-
I asked this because i think/or i'm sure that it's possible because of the next popular examples:
http://download.cnet.com/2701-20_4-1446.html?tag=sideBar;downloadLinks
[ It creates a special .exe with a predefinied link from where to download the real file ]
http://torrent2exe.com/
[ It's embedding the .torrent file to a special .exe just with some custom variables changed, like torrent name or download size ]
Again, i do apologise if i didn't asked my question correctly and for my bad english, trying my best.
So you have two parts to your question:
You want to have variables inside the program based on client for your app
You want to automate the process of making the settings changes.
To make custom settings:
Use AppSettings.
First, add a reference to System.Configuration assembly.
In your app.config file:
<configuration>
<appSettings>
<add key="ClientID" value="123" />
<add key="ApiUrl" value="http://somesite/TestApp/api.php" />
</appSettings>
</configuration>
In your code, to read the settings:
using System;
using System.Configuration;
class Program
{
private static int clientID;
private static string apiUrl;
static void Main(string[] args)
{
// Try to get clientID - example that this is a required field
if (!int.TryParse( ConfigurationManager.AppSettings["ClientID"], out clientID))
throw new Exception("ClientID in appSettings missing or not an number");
// Get apiUrl - example that this isn't a required field; you can
// add string.IsNullOrEmpty() checking as needed
apiUrl = ConfigurationManager.AppSettings["apiUrl"];
Console.WriteLine(clientID);
Console.WriteLine(apiUrl);
Console.ReadKey();
}
}
More about AppSettings on MSDN
To automate the creation of settings:
This all depends on how complex you want to get.
When you build your project, your app.config file becomes TestApp.exe.config
You can use ConfigurationManager class to write Config files.
Further, you can write a little Exe that writes the config file with custom settings and execute it as part of a build action. Lots of ways to accomplish automation which depend on how you intend to deploy your application.
A quick example of writing an app.config file appSettings section programmatically:
public static void CreateOtherAppSettings()
{
Configuration config =
ConfigurationManager.OpenExeConfiguration("OtherApp.config");
config.AppSettings.Settings.Add("ClientID", "456");
config.AppSettings.Settings.Add("ApiUrl", "http://some.other.api/url");
config.Save(ConfigurationSaveMode.Modified);
}

Debug.Assert seems not to work in Mono

Consider the following C# program:
using System;
using System.Diagnostics;
namespace Test
{
class MainClass
{
public static void Main (string[] args)
{
Debug.Assert(false);
Debug.Fail("fail!");
Console.WriteLine ("Hello World!");
}
}
}
When compiling this using:
dmcs -debug -d:DEBUG Main.cs
and then running it with:
mono --debug Main.exe
the assertion and fail seem to be ignored. The output is just:
Hello World!
I checked other related questions on StackOverflow, but I could not find a solution. In particular the solution give in Mono - Debug.Assert does not work does not work. (UPDATE: the updated solution does work, see below comments.)
I use Mono 2.10.5-1 on Ubuntu 11.10.
C# on mono - http://ebsteblog.wordpress.com/2009/05/06/debugassert-and-mono/
Excerpt from the article:
...if you create a .config file for your app and set the assertuienabled attribute to true, you get the same dialog as with .NET... File app.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.diagnostics>
<assert assertuienabled="true" />
</system.diagnostics>
</configuration>
Old answer: C++ comment if you did not specify -define DEBUG on command line/compile options.
For debug add
#define DEBUG
at the beginning of the code or
#define TRACE
for trace.
See the solution here: http://lists.ximian.com/pipermail/mono-list/2006-December/033774.html
p.s: I tried this with C++ not C#. This may not work for C#.
You can use the xml configuration, or you can place it under the control of your program by adding a trace listener at runtime:
var tl = new System.Diagnostics.ConsoleTraceListener();
System.Diagnostics.Debug.Listeners.Add ( tl );
This has the added advantage of you being able to enable it after the program has started.

How do I conditionally enable attributes in C#? "#if DEBUG" isn't working

The trusty old preprocessor directive in C# appear to work great when I write:
#if DEBUG
...
(Some code)
...
#endif
However, attributes enclosed in the conditional block appear to continue to get processed and I get errors indicating such. For instance, surrounding an [AssemblyVersion(...)] within the conditional block appears to have no affect.
I can go into the details as to why we want to conditionally ignore the [AssemblyVersion(..)], but it's irrelevant. Any ideas?
This works correctly for me. In my AssemblyInfo.cs file, I have the following:
#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Release")]
#endif
Looking at the compiled assembly in Reflector, I see the correct attributes.
You should make sure that your DEBUG symbol is only defined in the project properties and not any where else in your code as an actual #define DEBUG instruction. If you have it defined directly in code it will only be in effect for that file, not the entire project. Defining it in the project properties will cause it be in effect for the entire project.
I figured it out! There was a key piece of information I neglected to mention: that it was a Workflow project (Guid {14822709-B5A1-4724-98CA-57A101D1B079}). It turns out that there is a bug with the workflow project type, specifically the Workflow.Targets file that is included in the build file.
It appears that the preprocessor acts as though the DEBUG constant is defined. You can repro the issue by creating a workflow project and adding this to the AssemblyInfo file:
#if DEBUG
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
Then try a release build.
I filed this with MS: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466440
Best regards!
-Sean
Are you sure you're not building in release mode?
simpler - you can tag your debug function(s) with the metadata tag [Conditional]:
#define DEBUG1
...
public static void PrintText1(string txt) {
Console.Write("This is PrintText2\n");
}
[Conditional("DEBUG1")]
public static void PrintText2(string txt) {
Console.Write("This is PrintText2\n");
}
[STAThread]
static void Main(string[] args) {
PrintText1("This is the unconditional method");
PrintText2("This function will be called only if 'DEBUG1' is defined");
}
try it!
Also, what I noticed is that #define only exists within the context of the file it is defined, ex calling PrintText2 from another file, where debug is not defined, will not execute. This also works the other way around:
[Conditional("DEBUG1")]
public static void ConditionedPrint(string txt) {
Console.Write("This is PrintText2\n");
}
public static void UnconditionedPrint(string txt) {
ConditionedFunc(txt);
}
UnconditionedFunc will print "This is PrintText2\n" iff (if and only if) #define DEBUG1 was defined in this file, regardless of the other files.
There is also System.Diagnostics.Debug, I'm not sure what it does though.
To follow up #yoyoyoyosef comment answer, you need to check the Properties page of your Project.
You will see in the Build menu, under the General heading, make sure the "Define DEBUG constant" checkbox is not checked.
This value changes based upon the "Configuration" choice (dropdown) at the top of the Build menu.

Categories

Resources