TraceSource and TraceListener quietly fail to do anything - system.diagnostics

How do I troubleshoot System.Diagnostics trace when it quietly fails to do anything at all?

I'm so glad you asked! This problem happened to me recently. I suspected something in the chain of TraceSwitches, TraceSources and TraceListeners had gone awry. But with no trace and no error messages, I needed more information. The authors of the BCL helpfully put all the diagnostic information in a private list whose values disappear when ever the garbage collector feels like it. Still, the info was good enough and accessible via reflection. It turned out that I had several TraceSource's but the one in question didn't have a Switch set to something other than Off. (Another bad sign would be no listeners or only the "Default" listener)
This is the Page_Load event for a page with a label called DumpText. I'm sure this code could be adapted for Console or WinForms.
protected void Page_Load(object sender, EventArgs e)
{
TraceSource ts = new TraceSource("foo");
List<WeakReference> list = (List<WeakReference>)GetInstanceField(typeof(TraceSource), ts, "tracesources");
Dictionary<string, TraceSource> sources = new Dictionary<string, TraceSource>();
foreach (var weakReference in list)
{
if (!weakReference.IsAlive) continue;
TraceSource source = (weakReference.Target as TraceSource);
if (source == null || source.Name == "foo") continue;
if (sources.ContainsKey(source.Name)) continue;
sources.Add(source.Name, source);
}
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string,TraceSource> kvp in sources.OrderBy((x) => x.Key))
{
TraceSource source = kvp.Value;
if (source == null)
{
continue;
}
sb.Append("<h3>");
sb.Append(source.Name);
sb.Append(" - ");
sb.Append(source.Switch.Level);
sb.Append("</h3>");
if (source.Switch.Level == SourceLevels.Off)
{
continue;
}
foreach (TraceListener l in source.Listeners)
{
sb.Append(l.Name);
sb.Append(" - ");
sb.Append(l.GetType().ToString());
sb.Append("<br/>");
foreach (string att in l.Attributes.Values)
{
sb.Append(" ");
sb.Append(att);
sb.Append(",");
}
}
sb.Append("<br/>");
}
this.DumpText.Text = sb.ToString();
}
internal static object GetInstanceField(Type type, object instance, string fieldName)
{
BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Static;
FieldInfo field = type.GetField(fieldName, bindFlags);
return field.GetValue(instance);
}

Related

HTML Agility pack throw in "An unhandled exception of type 'System.ArgumentNullException' occurred in mscorlib.dll" Exception

I'm going to parsing a website content Website HTML Content. I use follow codes:
private async void loadButton_Click(object sender, RoutedEventArgs e)
{
string address = "http://www.iiees.ac.ir/fa/eqcatalog";
loadButton.IsEnabled = false;
//string htmlCode = await DownloadStringAsync(address, Encoding.UTF8);
string htmlCode = await GetDataAsync(address, Encoding.UTF8);
paragraph1.Inlines.Add(new Run(htmlCode));
loadButton.IsEnabled = true;
}
private async Task<string> GetDataAsync(string address, Encoding encoding)
{
string htmlCode = await DownloadStringAsync(address, encoding);
List<string> options = new List<string>();
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(htmlCode);
foreach (var table in doc.DocumentNode.SelectNodes("//table"))
{
if (table.Id == "CatalogForm")
{
foreach (HtmlNode row in table.SelectNodes("tr"))
{
if (row.Attributes.Any(a => a.Value == "hidecircle"))
{
foreach (HtmlNode td in row.SelectNodes("TD"))
{
foreach (HtmlNode option in td.SelectNodes("option"))
{
options.Add(option.InnerText);
}
}
}
}
}
}
var sb = new StringBuilder();
options.ForEach(str => sb.AppendLine(str));
return sb.ToString();
}
But throw in "An unhandled exception of type 'System.ArgumentNullException' occurred in mscorlib.dll" exception.
For more information, I upload my project here.
Download project
I created a sample from your code, and I found the following:
I am not particularly familiar with xpath, but seems it is case sensitive. Searching for "TD" will return nothing, while searching for "td" will.
SelectNodes will return null whenever nothing was found, and a foreach that depends on it will always throw an exception. So it is better to check whether the result of SelectNodes is not null before trying to loop over it.
foreach (HtmlNode td in row.SelectNodes("td"))
{
var ops = td.SelectNodes("option");
if (ops != null)
{
foreach (HtmlNode option in ops)
{
options.Add(option.InnerText);
}
}
}

