CRC 16 CCITT in C#

Once again I found myself needing another type of CRC algorithm in C#. I found one on code project, but their implementation of CRC 16 CCITT didn’t produce that checksum I needed. Come to find out there are different methods to calculate CRC 16 CCITT which use different initial values for the CRC.

I ended up writing this one for my own purposes:

using System;

public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }

public class Crc16Ccitt {
    const ushort poly = 4129;
    ushort[] table = new ushort[256];
    ushort initialValue = 0;

    public ushort ComputeChecksum(byte[] bytes) {
        ushort crc = this.initialValue;
        for(int i = 0; i < bytes.Length; ++i) {
            crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
        }
        return crc;
    }

    public byte[] ComputeChecksumBytes(byte[] bytes) {
        ushort crc = ComputeChecksum(bytes);
        return BitConverter.GetBytes(crc);
    }

    public Crc16Ccitt(InitialCrcValue initialValue) {
        this.initialValue = (ushort)initialValue;
        ushort temp, a;
        for(int i = 0; i < table.Length; ++i) {
            temp = 0;
            a = (ushort)(i << 8);
            for(int j = 0; j < 8; ++j) {
                if(((temp ^ a) & 0x8000) != 0) {
                    temp = (ushort)((temp << 1) ^ poly);
                } else {
                    temp <<= 1;
                }
                a <<= 1;
            }
            table[i] = temp;
        }
    }
}
C#

This was used for testing during the time we were looking at the Battlefield 2142 auth token, and were trying to figure out what the last 2 bytes of that token were made of.  Battlefield 2142’s auth token uses the CRC 16 CCITT with the initial value of 0 new Crc16Ccitt(InitialCrcValue.Zeros) in the above class. 

If you need for this code to be CLS compliant, you can change the method signature’s return type from ushort to int and it will operate the same (the ushort crc value will be implicitly converted from ushort to int)

Links to the other C# CRC implementations CRC32, CRC16, CRC16-CCITT Kermit, and CRC8

I’ve consolidated all of these into a single library on GitHub here: NullFX.CRC.

I’m also very into Swift at the moment and have created Swift versions of these same classes and released a Swift PM version of this library here as well Swift NullfxCrc Package

A Generic Singleton Pattern in C#

I don’t know why its never occurred to me to implement the singleton pattern as a generic type before. I’ve always just created the singleton pattern as part of my class (not that we’re talking about a lot of coding here), but it occurred to me that a singleton could be a lot easier to implement and spot if I used a generic type.

Here is my generic Singleton class:

public class Singleton<T> where T : class {
    static object SyncRoot = new object( );
    static T instance;
    public static T Instance {
        get {
            if ( instance == null ) {
                lock ( SyncRoot ) {
                    if ( instance == null ) {
                        ConstructorInfo ci = 
                          typeof( T ).GetConstructor( BindingFlags.NonPublic | 
                            BindingFlags.Instance, null, Type.EmptyTypes, null );
                        if ( ci == null ) { 
                            throw new InvalidOperationException( 
                            "class must contain a private constructor" ); }
                        instance = (T)ci.Invoke( null );
                    }
                }
            }
            return instance;
        }
    }
}
C#

Now, instead of implementing this same thing in every single class you want to act as a singleton, you simply use the generic definition: Foo.Instance.Whatever turns into Singleton<Foo>.Instance.Whatever.

Update: I’ve updated this implementation from using a mutex to using a simple lock (double checked) object. A mutex is pointless for a singleton (which I may go into in another article at some later time) as you can never have 2 separate execution contexts accessing one singleton anyway (which is where you would need a mutex over a simple lock object), and I changed the where T : new() to where T : class and changed the instantiation to use reflection to call the private default constructor instead, which I think is the correct implementation.

Triple DES between PHP and C#

The past while at work I’ve been working through some annoyingly over complicated encryption issues. The problem is not that Triple DES is all that complicated or annoying, it’s just that when you have 2 different technologies (one doing the encrypting and one doing the decrypting) at work; it can be frustrating to get anything accomplished.

Our issues stemmed around the fact that we were using .NET 1.1 and they were using Java (with the standard crypto providers). There are a few subtleties between Microsoft’s crypto providers and Java’s. .NET provides 3 (OK, really only 2) Padding modes, and Java provides like 5, but they don’t provide any in common. One easy padding mode is to append 0x00 bytes to the end of the final block to make it an even 64 bits wide. The Java provider didn’t have this, but its easy enough to add ( by appending null char’s ‘\0’ to the end of the string then calling getBytes() ). So that’s the route we took. After overcoming a few problems with “How do we encode our bytes used for the key and IV and still be compatible” we were off and running.

