Thursday, April 29, 2010

WPF: Find All Child Controls Of A Type

The following DependencyObject extension method (compatible with both WPF and Silverlight) recursively traverses the visual tree searching for children of the type specified by type parameter TChild before returning a collection containing the matches.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;


namespace WPFFindAllChildren
{
public static class DependencyObjectExtension
{
public static List<TChild> FindChildren<TChild>(this DependencyObject d)
where TChild : DependencyObject
{
List<TChild> children = new List<TChild>();

int childCount = VisualTreeHelper.GetChildrenCount(d);

for (int i = 0; i < childCount; i++)
{
DependencyObject o = VisualTreeHelper.GetChild(d, i);

if (o is TChild)
children.Add(o as TChild);

foreach (TChild c in o.FindChildren<TChild>())
children.Add(c);
}

return children;
}
}
}


Usage

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace WPFFindAllChildren
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}

void Window1_Loaded(object sender, RoutedEventArgs e)
{
StackPanel stack1 = new StackPanel();
stack1.Children.Add(new CheckBox());
stack1.Children.Add(new CheckBox());

StackPanel stack2 = new StackPanel();
stack2.Children.Add(new CheckBox());
stack2.Children.Add(stack1);

LayoutRoot.Children.Add(stack2);

this.FindChildren<CheckBox>().ForEach(x => x.IsChecked = true);
}
}
}



Download Sample

Wednesday, March 31, 2010

The remote server returned an error: NotFound. - Yet Another Cause And Solution

Having encountered this error while working with Silverlight and WCF the number of potential fixes I found while searching was overwhelming. To get an idea of just how many causes there are for this error take a look at this thread. None of the solutions appeared relevant to my application, so I decided to dig further by setting includeExceptionDetailInFault in the service's web.config to true. This yielded no new information so I moved on to observing the HTTP traffic with Fiddler. To my surprise the ASP.NET development server was closing the connection with no response. Even stranger was the fact that this behavior was only exhibited by one of my operation contracts when certain parameters were passed to it--the rest of my operation contracts worked fine! Naturally I stepped through the problematic method and everything appeared to be working. Seeing this I knew that the problem had to be in the data contract returned, so I resorted to trial and error: one by one I tested the service with different data members nulled. Finally I discovered the data member causing the issue and the actual problem: circular references. After setting the IsReference property of my data contract to true the CommunicationException disappeared. Below is a sample WCF service that displays the aforementioned issue along with comments noting the fix.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace NotFoundWcfService1
{
// Setting the IsReference parameter of this
// attribute to true eliminates NotFound error
[DataContract]
public class Item
{
[DataMember]
public List<Category> Categories { get; set; }
}

[DataContract]
public class Category
{
[DataMember]
public List<Item> Items { get; set; }
}

[ServiceContract]
public class Service1
{
[OperationContract]
public Item GetItem()
{
Item c = new Item()
{
Categories = new List<Category>()
{
new Category()
{
Items = new List<Item>()
}
}
};

// Commenting this out makes the operation
// contract appear to work. Tricky!
c.Categories[0].Items.Add(c);

return c;
}
}
}

Wednesday, March 17, 2010

The Easy Way To Synchronously Call WCF Services In Silverlight

If you're reading this you probably know why Microsoft tries to force the use of asynchronous WCF service calls in Silverlight. If not and you cannot infer based on your knowledge of threading I suggest you read up on the matter.

While Microsoft may have a strong case for their decision, it can lead to bloated, messy code when several service calls are chained together. The following extension method, through heavy use of reflection, allows for synchronous service calls. Remember, do not block the UI thread.

ICommunicationObjectExtension.cs

using System;
using System.Net;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.ServiceModel;

namespace SyncWCFCalls
{
public static class ICommunicationObjectExtension
{
public static TEventArgs SynchronousCall<TEventArgs>(this ICommunicationObject Client,
string Method, params object[] Parameters)
where TEventArgs : EventArgs
{
Type clientType = Client.GetType();

string methodName = Method + "Async";
string completedName = Method + "Completed";

MethodInfo[] methods = null;

try
{
methods = clientType.GetMethods().Where(x =>
x.Name == methodName).ToArray();
}
catch { }

if (methods == null || methods.Length == 0)
{
throw new MissingMethodException(methodName + " not found");
}

MethodInfo method = null;

try
{
method = methods.Single(x =>
x.GetParameters().Length == Parameters.Length);
}
catch { }

if (method == null)
{
throw new MissingMethodException(methodName +
" parameter count mismatch");
}

EventInfo completedEvent = null;

try
{
completedEvent = clientType.GetEvent(completedName);
}
catch { }

if (completedEvent == null)
throw new MissingMemberException(completedName + " not found");

ManualResetEvent reset = new ManualResetEvent(false);

EventHandler<TEventArgs> completedHandler = null;

TEventArgs args = null;

completedHandler = (s, e) =>
{
completedEvent.RemoveEventHandler(Client, completedHandler);

args = e;

reset.Set();
};

completedEvent.AddEventHandler(Client, completedHandler);

method.Invoke(Client, Parameters);

reset.WaitOne();

return args;
}
}
}