MSBuild WriteCodeFragment Task

It's not clear to me what the purpose of the WriteCodeFragment task is (https://msdn.microsoft.com/en-us/library/microsoft.build.tasks.writecodefragment.aspx). Google just seems to turn-up documentation and the one example I've seen isn't definitive.
Can someone clarify? Thanks.
It looks like it's only good for populating a sourcecode file (of your choice of language) with attributes (read: to embed build information into a project).
This is the sourcecode for the task:
https://github.com/Microsoft/msbuild/blob/master/src/XMakeTasks/WriteCodeFragment.cs
The specific GenerateCode() method for reference. The type that it's principally enumerating looks to be attribute-specific (read: declarative and non-functional):
/// <summary>
/// Generates the code into a string.
/// If it fails, logs an error and returns null.
/// If no meaningful code is generated, returns empty string.
/// Returns the default language extension as an out parameter.
/// </summary>
[SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.IO.StringWriter.#ctor(System.Text.StringBuilder)", Justification = "Reads fine to me")]
private string GenerateCode(out string extension)
{
extension = null;
bool haveGeneratedContent = false;
CodeDomProvider provider;
try
{
provider = CodeDomProvider.CreateProvider(Language);
}
catch (ConfigurationException ex)
{
Log.LogErrorWithCodeFromResources("WriteCodeFragment.CouldNotCreateProvider", Language, ex.Message);
return null;
}
catch (SecurityException ex)
{
Log.LogErrorWithCodeFromResources("WriteCodeFragment.CouldNotCreateProvider", Language, ex.Message);
return null;
}
extension = provider.FileExtension;
CodeCompileUnit unit = new CodeCompileUnit();
CodeNamespace globalNamespace = new CodeNamespace();
unit.Namespaces.Add(globalNamespace);
// Declare authorship. Unfortunately CodeDOM puts this comment after the attributes.
string comment = ResourceUtilities.FormatResourceString("WriteCodeFragment.Comment");
globalNamespace.Comments.Add(new CodeCommentStatement(comment));
if (AssemblyAttributes == null)
{
return String.Empty;
}
// For convenience, bring in the namespaces, where many assembly attributes lie
globalNamespace.Imports.Add(new CodeNamespaceImport("System"));
globalNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection"));
foreach (ITaskItem attributeItem in AssemblyAttributes)
{
CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(new CodeTypeReference(attributeItem.ItemSpec));
// Some attributes only allow positional constructor arguments, or the user may just prefer them.
// To set those, use metadata names like "_Parameter1", "_Parameter2" etc.
// If a parameter index is skipped, it's an error.
IDictionary customMetadata = attributeItem.CloneCustomMetadata();
List<CodeAttributeArgument> orderedParameters = new List<CodeAttributeArgument>(new CodeAttributeArgument[customMetadata.Count + 1] /* max possible slots needed */);
List<CodeAttributeArgument> namedParameters = new List<CodeAttributeArgument>();
foreach (DictionaryEntry entry in customMetadata)
{
string name = (string)entry.Key;
string value = (string)entry.Value;
if (name.StartsWith("_Parameter", StringComparison.OrdinalIgnoreCase))
{
int index;
if (!Int32.TryParse(name.Substring("_Parameter".Length), out index))
{
Log.LogErrorWithCodeFromResources("General.InvalidValue", name, "WriteCodeFragment");
return null;
}
if (index > orderedParameters.Count || index < 1)
{
Log.LogErrorWithCodeFromResources("WriteCodeFragment.SkippedNumberedParameter", index);
return null;
}
// "_Parameter01" and "_Parameter1" would overwrite each other
orderedParameters[index - 1] = new CodeAttributeArgument(String.Empty, new CodePrimitiveExpression(value));
}
else
{
namedParameters.Add(new CodeAttributeArgument(name, new CodePrimitiveExpression(value)));
}
}
bool encounteredNull = false;
for (int i = 0; i < orderedParameters.Count; i++)
{
if (orderedParameters[i] == null)
{
// All subsequent args should be null, else a slot was missed
encounteredNull = true;
continue;
}
if (encounteredNull)
{
Log.LogErrorWithCodeFromResources("WriteCodeFragment.SkippedNumberedParameter", i + 1 /* back to 1 based */);
return null;
}
attribute.Arguments.Add(orderedParameters[i]);
}
foreach (CodeAttributeArgument namedParameter in namedParameters)
{
attribute.Arguments.Add(namedParameter);
}
unit.AssemblyCustomAttributes.Add(attribute);
haveGeneratedContent = true;
}
StringBuilder generatedCode = new StringBuilder();
using (StringWriter writer = new StringWriter(generatedCode, CultureInfo.CurrentCulture))
{
provider.GenerateCodeFromCompileUnit(unit, writer, new CodeGeneratorOptions());
}
string code = generatedCode.ToString();
// If we just generated infrastructure, don't bother returning anything
// as there's no point writing the file
return haveGeneratedContent ? code : String.Empty;
}
That only other example that I found was this:
(Using WriteCodeFragment MSBuild Task)
<Target Name="BeforeBuild">
<ItemGroup>
<AssemblyAttributes Include="AssemblyVersion">
<_Parameter1>123.132.123.123</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<WriteCodeFragment Language="C#" OutputFile="BuildVersion.cs" AssemblyAttributes="#(AssemblyAttributes)" />
</Target>
Plugging this into an actual build renders:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: AssemblyVersion("123.132.123.123")]
// Generated by the MSBuild WriteCodeFragment class.

