I have a Netduino and it is currently outputting accelerometer data to the System. Diagnostics.Debug window. I am waiting on a USB->232 converter in the mail to properly get the data from the device into my app via a serial port but I was wondering just for quick testing purposes if anyone knows if it is possible to read the data from the Debug window back into my app?
EDIT - Solution:
I am posting this here for anyone who want my solution. I originally thought that Nuf's answer worked "Data written to System.Diagnostics.Debug can be captured with TraceListener class. MSDN has short tutorial how to set it up." but I found out that the Listener can only get data from within it's own application. Since I was using a Netduino, the Debug output was from a different program which meant the trace listener could not read it. So I found a way to read the text in the Output box directly.
Base on code from MSDN:
You will need to 3 references to your project. They are located in the .Net reference tab - EnvDTE, EnvDTE80, and extensibility.
using EnvDTE80;
using EnvDTE;
using Extensibility;
public static string ReadDebugBox()
{
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
string data = "";
OutputWindow ow = dte.ToolWindows.OutputWindow;
OutputWindowPane owP;
TextDocument owPTxtDoc;
EditPoint2 strtPt;
owP = ow.OutputWindowPanes.Item("Debug");
owP.Activate();
owPTxtDoc = owP.TextDocument;
strtPt = (EditPoint2)owPTxtDoc.StartPoint.CreateEditPoint();
return strtPt.GetText(owPTxtDoc.EndPoint);
}
public static void ClearDebugBox()
{
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
OutputWindow ow = dte.ToolWindows.OutputWindow;
OutputWindowPane owP;
TextDocument owPTxtDoc;
EditPoint2 strtPt;
owP = ow.OutputWindowPanes.Item("Debug");
owP.Activate();
owP.Clear();
}
There may be better ways of doing it but this is just one that worked for me so i thought I would share it.
Data written to System.Diagnostics.Debug can be captured with TraceListener class. MSDN has short tutorial how to set it up.
There are two ways to set this up, one way is to declaratively set this up in your app.config file. There's a lot of advantages to doing this such as not needing to recompile your application when changes are needed.
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="configConsoleListener"
type="System.Diagnostics.ConsoleTraceListener" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Alternatively, you can also do this inside of your code to output Debug traces to your application's console window.
Debug.Listeners.Add(new ConsoleTraceListener());
Related
Let's say I'm working on a little batch-processing console app in VB.Net. I want to be able to structure the app like this:
Sub WorkerMethod()
'Do some work
Trace.WriteLine("Work progress")
'Do more work
Trace.WriteLine("Another progress update")
'...
End Sub
Sub Main()
'Do any setup, like confirm the user wants to continue or whatever
WorkerMethod()
End Sub
Note that I'm using Trace rather than Console for my output. This is because the worker method may be called from elsewhere, or even live in a different assembly, and I want to be able to attach different trace listeners to it. So how can I connect the console to the trace?
I can already do it by defining a simple class (shown below) and adding an instance to the Trace's listeners collection, but I'm wondering if there's a more accepted or built in way to accomplish this:
Public Class ConsoleTrace
Inherits Diagnostics.TraceListener
Public Overloads Overrides Sub Write(ByVal message As String)
Console.Write(message)
End Sub
Public Overloads Overrides Sub WriteLine(ByVal message As String)
Console.WriteLine(message)
End Sub
End Class
You can add the following to your exe's .config file.
<?xml version="1.0"?>
<configuration>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<add name="logListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="cat.log" />
<add name="consoleListener" type="System.Diagnostics.ConsoleTraceListener"/>
</listeners>
</trace>
</system.diagnostics>
</configuration>
I included the TextWriter as well, in case you're interested in logging to a file.
Joel,
You could do this instead of the app config method:
Trace.Listeners.Add(new ConsoleTraceListener());
or this, if you want to manage adding or removing the listener during the life of the app:
ConsoleTraceListener listener = new ConsoleTraceListener();
Trace.Listeners.Add(listener);
Trace.WriteLine("Howdy");
Trace.Listeners.Remove(listener);
Trace.Close();
Great solution, but I have a situation where I have different dll's being run by the same calling exe, so I don't want to modify the calling exe's .config file. I want each dll to handle it's own alteration of the trace output.
Easy enough:
Stream outResultsFile = File.Create ("output.txt");
var textListener = new TextWriterTraceListener (outResultsFile);
Trace.Listeners.Add (textListener);
This will, of course, output Trace output to the "output.txt" file.
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.
I'm currently using CloudConfigurationManager.GetSetting("setting") to get settings for my application, but it's writing logs of everything it's checking to the console (in both Debug and Release):
Getting "setting" from ServiceRuntime: FAIL.
Getting "setting" from ConfigurationManager: PASS (Data Source=...
Getting "setting" from ServiceRuntime: FAIL.
Getting "setting" from ConfigurationManager: PASS (Data Source=...
Is there any way to prevent it from doing this, or an alternative version that's less verbose?
Mostly I just like my unit test output to be nice and clean, but I'm also a little concerned that it's printing out things like connection strings (and hence passwords) in plain text on the production server.
CloudConfigurationManager.GetSetting now has a method overload with a parameter called outputResultsToTrace.
If you pass false to this method, then it'll disable the Trace.WriteLine used elsewhere to "spam" the Trace log.
So
var mySetting = CloudConfigurationManager.GetSetting("MySetting");
becomes
var mySetting = CloudConfigurationManager.GetSetting("MySetting", false);
I found this by looking directly at the source code on GitHub: https://github.com/Azure/azure-sdk-for-net/blob/52fc67253a176bea01c37c164f71c7eba8eaedba/src/Common/Configuration/CloudConfigurationManager.cs#L35
It's probably worth mentioning that this overload is not documented: https://msdn.microsoft.com/en-us/library/azure/mt634648.aspx
So I'm not sure if it's an official and supported part of the API, or if it's something that might change or go away in the future.
This change was made at the end of 2015: https://github.com/Azure/azure-sdk-for-net/commit/e14398136d7d3b6d5e4675f1e8ccbdd37a8c6b01
Not really. If you look at the code of the underlying GetValue method you'll see this:
private static string GetValue(string providerName, string settingName, Func<string, string> getValue)
{
string str1 = getValue(settingName);
string str2;
if (str1 != null)
str2 = string.Format((IFormatProvider) CultureInfo.InvariantCulture, "PASS ({0})", new object[1]
{
(object) str1
});
else
str2 = "FAIL";
Trace.WriteLine(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "Getting \"{0}\" from {1}: {2}.", (object) settingName, (object) providerName, (object) str2));
return str1;
}
The Trace.WriteLine is always called without taking into account Debug or Release. Now you can simply remove the Default listener which should suppress all messages:
<system.diagnostics>
<trace>
<listeners>
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
Now if you look at the CloudConfigurationManager it doesn't do that much. If this is a problem for you you can cook up something yourself, starting with this:
if (RoleEnvironment.IsAvailable)
return RoleEnvironment.GetConfigurationSettingValue(setting);
else
return ConfigurationManager.AppSettings[setting];
Note: The CloudConfigurationManager does a lot more than this, like loading the assembly without assembly reference.
Alternative option, if you're calling CloudConfigurationManager.GetSetting() in one part (ie, a wrapper/helper class):
var oldListeners = Trace.Listeners.Cast<TraceListener>().ToArray();
Trace.Listeners.Clear();
var stringValue = CloudConfigurationManager.GetSetting(key);
Trace.Listeners.AddRange(oldListeners);
First, we remove all listeners on Trace. Then we grab the setting, and re-add the listeners. Of course, this potentially could cause problems with threaded applications
I just installed the nuget package Microsoft.WindowsAzure.ConfigurationManager version 3.1.0, and I can confirm that the issue has been fixed in this version. Taking a look at the github issue referenced in the question's comments, we can see, in the changelog, the fetched value is no longer written to the trace output. In particular, the trace message has been changed from:
message = string.Format(CultureInfo.InvariantCulture, "PASS ({0})", value);
to:
message = "PASS";
This still makes the configuration manager quite verbose though.
We just ran into this ourselves...so very frustrating.
We can't remove the default listener because we are logging our own stuff on it.
There is an easy workaround though. Just use the good old fashioned ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"] and you will get the info you need without the annoying logging.
Hope that helps,
David
I had quite similar problems. I updated from Azure SDK 2.0 to 2.2 - during this process I used the NuGet Manager to update the Microsoft.WindowsAzure.Storage to the latest. The PackageManager automatically took Microsoft.WindowsAzure.Configuration to 1.8.0.0. I was not able to get this running (it was for .Net 2.0!?). After I manually set all References to
Microsoft.WindowsAzure.Storage 2.1.0.0
Microsoft.WindowsAzure.Configuration 2.0.0.0
everything worked.
I think this is because of the way CloudConfigurationManager.GetSetting loads the assembly and calls the funktions (via reflection).
Fixed in version 3.0.0. Please update Microsoft Azure Configuration Manager nuget package.
There are two separate issues here:
Setting values are logged in plain text (a security concern)
Messages are logged every time a setting is retrieved (a verbosity concern)
As others have noted, #1 has been fixed in a more recent version of the plugin.
Based on my experience (and some of the other responses here), #2 is still a huge annoyance.
Looking at WADLogsTable in Visual Studio's Queue Editor, note that the message level is 5 (i.e. verbose, according to this list of ETW levels).
Going off of the diagnostic config file schema, my approach to solving issue #2 was to limit the minimum severity level (e.g. warning, informational, verbose) of generic tracing to "information" (or more severe) and just ensure my own logging did not use the "verbose" level.
Here is the change I made in diagnostics.wadcfgx:
Original:
<Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Verbose" />
Fixed:
<Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Information" />
I was looking for a solution to provide logging to my latest project when I came across an article ( http://www.daveoncsharp.com/2009/09/create-a-logger-using-the-trace-listener-in-csharp/ ) that talked about using System.Diagnostics and App.config to log via the Trace method. I was able to successfully implement both the class and the App.config but I'd really like to be able to dynamically assign the value/location (inside initializeData) of the log file and I don't have a clue how to do it. If you have any suggestions, please feel free to post!
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="myListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="fileSizeThreshold=512, fileSizeUnit=kilobytes,
fileAgeThreshold=1, fileAgeUnit=months, fileNameTemplate='{0}\MyApp-{1:MMM-yy}.log'"/>
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Logger Class:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace MyCurrentProject
{
class Logger
{
public void Error(string module, string message)
{
WriteEntry(message, "ERROR:", module);
}
public void Error(Exception ex, string module)
{
WriteEntry(ex.Message, "ERROR:", module);
}
public void Warning(string module, string message)
{
WriteEntry(message, "WARNING:", module);
}
public void Info(string module, string message)
{
WriteEntry(message, "INFO:", module);
}
private void WriteEntry(string message, string type, string module)
{
Trace.WriteLine(
string.Format("{0} {1} [{2}] {3}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
type,
module,
message));
}
}
}
RE: Sorry for not being clear... just to be clear, I need the file path that the log file output is save to to be dynamically set. I'd like the path to save to a location in %AppData%. The problem I had with the config was that once I set the value for 'initializeData' I couldn't find a way to change or dynamically set/reset that value. Truthfully... at this point I just want a solution that works and allows me to manage the location of the log file.
Here is a worked example using Systems.Diagnostics, which has two advantages over non-base class libraries. It is always allowed (in large organizations), always available, and to the extent that developers are familiar with the base class library, the next batch of maintenance developers will have heard of it.
using System.Diagnostics;
namespace DynamicTraceLog
{
class Program
{
static void Main(string[] args)
{
//Use TraceSource, not Trace, they are easier to turn off
TraceSource trace = new TraceSource("app");
//SourceSwitches allow you to turn the tracing on and off.
SourceSwitch level =new SourceSwitch("app");
//I assume you want to be dynamic, so probalby some user input would be here:
if(args.Length>0 && args[0]=="Off")
level.Level= SourceLevels.Off;
else
level.Level = SourceLevels.Verbose;
trace.Switch = level;
//remove default listner to improve performance
trace.Listeners.Clear();
//Listeners implement IDisposable
using (TextWriterTraceListener file = new TextWriterTraceListener("log.txt"))
using (ConsoleTraceListener console = new ConsoleTraceListener())
{
//The file will likely be in /bin/Debug/log.txt
trace.Listeners.Add(file);
//So you can see the results in screen
trace.Listeners.Add(console);
//Now trace, the console trace appears immediately.
trace.TraceInformation("Hello world");
//File buffers, it flushes on Dispose or when you say so.
file.Flush();
}
System.Console.ReadKey();
}
}
}
Re: how to format the output
Try either of these two for trace listeners that implement templated trace formating/output using Systems.Diagnostics classes:
http://essentialdiagnostics.codeplex.com
or http://ukadcdiagnostics.codeplex.com/
Systems.Diagnostics doesn't provide for any particular formating or outputing of standard tokens.
I know I may get down voted for this, but I'm going to go off the ranch for a minute and I'm going to suggest you use a different tool from the toolbox. Log4Net is a very powerful and succinct logging framework. For example, below is a console application that uses it and it's fully functional as you see it.
using Com.Foo;
// Import log4net classes.
using log4net;
using log4net.Config;
public class MyApp
{
// Define a static logger variable so that it references the
// Logger instance named "MyApp".
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
static void Main(string[] args)
{
// Set up a simple configuration that logs on the console.
BasicConfigurator.Configure();
log.Info("Entering application.");
Bar bar = new Bar();
bar.DoIt();
log.Info("Exiting application.");
}
}
But let's say we wanted to do that with a configuration file just like you're implying you would like to use. Well, that's pretty straight forward! Below is the configuration we'd place in the App.config to accomplish the same thing:
<log4net>
<!-- A1 is set to be a ConsoleAppender -->
<appender name="A1" type="log4net.Appender.ConsoleAppender">
<!-- A1 uses PatternLayout -->
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
</layout>
</appender>
<!-- Set root logger level to DEBUG and its only appender to A1 -->
<root>
<level value="DEBUG" />
<appender-ref ref="A1" />
</root>
</log4net>
Then that configuration can be used like this:
using Com.Foo;
// Import log4net classes.
using log4net;
using log4net.Config;
public class MyApp
{
private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));
static void Main(string[] args)
{
// BasicConfigurator replaced with XmlConfigurator.
XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));
log.Info("Entering application.");
Bar bar = new Bar();
bar.DoIt();
log.Info("Exiting application.");
}
}
And don't let the pattern stuff catch you off guard, it's just configuring what you're coding above so that you can have some consistency in the messages. It really keeps it easy though because all you ever have to log is the information that needs to be plugged into the pattern and the pattern is then encapsulated away.
This is a crash course in Log4Net, but the reason I'm really recommending it is because in the two examples above you see that they logged to the console, but you have a myriad of possible loggers, just look at this list:
log4net.Appender.AdoNetAppender: Writes logging events to a database using either prepared statements or stored procedures.
log4net.Appender.AnsiColorTerminalAppender: Writes color highlighted logging events to a an ANSI terminal window.
log4net.Appender.AspNetTraceAppender: Writes logging events to the ASP trace context. These can then be rendered at the end of the ASP page or on the ASP trace page.
log4net.Appender.ColoredConsoleAppender: Writes color highlighted logging events to the application's Windows Console.
log4net.Appender.ConsoleAppender: Writes logging events to the application's Console. The events may go to either the standard our stream or the standard error stream.
log4net.Appender.DebugAppender: Writes logging events to the .NET system.
log4net.Appender.EventLogAppender: Writes logging events to the Windows Event Log.
log4net.Appender.FileAppender: Writes logging events to a file in the file system.
log4net.Appender.LocalSyslogAppender: Writes logging events to the local syslog service (UNIX only).
log4net.Appender.MemoryAppender: Stores logging events in an in memory buffer.
log4net.Appender.NetSendAppender: Writes logging events to the Windows Messenger service. These messages are displayed in a dialog on a users terminal.
log4net.Appender.OutputDebugStringAppender: Writes logging events to the debugger. If the application has no debugger, the system debugger displays the string. If the application has no debugger and the system debugger is not active, the message is ignored.
log4net.Appender.RemoteSyslogAppender: Writes logging events to a remote syslog service using UDP networking.
log4net.Appender.RemotingAppender: Writes logging events to a remoting sink using .NET remoting.
log4net.Appender.RollingFileAppender: Writes logging events to a file in the file system. The RollingFileAppender can be configured to log to multiple files based upon date or file size constraints.
log4net.Appender.SmtpAppender: Sends logging events to an email address.
log4net.Appender.SmtpPickupDirAppender: Sends logging events to an email address but writes the emails to a configurable directory rather than sending them directly via SMTP.
log4net.Appender.TelnetAppender: Clients connect via Telnet to receive logging events.
log4net.Appender.TraceAppender: Writes logging events to the .NET trace system.
log4net.Appender.UdpAppender: Sends logging events as connectionless UDP datagrams to a remote host or a multicast group using a UdpClient.
So, as you can see, it's extremely capable OOB. I hope this post has been helpful.
I'm using System.Diagnostics.TraceSource for logging and one of my listeners is a TextWriterTraceListener. In the tracing primer here it sets this up as follows:
<listeners>
<add initializeData="output.txt"
type="System.Diagnostics.TextWriterTraceListener"
name="myLocalListener" />
</listeners>
The problem is that this will always append to output.txt. How do you alter this to an overwrite in the config file?
Programmatically the listener I want is a:
new TextWriterTraceListener(new StreamWriter("output.txt", false));
The simplest solution is to make your own.
I suggest that you inherit from TextWriterTraceListener and in your constructor set the base Writer to what you proposed: new StreamWriter("output.txt", false).
Some sample code:
public class MyTextWriterTraceListener : TextWriterTraceListener
{
public MyTextWriterTraceListener(string logFileName)
: base(logFileName)
{
base.Writer = new StreamWriter(logFileName, false);
}
}
This lets you take the initializeData parameter from a configuration file to specify the name of the file, or specify one if created in code.
I know this doesn't directly answer your question, but use NLog instead. It does more stuff than out-of-the-box diagnostics in terms of logging options and it's really easy to use.
Even more simpler, just tell the TestWriterTraceListener to not append the file:
TextWriterTraceListener twtl = new TextWriterTraceListener(new StreamWriter(#"<path to my logfile>", false));
By selecting false the logfile is overwritten each time you initialize the TextWriterTraceListener.