Asynchronous WCF Service Call

void AsyncTest()
{
CalculatorServiceClient client = new CalculatorServiceClient();

Guid addState1 = Guid.NewGuid(), addState2 = Guid.NewGuid();

client.AddCompleted += (s, e) =>
{
if ((Guid)e.UserState == addState1)
{
// Do something with AddCompletedEventArgs
client.AddAsync(e.Result, 10, addState2);
}
else if ((Guid)e.UserState == addState2)
{
// Do something with AddCompletedEventArgs
client.SubtractAsync(e.Result, 5);
}
};

client.SubtractCompleted += (s, e) =>
{
// Do something with SubtractCompletedEventArgs
};

client.AddAsync(1, 1, addState1);
}


Synchronous WCF Service Call

void SyncTest()
{
CalculatorServiceClient client = new CalculatorServiceClient();

ThreadPool.QueueUserWorkItem(x =>
{
AddCompletedEventArgs addArgs1 =
client.SynchronousCall<AddCompletedEventArgs>("Add", 1, 1);
// Do something with AddCompletedEventArgs

AddCompletedEventArgs addArgs2 =
client.SynchronousCall<AddCompletedEventArgs>("Add",
addArgs1.Result, 10);
// Do something with AddCompletedEventArgs

SubtractCompletedEventArgs subtractArgs =
client.SynchronousCall<SubtractCompletedEventArgs>("Subtract",
addArgs2.Result, 5);
// Do something with SubtractCompletedEventArgs
});
}



Updated 3/21/2010

Wednesday, March 3, 2010

.NET Assembly Tamperproofing

Development of an application that verifies its own integrity presents unique challenges. Using a cryptographic hash function to detect potentially malicious modifications to an assembly is a common approach. Embedding the the digest of an assembly within it and then, at runtime, comparing the embedded digest to a newly computed hash will achieve this. However, attempting to embed the assembly digest by adding it to the source of the application and recompiling will alter the hash value of the resulting file. Because of this, the value must be patched into the assembly after compilation; also, during the integrity check the embedded hash within the message needs to somehow be ignored before the hash is computed, otherwise it too will affect the result.

The following C# solution shows how to create an application that detects modifications through the use of the RIPEMD-160 cryptographic hash function. PatchDigest (configured to run as a post-build event of Calculator) searches Calculator.exe for the _embeddedDigest value, zeroes it, hashes the result, then overwrites the array with the actual digest. When Calculator is run it reads itself, zeroes _embeddedDigest, then hashes the result just as PatchDigest does before comparing the computed digest to the embedded one. If they don't match it is assumed the application has been modified in a malicious manner and, in an attempt to throw the attacker off, the output of the application is corrupted. This behavior can be observed by removing Calculator's post-build event and recompiling.

Download


Calculator

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Security.Cryptography;

namespace Calculator
{
class Program
{
private static byte[] _embeddedDigest = new byte[20]
{
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
};

private static Random _rnd = new Random();

static bool CheckIntegrity()
{
string asmLocation = Assembly.GetExecutingAssembly().Location;

byte[] buffer = File.ReadAllBytes(asmLocation);

bool match;

for (int x = 0; x < buffer.Length; x++)
{
match = true;

for (int y = 0; y < _embeddedDigest.Length; y++)
{
if (_embeddedDigest[y] != buffer[x + y])
{
match = false;

break;
}
}

if (match)
{
for (int y = 0; y < _embeddedDigest.Length; y++)
buffer[x + y] = 0;

break;
}
}

RIPEMD160Managed ripemd = new RIPEMD160Managed();
byte[] digest = ripemd.ComputeHash(buffer);

match = true;

for (int x = 0; x < digest.Length; x++)
{
if (_embeddedDigest[x] != digest[x])
{
match = false;

break;
}
}

return match;
}

static void Main(string[] args)
{
Console.Write("X: ");
int x = int.Parse(Console.ReadLine());

Console.Write("Y: ");
int y = int.Parse(Console.ReadLine());

// if the integrity check fails replace y with a random value
y = CheckIntegrity() ? y : _rnd.Next();

Console.WriteLine("X + Y = {0}\r\n" +
"Press any key to continue...", x + y);
Console.ReadKey();
}
}
}


PatchDigest

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Security.Cryptography;

