mikeobrien.net Curriculum Vitae Blog Labs
Tuesday, February 02, 2010

I’m currently working on an F# library that will be accessed from C#. When doing this the obvious question is; “How will this look from C#?” This wasn't quite clear to me at first so I’ll go through a couple custom F# types and show how they are compiled.

Record type, Fermion.fs:

type Spin = 
    | Up = 0
    | Down = 1

type Class = 
    | Quark = 0
    | Lepton = 1

type Type = 
    ...
    | Electron = 6
    ...
type Fermion = 
    { spin: Spin; particleClass: Class; particleType: Type }
    member yada.Spin = yada.spin
    member v.Class = v.particleClass
    member v.Type = v.particleType
    member stuff.GetDescription() = 
        System.String.Format(
            "This {0} is a spin {1} {2}.", 
            stuff.particleType.ToString(), 
            stuff.spin.ToString(), 
            stuff.particleClass.ToString())

Using the record type in F#

let electron = { 
    spin = Spin.Down; 
    particleClass = Class.Lepton; 
    particleType = Type.Electron }

In Reflector:

public static class Fermion
{
    public sealed class Fermion : 
        IStructuralEquatable, 
        IComparable, 
        IStructuralComparable
    {
        internal Particles.Class particleClass@;
        internal Particles.Type particleType@;
        internal Particles.Spin spin@;

        public Fermion(
            Particles.Spin spin, 
            Particles.Class particleClass, 
            Particles.Type particleType)
        {
            this.spin@ = spin;
            this.particleClass@ = particleClass;
            this.particleType@ = particleType;
        }

        public string GetDescription()
        {
            return string.Format("This {0} is a spin {1} {2}.",
                this.particleType@.ToString(), 
                this.spin@.ToString(), 
                this.particleClass@.ToString());
        }

        public Particles.Class Class { get { return this.particleClass@; } }
        public Particles.Class particleClass { get { return this.particleClass@; } }
        public Particles.Type particleType { get { return this.particleType@; } }
        public Particles.Spin spin { get { return this.spin@; } }
        public Particles.Spin Spin { get { return this.spin@; } }
        public Particles.Type Type { get { return this.particleType@; } }

        public int CompareTo(Particles.Fermion obj);
        public sealed override int CompareTo(object obj);
        public sealed override int CompareTo(object obj, IComparer comp);
        public bool Equals(Particles.Fermion obj);
        public sealed override bool Equals(object obj);
        public sealed override bool Equals(object obj, IEqualityComparer comp);
        public override int GetHashCode();
        public sealed override int GetHashCode(IEqualityComparer comp);
    }
}

Some things to note:

  • This is a “record type” so a constructor is generated to set all the private fields. No initialization is performed other than this. So record types are essentially a DTO.
  • It is sealed.
  • When creating an instance of this type it it not necessary to explicitly specify it because of F# type inference.
  • The IComparable, IStructuralComparable and IStructuralEquatable interfaces are all automatically implemented by the F# compiler.
  • A namespace was not explicitly defined in the example so the type has no namespace and the type is nested in a static class with the name of the file it was declared in. If a namespace had been defined then this would not have been nested in a static class and would have simply resided under said namespace.
  • The identifiers (“v”, “yada”, “stuff”) which are equivalent to the “this” keyword in C# are all converted to "this" in the output. And as an aside they do not need to be the same throughout the type, just in the method or property declaration.
  • Fields are publicly exposed via a property that is named as you named the field in the F# source. The fields are suffixed with an “@”.
  • As an aside, enumerations must explicitly have a value defined or they will be compiled as discriminated unions.

Now lets mix things up a bit…

Constructed type, Fermion.fs:

namespace Particles

    type Spin = 
        | Up = 0
        | Down = 1

    type Class = 
        | Quark = 0
        | Lepton = 1

    type Type = 
        ...
        | Electron = 6
        ...
    type Fermion(spin: Spin, particleClass: Class, particleType: Type) = 
        let _description = System.String.Format(
                                "This {0} is a spin {1} {2}.", 
                                particleType.ToString(), 
                                spin.ToString(), 
                                particleClass.ToString())
        member yada.Spin = spin
        member v.Class = particleClass
        member v.Type = particleType
        member stuff.GetDescription() = _description

Using the constructed type in F#:

let electron = new Fermion(Spin.Down, Class.Lepton, Type.Electron)

In Reflector:

public class Fermion
{
    internal string _description;
    internal Class particleClass;
    internal Type particleType;
    internal Spin spin;

    public Fermion(Spin spin, Class particleClass, Type particleType)
    {
        this.spin = spin;
        this.particleClass = particleClass;
        this.particleType = particleType;
        this._description = string.Format("This {0} is a spin {1} {2}.", 
                    this.particleType.ToString(), 
                    this.spin.ToString(), 
                    this.particleClass.ToString());
    }

    public string GetDescription() { return this._description; }

    public Class Class {  get { return this.particleClass; } }
    public Spin Spin { get { return this.spin; } }
    public Type Type { get { return this.particleType; } }
}

Some things to note:

  • This is a “constructed type” so there is a constructor. You’re constructor code is simply put in the body of the type and not in a special function like C#.
  • Requires you to explicitly new up the type and pass the parameters in.
  • No interfaces get automatically implemented as in the case of the record type.
  • This class is not sealed.
  • This type was defined under a namespace so it is not wrapped in a static class.
C# | F#
Tuesday, February 02, 2010 6:16:27 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Monday, December 28, 2009

Today I had to write some code that had nullable parameters that could filter the results of a Linq query. At first I was doing “if” statements on the nullable parameters to determine if they needed to be applied. This was pretty verbose so I came up with a more succinct approach with conditional Linq extension methods.

First define conditional extension methods on IQueryable<>:

public static class IQueryableExtensions
{
    public static IQueryable<T> Where<T>(this IQueryable<T> query, bool condition, 
        System.Linq.Expressions.Expression<Func<T, bool>> predicate)
    {
        return condition ? query.Where(predicate) : query;
    }

    public static IQueryable<T> Take<T>(this IQueryable<T> query, bool condition, int count)
    {
        return condition ? query.Take(count) : query;
    }

    public static IQueryable<T> Skip<T>(this IQueryable<T> query, bool condition, int count)
    {
        return condition ? query.Skip(count) : query;
    }

    // ...
}

Then you get a nice fluent way to conditionally apply the parameters:

public List<Template> EnumerateTemplates(
    Guid accountId,
    int? startIndex,
    int? maxResults,
    Guid? groupId,
    bool? includeSubGroups,
    DateTime? olderThan,
    DateTime? newerThan)
{
    using (IRepository<Template> templates = Context.Current.Create<IRepository<Template>>())
    {
        var selectedTemplates = templates.
            Where(t => t.Account.Id == accountId).
            Where(groupId.HasValue, t => t.Group.Id == groupId.Value).
            Where(!groupId.HasValue && includeSubGroups.HasValue && 
                  !includeSubGroups.Value, t => t.Group == null).
            Where(olderThan.HasValue, t => t.Created < olderThan.Value).
            Where(newerThan.HasValue, t => t.Created > newerThan.Value).
            Take(maxResults.HasValue, maxResults.Value).
            Skip(startIndex.HasValue, startIndex.Value - 1);

        return selectedTemplates.ToList();
    }
}
C# | Linq | NHibernate
Monday, December 28, 2009 9:34:05 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Saturday, November 14, 2009

I had a crazy situation where I couldn't modify an installation of SQL server nor could I uninstall it. So I did the dirty work of manually uninstalling it so that I could reinstall it with the components I needed. But when I did the reinstall the installer errored out! Turns out that for some reason about 1,300 registry keys related to the SQL server install had their security info wiped out (No owner, no permissions). I tried using subinacl to reset the owner and permissions but it appears that it cant understand 32 and 64 bit registry views so it could not even see the keys I needed altered. Manually fixing this was out of the question so I came up with some code to do it. Actually I didn't really come up with anything; a bunch of other people who are much smarter than me did and I just pieced together what they did... :) Also, I realize that it is probably possible to do this with the new API’s that were introduced with .NET 2.0 but I couldn't seem to figure out how to do it with registry keys and I didn’t have the time to dig into it further. So if you have the time to check those out you may be able to find a managed solution. Keith Brown has an excellent book which goes deeply into Windows security and the .NET API’s, I highly recommend it.

Here is an example of using the code to modify the permissions of a registry key. Note that for the local machine hive its not prefixed with “HKEY_LOCAL_MACHINE” but just “MACHINE”:

Security.GrantAdministratorsAccess(
    @"MACHINE\SOFTWARE\Microsoft\Windows\...\E53B08216D22271418A3F85F6654D6EE",
    Security.SE_OBJECT_TYPE.SE_REGISTRY_KEY);

Here is the method to make the administrators group the owner and give it permissions:

public static void GrantAdministratorsAccess(string name, SE_OBJECT_TYPE type)
{
    SID_IDENTIFIER_AUTHORITY sidNTAuthority = SECURITY_NT_AUTHORITY;

    // Create a SID for the BUILTIN\Administrators group.
    IntPtr sidAdmin = IntPtr.Zero;
    AllocateAndInitializeSid(ref sidNTAuthority, 2,
                             SECURITY_BUILTIN_DOMAIN_RID,
                             DOMAIN_ALIAS_RID_ADMINS,
                             0, 0, 0, 0, 0, 0,
                             ref sidAdmin);

    // Set full control for Administrators.
    EXPLICIT_ACCESS[] explicitAccesss = new EXPLICIT_ACCESS[1];
    explicitAccesss[0].grfAccessPermissions = ACCESS_MASK.GENERIC_ALL;
    explicitAccesss[0].grfAccessMode = ACCESS_MODE.SET_ACCESS;
    explicitAccesss[0].grfInheritance = NO_INHERITANCE;
    explicitAccesss[0].Trustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_SID;
    explicitAccesss[0].Trustee.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_GROUP;
    explicitAccesss[0].Trustee.ptstrName = sidAdmin;

    IntPtr acl = IntPtr.Zero;
    SetEntriesInAcl(1,
                    ref explicitAccesss[0],
                    0,
                    ref acl);

    Action<string, bool> setPrivilege = (privilege, allow) =>
    {
        IntPtr token = IntPtr.Zero;
        TOKEN_PRIVILEGES tokenPrivileges = new TOKEN_PRIVILEGES();
        OpenProcessToken(GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out token);

        if (allow)
        {
            LUID luid;
            LookupPrivilegeValueA(null, privilege, out luid);
            tokenPrivileges.PrivilegeCount = 1;
            tokenPrivileges.Privileges = new LUID_AND_ATTRIBUTES[1];
            tokenPrivileges.Privileges[0].Luid = luid;
            tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        }

        AdjustTokenPrivileges(token, false, ref tokenPrivileges, 0,
            IntPtr.Zero, IntPtr.Zero);
        CloseHandle(token);
    };

    // Enable the SE_TAKE_OWNERSHIP_NAME privilege.
    setPrivilege(SE_TAKE_OWNERSHIP_NAME, true);

    // Set the owner in the object's security descriptor.
    SetNamedSecurityInfo(
        name,
        type,
        SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION,
        sidAdmin,
        IntPtr.Zero,
        IntPtr.Zero,
        IntPtr.Zero);

    // Disable the SE_TAKE_OWNERSHIP_NAME privilege.
    setPrivilege(SE_TAKE_OWNERSHIP_NAME, false);

    // Modify the object's DACL,
    SetNamedSecurityInfo(
        name,
        type,
        SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
        IntPtr.Zero, IntPtr.Zero,
        acl,
        IntPtr.Zero);

    FreeSid(sidAdmin);
    LocalFree(acl);
}