Is it possible to handle the Visual State Changed event for the Windows Phone Toolkit HubTile?

I would like to change the Source (Image) of a HubTile when the Visual State changes to Flipped however I don't seem to be able to get the VisualStateManager.GetVisualStateGroups working for the HubTile control from the Windows Phone Toolkit.
I presume that once I have the VisualStateGroup I can then handle the CurrentStateChanged event however I don't seem to be able to get the group.
I have seen the following thread which unfortunately doesn't include a code snippet :-
Changing image source when Hubtile "resets"
I have also tried to use the VisualTreeHelper.GetChild, which I don't think is required.
I would be very grateful if you could share some ideas?
Based on the following blog post :-
http://blogs.msdn.com/b/ptorr/archive/2010/07/23/how-to-detect-when-a-list-is-scrolling-or-not.aspx
I came up with the following :-
bool alreadyHookedEvents = false;
List<string> _images = new List<string>();
int _index = 0;
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (_images.Count == 0)
{
_images.Add(#"\Images\1.jpg");
_images.Add(#"\Images\2.jpg");
_images.Add(#"\Images\3.jpg");
_images.Add(#"\Images\4.jpg");
_images.Add(#"\Images\5.jpg");
_images.Add(#"\Images\6.jpg");
_images.Add(#"\Images\7.jpg");
_images.Add(#"\Images\8.jpg");
_images.Add(#"\Images\9.jpg");
_images.Add(#"\Images\10.jpg");
_images.Add(#"\Images\11.jpg");
_images.Add(#"\Images\12.jpg");
}
if (alreadyHookedEvents)
return;
alreadyHookedEvents = true;
// Visual States are always on the first child of the control template
FrameworkElement element = VisualTreeHelper.GetChild(this.MyHubTile, 0) as FrameworkElement;
if (element != null)
{
VisualStateGroup group = FindVisualState(element, "ImageStates");
if (group != null)
{
group.CurrentStateChanged += (s, args) =>
{
if (group.CurrentState.Name == "Flipped")
{
_index++;
this.MyHubTile.Source = new BitmapImage(new Uri(_images[_index], UriKind.Relative));
}
};
}
}
}
VisualStateGroup FindVisualState(FrameworkElement element, string name)
{
if (element == null)
return null;
IList groups = VisualStateManager.GetVisualStateGroups(element);
foreach (VisualStateGroup group in groups)
if (group.Name == name)
return group;
return null;
}
T FindSimpleVisualChild<T>(DependencyObject element) where T : class
{
while (element != null)
{
if (element is T)
return element as T;
element = VisualTreeHelper.GetChild(element, 0);
}
return null;
}

Force tags to update from external event

this is a somewhat exotic question but I will try anyway.
I am writing a Visual Studio 2010 Extension using MEF. At some point in my code, I am required to provide some error glyphs ( like brakepoints ) whenever a document is saved. The problem is that I can't seem to find how to force GetTags of my ITagger to be called without having the user writing anything.
I can catch the document save event but I am missing the "link" between this and somehow getting GetTags method to be called. Any ideas?
Here is some code :
internal class RTextErrorTag : IGlyphTag
{}
class RTextErrorGlyphTagger : ITagger<RTextErrorTag>
{
private IClassifier mClassifier;
private SimpleTagger<ErrorTag> mSquiggleTagger;
private EnvDTE._DTE mMSVSInstance = null;
private List<object> mDTEEvents = new List<object>();
internal RTextErrorGlyphTagger(IClassifier classifier, IErrorProviderFactory squiggleProviderFactory, ITextBuffer buffer, IServiceProvider serviceProvider)
{
this.mClassifier = classifier;
this.mSquiggleTagger = squiggleProviderFactory.GetErrorTagger(buffer);
mMSVSInstance = serviceProvider.GetService(typeof(EnvDTE._DTE)) as EnvDTE._DTE;
var eventHolder = mMSVSInstance.Events.DocumentEvents;
mDTEEvents.Add(eventHolder);
eventHolder.DocumentSaved += new EnvDTE._dispDocumentEvents_DocumentSavedEventHandler(OnDocumentSaved);
}
void OnDocumentSaved(EnvDTE.Document Document)
{
//fire up event to renew glyphs - how to force GetTags method?
var temp = this.TagsChanged;
if (temp != null)
temp(this, new SnapshotSpanEventArgs(new SnapshotSpan() )); //how to foce get
}
IEnumerable<ITagSpan<RTextErrorTag>> ITagger<RTextErrorTag>.GetTags(NormalizedSnapshotSpanCollection spans)
{
foreach (SnapshotSpan span in spans)
{
foreach (var error in this.mSquiggleTagger.GetTaggedSpans(span))
{
yield return new TagSpan<RTextErrorTag>(new SnapshotSpan(span.Start, 1), new RTextErrorTag());
}
}
}
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
}

How to get invalid XMLNode in XmlReaderSettings.ValidationEventHandler in C#

I am trying to construct a custom Error Message for unsuccessful XML validation using the callback validation event. I noticed that the sender object of the element is XMLReader and i got the Element or current Node name from ((XmlReader)sender).Name and exeception message from ValidationEventargs.Exception.Message. I trying to build the path of the current node failing in the validation by getting the parent nodes of the current node
Given below is the code snippet
XmlReaderSettings xrs = new XmlReaderSettings();
xrs.ValidationEventHandler += new ValidationEventHandler(ValidationEvent);
public void ValidationEvent(object sender, ValidationEventArgs e)
{
XmlReader xe = (XmlReader)sender;
ValidationError ve = new ValidationError();
ErrorElement = xe.Name;
ErrorMessage = e.Exception.Message;
ErrorPath = ""\\want to build the Node path
}
As per this thread, You need to use XmlDocument.Validate instead. Here's my code:
private static void ValidationErrorHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Error || e.Severity == XmlSeverityType.Warning)
{
string offendingElementName = BuildQualifiedElementName((e.Exception as XmlSchemaValidationException));
// meaningful validation reporting code goes here
Console.Out.WriteLine("{0} is invalid", offendingElementName);
}
}
private static string BuildQualifiedElementName(XmlSchemaValidationException exception)
{
List<string> path = new List<string>();
XmlNode currNode = exception.SourceObject as XmlNode;
path.Add(currNode.Name);
while (currNode.ParentNode != null)
{
currNode = currNode.ParentNode;
if (currNode.ParentNode != null)
{
path.Add(currNode.Name);
}
}
path.Reverse();
return string.Join(".", path);
}

Resources