namespace PatchDigest
{
/// <summary>
/// Usage: PatchDigest [Target Application]
/// </summary>
class Program
{
private static byte[] _embeddedDigest = new byte[20]
{
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
0x00, 0x0F, 0xF0, 0xFF,
};

static void Main(string[] args)
{
string file = args[0];

byte[] buffer = File.ReadAllBytes(file);

int index = -1;

bool patched = false;

for (int x = 0; x < buffer.Length; x++)
{
bool match = true;

for (int y = 0; y < _embeddedDigest.Length; y++)
{
if (_embeddedDigest[y] != buffer[x + y])
{
match = false;

break;
}
}

if (match)
{
index = x;

for (int y = 0; y < _embeddedDigest.Length; y++)
buffer[x + y] = 0;

RIPEMD160Managed ripemd = new RIPEMD160Managed();
byte[] digest = ripemd.ComputeHash(buffer);

for (int y = 0; y < _embeddedDigest.Length; y++)
buffer[x + y] = digest[y];

File.WriteAllBytes(file, buffer);

patched = true;

break;
}
}

Console.WriteLine((patched ? "Patched" : "Patch Failed") +
"Press any key to continue...");
}
}
}

Saturday, February 20, 2010

ObservableItemCollection Class

While working with WPF data binding I often found myself populating an ObservableCollection with instances of classes that implement INotifyPropertyChanged, and then subscribing the same method to the PropertyChanged event of each element. To eliminate such boilerplate code, I derived from ObservableCollection to create ObservableItemCollection. When the PropertyChanged event of any element of the the collection is raised, the ObservableItemCollection's own PropertyChanged event is invoked. Coincidentally Microsoft is planning on releasing a similar class with the same name.


using System;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Collections.ObjectModel;

namespace ExploringDotNet
{
public class ObservableItemCollection<T> : ObservableCollection<T>
{
public event PropertyChangedEventHandler ItemPropertyChanged;

void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (ItemPropertyChanged != null)
ItemPropertyChanged(sender, e);
}

protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (INotifyPropertyChanged i in e.NewItems)
i.PropertyChanged += Item_PropertyChanged;

if (e.OldItems != null)
foreach (INotifyPropertyChanged i in e.OldItems)
i.PropertyChanged -= Item_PropertyChanged;

base.OnCollectionChanged(e);
}
}
}

Wednesday, February 17, 2010

C# Stream Array Merge Extension Method

If the need to sort a collection larger than the amount of RAM available arises, merge sort algorithms are a good solution. The following extension method is a merge algorithm implementation that combines two or more sorted Streams using Read and Output functions passed as parameters.


public static class StreamArrayExtension
{
public static void Merge<T>(this Stream[] Streams,
Func<Stream, T> ReadItem, Action<T> OutputItem)
where T : IComparable<T>
{
T[] buffer = new T[Streams.Length];

for (int x = 0; x < Streams.Length; x++)
buffer[x] = ReadItem(Streams[x]);

int end = Streams.Length - 1;

bool[] completed = new bool[Streams.Length];

int completedCount = 0;

while (completedCount < Streams.Length)
for (int x = 0; x < Streams.Length; x++)
if (completed[x])
continue;
else
for (int y = 0; y < Streams.Length; y++)
if (x == y && x != end)
continue;
else if (!completed[y] &&
buffer[x].CompareTo(buffer[y]) == 1)
break;
else if (y == end)
{
OutputItem(buffer[x]);

if (Streams[x].Position != Streams[x].Length)
buffer[x] = ReadItem(Streams[x]);
else
{
completed[x] = true;

completedCount++;
}
}
}
}


It can be used as follows:

Stream[] sortedStreams = new Stream[]
{
new MemoryStream(new byte[] { 1, 2, 3 }),
new MemoryStream(new byte[] { 0, 4 }),
new MemoryStream(new byte[] { 1, 5 }),
};

sortedStreams.Merge(x => x.ReadByte(), x => Console.WriteLine(x));

Console.ReadKey();


With the resulting output:
0
1
1
2
3
4
5

Tuesday, February 16, 2010

Enumerating ResourceDictionary Keys in Silverlight 2

The Microsoft response to this need is that the feature was not implemented in Silverlight 2. However, enumerating ResourceDictionary Keys is possible through the use of reflection. Aside from the performance cost incurred by reflection, the only other caveat I'm aware of is that the end-user must have the Silverlight 3 runtime installed for this to work.


ResourceDictionary dictionary = new ResourceDictionary()
{
{ "a", "" },
{ "b", "" },
{ "c", "" }
};

PropertyInfo prop = typeof(ResourceDictionary).GetProperty("Keys");
object[] keys = prop.GetValue(dictionary, null) as object[];

foreach (object o in keys)
MessageBox.Show(o.ToString());