Jun 26, 2009

Keep an eye on a reference.

When debugging I often find myself wishing I could just watch a single object throughout its life cycle. This is especially useful for debugging state problems (I’m thinking detached row error). Someone is modifying the state of your object and you need to figure out who. The problem lies in scoping. Every time you step in you have to change the watch window statement to track your objects state.

What you end up with is a nasty watch window.

The immediate window comes to the rescue!  Simply declare a variable with a globally unique name (DataRow watchMyRow=_dr;) for example. Then go to the watch window and add a watch for watchMyRow.  watchMyRow is always in scope. So now step through at your leisure and find the offending entry point and step deeper. Its that easy!

 

So we will start with a simple test program that calls methods with several different names and types.



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

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
MyObject val = new MyObject();
Method1(val);
Method2(val);
Method3(val);
}

static void Method1(MyObject obj)
{
obj.state = 1;
}

static void Method2(MyObject myobj)
{
myobj.state = 2;
}

static void Method3(object obj)
{
((MyObject)obj).state = 3;
}
}

public class MyObject
{
public int state = 5;
}
}


We set our break points.



image



And at the end of the cycle our watch window looks like this! 



image 



All to track the same value on the same object!



 



The real problem is that with events thrown into the mix it becomes impossible to track state on some foreign object (Detached Row I loathe you!).



Now lets do the same example with the immediate window.



Our first break point gets hit. We type MyObject WATCHMYOBJECT=obj; into the immediate window.



image



Next I add that variable to the watch window.



image



Finnally after the many function calls this is the result.



image



 



I only had to watch one object the entire time! Now if I can only build a VSADDIN to automate this process (evil grin)!

May 26, 2009

Silverlight WCF Inner-Exceptions

Found a quick and dirty way to do WCF exceptions in silverlight http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=silverlightws&DownloadId=3473 .  The problem is that it doesn’t do inner-exceptions.

I changed the raw fault exception around a bit to get inner exceptions working.

 

    public static RawFaultException BuildRawFaultException(XmlDictionaryReader reader)
{
List<string> messages = new List<string>();
List<string> stacktraces = new List<string>();
while (reader.ReadToFollowing("Message"))
{
string message = reader.ReadElementContentAsString();
string stackTrace = reader.ReadElementContentAsString("StackTrace", reader.NamespaceURI);
messages.Add(message);
stacktraces.Add(stackTrace);
}
RawFaultException e = null;
for (int i = 0; i < messages.Count; i++)
{
if (e == null) { e = new RawFaultException(messages[i]) { stackTrace = stacktraces[i] }; }
else { e = new RawFaultException(messages[i], e) { stackTrace = stacktraces[i] }; }
}

return e;

}
}

May 11, 2009

Flag enums

I was working on a project that needed to use flag enums to store state.  Flag enums are great, except after 2^15 the numbers get hard to calculate. I resorted to using excel to generate the enum code for me, that is until I learned I can do math expressions inside of enums! What I forgot is that 2^0 is not equivalent to Math.Pow(2,0).  This is when I discovered my old friend shift.

 

 

using System;

namespace TestEnum
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(oldway.All);
Console.WriteLine(newway.All);
}
}

[Flags]
enum oldway
{
None=0,
One=1,
Two=2,
Three=4,
Four=8,
All=15
}

[Flags]
enum newway
{
None = 0,
One = 1<<0,
Two = 1<<1,
Three = 1<<2,
Four = 1<<3,
All = (1<<4) - 1
}
}

 


As you can see they both work the same :)


image

Apr 23, 2009

State Bag for all objects

Extension methods are very powerful, but sometimes you need to store state on the object you are processing in an extension method.  The problem is implementing state maintenance in a static method can be a real chore.  Not to mention when you only want to track state on an object you can’t.  I wrote this quick and dirty state maintenance set of extension methods.  There is a caveat that I cannot fix at the time of writing. 

 

If you store data in the statebag, you need someway of knowing when the object is getting destroyed so that you can manually call ClearVariables.  If you do not clear the variables the values will be left in the statebag FOREVER causing massive memory leaks!  I would like a way to alleviate this if anyone has any ideas.

 

using System;
using System.Collections.Generic;