That made me wonder how compatible PHP and .NET’s 3DES were. Since I didn’t see any “Padding Mode” for PHP’s, I simply hand coded the padding the same way we did with the Java code.

Here’s my PHP script:

<?php

if(!isset($_POST['op'])) {
    ?>
<form id="form1" name="form1" method="post" action="">
  enter text
  <input name="data" type="text" />
  <input type="hidden" value="op" name="op" />
  <input type="submit" name="Submit" value="Submit" />
</form>
    <?php
}else {
    $buffer = $_POST['data']; 
    // get the amount of bytes to pad
    $extra = 8 - (strlen($buffer) % 8);
    // add the zero padding
    if($extra > 0) {
        for($i = 0; $i < $extra; $i++) {
            $buffer .= "\0";
        }
    }
    // very simple ASCII key and IV
    $key = "passwordDR0wSS@P6660juht";
    $iv = "password";
    // hex encode the return value
    echo "Result: ".bin2hex(mcrypt_cbc(MCRYPT_3DES, $key, $buffer, MCRYPT_ENCRYPT, $iv));	
}
?>
PHP

Then entered in my text (in this case I used “Test” in both)

Then I wrote up a sample in .NET to try to see if we had to massage the data or not:

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace TestBed {
    class Program {
        static void Main(string[] args) {
            byte[] key = Encoding.ASCII.GetBytes("passwordDR0wSS@P6660juht");
            byte[] iv = Encoding.ASCII.GetBytes("password");
            byte[] data = Encoding.ASCII.GetBytes("Test");
            byte[] enc = new byte[0];
            TripleDES tdes = TripleDES.Create();
            tdes.IV = iv;
            tdes.Key = key;
            tdes.Mode = CipherMode.CBC;
            tdes.Padding = PaddingMode.Zeros;
            ICryptoTransform ict = tdes.CreateEncryptor();
            enc = ict.TransformFinalBlock(data, 0, data.Length);
            Console.WriteLine(Bin2Hex(enc));
            Console.ReadLine();
        }
        // my bin2hex implementation		
        static string Bin2Hex(byte[] bin) {
            StringBuilder sb = new StringBuilder(bin.Length * 2);
            foreach(byte b in bin) {
                sb.Append(b.ToString("x").PadLeft(2, '0'));
            }
            return sb.ToString();
        }
    }
}
C#

47794945c0230c3d” Wouldn’t you know it! It worked like a charm!

Would have been nice if the Java -> .NET solution had been that easy.