Here are the native methods and constants:

[StructLayoutAttribute(LayoutKind.Sequential)]
private struct SID_IDENTIFIER_AUTHORITY
{
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
    public byte[] Value;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
private struct TRUSTEE
{
    public System.IntPtr pMultipleTrustee;
    public MULTIPLE_TRUSTEE_OPERATION MultipleTrusteeOperation;
    public TRUSTEE_FORM TrusteeForm;
    public TRUSTEE_TYPE TrusteeType;
    public IntPtr ptstrName;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
private struct EXPLICIT_ACCESS
{
    public ACCESS_MASK grfAccessPermissions;
    public ACCESS_MODE grfAccessMode;
    public uint grfInheritance;
    public TRUSTEE Trustee;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
private struct TOKEN_PRIVILEGES
{
    public uint PrivilegeCount;
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.Struct)]
    public LUID_AND_ATTRIBUTES[] Privileges;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
private struct LUID_AND_ATTRIBUTES
{
    public LUID Luid;
    public uint Attributes;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
private struct LUID
{
    public uint LowPart;
    public int HighPart;
}

private enum TRUSTEE_TYPE
{
    TRUSTEE_IS_GROUP,
}

private enum TRUSTEE_FORM
{
    TRUSTEE_IS_SID,
}

private enum MULTIPLE_TRUSTEE_OPERATION { }

public enum SE_OBJECT_TYPE
{
    SE_UNKNOWN_OBJECT_TYPE = 0,
    SE_FILE_OBJECT,
    SE_SERVICE,
    SE_PRINTER,
    SE_REGISTRY_KEY,
    SE_LMSHARE,
    SE_KERNEL_OBJECT,
    SE_WINDOW_OBJECT,
    SE_DS_OBJECT,
    SE_DS_OBJECT_ALL,
    SE_PROVIDER_DEFINED_OBJECT,
    SE_WMIGUID_OBJECT,
    SE_REGISTRY_WOW64_32KEY
}

[Flags]
private enum ACCESS_MASK : uint
{
    GENERIC_ALL = 0x10000000,
}

[Flags]
private enum SECURITY_INFORMATION : uint
{
    OWNER_SECURITY_INFORMATION = 0x00000001,
    DACL_SECURITY_INFORMATION = 0x00000004,
}

private enum ACCESS_MODE
{
    SET_ACCESS
}

private const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
private static SID_IDENTIFIER_AUTHORITY SECURITY_NT_AUTHORITY =
    new SID_IDENTIFIER_AUTHORITY() { Value = new byte[] { 0, 0, 0, 0, 0, 5 } };

private const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
private const int NO_INHERITANCE = 0x0;
private const int SECURITY_BUILTIN_DOMAIN_RID = 0x00000020;
private const int DOMAIN_ALIAS_RID_ADMINS = 0x00000220;
private const int TOKEN_QUERY = 8;
private const int SE_PRIVILEGE_ENABLED = 2;

[DllImportAttribute("advapi32.dll", EntryPoint = "OpenProcessToken")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern bool OpenProcessToken(
    [InAttribute] 
    IntPtr ProcessHandle,
    uint DesiredAccess,
    out IntPtr TokenHandle);

[DllImportAttribute("advapi32.dll", EntryPoint = "AllocateAndInitializeSid")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern bool AllocateAndInitializeSid(
    [InAttribute] ref SID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
    byte nSubAuthorityCount,
    uint nSubAuthority0,
    uint nSubAuthority1,
    uint nSubAuthority2,
    uint nSubAuthority3,
    uint nSubAuthority4,
    uint nSubAuthority5,
    uint nSubAuthority6,
    uint nSubAuthority7,
    ref IntPtr pSid);

[DllImportAttribute("kernel32.dll", EntryPoint = "CloseHandle")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern bool CloseHandle([InAttribute] IntPtr hObject);

[DllImportAttribute("kernel32.dll", EntryPoint = "GetCurrentProcess")]
private static extern IntPtr GetCurrentProcess();

[DllImportAttribute("advapi32.dll", EntryPoint = "FreeSid")]
private static extern IntPtr FreeSid([InAttribute] IntPtr pSid);

[DllImportAttribute("kernel32.dll", EntryPoint = "LocalFree")]
private static extern IntPtr LocalFree(IntPtr hMem);

[DllImportAttribute("advapi32.dll", EntryPoint = "LookupPrivilegeValueA")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern bool LookupPrivilegeValueA(
    [InAttribute] 
    [MarshalAsAttribute(UnmanagedType.LPStr)] 
    string lpSystemName,
    [InAttribute] 
    [MarshalAsAttribute(UnmanagedType.LPStr)] 
    string lpName,
    [OutAttribute] 
    out LUID lpLuid);

[DllImportAttribute("advapi32.dll", EntryPoint = "AdjustTokenPrivileges")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern bool AdjustTokenPrivileges(
    [InAttribute()] 
    IntPtr TokenHandle,
    [MarshalAsAttribute(UnmanagedType.Bool)] 
    bool DisableAllPrivileges,
    [InAttribute()] 
    ref TOKEN_PRIVILEGES NewState,
    uint BufferLength,
    IntPtr PreviousState,
    IntPtr ReturnLength);

[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
private static extern int SetNamedSecurityInfo(
    string pObjectName,
    SE_OBJECT_TYPE ObjectType,
    SECURITY_INFORMATION SecurityInfo,
    IntPtr psidOwner,
    IntPtr psidGroup,
    IntPtr pDacl,
    IntPtr pSacl);

[DllImport("Advapi32.dll", EntryPoint = "SetEntriesInAclA",
 CallingConvention = CallingConvention.Winapi,
 SetLastError = true, CharSet = CharSet.Ansi)]
private static extern uint SetEntriesInAcl(
    int CountofExplicitEntries,
    ref EXPLICIT_ACCESS ea,
    uint OldAcl,
    ref IntPtr NewAcl);
.NET | C# | PInvoke | Security | Win32 API
Saturday, November 14, 2009 2:36:46 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Wednesday, October 21, 2009

I just changed the domain of my site and I wanted to create a page notifying that the site has moved and then auto redirect them after a few seconds. Here’s how I did it:

1) I’m using IIS 7.5 so I opted to use the IIS7 RewriteModule. I simply ran the installer and the applet appears under the site options.

2) I created a catch all site in IIS and bound it to all the old public domains:

image

3) Then created a UrlRewrite Rule to rewrite all requests to /Default.aspx (Except ones specifically to /Default.aspx):

image

4) Next created the redirection page (Stripped down for clarity):

<%@ Page Language="C#" %>
<%
string redirectUrl = string.Format("{0}://{1}{2}{3}", 
    Request.Url.Scheme,
    Request.Url.Host.Replace("mikeobrien.net", "mikeobrien.net"),  
    (Request.Url.Port != 80 ? ":" + Request.Url.Port : string.Empty), 
    Request.Headers["X-Original-URL"]);
%>
<html>
<head>
    <title>We've Moved</title>
    <script language="javascript">
        function RedirectPage(url, seconds)
        {
            self.setTimeout('self.location.href = \'' + url + '\';', seconds * 1000);
        }

        function CountDown(seconds, elementId)
        {
            if (seconds == 0) return;
            document.getElementById(elementId).innerHTML = seconds;
            self.setTimeout('CountDown(' + (seconds - 1) + ', \'' + elementId + '\');', 1000);
        }
    </script>
</head>
<body onLoad="RedirectPage('<% = redirectUrl %>', 5);CountDown(5, 'timeLeft');">
    <h3>We've moved!</h3>

    <p>
    The page you requested can now be found <a href="<% = redirectUrl %>">here</a>. 
    You will be redirected in <span id="timeLeft">5</span> seconds.
    </p>
</body>
</html>

5) And voila!

image

C# | IIS 7 | IIS7.5 | JavaScript
Wednesday, October 21, 2009 1:23:22 AM (GMT Daylight Time, UTC+01:00)  #   |  Comments [1]  |  Trackback
Saturday, October 10, 2009

We have a number of Windows Services in our infrastructure, all of which have a frequency in their configuration. Originally this frequency was in milliseconds but this is a real pain since when you set or read the configuration you are always doing the math between milliseconds and hours/minutes/seconds. Then is occurred that we could probably use a TimeSpan in the configuration to represent frequency instead of an integer of milliseconds. The .NET configuration API has a built in converter for the TimeSpan class so all you have to do is set the configuration property type to TimeSpan and your good to go!

Here is the configuration class:

public class Section : ConfigurationSection
{
    private const string FREQUENCY = "frequency";

    [ConfigurationProperty(FREQUENCY)]
    public TimeSpan Frequency
    {
        get { return (TimeSpan)this[FREQUENCY]; }
    }
}

Here is the configuration, much easier to read/set:

<company>
  <services>
    <someService frequency="00:00:30"/>
  </services>
</company>

And the usage:

private Common.Timers.Timer _processTimer =
        new Common.Timers.Timer(
            Configuration.Manager.Current.SomeService.Frequency.TotalMilliseconds,
            Common.Timers.Timer.TimerElapseStartMode.Immediate,
            Common.Timers.Timer.TimerElapseReentranceMode.NonReentrant);
Saturday, October 10, 2009 3:33:27 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Thursday, October 08, 2009

I needed a timer that I could set to elapse immediately when it was enabled (Instead of waiting for the first elapse event) and also not be reentrant on the elapsed event. I couldn’t seem to find anything out there so I rolled my own. Unfortunately the System.Timers.Timer doesn't offer a lot in the way of extension so I ended up just using composition over inheritance. Here is a quick test:

static Timer _timer = 
    new Timer(5000, 
        Timer.TimerElapseStartMode.Immediate,
        Timer.TimerElapseReentranceMode.NonReentrant);

static void Main(string[] args)
{
    Console.WriteLine(
        "Started @ {0}\r\n-----------------------------", DateTime.Now);

    _timer.Elapsed += _timer_Elapsed;
    _timer.Start();

    Application.Run();
}

static void _timer_Elapsed(object sender, Timer.ElapsedEventArgs e)
{
    Console.WriteLine("Elapsed @ {0}", e.SignalTime);
    Thread.Sleep(10000);
}

Here is the implementation:

public class Timer
{
    // ────────────────────────── Enumerations ──────────────────────────

    public enum TimerElapseStartMode
    {
        Immediate,
        AfterInterval
    }

    public enum TimerElapseReentranceMode
    {
        Reentrant,
        NonReentrant
    }

    // ────────────────────────── Events ──────────────────────────

    public delegate void ElapsedEventHandler(object sender, ElapsedEventArgs e);
    public event ElapsedEventHandler Elapsed;

    // ────────────────────────── Private Fields ──────────────────────────

    private System.Timers.Timer _timer = new System.Timers.Timer();
    private int _executing;

    // ────────────────────────── Constructor ──────────────────────────

    public Timer(double interval) : 
        this(
            interval,
            TimerElapseStartMode.AfterInterval, 
            TimerElapseReentranceMode.Reentrant) { }

    public Timer(
        double interval,
        TimerElapseStartMode startMode, 
        TimerElapseReentranceMode reentranceMode)
    {
        _timer = new System.Timers.Timer(interval);
        _timer.Elapsed += OnElapsed;
        ElapseStartMode = startMode;
        ElapseReentranceMode = reentranceMode;
    }

    // ────────────────────────── Public Members ──────────────────────────

    public bool AutoReset
    {
        get { return _timer.AutoReset; }
        set { _timer.AutoReset = value; }
    }

    public bool Enabled
    {
        get { return _timer.Enabled; }
        set { _timer.Enabled = value; }
    }

    public double Interval
    {
        get { return _timer.Interval; }
        set { _timer.Interval = value; }
    }

    public TimerElapseStartMode ElapseStartMode { get; set; }
    public TimerElapseReentranceMode ElapseReentranceMode { get; set; }

    public void Start()
    {
        if (ElapseStartMode == TimerElapseStartMode.Immediate)
            ThreadPool.QueueUserWorkItem(
                state => Elapse(new ElapsedEventArgs()));
        Enabled = true;
    }

    public void BeginInit() { _timer.BeginInit(); }
    public void Close() { _timer.Close(); }
    public void EndInit() { _timer.EndInit(); }
    public void Stop() { Enabled = false; }

    // ────────────────────────── Private Members ──────────────────────────

    private void OnElapsed(object sender, System.Timers.ElapsedEventArgs e)
    { Elapse(new ElapsedEventArgs(e)); }

    private void Elapse(ElapsedEventArgs args)
    {
        if (ElapseReentranceMode == TimerElapseReentranceMode.NonReentrant &&
            Interlocked.CompareExchange(ref _executing, 1, 0) == 1) return;

        if (Elapsed != null) Elapsed(this, args);

        _executing = 0;
    }

    // ────────────────────────── Nested Types ──────────────────────────

    public class ElapsedEventArgs : EventArgs
    {
        private DateTime _signalTime;

        public ElapsedEventArgs() { _signalTime = DateTime.Now; }

        public ElapsedEventArgs(System.Timers.ElapsedEventArgs args)
        { _signalTime = args.SignalTime; }

        public DateTime SignalTime { get { return _signalTime; } }
    }
}
C#
Thursday, October 08, 2009 10:39:44 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Thursday, April 02, 2009

Today I wanted to setup a debugging page to read the trace log for our prototype WCF services and display the last 10 messages that have come across the wire. I'm using the XmlWriterTraceListener to write the entries. The XmlWriterTraceListener writes Xml fragments to the log file.  This is good and all but the problem is reading in the log. Since a well formed xml file can only have one root element the log cant be successfully parsed (As far as I could tell anyway's, if anyone knows of another way please let me know). So the only decent solution I could come up with was to create a reader that injects a root element.  The usage is simple, just pass in a stream or stream reader and the name of the root element:

XDocument log = XDocument.Load(
    new XmlFragmentTextReader(
        new FileStream(
            @"D:\Logs\Wcf.log", 
            FileMode.Open, 
            FileAccess.Read, 
            FileShare.ReadWrite), 
         "root"));

var entries = from entry in log.Element("root")
                  .Elements(
                    XName.Get(
                    "E2ETraceEvent", 
                    "http://schemas.microsoft.com/2004/06/E2ETraceEvent"))
              select entry;

foreach (XElement entry in entries)
{
    // Do Something...
}

Here is the implementation. Since the read/peek methods in the readers in the BCL are not virtual I'm forced to choose aggregation over inheritance. Only the Read and Peek methods need to be implemented as all other methods call these in the base TextReader class.

public class XmlFragmentTextReader : TextReader
{
    #region Private Members