namespace StateBagTest
{
class Program
{
static void Main(string[] args)
{
object o = new object();
o.Set("newvar", 5);
int number = (int)o.Get("newvar");
o.ClearVariables(); //very very important!
Console.ReadLine();
}

}

public static class StateBag
{
static Dictionary<int, Dictionary<string, object>> _stateBag = new Dictionary<int, Dictionary<string, object>>();
public static void Set(this object obj, string var, object value)
{
int hashcode = obj.GetHashCode();
if (!_stateBag.ContainsKey(hashcode))
{
_stateBag.Add(hashcode, new Dictionary<string, object>());
}
_stateBag[hashcode][var] = value;
}

public static object Get(this object obj, string var)
{
int hashcode = obj.GetHashCode();
if (_stateBag.ContainsKey(hashcode) && _stateBag[hashcode].ContainsKey(var))
{
return _stateBag[hashcode][var];
}
return null;
}

//Really need to call this when your object is done using the state bag, which may be hard for some objects you are extending!
public static void ClearVariables(this object obj)
{
int hashcode = obj.GetHashCode();
if (_stateBag.ContainsKey(hashcode))
{
_stateBag[hashcode] = null;
}
}
}
}

Dec 18, 2008

Mono.Cecil Profiler

So we have been trying to develop a profiler for a long time.  All the posts seem to require an inordinate amount ofMSIL knowledge or to know C++ to interface with the CLR directly.  Both of these approaches were painful.  All I wanted to do was inject a Profile.Start and Profile.End into our code base for every class giving us a simple profiler.  With Mono.Cecil I could do exactly that, and without Mono installed on my computer.  Go get the original example from the Mono.Cecil website or just download it directly here. There is a dll called lib.  I just added that to my solution in VS2008 and wrote the following simple profiler.

 

 

static void Main(string[] args)
{
string pathBin = @"C:\Users\michael\Documents\Visual Studio 2008\Projects\ConsoleApplication1\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe";

MethodInfo startMethod = typeof(ProfileClient).GetMethod("Start", new Type[] { typeof(string) });
MethodInfo endMethod =typeof(ProfileClient).GetMethod("End", new Type[] { typeof(string) });

AssemblyDefinition assembly = AssemblyFactory.GetAssembly(pathBin);

foreach (TypeDefinition type in assembly.MainModule.Types)
{
if (type.Name != "<Module>")
{
foreach (MethodDefinition method in type.Methods)
{
CilWorker worker = method.Body.CilWorker;
string sentence = method.Name;
MethodReference start=assembly.MainModule.Import(startMethod);
MethodReference end= assembly.MainModule.Import(endMethod);

//Creates the MSIL instruction for inserting the sentence
Instruction startSentence = worker.Create(OpCodes.Ldstr, sentence);
Instruction endSentence= worker.Create(OpCodes.Ldstr, sentence);

List<Instruction> parameters = new List<Instruction>();

//Creates the CIL instruction for calling the start and end
Instruction callStart= worker.Create(OpCodes.Call, start);
Instruction callEnd= worker.Create(OpCodes.Call, end);

//-2 cause you need to go before the return opcode
Instruction lastinstruction= method.Body.Instructions[method.Body.Instructions.Count-2];
worker.InsertAfter(lastinstruction, endSentence);
worker.InsertAfter(endSentence, callEnd);

Instruction firstinstruction = method.Body.Instructions[0];
worker.InsertBefore(firstinstruction, startSentence);
worker.InsertAfter(startSentence, callStart);


}
}
}

AssemblyFactory.SaveAssembly(assembly, pathBin.Replace(".exe","")+"-new-.exe");
}


 



public class ProfileClient
{
public static void Start(string method,params object[] args)
{
Console.WriteLine("Start " + method+">");
}

public static void End(string method, params object[] args)
{
Console.WriteLine(">End "+ method);
}
}



 



class Program
{
static void Main(string[] args)
{
Console.WriteLine("My Code2 ");
}
}




So if you build the last program and run it, it will output



My Code2



Once you run the second console application and then run ConsoleApplication2-new-.exe you will get



Start Main>

My Code2 ?


>End Main



I’m still not sure where the ? comes from but for now this simple profiler works and will be the basis of our more complex profiler we are planning to start constructing.

Sep 2, 2008

Remove SVN

There is probably an easier way to do this.  I accidentally tried to add a  large directory to a svn repo.  It failed after 3 hours leaving half my directory with .svn folders. Since Tortoise SVN didn't seem to have an option to unbind a folder I wrote this powershell script.

 

 

function removesvn
{
  dir -path $pwd.Path -recurse -force | where{    $_.Name -eq ".svn"} | rm -recurse -force
}
removesvn

Aug 26, 2008

Convert Bitmaps to transparent png

Not much to say.  This was really useful with an icon set we were using.

 

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string directory=@"c:\temp\";
string[] files = Directory.GetFiles(directory, "*.bmp");
foreach (string path in files)
{
Bitmap bmp = new Bitmap(path);
bmp.MakeTransparent(Color.Magenta);
FileInfo fi = new FileInfo(path);
bmp.Save(directory + fi.Name.Replace(".bmp", "") + ".png", ImageFormat.Png);
bmp.Dispose();
}
}
}
}


 

Followers