A Command Line style string parser (in C#)

Last week I was writing a service that could be run as a console app. I needed to be able to parse a single string into an array like the shell does for command line apps, and the service does for start parameters. I did a little googling, but found only command line arg classes that put command line args into associative array’s for easy indexing, which isn’t what I was looking for.

The class had basically 2 requirements:

  1. It had to be able to split the string on spaces (simple right?)
  2. It had to escape spaces that were quoted (as well as quotes that were escaped).

First I tried to iterate through the string a character at a time, looking for spaces keeping the state of whether we were inside a quote or not, whether the current character was an escaped quote, and so on.

That was a major pain, so I stepped back and rethought my algorithm. this is what I ended up with, which was much simpler, and did exactly what I wanted without a lot of fuss.

So here’s my command line parser:

public class CommandLineParser {
    CommandLineParser() { }
    public static string[] Parse(string str) {        
        if(str == null || !(str.Length > 0)) return new string[0];
        int idx = str.Trim().IndexOf(" "); 
        if(idx == -1) return new string[] { str };
        int count = str.Length;
        ArrayList list = new ArrayList(); 
        while(count > 0) {
            if(str[0] == '"') {
                int temp = str.IndexOf("\"", 1, str.Length - 1);
                while(str[temp - 1] == '\\') {
                    temp = str.IndexOf("\"", temp + 1, str.Length - temp - 1);
                }
                idx = temp+1;
            }
            if(str[0] == '\'') {   
                int temp = str.IndexOf("\'", 1, str.Length - 1);
                while(str[temp - 1] == '\\') {
                    temp = str.IndexOf("\'", temp + 1, str.Length - temp - 1);
                }
                idx = temp+1;
            }
            string s = str.Substring(0, idx);
            int left = count - idx;
            str = str.Substring(idx, left).Trim();
            list.Add(s.Trim('"'));
            count = str.Length;
            idx = str.IndexOf(" ");
            if(idx == -1) {
                string add = str.Trim('"', ' ');
                if(add.Length > 0) {
                    list.Add(add);
                }
                break;
            }
        }
        return (string[])list.ToArray(typeof(string));
    }
}
C#

An IPAddress Control (the Win32 SysIPAddress32 control in C#)

The Common Controls library from the Platform SDK provides a control that Microsoft failed to provide a .NET counterpart to: the IPAddress Control (known as SysIPAddress32).

Quite a while ago I wrote a C# / .NET control that wrapped the functionality of the SysIPAddress32 control from comctl32.dll

I had a much better implementation back then (with quite a few nice things included), but the hard drive that it lived on has since died, and I just haven’t wanted to spend the time putting all that stuff back into the control.

Some time after having written the “nice” version of this control, I posted the following code to another website. Now, it’s all I have left of the original. There is a known problem with the handle to the font being disposed incorrectly, but the code that fixed it, was given to me by a software engineer who worked at Microsoft that went by jfo, and I did a cut/paste of the solution without really paying much attention to it (kind of regretting that now…). You may notice all the system fonts will always be displayed in BOLD in the forms designer (even when the font is not set to bold). This goes away a runtime, it’s caused by an improperly disposed handle during design time.

Anyway, here it is, my IPAddress Control:

/******************************************************/
/*          NULLFX FREE SOFTWARE LICENSE              */
/******************************************************/
/*  IPAddressControl                                  */
/*  by: Steve Whitley                                 */
/*  © 2004 NullFX Software                            */
/*                                                    */
/* NULLFX SOFTWARE DISCLAIMS ALL WARRANTIES,          */
/* RESPONSIBILITIES, AND LIABILITIES ASSOCIATED WITH  */
/* USE OF THIS CODE IN ANY WAY, SHAPE, OR FORM        */
/* REGARDLESS HOW IMPLICIT, EXPLICIT, OR OBSCURE IT   */
/* IS. IF THERE IS ANYTHING QUESTIONABLE WITH REGARDS */
/* TO THIS SOFTWARE BREAKING AND YOU GAIN A LOSS OF   */
/* ANY NATURE, WE ARE NOT THE RESPONSIBLE PARTY. USE  */
/* OF THIS SOFTWARE CREATES ACCEPTANCE OF THESE TERMS */
/*                                                    */
/* USE OF THIS CODE MUST RETAIN ALL COPYRIGHT NOTICES */
/* AND LICENSES (MEANING THIS TEXT).                  */
/*                                                    */
/******************************************************/


namespace NullFX.Controls {
    using System;
    using System.Net;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Drawing;
    [StructLayout(LayoutKind.Sequential)]
    public struct Nmhdr {
        public IntPtr HWndFrom;
        public UIntPtr IdFrom;
        public int Code;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct NmIPAddress {
        public Nmhdr Hdr;
        public int Field;
        public int Value;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct InitCommonControlsEX {
        public int Size;
        public int Icc;
    }
    public enum IPField { OctetOne = 0, OctetTwo = 1, OctetThree = 2, OctetFour = 3 }
    public delegate void FieldChangedHandler(object sender, FieldChangedEventArgs e);
    public class FieldChangedEventArgs : EventArgs {
        private int _field, _value;
        public int Field {
            get { return _field; }
        }
        public int Value {
            get { return _value; }
        }
        public FieldChangedEventArgs(int field, int value)
            : base() {
            _field = field;
            _value = value;
        }
    }
    public class IPAddressControl : TextBox {
        private const int WM_NOTIFY = 0x004E,
            WM_USER = 0x0400,
            WM_REFLECT = WM_USER + 0x1C00,
            IPN_FIRST = -860,
            IPM_SETRANGE = (WM_USER + 103),
            IPM_GETADDRESS = (WM_USER + 102),
            IPM_SETADDRESS = (WM_USER + 101),
            IPM_CLEARADDRESS = (WM_USER + 100),
            IPM_ISBLANK = (WM_USER + 105),
            ICC_INTERNET_CLASSES = 0x00000800,
            CS_VREDRAW = 0x0001,
            CS_HREDRAW = 0x0002,
            CS_DBLCLKS = 0x0008,
            CS_GLOBALCLASS = 0x4000,
            WS_CHILD = 0x40000000,
            WS_VISIBLE = 0x10000000,
            WS_TABSTOP = 0x00010000,
            WS_EX_RIGHT = 0x00001000,
            WS_EX_LEFT = 0x00000000,
            WS_EX_RTLREADING = 0x00002000,
            WS_EX_LTRREADING = 0x00000000,
            WS_EX_LEFTSCROLLBAR = 0x00004000,
            WS_EX_RIGHTSCROLLBAR = 0x00000000,
            WS_EX_NOPARENTNOTIFY = 0x00000004,
            WS_EX_CLIENTEDGE = 0x00000200;
        private int[] values = new int[4];
        bool initialized = false;		
        public event FieldChangedHandler FieldChanged;
        public IPAddressControl()
            : base() {
            for(int i = 0; i < 4; i++)
                values[i] = 0;
        }
        [DllImport("comctl32")]
        static extern bool InitCommonControlsEx(ref InitCommonControlsEX lpInitCtrls);

        protected virtual void OnFieldChanged(FieldChangedEventArgs e) {
            if(FieldChanged != null) FieldChanged(this, e);
        }
        protected override CreateParams CreateParams {
            get {
                if(!initialized) {
                    InitCommonControlsEX ic = new InitCommonControlsEX();
                    ic.Size = Marshal.SizeOf(typeof(InitCommonControlsEX));
                    ic.Icc = ICC_INTERNET_CLASSES;
                    initialized = InitCommonControlsEx(ref ic);
                }
                if(initialized) {
                    CreateParams cp = base.CreateParams;
                    cp.ClassName = "SysIPAddress32";
                    cp.Height = 23;
                    cp.ClassStyle = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_GLOBALCLASS;
                    cp.Style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | 0x80;
                    cp.ExStyle = WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE;
                    if(RightToLeft == RightToLeft.No || 
                      (RightToLeft == RightToLeft.Inherit && 
                       Parent.RightToLeft == RightToLeft.No )) {
                        cp.ExStyle |= WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
                    } else {
                        cp.ExStyle |= WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR;
                    }
                    return cp;
                } else {
                    return base.CreateParams;
                }
            }
        }
        public bool SetIPRange(IPField field, byte lowValue, byte highValue) {
            if(!initialized) return false;		
            Message m = Message.Create(
                                  Handle, 
                                  IPM_SETRANGE, 
                                  (IntPtr)((int)field), 
                                  MakeRange(lowValue, highValue));
            WndProc(ref m);
            return m.Result.ToInt32() > 0;
        }
        public System.Net.IPAddress IPAddress {
            get {
                if(!initialized) return IPAddress.None;			
                return IPAddress.Parse(base.Text);
            }
        }
        public bool IsBlank {
            get {
                if(!initialized) return !(base.Text.Length > 0);
                Message m = Message.Create(Handle, IPM_ISBLANK, IntPtr.Zero, IntPtr.Zero);
                WndProc(ref m);
                return m.Result.ToInt32() > 0;
            }
        }
        new public void Clear() {
            if(!initialized) {
                base.Clear();
                return;
            }		
            Message m = Message.Create(Handle, IPM_CLEARADDRESS, IntPtr.Zero, IntPtr.Zero);
            WndProc(ref m);
        }
        private System.Net.IPAddress GetIpAddress(IntPtr ip) {
            if(!initialized) return IPAddress.None;		
            return new IPAddress(ip.ToInt64());
        }
        private IntPtr MakeRange(byte low, byte high) {
            return (IntPtr)((int)((high << 8) + low));
        }
        protected override void WndProc(ref Message m) {
            if(m.Msg == (WM_REFLECT + WM_NOTIFY)) {
                NmIPAddress ipInfo = (NmIPAddress)Marshal.PtrToStructure(m.LParam,
                                                                   typeof(NmIPAddress));
                if(ipInfo.Hdr.Code == IPN_FIRST) {
                    if(values[ipInfo.Field] != ipInfo.Value) {
                        values[ipInfo.Field] = ipInfo.Value;
                        OnFieldChanged(
                          new FieldChangedEventArgs(ipInfo.Field, ipInfo.Value));
                    }
                }
            }
            base.WndProc(ref m);
        }
    }
}
C#

It does have one wrapped event from the original control and that is FieldChanged, which provides feedback when each octet is changed (similar to TextChanged for a text box, but only fires after the user has entered the entire text for an octet). Likewise, if the value of an octet is larger than a byte, it is automatically changed back to 255 (i.e., the max value of a byte). When the event fires, it passes back, the octet that was changed, and its value.

You can specify the IP Range (which the original control allows, and I’ve wrapped into this control as well) so that you can edit the control to only accept a specified IP Address Range.

I’ve also provided Native Clear functionality as well as the IsBlank from the original control. I added a System.Net.IPAddress property so that when accessing the IPAddress of the control, you didn’t need to parse the System.Net.IPAddress every time. My original control completely removed the Text property so that you get / set the IPAddress through this property, but alas, that functionality doesn’t exist in this control.

UPDATE: 8/25/2006 – I Made two changes to the source code, 1. added some Initialization logic to keep InitCommonCtrls from being called multiple times and, 2. added styles for ClassStyle, StyleEX and Style to keep an exception from being thrown in certain cases when the WM_GETTEXTLENGTH message was sent.

The C# 3.0 language specification

I know I’m a bit late here, but better late than never.

I’ve been reading over some of the changes to C# for version 3. I had heard that v3 would be v2 with the addition of the new WPF, but looking over the new spec (well, fairly new anyway), there is quite a bit more.

Implicit types, method extensions, lambda expressions, object / collection initializers, and LINQ… C# is going to look really weird! So much for simplicity.

Implicit types (csharp meets js or PHP) allow you to define the variable without a (or with an implied) type:

var foo = "hello";
var bar = 32;
C#

so foo is implied to be of type string, and bar is implied to be of some numeric type.

Method extensions look very strange. Think of old dog learns new tricks meets operator overloading. Method extensions allow you to create “extension” methods for existing types:

public class Bar {
    string what = "hello";
    public string What { get { return what; } set { what = value; } }
    public Bar() {}
    public void Hello() { 
        Console.WriteLine(what); 
    }
}

public static class Foo {
    public static void SayHelloToSteve(this Bar bar) {
        bar.What += " steve";
        bar.Hello();
    }
    public static void SayHelloToSomeone(this Bar bar, string who) {
        bar.What = who;
        bar.Hello();
    } 
}

public class Program {
    static void Main(string[] args) {
        Bar b = new Bar();
        b.Hello();
        b.SayHelloToSteve();
        b.SayHelloToSomeone("Hello Bob!");
    }
}
C#

Notice that SayHelloToSteve() and SayHelloToSomeone(string s) are not member methods of the Bar class, but are invoked as if they were (by virtue of the Method extension defined in Foo that are available to Bar). This seems like a feature that will be abused to defeat inheritance (by adding reflection to the method extensions to manipulate internal class member’s without inheriting and changing functionality of the object) that would otherwise look odd and ugly.

OUTPUT:

hello
hello steve
Hello Bob!

At this point lambda expressions don’t make much sense to me, but it seems its a way to define more than one method body in an anonymous method.

Object / collection initialization makes initialization a lot easier. I don’t know if you’ve ever wanted to declare a new object inline inside a method, only to realize that you needed to set a few properties before it was used, well this is the answer to that:

myObject.Blah(new SomeObject() { PropertyA = 1, PropertyB = "dude", PropertyC = false });
C#

Then there’s LINQ: which feels something like SQL for C#.

feel free to download the spec here

fin

PHP WebServices and C# / .NET SOAP Clients

Code Zulu Bind Maker is a project I started working on about 3 years ago. Its a stupid little app that configures game settings for Counter Strike. When I wrote it, version CS v1.6 was in beta, and everybody played version CS v1.5 (which was ever so different). Anyway I run a website that supports the app, and of course, its written in PHP / MySql (my poison of choice on the web).

The reason for the boring and seemingly pointless background is that ever since I wrote the app, I always wanted to integrate the website and application, but never really thought of a “good” way to do it. A couple days ago, I had some spare time and sat down to see how easy it would be to create some PHP webservices that I could easily consume in C#. I had been considering expanding the community aspect of the bind maker website into the application so that they’d work seamlessly together. I also wanted to add a common place that gaming communities could spend their time (which I had previously planned for just the website, but was thinking of the possibilities of bringing that into the app as well), and a PHP webservice combined with a C# windows app seemed like the best option.

C# web services (server side) are about as easy-as-it-gets to write. C#’s SOAP client is completely transparent (or I should say completely generated so you code just like you would use any other objects) and is completely brainless to use. Since I’d never done web service work in PHP, I started asking Mr. Google how it worked, and what would you now but that I stumbled across the NuSOAP library for PHP. It sure beat the heck out of writing all my WSDL files by hand, wrapping and unwrapping stupidly simple SOAP messages, and hacking everything very poorly.

My first PHP web service iteration was a simple “hello <name>” web method. It used a simple type (xsd:string) as its parameter and returned a simple type (again another xsd:string) as its return value and looked like this:

 /**
 * ProcessSimpleType method
 * <strong>@param</strong> string $who name of the person we'll say hello to
 * <strong>@return</strong> string $helloText the hello  string
 */
function ProcessSimpleType($who) {
	return "Hello $who";
}
PHP

NuSoap was great. It took care of all the nitty-gritty work that I had previously done myself. All it took was about 8 lines of code to set up the SOAP server and register the method and my types.

require_once("lib/nusoap/nusoap.php");
$namespace = "http://sanity-free.org/services";
// create a new soap server
$server = new soap_server();
// configure our WSDL
$server->configureWSDL("SimpleService");
// set our namespace
$server->wsdl->schemaTargetNamespace = $namespace;
// register our WebMethod
$server->register(
                // method name:
                'ProcessSimpleType', 		 
                // parameter list:
                array('name'=>'xsd:string'), 
                // return value(s):
                array('return'=>'xsd:string'),
                // namespace:
                $namespace,
                // soapaction: (use default)
                false,
                // style: rpc or document
                'rpc',
                // use: encoded or literal
                'encoded',
                // description: documentation for the method
                'A simple Hello World web method');
                
// Get our posted data if the service is being consumed
// otherwise leave this data blank.                
$POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) 
                ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';

// pass our posted data (or nothing) to the soap service                    
$server->service($POST_DATA);                
exit();
PHP

That was it. From visual studio I was then able to consume the web service by adding a web reference

This article was first written with visual studio 2005. Visual studio 2008 and 2010 no longer have the “Add Web Reference” menu item. Instead they have an option to add a service reference. Selecting this option ends up generating a WCF C# client proxy, but we’ll want to use the asmx style web service client proxy, so we’ll navigate to the add web reference dialog which is hidden deep inside Add Service Reference dialog.

Finally click the Add Web Reference button

With the reference added, I put a button on my form, and added the following button click event handler:

private void button1_Click(object sender, EventArgs e) {
    SimpleService svc = new SimpleService();
    string s = svc.ProcessSimpleType("steve");
    MessageBox.Show(s);
}
C#

Ran my application, pressed the button (which in turn called the web service), and voilà I get a message box telling me Hello:

That’s great! Completely useless, but great!

Now to get a little more complicated… I had planned on using complex data types that would be consumed by both PHP and .NET clients (A PHP SOAP client for the website, and .NET client for the windows application). It may sound stupid to have a PHP client when most likely I’d have access to the method directly, but the server that is going to host the web services is actually different than the “web presence” server I host my website on. Anyway, the test complex types I came up needed to look like simple structs (in C#) which would also be used in an array, and they looked something like this:

public struct MySoapObject {
    public string Author;
    public string Name;
    public string Description;
    public string Text;
    public int VoteTotal;
    public int VoteCount;
}

MySoapObject[] soapObjects = new MySoapObject[10];
C#

so I added the definitions in PHP using NuSOAP like this:

$server->wsdl->addComplexType(
    'MySoapObject',
    'complexType',
    'struct',
    'all',
    '',
    array(
        'Author' => array('name'=>'Author','type'=>'xsd:string'),
        'Name' => array('name'=>'Name','type'=>'xsd:string'),
        'Description' => array('name'=>'Description','type'=>'xsd:string'),
        'Text' => array('name'=>'Text','type'=>'xsd:string'),
        'VoteTotal' => array('name'=>'VoteTotal','type'=>'xsd:int'),
        'VoteCount' => array('name'=>'VoteCount','type'=>'xsd:int')
    )
);

$server->wsdl->addComplexType(
    'MySoapObjectArray',
    'complexType',
    'array',
    '',
    'SOAP-ENC:Array',
    array(),
    array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'tns:MySoapObject[]')),
    'tns:MySoapObject'
);
PHP

I defined the method in PHP that would take in an array of MySoapObjects, process them, and then return one MySoapObject that it had “processed”.

That method looked like this:

function ProcessMySoapObject($mySoapObjects) {
	$mso = $mySoapObjects[3];
	$mso['Name'] = "|||";
	return $mso;
}
PHP

The SOAP server registration:

$server->register(
    'ProcessMySoapObject',
    array('soapObjects'=>'tns:MySoapObjectArray'),
    array('return'=>'tns:MySoapObject'),
    $ns,
    false,
    'rpc',
    false,
    'Processes an array of MySoapObjects and returns one of them');
PHP

And I did exactly the same as I did before–and added the web reference in visual studio to my project. This time not only did Visual Studio add the Service class and web method, it added the 2 data types I had defined in PHP on my SOAP server (actually, it just built the MySoapObject, and the array was left out because arrays are an implied data type).

I changed my button click event in my windows form and added the following code:

private void button1_Click(object sender, EventArgs e) {
    Services s = new Services();
    MySoapObject[] ms = new MySoapObject[10];
    for(int i = 0; i < ms.Length; i++) {
        ms[i] = new MySoapObject();
        ms[i].Author = "Steve";
        ms[i].Description = "The One that should be returned";
        ms[i].Name = i.ToString();
        ms[i].Text = "something something something " + i.ToString();
        ms[i].VoteCount = i * 2;
        ms[i].VoteTotal = (int)Math.Pow(ms[i].VoteCount, 2);
    }
    MySoapObject retn = s.ProcessMySoapObject(ms);
    string output = "";
    output += retn.Author + "\t\t\r\n";
    output += retn.Description + "\t\t\r\n";
    output += retn.Name + "\t\t\r\n";
    output += retn.Text + "\t\t\r\n";
    output += retn.VoteCount.ToString() + "\t\t\r\n";
    output += retn.VoteTotal.ToString() + "\t\t\r\n";
    MessageBox.Show(output);
}
C#

Compiled, ran and clicked.

Simple, Easy, Can’t believe I never tried it before now!

This opened up a whole new world of opportunities in cross-platform distributed computing that I’d never exposed myself to before… what a wonderful thing!

Dependency Scanner (for .NET 1.1)

Download Project & Source Code

Here’s a little tool I wrote a while ago. Right now its only for .NET 1.1, but I’m working on a port for 2.0 (which should look a lot nicer).

When I wrote this, I was dealing with assemblies that had very complex inner-dependencies. Some assemblies were private, others were shared, and I ended up having to have a ton of ildasm.exe’s open to the assembly manifest to try to see which assembly had referenced which assembly and had to verify that the assembly version referenced was correct. On top of that I needed to verify that assemblies that were referenced–that had policy files–were being redirected to the correct versions.

Basically all this tool does, is load an assembly, display its version, and lists any referenced assemblies, their versions, and whether or not the reference version resolves to any other version. It doesn’t look like much, but its saved me a lot of time and head ache. It also has a copy / paste feature that can copy selected ListView data to the clipboard in a nice column formatted manner.

Here’s the main bulk of whats going on. Basically what I did, was to load the assembly file, then try to load another assembly based on the partial name from the assembly file that I just loaded. At first glance, it looks as if I’m creating 2 identical assembly objects. The difference is, that if one assembly was version 1.1.2 and there was a policy file for version 1.1.2 to redirect to version 1.2.3, the second assembly load would load version 1.2.3 instead of version 1.1.2. That info would be displayed in the top line of the assembly entry

private void ResolveAssemblyImports(string file) {
    try {
        Assembly asm = Assembly.LoadFile(file);
        Assembly d = Assembly.LoadWithPartialName(asm.FullName);
C#

Then I matched the two assemblies version numbers to see if they matched

        string ver = "", re = "";
        bool nill = d == null;
        if(!nill) {
            re = _r.Match(d.FullName).Groups["version"].Value;
        } else {
            re = "NULL";
        }
        ver = _r.Match(asm.FullName).Groups["version"].Value;
        bool r_1 = false;
        if(ver != re && re != "NULL") {
            Version v_1 = new Version(ver);
            Version v_2 = new Version(re);
            if(v_2 >= v_1) r_1 = true;
        }
        AddItem(asm.GetName().Name, "----", ver, re, "True", nill ? "Failed" : (r_1 ? "True" : "False"));
C#

Then I iterate through the assembly’s referenced assemblies and try to do the same thing (match version numbers & see if they resolve to the same version)

        foreach(AssemblyName asmName in asm.GetReferencedAssemblies()) {
            string v1 = _r.Match(asmName.FullName).Groups["version"].Value,
                v2 = v1;
            bool exist = false, res = false;
            Assembly dep;
            try {
                dep = Assembly.LoadWithPartialName(asmName.FullName);
                if(dep != null) {
                    string temp = _r.Match(dep.FullName).Groups["version"].Value;
                    exist = true;
                    if(v2 != temp) {
                        Version v = new Version(v2);
                        Version t = new Version(temp);
                        if(t >= v) res = true;
                    }
                }
            } finally {
                AddItem("    +----", asmName.Name, v1, v2, exist.ToString(), res.ToString());
            }
        }
    } catch {
    }
}
C#

Then I finally print out the results of my findings to the ListView.


I had forgotten about this app until today when I couldn’t understand why I kept getting an error for a method that had been updated in the assembly I was referencing. I pulled this tool out and saw that it indeed referenced the correct assembly but because another assembly being used referenced an older version of that assembly, the local copy was using the newer version but the older version was in the GAC so my code was using the older assembly that didn’t have the current code that I needed (confused… I am and I was there).

Anyway, here’s the project / source code for the app.

Update 7/16/2009 I’ve converted this app over to .NET 3.5 and complied app binaries that can be downloaded here

Visual Studio .NET 2005 Troubleshooting Tool

I was having some troubles with the final release visual studio Team System. I’ve been using VS.NET 2005 on my home computer since the first previews were available on MSDN. I had installed and uninstalled each release of the IDE. I was experiencing problems viewing some of the docking window contents (entire panels loosing their contents, and were not able to be closed). I found A trouble shooting tool on Aaron Stebner’s blog. I ran it, it found an orphaned beta assembly that was causing all the problems, and now I’m up and running without any problems…

Very Nice!

A Battlefield 2 Rank Avatar Script in PHP

This is a little departure from my typical topic.

To cut a rather tedious and boring story short, I play Battlefield 2, which has a cool stats service that folks have been hacking with outside of the game (the game has a stats board built in, which stats board uses some pseudo web-services to obtain game statistic info).

There are a multitude of server hosts out there that generate dynamic signature images with your game stats in them, so that you can look cool and show off how much time you actually waste online gaming, on every forum you frequent.

I decided to join the masses and write a script that pulls my users rank and score from the stats servers and returns an image that can be used as an avatar on most bulletin board systems out there. I had a size restriction on the server I wanted it for, so the images produced are 80×80 and less than 6k in size.

Using the avatar script is pretty easy, you direct the image source URL to the server where you install the script (or you can just use the one here)

html
<img src="http://www.sanity-free.org/bf2rank/?pid=45647367">

bbCode
[img]http://www.sanity-free.org/bf2rank/?nick=[OinK]_MadHatter[/img]

most bulletin board systems have places for you to link in a remote avatar, and one would add this same url w/ a name just as you would a normal image.

One annoying thing about most bbcode systems is that they require a valid image extension (.png, .jpg, .gif … ) on the URL inside the [img][/img] blocks (otherwise it just shows text inside the img blocks). To get your rank image to show up if you’re having troubles is to simply add an &avatar.jpg to the end of the URL. The PHP code will ignore it, and the forum will think its a valid image and will show it correctly.

The resulting image looks like this:
rank image

You can also specify a couple of options.

  • adding &score will display your global score at the top of the image.
  • adding &no_text to the end of the URL will keep the text from being written on the image.
  • adding &delta to the end will show the difference in your progress between your last rank and your next one.
  • you can also combine any combination of them as well (this one is using &delta, &no_text, and &score options).

EDIT Feb. 15 2006: since the last patch, I haven’t updated this article source code. HERE’S the most recent version of the script. you can download the package and copy that over the script provided.

EDIT March 20 2006: I updated the code to include nick name resolution (using searchforplayers.aspx). the link to the code above has that change in it. so you can use your player nick again instead of trying to find out your player ID.

EDIT June 30 2006: I removed the source code from the article and repacked the download with everything you need.

EDIT July 18 2006: I’ve added easy URLs for the rank avatars. for more info on that–and if you’d like to add them to your server–take a look at the thread in the forums here. (forums no longer part of the site)

Here’s the code for the script. Edit: this for entertainment purposes only since nothing about this game exists anymore 😭.

Download source and resources here.