        private enum Location
        { RootOpen, Fragments, RootClose }

        private StreamReader _fragmentReader;
        private Location _location = Location.RootOpen;
        private int _index = 0;
        private char[] _rootOpenBuffer;
        private char[] _rootCloseBuffer;

    #endregion

    #region Constructors

        public XmlFragmentTextReader(StreamReader reader, 
            string rootElementName) : base()
        {
            _fragmentReader = reader;
            _rootOpenBuffer = string.Format("<{0}>\r\n", 
                rootElementName).ToCharArray();
            _rootCloseBuffer = string.Format("\r\n</{0}>", 
                rootElementName).ToCharArray();
        }

        public XmlFragmentTextReader(Stream stream, 
            string rootElementName) : 
            this(new StreamReader(stream), rootElementName) { }

    #endregion

    #region Overridden Methods

        public override int Peek()
        {
            switch (_location)
            {
                case Location.RootOpen:
                    return _rootOpenBuffer[_index];
                case Location.Fragments:
                    return _fragmentReader.Peek();
                case Location.RootClose:
                    return _rootCloseBuffer[_index];
                default : return - 1;
            }
        }

        public override int Read()
        {
            switch (_location)
            {
                case Location.RootOpen:
                    if (_index < _rootOpenBuffer.Length)
                        return _rootOpenBuffer[_index++];
                    else
                    {
                        _location = Location.Fragments;
                        return Read();
                    }
                case Location.Fragments:
                    if (!_fragmentReader.EndOfStream)
                        return _fragmentReader.Read();
                    else
                    {
                        _location = Location.RootClose;
                        _index = 0;
                        return Read();
                    }
                case Location.RootClose:
                    if (_index < _rootCloseBuffer.Length)
                        return _rootCloseBuffer[_index++];
                    else return -1;
                default: return -1;
            }
        }

        public override void Close()
        { _fragmentReader.Close(); }

    #endregion
}

Like I said, if anyone knows of a better way please drop me a line!

.NET 3.5 | C# | Logging | XML/XSL
Thursday, April 02, 2009 11:47:17 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Wednesday, February 18, 2009

The DateTime.ParseExact() method has come in handy on a number of occasions. I really wish there was something similar for strings as sometimes you need to grab specific components of a string. You can use regex directly but that seems a little cumbersome. So here is an extension method that works like the DateTime.ParseExact() but returns an array of strings.

string value = "2/17/2009 10:57:42 AM...Executing file 26 of 81 files";
string[] parts = value.ParseExact("{0}...Executing file {1} of {2} files");
foreach (string part in parts)
    Console.WriteLine(part);
Console.ReadKey();
image 

Implementation:

public static class StringExtensions
{
    public static string[] ParseExact(
        this string data, 
        string format)
    {
        return ParseExact(data, format, false);
    }

    public static string[] ParseExact(
        this string data, 
        string format, 
        bool ignoreCase)
    {
        string[] values;

        if (TryParseExact(data, format, out values, ignoreCase))
            return values;
        else
            throw new ArgumentException("Format not compatible with value.");
    }

    public static bool TryExtract(
        this string data, 
        string format, 
        out string[] values)
    {
        return TryParseExact(data, format, out values, false);
    }

    public static bool TryParseExact(
        this string data, 
        string format, 
        out string[] values, 
        bool ignoreCase)
    {
        int tokenCount = 0;
        format = Regex.Escape(format).Replace("\\{", "{");

        for (tokenCount = 0; ; tokenCount++)
        {
            string token = string.Format("{{{0}}}", tokenCount);
            if (!format.Contains(token)) break;
            format = format.Replace(token,
                string.Format("(?'group{0}'.*)", tokenCount));
        }

        RegexOptions options = 
            ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;

        Match match = new Regex(format, options).Match(data);

        if (tokenCount != (match.Groups.Count - 1))
        {
            values = new string[] { };
            return false;
        }
        else
        {
            values = new string[tokenCount];
            for (int index = 0; index < tokenCount; index++)
                values[index] = 
                    match.Groups[string.Format("group{0}", index)].Value;
            return true;
        }
    }
}
.NET | C#
Wednesday, February 18, 2009 7:11:40 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Monday, January 19, 2009

The WindowsIdentity class offers a constructor that accepts a user principal name (username@domain.int) and doesn't require the password. This sounds like a great way to get a token for impersonation but there are some limitations. First of all the account must be an AD account and...

  1. To use it on the network you must use constrained delegation to grant permission to the source server to generate tokens (And mark restricted accounts as not authorized for delegation) and also which target servers can be accessed with the token generated.
  2. To use it locally to access secured resources (Like files, etc) the process needs to have the trusted computing base priviledge which is root access to the box.

Keith Brown covers this here in detail. Unfortunately if you need to impersonate a LSA account or you cant/dont want to use constrained delegation you have to use the LogonUser API call to get a token to pass to the WindowsIdentity constructor. This call requires the domain, username and password. The WindowsIdentity class doesent offer a constructor that does this so you have to roll your own. Below is a simple class I whipped up that will do this.

Interesting aside, the SafeUserTokenHandle class is actually defined in the FCL but marked internal. There are actually a number of SafeHandle derived classes in System.dll (Under the Microsoft.Win32.SafeHandles namespace). So if you need a SafeHandle for a handle for a particular API call you may be able to snag one here for "free" with Reflector.

Some further reading on this subject; MSDN - How To: Use Impersonation and Delegation in ASP.NET 2.0, The .NET Developer's Guide to Windows Security (Or free online here!) and Professional ASP.NET 3.5 Security, Membership, and Role Management with C# and VB.

Here is the usage:

using (WindowsImpersonationContext context = 
        Impersonation.Impersonate("domain", "username", P@$$w0rd, LogonSessionType.Network))
{
    //Do something...
}

Here is the class:

using System;
using System.ComponentModel;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
using Microsoft.Win32.SafeHandles;

public static class Impersonation
{
    #region Public Methods

        public static WindowsImpersonationContext Impersonate(
            string domain, string username, string password, LogonSessionType sessionType)
        {
            WindowsImpersonationContext impersonationContext = null;
            SafeUserTokenHandle token;

            if (LogonUser(
               username,
               domain,
               password,
               sessionType,
               LogonProvider.Default,
               out token))
            {
                using (token)
                {
                    impersonationContext = WindowsIdentity.Impersonate(
                        token.DangerousGetHandle());
                }
            }
            else
                throw new Win32Exception(Marshal.GetLastWin32Error());

            return impersonationContext;
        }

    #endregion

    #region Native Methods

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(
          string principal,
          string authority,
          string password,
          LogonSessionType logonType,
          LogonProvider logonProvider,
          out SafeUserTokenHandle token);

        public enum LogonSessionType : uint
        {
            Interactive = 2,
            Network,
            Batch,
            Service,
            NetworkCleartext = 8,
            NewCredentials
        }

        private enum LogonProvider : uint
        {
            Default = 0, // default for platform (use this!)
            WinNT35,     // sends smoke signals to authority
            WinNT40,     // uses NTLM
            WinNT50      // negotiates Kerb or NTLM
        }

    #endregion

    #region SafeTokenHandle Class

        [SuppressUnmanagedCodeSecurity, 
         HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort=true)]
        private sealed class SafeUserTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            internal SafeUserTokenHandle() : base(true) { }

            internal SafeUserTokenHandle(IntPtr existingHandle, bool ownsHandle) : 
                base(ownsHandle)
            {
                base.SetHandle(existingHandle);
            }

            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), 
             DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
            private static extern bool CloseHandle(IntPtr handle);

            protected override bool ReleaseHandle()
            {
                return CloseHandle(base.handle);
            }
        }

    #endregion
}
.NET 3.5 | C#
Monday, January 19, 2009 3:28:11 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Friday, January 02, 2009

While reading CLR via C# I picked up a couple of interesting tidbits about the using block that I never realized. First you can declare/instantiate multiple objects as long as they are of the same type and second you can pass in objects that have been declared outside the block. Not sure how useful these would be but interesting none the less. I think more useful would be allowing the developer to declare/instantiate multiple objects of different types.

class Program
{
    static void Main(string[] args)
    {
        Stuff stuff = new Stuff();

        using (
            Stuff stuff1 = new Stuff(),
            stuff2 = new Stuff(),
            stuff3 = stuff)
        {
        }
    }
}

class Stuff : IDisposable
{
    #region IDisposable Members

        public void Dispose() { }

    #endregion
}
.NET | .NET 3.5 | C#
Friday, January 02, 2009 10:23:04 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [1]  |  Trackback
Tuesday, November 18, 2008

One thing I really love about Linq is how succinctly you can write import and export code. I've had to do this many times before Linq and it always felt kludgy no matter how clean you did it (Especially building xml documents). I think the decision to bake a set based syntax into C# and VB.NET was a great idea. So here is yet another Linq code sample, aren't there already a million of them out there??

Exporting data from a SQL Server table to xml using Linq2Sql and Link2Xml:

TestDataContext dataContext =
    new TestDataContext(@"Data Source=localhost;
        Initial Catalog=Test;Integrated Security=True");

XDocument export = new XDocument(
    new XElement(
        "clients",
            new XComment("This is a comment!"),
            from client in dataContext.Clients
            orderby client.State, client.City 
            select new XElement(
                "client",
                    new XAttribute("id", client.Id.ToString()),
                    new XElement("name", new XText(client.Name)),
                    new XElement("address", new XText(client.Address)),
                    new XElement("address2", new XText(client.Address2)),
                    new XElement("city", new XText(client.City)),
                    new XElement("state", new XText(client.State)),
                    new XElement("zip", new XText(client.Zip)),
                    new XElement("comments", new XCData(
                        string.Format("{0} is based out of {1}.", 
                        client.Name, client.State)))
                )
            )
        );
export.Save(@"D:\Temp\Clients.xml");

Importing data from an xml document to a SQL Server table using Linq2Xml and Linq2Sql (And as Anon pointed out we can do a direct cast since the XAttribute (And XElement) class define explicit conversion operators for primitive types. On that note we also dont need to check if the XElement or XAttribute is null. The Linq2Sql entity defines fields (Or properties) as nullable types and the XElement and XAttribute classes define conversion operators for nullable primitive types. So if an attribute or element does not exist the entity value is simply set to null.):

TestDataContext dataContext =
    new TestDataContext(@"Data Source=localhost;
        Initial Catalog=Test;Integrated Security=True");

XDocument document = XDocument.Load(@"D:\Temp\Clients.xml");

var clients = from client in document.Element("clients").Elements("client")
    select new Client()
    {
        Id = (int)client.Attribute("id"),
        Name = (string)client.Element("name"),
        Address = (string)client.Element("address"),
        Address2 = (string)client.Element("address2"),
        City = (string)client.Element("city"),
        State = (string)client.Element("state"),
        Zip = (string)client.Element("zip")
    };

foreach (var client in clients)
    dataContext.Clients.InsertOnSubmit(client);

dataContext.SubmitChanges();
Tuesday, November 18, 2008 2:10:56 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [2]  |  Trackback
Saturday, July 26, 2008

I'm working on a media center application right now that I want to run kiosk style; topmost and fullscreen. This is amazingly simple to do in WPF, simply set the Topmost property to true, the WindowState property to Maximized and the WindowStyle to None.

.NET | .NET 3.5 | C# | WPF
Saturday, July 26, 2008 1:21:30 AM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Thursday, June 19, 2008

I never realized this but you can set the default SMTP information in the .config file (Thanks Viktar!). This applies to the new System.Net.Mail.* classes (Not the deprecated System.Web.Mail.* classes). MSDN defines the elements here and here.

<configuration>
  <system.net>
    <mailSettings>
      <smtp deliveryMethod="network" 
         from="appointments@TrepanationNation.com"> <network host="smtp.TrepanationNation.com"
         port="25" defaultCredentials="true"/> </smtp> </mailSettings> </system.net>

The code is the same but you no longer have to specify the from and SMTP server details:

using (MailMessage message = new MailMessage())
{
    message.IsBodyHtml = true;
    message.To.Add("someguy@someserver.com");
    message.Subject = "Trepanation Appointment";
    message.Body = @"<b>This confirms your 
        Trepanation appointment this Friday.</b>";
    SmtpClient mailClient = new SmtpClient();
    mailClient.Send(message);
}
.NET 2.0 | C# | SMTP
Thursday, June 19, 2008 3:56:35 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Wednesday, May 21, 2008

Reachmail (the company I work for) is looking for a senior ASP.NET/C# developer. If you are a progressive developer who is a true geek, really understands OO and patterns and is looking for a change, browse to the link below to apply. We are currently located in Naperville but will be moving to downtown Chicago the 1st of July (Within walking distance of Union and Ogilvie). We really need someone who knows their stuff and doesn't require hand holding. Although we need someone who is able to work independently we don't want an independent person (IE "cowboy"); they must be a team player or they wont last long. We have a relaxed environment and a lot of growth.

The software is a permission based email marketing SAAS written primarily in classic ASP with a SQL Server 2005 back end. Parts of the system are written in VB.NET and C#. One of our goals is to get the application converted over to ASP.NET/C# and rearchitect much of the system. All of our existing .NET code has been upgraded to 3.5 and new development is obviously in 3.5 and C#.

 

.NET | C#
Wednesday, May 21, 2008 4:42:58 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Tuesday, May 06, 2008

Parsing a date with a custom format is as easy as pie with the DateTime.ParseExact method, check it:

DateTime.ParseExact("04292008", "MMddyyyy", null)

Where the first parameter is the value to parse, the second is a format string and for the culture info you can pass null for the current culture (Unless you need to specify one).

UPDATE:

If you need to exclude other characters in the string you can add the literal values qualified by single quotes in the format string. So for example lets say you wanted to extract the date and hour from an IIS log filename, ex08041013.log. You could pass the format string 'ex'yyMMddHH'.log' and the parse method will ignore the ex and .log portions of the string.

DateTime.ParseExact("ex08041013.log", "'ex'yyMMddHH'.log'", null)
C#
Tuesday, May 06, 2008 9:46:21 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Monday, February 11, 2008

I cant believe I wasn't aware of this cool little feature but with the release of C# 2.0 came the yield keyword. Basically it allows you to create an enumerator that "yields" when it has the current value ready. It's much simpler and elegant than enumerator code you would normally have to write. As an example we will create an enumerable class that returns numbers in the Fibonacci sequence.

public class FibonacciSeries : IEnumerable
{
    int size;

    internal FibonacciSeries(int size)
    { this.size = size; }

    public IEnumerator GetEnumerator()
    {
        int termA = -1;
        int termB = 1;

        for (int index = 0; index < size; index++)
        {
            int current = termA + termB;
            termA = termB;
            termB = current;
            yield return current;
        }
    }
}

Instead of creating a separate class that implements IEnumerable and keeps track of iterator state, we simply put our enumerator code in the GetEnumerator() method and call yield return ...; when we have a value ready. This allows the iterator to be written as if we were pushing the value out, much cleaner and simpler. Behind the scenes, when our code is compiled, the compiler builds what we would have normally had to write . Below is the compiled version of the above code in Reflector (Albeit cleaned it up a bit):

public class FibonacciSeries : IEnumerable
{
    private int size;

    internal FibonacciSeries(int size)
    {
        this.size = size;
    }

    public IEnumerator GetEnumerator()
    {
        Enumerator enumerator = new Enumerator(0);
        enumerator.parent = this;
        return enumerator;
    }

    private sealed class Enumerator : IEnumerator<object>, IEnumerator, IDisposable
    {
        private int state;
        private object current;
        public FibonacciSeries parent;
        public int currentValue;
        public int index;
        private int termA = -1;
        private int termB = 1;

        public Enumerator(int state)
        {
            this.state = state;
        }

        public bool MoveNext()
        {
            switch (this.state)
            {
                case 0:
                    this.index = 0;
                    break;

                case 1:
                    this.index++;
                    break;
            }

            this.state = -1;

            while (this.index < this.parent.size)
            {
                this.currentValue = this.termA + this.termB;
                this.termA = this.termB;
                this.termB = this.currentValue;
                this.current = this.currentValue;
                this.state = 1;
                return true;
            }

            return false;
        }

        void IEnumerator.Reset()
        { throw new NotSupportedException(); }

        void IDisposable.Dispose() { }

        object IEnumerator<object>.Current
        { get { return this.current; } }

        object IEnumerator.Current
        { get { return this.current; } }
    }
}
C#
Monday, February 11, 2008 1:43:21 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Monday, January 28, 2008

Mike Jones has posted an analysis of an adaptation of the Concurrent Life app (That ships with the F# distro) here. I haven't gotten through the entire article yet but so far it is great. The sample app has a C# interface and consumes an F# library. He suggests that C#'ers not familiar with functional programming use F# imperatively to get comfortable with the language syntax then tackle the functional style.

Also, I came across these articles by Thomas Petricek that are proving very helpfull:

  • F# Overview (I.) - Introduction
  • F# Overview (II.) - Functional Programming
  • F# Overview (III.) - Object Oriented and Imperative Programming
  • F# Overview (IV.) - Language Oriented Programming
  • And also a nice intro by The Flying Frog Consultancy...

    C# | F#
    Monday, January 28, 2008 4:38:04 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Tuesday, November 13, 2007

    I have gotten the following exception a couple of times:

    Service 'Translator' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.

    There are a number of things that could potentially cause this exception but the one that has gotten me a couple of times is making sure the name attribute of the service element in the .config contains the fully qualified class name. So for example if I have the following service:

    namespace BabelFish.ServiceHost.Web
    {
        public class Translator : BabelFish.Services.Translator
        {
        }
    }

    The service name should be as follows (in bold):

    <configuration>
        <
    system.serviceModel>
            <
    services>
                <
    service behaviorConfiguration="TranslatorBehavior" name="BabelFish.ServiceHost.Web.Translator">
                    <
    endpoint address="http://localhost/BabelFish.ServiceHost.Web/Translator.svc" binding="wsHttpBinding" name="Translator" contract="BabelFish.Services.Contracts.Service.ITranslator"/>
                   <
    endpoint address="mex" binding="mexHttpBinding" name="MetaDataExchange" contract="IMetadataExchange"/>
                </
    service>
            </
    services>
            ...
        </system.serviceModel>
        ...
    </configuration>
    Tuesday, November 13, 2007 4:36:39 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Tuesday, September 18, 2007

    Here is a simple method to invert an HTML color:

    private static string InvertHTMLColor(string htmlColor)

    {

    htmlColor = htmlColor.Replace("#", string.Empty).Trim();

    if (string.IsNullOrEmpty(htmlColor) || htmlColor.Length != 6)

         throw new ArgumentException("Invalid HTML color.");

    return string.Format("#{0}{1}{2}",

         InvertChannel(htmlColor.Substring(0, 2)),

         InvertChannel(htmlColor.Substring(2, 2)),

         InvertChannel(htmlColor.Substring(4, 2)));

    }

    private static string InvertChannel(string channel)

    {

    channel = channel.Trim();

    if (string.IsNullOrEmpty(channel) || channel.Length != 2)

         throw new ArgumentException("Invalid color channel.");

    int a = int.Parse(channel.Substring(0, 1), System.Globalization.NumberStyles.HexNumber);

    int b = int.Parse(channel.Substring(1, 1), System.Globalization.NumberStyles.HexNumber);

    return (255 - ((16 * a) + b)).ToString("X");

    }

    .NET | C#
    Tuesday, September 18, 2007 5:26:53 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [1]  |  Trackback
    Tuesday, August 21, 2007

    Attached is the source for a simple TCP proxy server. I whipped it up pretty quickly so it probably needs some refactoring if you plan to use it in production. The server class is loosely based on the Cassini implementation. You can set the listen port and forward host/port in the app config:

    <configuration>

        <appSettings>

            <add key="listenPort" value="443"/>

            <add key="forwardHost" value="wush.net"/>

            <add key="forwardPort" value="443"/>

        </appSettings>

    </configuration>

    image

    TCPProxy.zip (24.81 KB)
    Tuesday, August 21, 2007 6:42:09 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
    Friday, July 06, 2007

    Attached is a simple contact generator (And source) that creates random contact data in CSV format. The data generated, although random, is pretty realistic as address and phone numbers correspond correctly and other values are sampled from a realistic set of data. The data generated appears as follows:

    "Index","Id","FirstName","LastName","FullName","Username","Username2","Password","Email1","Email2","Phone1","Phone2","Fax1","Fax2","Address1","City1","State1","Zip1","Address2","City2","State2","Zip2"
    "1","{c0d4079c-50c7-4214-a094-b09d51b9d143}","Raven","Huddle","Raven Huddle","rhuddle","raven.huddle","13af04ae","raven.huddle@aol.com","raven.huddle@earthlink.net","(303) 998-8084","(718) 229-7963","(303) 998-5593","(718) 229-4928","84596 Brimm BLVD","Boulder","CO","80302","36863 Noakes LN","Flushing","NY","11364"
    "2","{74e80927-a654-4010-9020-7098452b4193}","Rhonda","Reitz","Rhonda Reitz","rreitz","rhonda.reitz","3282e152","rhonda.reitz@btinternet.com","rhonda.reitz@verizon.net","(907) 252-0297","(703) 242-6715","(907) 252-0163","(703) 242-9363","89079 Sterrett PL","Soldotna","AK","99669","41346 Mccauley HWY","Vienna","VA","22181"
    "3","{742a3ad4-e1e8-44ed-a6a0-1654981e0c9b}","Ruth","Mcnemar","Ruth Mcnemar","rmcnemar","ruth.mcnemar","16548a78","rmcnemar@aol.com","rmcnemar@verizon.net","(305) 541-2410","(704) 892-5466","(305) 541-4633","(704) 892-3899","93562 Bruno BLVD","Miami","FL","33129","45829 Meadowview HWY","Davidson","NC","28036"
    "4","{d72fb280-66cf-49a8-81bb-f5da4a096614}","Jimmy","Kizer","Jimmy Kizer","jkizer","jimmy.kizer","3528671c","jkizer@verizon.net","jimmy.kizer@earthlink.net","(704) 854-4523","(734) 797-4218","(704) 854-9102","(734) 797-8335","98044 Meadows HWY, Suite 370","Gastonia","NC","28054","50311 Pamona LN","Livonia","MI","48150"
    "5","{90409c90-c967-4b1f-b66c-6b9f31043303}","Kiehl","Gillum","Kiehl Gillum","kgillum","kiehl.gillum","18fa1042","kiehl.gillum@gmail.com","kiehl.gillum@rediffmail.com","(320) 679-6636","(810) 863-2970","(320) 679-3672","(810) 863-2871","2578 Claywood BLVD","Mora","MN","55051","54794 Rockledge PKWY, Suite 945","Roseville","MI","48035"
    "6","{f47a479c-d0a9-43d8-84aa-97970b0c4892}","Walletta","Spivey","Walletta Spivey","wspivey","walletta.spivey","37cdece6","wspivey@hotmail.com","wspivey@bellsouth.net","(218) 723-8749","(650) 357-1721","(218) 723-8142","(650) 357-7306","7061 Baypointe AVE","Duluth","MN","55802","59277 Mack HWY","San Mateo","CA","94403"
    "7","{f2b1687a-78ce-437b-baa0-2b959ee260d5}","Chauncey","Slemp","Chauncey Slemp","cslemp","chauncey.slemp","1b9f960c","cslemp@comcast.net","cslemp@charter.net","(412) 393-0962","(916) 492-0473","(412) 393-2712","(916) 492-1842","11544 Dumesnil CIR","Pittsburgh","PA","15222","63760 Tiburon PL, Suite 814","Sacramento","CA","95814"
    "8","{19189dab-e300-42d2-8580-c4216fcaafb3}","Roxanne","Bond","Roxanne Bond","rbond","roxanne.bond","3a7372b0","roxanne.bond@msn.com","roxanne.bond@aol.com","(336) 506-3075","(308) 652-9124","(336) 506-7181","(308) 652-6278","16027 Continental CIR","Burlington","NC","27215","68242 Burning BLVD","Orleans","NE","67647"
    "9","{7703a831-1f56-43cd-87ea-c998fcb52682}","Elvie","Cissell","Elvie Cissell","ecissell","elvie.cissell","1e451bd6","elvie.cissell@charter.net","ecissell@cox.net","(917) 344-5189","(770) 242-7876","(917) 344-1751","(770) 242-0814","20509 Tivoli RD, Suite 491","New York","NY","10041","72725 Perlman LN","Norcross","GA","30071"
    "10","{0aed5fd3-70e8-41e0-bbc4-418d122a590b}","Newman","Peters","Newman Peters","npeters","newman.peters","216c4fb","npeters@earthlink.net","npeters@hotmail.com","(719) 530-7302","(281) 944-6628","(719) 530-6221","(281) 944-5249","24992 Oak LN","Salida","CO","81201","77208 Bolsa BLVD","Houston","TX","77037"

    Installer: SetupContactGenerator.EXE (833.81 KB)

    Source: ContactGeneratorSource.zip (584.5 KB)

    Friday, July 06, 2007 4:29:07 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
    Thursday, July 05, 2007

    I must say, the OOB development experience in SharePoint has been less than desirable. I feel like MS has given us a number of tools but left us in the lurch figuring out how to use them, and its not always obvious how. One thing I have wanted to do is use the designer to develop web parts and deploy them with the click of a button. The VSeWSS have made the "deploy with the click of the button" part possible but the designer part has not been so obvious. How can you marry a designer experience with the VSeWSS ease of solution deployment? I'll show you how...

    For Starters

    The following information utilizes the Visual Studio Extensions for WSS (VSeWSS) which can be downloaded here. VSeWSS only offers a subset of the features available with solution deployment but offers "one touch" deployment OOB. Creating your own solutions manually will give you more options but may be more work than its worth (Unless you have found some nifty 3rd party tool or created your own). So the following information will strictly use what VSeWSS has to offer. VSeWSS can only run on a Windows Server 2003 box with MOSS 2007 & Visual Studio 2005 installed (Although it can be hacked to run on XP, most of the features do not work). VSeWSS may have problems if MOSS 2007 was not installed as a standalone server, so says the download notes and my experience with it. Although I have a colleague who has used it in a farm configuration and not had an issue.

    Creating a blank VSeWSS Project & Web Part

    Obviously you cant use the designer with a web part but you can with a Web User Control (This is the thought behind SmartParts). So lets start off by creating a project from an empty VSeWSS template.

    image

    Next add a new Web Part from the VSeWSS templates.

    image

    Now your probably thinking "Now add a Web User Control, yada yada yada", right? Wrong! If you have gone down this path before you will probably discover a couple of things; first the Web User Control is not available as a new item in a VSeWSS project. This can be worked around fairly easily by modifying the templates available to the class library project type or by creating the user control in a Web Application Project (WAP) and copy the files over, either way hacky. Second, you will discover that the designer does not behave as it does in a WAP or web site. For example your code behind and designer classes are not linked together and when you double click a control the default event code is generated in the ascx file instead of the code behind. This and a number of other quirks render this method almost as bad as just coding your entire control in the Web Part (Almost, but not quite). So how do we get the designer to work properly? .

    Creating a hybrid VSeWSS/WAP Project

    We need to create a hybrid VSeWSS/WAP project. This requires that you either have VS2005 SP1 installed or the WAP extensions installed (If you decided not to wait 5 hours for SP1 to install...). In order to make your VSeWSS project also a WAP project you will need to adjust the project type in the .xxproj file. To do this, right click the project we just created an select "Unload Project". It may ask you to save, press yes.

    image

    Once the project is unloaded, right click it again and select "Edit xxxxxxxxxxx.xxproj".

    image

    Once you have opened the project file you will need to add in the WAP guid into the ProjectTypeGuids element under the first PropertyGroup. This guid, {349c5851-65df-11da-9384-00065b846f21}, should be the second guid in the list (Shown in bold/green below), the first one being the VSeWSS project guid. All the guids in this element should be separated by a semicolon as shown below.

    <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

      <PropertyGroup>

        <ProductVersion>8.0.50727</ProductVersion>

        <SchemaVersion>2.0</SchemaVersion>

        <ProjectGuid>{7A3CF036-DC02-4868-8CBA-A88E75552372}</ProjectGuid>

        <ProjectTypeGuids>{9E5D3E2D-E4E2-418e-8D80-2F0DA9A94F9A};{349c5851-65df-11da-9384-00065b846f21};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

        <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

        <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>

        <OutputType>Library</OutputType>

        <RootNamespace>MyGroovySharePointLibrary</RootNamespace>

        <AssemblyName>MyGroovySharePointLibrary</AssemblyName>

        <SignAssembly>true</SignAssembly>

        <AssemblyOriginatorKeyFile>Properties\Temporary.snk</AssemblyOriginatorKeyFile>

      </PropertyGroup>

     After this has been set, right click the the project again and select "Reload Project". Click yes to save when prompted.

    image

    Now close out of Visual Studio, save your project when prompted. Restart Visual Studio and open your project.

    VSeWSS Deployment

    Now your probably thinking "Now add a Web User Control, yada yada yada", right? Well, yes, you can now add a Web User Control and its designer will work properly. But we want to be able to deploy it strictly with VSeWSS and its solution builder. In order to do this we will need to install the user control with a Module, so lets do that first. Right click your project and add a new Module. I will generically call it UserControls as I will want to add more user controls to it as I add web parts.

    image

    Once your module is created you can delete the "sample.txt" file from the UserControls folder. Now right click the UserControls folder and click Add --> New Item and select the standard Web User Control.

    image

    Next open the module.xml in the UserControls folder and add a reference to your newly created user control.

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

      <Module Name="UserControls" Url="UserControls" Path="">

        <File Url="MyGroovyUserControl.ascx" />

      </Module>

    </Elements>

    The Url attribute in the Module element specifies the relative path on the SharePoint site where the file will be deployed to. In this case I chose a sub folder called "UserControls".

    Creating the User Control and Linking the Web Part

    Now, add a label to your User Control called CurrentTime (Or whatever you want to call it...). And set it, in the control load event, to the current time.

    namespace MyGroovySharePointLibrary.UserControls

    {

        public partial class MyGroovyUserControl : System.Web.UI.UserControl

        {

            protected void Page_Load(object sender, EventArgs e)

            {

                CurrentTime.Text = DateTime.Now.ToString();

            }

        }

    }

    Since the VSeWSS Solution Builder creates a solution that installs only the project assembly to the GAC (Which is lame indeed) you will need to add an assembly directive to the user control, before the control directive is defined. If you do not add it before the control directive your control will fail to load as it will not have a reference to the project assembly in the GAC.

    <%@ Assembly Name="MyGroovySharePointLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" %>

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyGroovyUserControl.ascx.cs" Inherits="MyGroovySharePointLibrary.UserControls.MyGroovyUserControl" %>

    <asp:Label ID="CurrentTime" runat="server" Text="Label"></asp:Label>

    To obtain the public key token you can run the sn.exe utility in the SDK with the -T parameter and the path to the assembly. For example:

    image

    Next, override the CreateChildControls method of your web part and load the user control with the Page.LoadControl method. UPDATE: Thanks to Charles for pointing out that you also need to remove (If your not using it) the default Render(...) override. The WebPart template has this defined and by default it does not call the base implementation so ya get nothing displayed!

    namespace MyGroovyWebPart

    {

        [Guid("cc2a1b52-324a-4a20-bca8-0d512f8348b4")]

        public class MyGroovyWebPart :

            System.Web.UI.WebControls.WebParts.WebPart

        {

            public MyGroovyWebPart()

            {

                this.ExportMode = WebPartExportMode.All;

            }

     

            protected override void CreateChildControls()

            {

                string userControl = "/UserControls/MyGroovyUserControl.ascx";

                try

                {

                    Controls.Add(this.Page.LoadControl(userControl));

                }

                catch (Exception exception)

                {

                    string message = string.Format("{0} failed to load: {1}",

                        userControl,

                        exception.Message);

                    Controls.Add(new LiteralControl(message));

                }

            }

        }

    }

    Now hit F5 and deploy!

    image

    As you can see, this method gives you the benefit of the designer and VSeWSS solution deployment. The full source of the sample can be downloaded here:

    MyGroovySharePointLibrary.zip (417.78 KB)
    Thursday, July 05, 2007 6:18:06 AM (GMT Daylight Time, UTC+01:00)  #   |  Comments [8]  |  Trackback
    Thursday, June 07, 2007

    If you have worked much with WSS and the many XML definition files that accompany it you will no doubt be generating a lot of guids. The "Tools|Create GUID" can be a bit cumbersome so I searched for an alternative and couldn't find one. So I wrote a simple GUID insert AddIn that adds three links to your editor context menu to insert guids in different formats. First a standard guid; "6D7C589A-DDBB-4B01-BCEE-6F921885F942", second an undecorated guid; "AFCE87A3021C4BF7A51078DFA1F73995" (Good for content type ID's), and third a "registry" guid; "{0E0057DF-B8EC-44E3-A9AA-3EDBFEA7025B}". The setup installs the source as well if you want to modify it.

    Visual Studio 2005

    Installer: InstallInsertGUIDAddin.EXE (288.28 KB)

    Visual Studio 2008

    Installer: InstallInsertGUIDAddin2008.EXE (234.92 KB)
    Source: InsertGUIDAddinSource2008.zip (101.51 KB)

    Thursday, June 07, 2007 6:10:08 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
    Wednesday, June 06, 2007

    Having just built a couple of VS2005 addins I wanted to share a couple of resources that really helped me:

    Creating Menu Bitmaps and AboutIcons for Add-ins in Visual Studio .NET 2005
    Creating a CommandBar and adding Commands to it in a VS.NET Add-in
    Visual Studio 2005 Automation Samples

    Hopefully when I get more time I can post a walk through. Many thanks to Rick Strahl who seems to always have good info on how to do advanced development in .NET! 9 times out of 10 I'll find something on his blog/site, great resource!

    Wednesday, June 06, 2007 8:07:19 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
    Thursday, April 12, 2007

    So I am trying to write log information to an XML document using the XmlTextWriter.  When it reaches a certian size I want it closed out and archived. What I mean by "closed out" is that while the log file is "open" the root element is not closed so that I can keep adding entries over a period of time. In other words:

    <?xml version="1.0"?>
    <log>
        <entry date="1/1/2007">Yada yada yada</entry>
        <entry date="1/1/2007">Yada yada yada</entry>
        ...


    Then once its full I will write the closing root element and rename it:

    <?xml version="1.0"?>
    <log>
        <entry date="1/1/2007">Yada yada yada</entry>
        <entry date="1/1/2007">Yada yada yada</entry>
        ...
        <entry date="1/1/2007">Yada yada yada</entry>
    </log>

    Well the XmlTextWriter automatically closes out all open elements when you close it. Looking in Reflector reveals what is happening behind the scenes:

    public override void Close()
    {
       try
       {
          this.AutoCompleteAll();
       }
       catch {}
       finally
       {
          this.currentState = State.Closed;
          this.textWriter.Close();
       }
    }

    First the AutoCompleteAll() method is called, then the underlying stream is closed. The AutoCompleteAll() method is as follows:

    private void AutoCompleteAll()
    {
       if (this.flush)
       {
          this.FlushEncoders();
       }
       while (this.top > 0)
       {
          this.WriteEndElement();
       }
    }

    Doesent look like there is any official way to explicitly close only the elements you want to close, its just automatically done for you when you close the writer. The only work around I could figure out is to explicitly close the elements I want closed, then close the base stream (Not the XmlTextReader). This works but IMO its a little hackey since the code in the Close() method could potentially change in the future and you could end up circumventing some code that you might want executed when your done with the reader.

    .NET | C# | VB.NET | XML/XSL
    Thursday, April 12, 2007 8:01:42 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
    Friday, March 23, 2007

    I have been working with the new custom configuration classes in .NET 2.0 and they really make creating custom xml configuration a snap. They are a little quirky to use at first but once you get past the initial learning curve they really make the job a lot easier.

    One thing I really wanted to figure out is how to use these new classes to read files other than the default app/web.config. For example if you have one config file that might be shared between exes or if a config file is pulled from a URL. Its actually pretty easy to do.

    First create your custom configuration file. It will look exactly the same as a web/app.config file except it will only contain your custom section(s). Create a section handler element identifying the custom section handler and the name of the section. Again, nothing different from doing this in the app/web.config.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
     <configSections>
      <section name="mySettings" type="CustomConfigHandler.MySettingSection, CustomConfigHandler"/>
     </configSections>
     <mySettings>
      <someSetting someAttribute="This is an attribute value from Settings1.config"/>
     </mySettings>
    </configuration>

    Next create a Configuration object that points to your file by passing in an ExeConfigurationFileMap with the ExeConfigFilename set.

    // Create an exe file map containing the path to your config file
    ExeConfigurationFileMap FileMap = new ExeConfigurationFileMap();
    FileMap.ExeConfigFilename = "MySystem.config";

    // Create a configuration object that is tied to your custom config file.
    Configuration Config = ConfigurationManager.OpenMappedExeConfiguration(FileMap, ConfigurationUserLevel.None);

    // Create the custom config section handler
    MySettingSection MySettings = (MySettingSection)Config.GetSection("mySettings");

    Console.WriteLine(MySettings.SomeSetting.SomeAttribute);


    The entire source can be downloaded here:

    ExternalConfigFile.zip (40.24 KB)
    .NET | C# | Configuration | VB.NET
    Friday, March 23, 2007 8:30:17 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Wednesday, February 14, 2007

    I had a baffling problem arise today. Here is the scenario; I have a .NET WinForms app with a WebBrowser control. The WebBrowser control loads a web page that contains an embedded Flash movie. I need to send keystrokes to the Flash movie from the WinForms app. Now MS provides the SendKeys class under the Windows.Forms namespace for this very purpose, but in this instance it doesent pass them on to the Flash movie (Although it does pass them to HTML elements in the page). Hmmmmmm... A little digging in Reflector uncovers the reason. The SendKeys class internally calls the SetKeyboardState() native method to send the keyboard input. Here is what MSDN says about that call:

    The SetKeyboardState function copies a 256-byte array of keyboard key states into the calling thread's keyboard input-state table. This is the same table accessed by the GetKeyboardState and GetKeyState functions. Changes made to this table do not affect keyboard input to any other thread.

    I'm no expert on how embedded ActiveX controls work within a web page in IE but I bet the Flash control is not running in the same thread as the browser UI. And in the case of using the WebBrowser control, not in the UI thread of the WinForms app. So SendKeys will not be able to send keystrokes to embedded Flash in a WebBrowser control. Just a guess, but it seems that is what is happening here. Well, scratch that, I just checked Spy++ and everything is running under the WinForm UI thread including the Flash ActiveX control. So at this point I have no idea why SendInput() works but SetKeyboardState() doesent (And thus the SendKeys class), very strange indeed! If anyone knows for sure, please leave a comment! :)

    So the other option is calling the SendInput method. FYI, this method supersedes the keybd_event method. Here is a sample of the code required to send keystrokes to the foreground window. Remember, you must make sure that the WebBrowser control has focus for it to receive the keystrokes (As does the Flash control in the web page, see further down for more info).

    private void Main_Load(object sender, EventArgs e)
    {
        WebBrowserControl.Navigate(@"file://C:\Temp\Flash.html");
        Timer.Enabled = true;
    }

    private int Index = 0;

    private void Timer_Tick(object sender, EventArgs e)
    {
        Index++;

        NativeMethods.INPUT[] structInput = new NativeMethods.INPUT[1];

        structInput[0] = new NativeMethods.INPUT();
        structInput[0].type = NativeMethods.INPUT_KEYBOARD;
        structInput[0].ki.wScan = 0;
        structInput[0].ki.time = 0;
        structInput[0].ki.dwFlags = 0;
        structInput[0].ki.dwExtraInfo = NativeMethods.GetMessageExtraInfo();
        structInput[0].ki.wVk = NativeMethods.VK_RIGHT;

        // Key up every other pass
        if (Index % 2 == 0)
        {
            structInput[0].ki.dwFlags = NativeMethods.KEYUP;
        }

        NativeMethods.SendInput(1, structInput, Marshal.SizeOf(structInput[0]));
    }

    The basic native method & struct declarations are as follows. PInvoke.NET has a nice definition of all of these.

    public const int INPUT_KEYBOARD = 1;
    public const int KEYUP = 2;

    public const int VK_LEFT = 0x25;
    public const int VK_UP = 0x26;
    public const int VK_RIGHT = 0x27;
    public const int VK_DOWN = 0x28;


    [StructLayout(LayoutKind.Sequential)]
    public struct MOUSEINPUT
    {
        int dx;
        int dy;
        int mouseData;
        int dwFlags;
        int time;
        IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct KEYBDINPUT
    {
        public short wVk;
        public short wScan;
        public int dwFlags;
        public int time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct HARDWAREINPUT
    {
        int uMsg;
        short wParamL;
        short wParamH;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct INPUT
    {
        [FieldOffset(0)]
        public int type;
        [FieldOffset(4)]
        public MOUSEINPUT mi;
        [FieldOffset(4)]
        public KEYBDINPUT ki;
        [FieldOffset(4)]
        public HARDWAREINPUT hi;
    }

    [DllImport("user32.dll", SetLastError = true)]
    public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

    [DllImport("user32.dll", SetLastError = false)]
    public static extern IntPtr GetMessageExtraInfo();

    The only other thing you need to do to make this completely automated is to set focus on the Flash movie in the web page using JavaScript. Simply call the focus method of the Flash control as follows:

    window.document.MyFlash.focus();

    The entire project can be downloaded here.

    .NET | C# | Flash | Win32 API
    Wednesday, February 14, 2007 10:31:15 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [4]  |  Trackback
    Monday, January 29, 2007

    There is a new version of the Hid Library in the labs. It has been converted to .NET 2.0 and includes a bug fix. This bug fix involved how the vendor and product id were cast in the structure consumed by the Hid API. So some devices like Logitec's gamepads would not be recognized by their product and vendor id's. Now that issue is resolved. N-joy!

    USB Hid Device Library

    .NET | C# | USB HID | VB.NET
    Monday, January 29, 2007 10:36:12 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [27]  |  Trackback
    Tuesday, January 09, 2007

    I was looking over a peice of my code today and noticed I had some finalization code in a try-finally block but there was a code path that had a return statement. So I thought, "thats a bug because I'm jumping out of the method before the finally block is called!". Silly me! MSDN says "Control is always passed to the finally block regardless of how the try block exits". For some reason I always thought that the finally block was bypassed when you exited a method via the return statement... :-S

    .NET | C# | VB.NET
    Tuesday, January 09, 2007 5:02:49 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Thursday, January 04, 2007

    Removing special chars (Control chars 0-31 and extended ASCII 127-255) is pretty easy to do with a regular expression. Simply select chars that are not in the range of ASCII 32-126 (Hex 20-7E) and replace these chars with an empty string.

    Regex SpecialCharExpression = new Regex(@"[^\x20-\x7E]");
    string NewData = SpecialCharExpression.Replace(OldData, string.Empty);

    Here is a working example:

    class Program
    {
       static void Main(string[] args)
       {
          string OldData = string.Empty;

          for (int Index = 0; Index < 256; Index++)
          {
             OldData += ((char)Index).ToString();
          }

          Regex SpecialCharExpression = new Regex(@"[^\x20-\x7E]");
          string NewData = SpecialCharExpression.Replace(OldData, string.Empty);

          Console.WriteLine("Length: " + NewData.Length);
          Console.WriteLine(NewData);
          Console.ReadKey();

       }
    }

    .NET | C# | VB.NET
    Thursday, January 04, 2007 6:47:38 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Wednesday, January 03, 2007

    I really have to remember to use the IsNullOrEmpty method in the string class. I keep forgetting to use it so I figure if I blog about it I'll remember.. ;)

    // Why do this...
    if (MyString != null && MyString.Length > 0) {...}

    // When you could do this???
    if (string.IsNullOrEmpty(MyString) == false) {...}

    And while we are on the subject, the .NET framework defines a lot of nice constants for us to use instead of defining our own or using literals. See if one exists in a class near you... Here are a couple of examples:

    // Why use the "" literal when you can use
    String.Empty;

    // = "\"
    System.IO.Path.DirectorySeparatorChar;

    // = "/"
    System.IO.Path.AltDirectorySeparatorChar;

    // Returns char[] {'"', ...}
    System.IO.Path.GetInvalidPathChars();

    // Returns char[] {'"', ...}
    System.IO.Path.GetInvalidFileNameChars();

    .NET | C# | VB.NET
    Wednesday, January 03, 2007 9:59:05 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Tuesday, December 26, 2006

    Ran into a weird problem with the following code. When I atempted to save the bitmap I recieved a "Parameter is not valid" error. I snagged this code from a VB.NET app I wrote and translated it, so I knew that it worked.

    Bitmap ChartImage = GeneratePieChart(...);

    EncoderParameter QualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100);
    EncoderParameters EncoderParams = new EncoderParameters();
    EncoderParams.Param[0] = QualityParam;

    MemoryStream ChartStream = new MemoryStream();

    ChartImage.Save(ChartStream, GetEncoderInfo("image/jpeg"), EncoderParams);

    Rob Gruen ran into the same issue and fortunately blogged about it here. Long story short the quality in the EncoderParamater must explicitly passed as a long:

    EncoderParameter QualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);

    .NET | C# | Graphics
    Tuesday, December 26, 2006 7:40:39 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [1]  |  Trackback
    Monday, December 18, 2006

    This should actually be "System.Runtime.CompilerServices.IndexerName" from what I can tell. It appears that there is a typo in the MSDN docs (And elsewhere on the web) unless I'm just totally missing something here... Supposedly its in the mscorlib.dll but I couldnt seem to find a "CSharp" class anywhere under System.Runtime.CompilerServices either in v1.1 or v2.0. And other CSharp classes elsewhere did not contain the "IndexerName" attribute. Weird. The truth is out there...

    .NET | C#
    Monday, December 18, 2006 11:00:22 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Sunday, December 17, 2006

    I needed an efficient and performant way to keep track of the current number of files/folders in a folder. Directory.GetFiles() was out of the question for a number of reasons. So I ended up using a two step process. First grab the current number of files/folders in the folder using the FindFirstFile() and FindNextFile() Win32 API calls (Which is what Directory.GetFiles() uses under the covers.). These increment the file counter. Then immediately after that completes, activate a FileSystemWatcher to monitor file creation and deletion. These events respectively increment or decrement the counter. I have been putting this through the ringer and it seems to do the job superbly.

    Interesting observation about the FindNextFile() method; this method will continue to grab files as long as they exist in the directory, it’s not like it’s working from some sort of static snapshot of the files created by FindFirstFile() when it is called. So in other words if other files are added to the folder that match the criteria of your filter while you are in the process of iterating with FindNextFile(), FindNextFile() will eventually “find” them. Although this seems implied by the name of both the method calls, you never know what might actually be going on under the hood…

    The following code illustrates how to do this. Note that there can potentially be a significant performance hit when a folder is first enumerated. This is especially true when the file/folder count gets past the hundreds of thousands. But once the folder is first enumerated the FSW will keep track of the additional creates/deletes, no need to re-enumerate.

    class Program
    {

       static FileSystemWatcher _Watcher = new FileSystemWatcher();
       static int _Count = 0;

       static void Main(string[] args)
       {

          _Watcher.Filter = "*.*";
          _Watcher.Path = @"D:\Temp";

          _Watcher.Created += new FileSystemEventHandler(OnCreated);
          _Watcher.Deleted += new FileSystemEventHandler(OnDeleted);

          NativeMethods.FindData FileInfo = new NativeMethods.FindData();

          IntPtr FileHandle = NativeMethods.FindFirstFile(@"D:\Temp\*.*", FileInfo);

          do
          {
             if (FileInfo.fileName != "." && FileInfo.fileName != "..") { _Count++; }
          } while (NativeMethods.FindNextFile(FileHandle, FileInfo) == true);

          NativeMethods.FindClose(FileHandle);
          _Watcher.EnableRaisingEvents = true;

          do
          {
             Console.WriteLine("Total Files: " + _Count.ToString());
          } while (Console.ReadLine() != "q");

       }

       private static void OnCreated(object source, FileSystemEventArgs e)
       {
          _Count++;
       }

       private static void OnDeleted(object source, FileSystemEventArgs e)
       {
          _Count--;
       }

    }

    class NativeMethods
    {
       // Declares a class member for structure element.
       [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
       public class FindData
       {
          public int fileAttributes = 0;
          // creationTime was an embedded FILETIME structure.
          public int creationTime_lowDateTime = 0;
          public int creationTime_highDateTime = 0;
          // lastAccessTime was an embedded FILETIME structure.
          public int lastAccessTime_lowDateTime = 0;
          public int lastAccessTime_highDateTime = 0;
          // lastWriteTime was an embedded FILETIME structure.
          public int lastWriteTime_lowDateTime = 0;
          public int lastWriteTime_highDateTime = 0;
          public int nFileSizeHigh = 0;
          public int nFileSizeLow = 0;
          public int dwReserved0 = 0;
          public int dwReserved1 = 0;
          [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
          public String fileName = null;
          [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
          public String alternateFileName = null;
       }

       [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
       public static extern IntPtr FindFirstFile(String fileName, [In, Out] 
       FindData findFileData);

       [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
       public static extern bool FindNextFile(IntPtr hFindFile, [In, Out] 
       FindData findFileData);

       [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
       public static extern bool FindClose(IntPtr hndFindFile);

    }

    .NET | C#
    Sunday, December 17, 2006 8:45:09 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Wednesday, November 22, 2006

    So I'm implementing an interface, defined in an assembly written in VB.NET, on a class in an assembly written in C#. The interface defines a number of events. VB.NET event declaration doesent require you to define the corresponding delegate (as C# does) so the question is where does the VB.NET compiler declare it for you after compilation? Well it seems that the delegate definition is declared right in the interface. This could be confusing for someone who doesent know VB.NET since C# does not allow the declaring of types within an interface whereas VB.NET does.

    Here IDataInputDevice is an interface residing in an assembly written in VB.NET with three events defined. The corresponding delegate definitions are defined right within the interface.

    .NET | C# | VB.NET
    Wednesday, November 22, 2006 11:39:52 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Friday, November 10, 2006

    One of the shortcuts of C# (And now in VB.NET 2005) I love is the using statement. For those not familiar with it, it allows you to create objects within the scope of the using block and then once the block completes execution, calls the Dispose method on all the specified objects if they implement IDisposable. This occurs even if an exception is thrown. From what I understand, the using block in the resulting IL is a try/finally block, where the object disposal takes place in the finally.

    This is perfect for working with a DataReader and instances where we want to make sure a database connection is closed right after a call. Since the Dispose method on a DataReader and Connection object call their own Close method they will be implicitly closed when we exit the using block, regardless of errors.

    string ConnectionString = "server=127.0.0.1;database=duwamish7vb;Trusted_Connection=true";

    using (SqlConnection Conn = new SqlConnection(ConnectionString))
    {

        Conn.Open();

        SqlCommand Command = new SqlCommand("SELECT Name FROM Authors",Conn);

        using (SqlDataReader Reader = Command.ExecuteReader())
        {

            Authors.DataTextField = "Name";
            Authors.DataSource = Reader;
            Authors.DataBind();

        }

        Command = new SqlCommand("SELECT Subject FROM Books", Conn);

        using (SqlDataReader Reader = Command.ExecuteReader())
        {

            Books.DataTextField = "Subject";
            Books.DataSource = Reader;
            Books.DataBind();

        }

    }

    .NET | C# | VB.NET
    Friday, November 10, 2006 9:17:27 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback

    I have seen a lot of debate about VB.NET and C# and which one is "better". Before I started coding in C# I had some prejudice about it, but it’s interesting to see how my viewpoint has in some cases changed, and in others not changed after making the switch.

    My viewpoint before switching over:

    • .NET languages are as MS put it a "lifestyle choice".
    • Many C# programmers think a little too much of themselves, projecting an elitist status as if a VB.NET developer knows nothing about OOD/OOP, design patterns and are just script kiddies.
    • Case sensitivity within a language is moronic, inelegant and causes ambiguity.
    • VB.NET is a very expressive language, like reading a book whereas C# looks like a bunch of ugly symbols.
    • And what’s with that stupid semi-colon anyway??

    My viewpoint after switching over:

    • I still think it’s a lifestyle choice. I’m sure some C# purists will probably say I "don’t know enough about C#" or "that sounds like something a VB programmer would say". :-) The power of the .NET framework is, in my opinion, expressed well in both languages except for a few things here and there. Especially now with the release of v2.0 it’s not about whether or not you use a particular language syntax, it’s really about knowing how to develop .NET applications and about programming and design principles.
    • I still think some C# programmers think too much of themselves. I do realize however that the majority of VB.NET programmers come from the VB6/VBScript world, a world I am from. Many of those individuals carry a lot of baggage with them and do not have a good grasp of OO, design patterns, etc and are just not skilled developers. Many of them are the script kiddie type because it was so easy to pound out code in those languages, didnt require a whole lot of skill. But don’t judge a book by its cover. I think there are a lot of developers who came from that world who have embraced the principles, now present in the .NET framework (Not just a particular language syntax), that Java and C++ programmers have practiced and enjoyed for years.
    • I've not noticed the case sensitivity in C#… In fact in cases where I have not had VS prettying up my VB code I manually format my code anyway. Not even an issue. Ambiguity is definitely a possibility but I think a good developer would avoid that for clarity.
    • I actually now like all those "ugly symbols" over the expressive and verbose VB syntax… Very strange because that was one of my biggest prejudices aside from case sensitivity. It’s just a lot simpler and once you get used to it it’s not hard to read. If you are only familiar with the expressive syntax of VB it is hard to follow. I feel like I have much more flexibility over how I structure my code. Even going back to do maintenance on VB.NET code is less than enjoyable now that I have been working with C#.
    • Ok, the semi-colon is a little annoying at first but you get to the point where you don’t even think about it. It’s actually very nice in instances where you have a large string literal or a long line of code.

    Bottom line is, "...just listen to your heart. That's what I always do". Dont be caught up in the hype that coding in VB.NET makes you a script kiddie. But I would seriously recomend, if you are a VB.NET developer who has not learned C#, to at least give it a try. You might be very surprised at how much you like the syntax over VB.

    .NET | C# | VB.NET
    Friday, November 10, 2006 8:25:01 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Tuesday, November 07, 2006

    I ran into an issue today where I was coding in a class under a particular namespace but couldn’t access a class in another namespace that only differed by its namespace root. Here is what it looked like:

    MyApp.Common.MyClass // Class I want to reference (For a unit test)

    TestSuite.MyApp.Common.MyClass // the class I'm coding in (A unit test...)

    When I referenced MyApp.Common.MyClass it was actually resolving to TestSuite.MyApp.Common.MyClass. So if you want to reference the former, you need to use the "global::" prefix as follows:

    global::MyApp.Common.MyClass

    .NET | C#
    Tuesday, November 07, 2006 8:49:11 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
    Wednesday, October 11, 2006

    The following is a breakdown of 4 basic bitwise operators; NOT, OR, XOR and AND.

    NOT

    NOT produces the inverse of a binary value. For example:

    1 will be 0 and 0 will be one. In C# NOT operations are only allowed on Boolean values. The NOT operator is an exclamation point (!).

    bool i = true;

    Console.WriteLine(!i);

    // returns false

    OR

    OR produces a 1 if either corresponding bit is 1. This means that if both are one or if only one is 1 the result is 1. If both are zero then the result is zero. For example:

    In C# the OR operator is the pipe (|).

    int i = 23; // 010111
    int z = 45; // 101101

    Console.WriteLine(i | z);

    // 63 - 111111

    XOR

    XOR (Or Exclusive OR) produces a 1 if either corresponding bit is 1 but not both, in other words mutually exclusive. This means that 1 and 0 or 0 and 1 will be 1. 0 and 0, 1 and 1 will produce 0. For example:

    In C# the XOR operator is the caret (^).

    int i = 23; // 010111
    int z = 45; // 101101

    Console.WriteLine(i ^ z);

    // 58 - 111010

    AND

    AND produces a 1 only if both corresponding bits are 1, otherwise it produces a 0. For example:

    In C# the AND operator is the ampersand (&).

    int i = 23; // 010111
    int z = 45; // 101101

    Console.WriteLine(i & z);

    // 5 - 000101


     

    .NET | Binary | C#
    Wednesday, October 11, 2006 9:07:13 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
    Creative Commons License