December 17, 2009

WPF Timer (DispatcherTimer )

Comparison of different timers in .NET is found here. Unfortuneately this does not mention the DispatchTimer which is more appropriate for WPF usage (but not only)
using System.Windows.Threading;
...
private DispatcherTimer timer;    
...
const int MILLISECOND = 10000L;
timer = new DispatcherTimer();  
// Disable (stop) it 
timer.IsEnabled = false;
// Set timer event interval
timer.Interval = new TimeSpan(3000L * MILLISECOND);
// Timer events
timer.Tick += new EventHandler(timer_Tick);
...
timer.Start(); // at some point start the timer
...
void timer_Tick(object sender, EventArgs e)
{
  if (...)
  {
    timer.Stop();
  }
}

December 16, 2009

Sample Custom Method Attribute.

An example of a custom attribute on a method:
[AttributeUsage(AttributeTargets.Method)] 
public class ProjectReloadRequiredAfterTestAttribute
 : System.Attribute
{
}

public void Discover(MethodBase mb)
{
  if (mb.GetCustomAttributes(typeof(
      ProjectReloadRequiredAfterTestAttribute), 
      false).Length > 0)
  {
    reloadProjectRequired = true;
  }
}  
 
[Test]
[ProjectReloadRequiredAfterTestAttribute]
public void TestCreateAndDeletePart()
{
  Discover(System.Reflection.MethodBase.GetCurrentMethod());
  ...
}

Adjusting Privileges

This code is untested but may be required to shut down a PC using the exit windows API (see here
#region Adjust Priveleges

//This snippet is tested on WinXP and Vista
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
               ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, 
                                             ref IntPtr phtok);

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name,
                                                 ref long pluid);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
    public int Count;
    public long Luid;
    public int Attr;
}

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
//http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
internal const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege"; 
internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

private bool AddShutDownPrivilegeToApp()
{
    try
    {
        bool retVal;
        TokPriv1Luid tp;
        IntPtr hproc = GetCurrentProcess();
        IntPtr htok = IntPtr.Zero;
        retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES |
                                   TOKEN_QUERY, ref htok);
        tp.Count = 1;
        tp.Luid = 0;
        tp.Attr = SE_PRIVILEGE_ENABLED;
        retVal = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
        retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, 
                                      IntPtr.Zero, IntPtr.Zero);
        return retVal;
    }
    catch (Exception ex)
    {
        //throw;
        return false;
    }

}

#endregion


Visual Studio Plug-In Build Properties

Lets say your writing a plug-in for an application "SomeApp.exe" at the following directory:
"D:\Projects\Smed\win32_vs90\Debug\SomeApp.exe"

Under "Build" tab set
"Output path:" by using the "Browse" button browse to "D:\Projects\Smed\win32_vs90\Debug\"

Under "Debug" tab set
"Start external program:" to "D:\Projects\Smed\win32_vs90\Debug\SomeApp.exe"
"Working directory" to "D:\Projects\Smed\win32_vs90\Debug\"

Under "Reference Paths" tab
Add "D:\Projects\Smed\win32_vs90\Debug\" to the reference paths

December 15, 2009

GetRelativePath Helper

public static class FileSystemInfoExtender
{
    public static string GetPathRelativeTo(this FileSystemInfo file, string path)
    {
        string fullPath = Path.GetFullPath(path);
        string res = string.Empty;
        if (file.FullName.StartsWith(fullPath))
        {
            res = file.FullName.Substring(fullPath.Length);
        }
        res = res.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
        string sep = Path.DirectorySeparatorChar.ToString();
        if (res.StartsWith(sep))
        {
            res = res.Substring(1);
        }
        return res;
    }
}
and some tests
FileInfo file = new FileInfo(@"D:\Projects\smeg\src\blah\xxxx\whistle\stop\Carbuncle.cs");
string relPath = file.GetPathRelativeTo(@"D:\Projects\smeg\src");
Debug.Assert(relPath.Equals(@"blah\xxxx\whistle\stop\Carbuncle.cs", 
StringComparison.OrdinalIgnoreCase));
relPath = file.GetPathRelativeTo(@"D:/Projects/smeg/src");
Debug.Assert(relPath.Equals(@"blah\xxxx\whistle\stop\Carbuncle.cs", 
StringComparison.OrdinalIgnoreCase));
relPath = file.GetPathRelativeTo(@"D:\Projects\smeg\src\");
Debug.Assert(relPath.Equals(@"blah\xxxx\whistle\stop\Carbuncle.cs", 
StringComparison.OrdinalIgnoreCase));

November 26, 2009

Accessing Command Line Arguments In WPF

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs sea)
    {
        CommandLine.Instance.SetArguments(sea.Args);
        base.OnStartup(sea);
    }
}

public class CommandLine
{
    private CommandLine()
    {}

    private static readonly CommandLine instance = new CommandLine();

    public static CommandLine Instance
    {
        get { return instance; }
    }

    public IEnumerable Arguments
    {
        get { return args; }
    }

    public void SetArguments(string[] args)
    {
        this.args = args ?? new string[0];
    }

    private string[] args = new string[0];
}
then to use
private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            foreach (string arg in CommandLine.Instance.Arguments)
            {
                if (arg.ToUpper() == "/C")
                {
                    if (System.Windows.Forms.Clipboard.ContainsText())
                    {
                        tbCode.Text = System.Windows.Forms.Clipboard.GetText();
                    }
                }
            }

        }
Doh!
Even easier:
string[] arguments = Environment.GetCommandLineArgs();
When processing command line args using Environment.CommandLineArgs(), found that the system automatically matches " in an argument. So if you have a path that contains a spaces, as long as that path is wrapped with " marks, the path will not be parsed into multiple arguments but rather appear as a single argument. eg.:
-myArg:C:\Program Files\MyProgram\Something.exe
will get parsed as multiple arguments:
  • -myArg:C:\Program
  • Files\MyProgram\Something.exe
whereas
-myArg:"C:\Program Files\MyProgram\Something.exe"
will get parsed as a single argument:
  • -myArg:C:\Program Files\MyProgram\Something.exe

Have also noticed that carriage return line feeds can get sucked into a command line argument. Perhaps a "Trim()" should be applied to each argument string before it is processed to be sure this whitespace is removed. Here is a sample command line parser:
internal class CommandLineParser
{
    public string Drive { get; set; }
    public string TrueCryptFile { get; set; }
    public string KeyFile { get; set; }

    const string DrivePrefix = "-D";
    const string TrueCryptFilePrefix = "-T";
    const string KeyFilePrefix = "-K";

    public void CommandLineArgs(string[] args)
    {
        //string[] args = Environment.GetCommandLineArgs();
        Debug.WriteLine("Args:" + string.Join(",", args));
        int ix = 0;
        foreach (string arg in args)
        {
            Debug.WriteLine("arg[" + ix++.ToString() + "]=\'" + arg + "\'");
        }
        foreach (string rawArg in args)
        {
            // Get rid of whitespace chars at the beginning and end
            string arg = rawArg.Trim(); 
            if (arg.Length < 2)
              continue;
            string argument = (arg[0] == '/') ? "-" + arg.Substring(1) : arg;
            int end = argument.IndexOf(':');
            if ((end == -1) && ((end + 1) >= argument.Length))
                continue;
            if (argument.ToUpper().StartsWith(DrivePrefix))
            {
                Drive = argument.Substring(end + 1).Substring(0, 1) + ":";
            }
            else if (argument.ToUpper().StartsWith(TrueCryptFilePrefix))
            {
                TrueCryptFile = argument.Substring(end + 1);
            }
            else if (argument.ToUpper().StartsWith(KeyFilePrefix))
            {
                KeyFile = argument.Substring(end + 1);
            }
        }
        Debug.WriteLine("Processed command line args:");
        Debug.WriteLine("Drive=\"" + Drive + "\"");
        Debug.WriteLine("TrueCryptFile=\"" + TrueCryptFile + "\"");
        Debug.WriteLine("KeyFile=\"" + KeyFile + "\"");
    }
}

// and tester (not really finished)
class CommandLineParserTester
{
    public void TestCommandLineParser()
    {
        CommandLineParser clp = new CommandLineParser();
        clp.CommandLineArgs(new string[] { 
            @"-D:M",
            @"-T:F:/Temp/truecrypt.tc",
            @"-K:F:/Temp/truecrypt.keyfile" });
        Assert(clp.Drive == "M:");
        Assert(clp.TrueCryptFile == @"F:/Temp/truecrypt.tc");
        Assert(clp.KeyFile == @"F:/Temp/truecrypt.keyfile");
    }
}

November 19, 2009

Debugger/Editor Attributes

DebuggerDisplay - Use it to specify how a class or struct should be displayed in the debugger when the cursor hover over the item
[DebuggerDisplay("Count = {count}")]
class blahblahblah ...
DebuggerStepThrough - Instructs the debugger to step through that marked property or attribute, and not into it:
[DebuggerStepThrough]
public int Key
{
  [System.Diagnostics.DebuggerStepThrough]
  get { return key; }
  [System.Diagnostics.DebuggerStepThrough]
  set { key = value; }
}
DebuggerBrowsable - Determines if and how a field or property is displayed in the debugger variable windows.
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int key;
see also DebuggerDisplay and DebuggerBrowsable – Two Debugger Attributes you should know

EditorBrowsable - Use this 'EditorBrowsable' property to restrict intellisense/visual studio visibility of a property
[EditorBrowsable(EditorBrowsableState.Never)]
int MyProperty
...

DefaultValue - Then there is the 'DefaultValue' property that sets the default value of a C# class property. Used by visual designers, etc
[DefaultValue(42)] 
public int MyProperty { get; set; }

Sample Linq

In order to use Linq in the following ways a reference to the 'System.Core' assembly is required. The namespace is 'System.Linq'.
Useful Links
This code shows the same method 3 times using different forms of Linq. It also demonstrates some lambda expressions.
private Smeg FindSmeg(Project project, string smegName)
{
    SpellRoot spellRoot = SpellRoot.Get(project);
    SmegCollection smegs = spellRoot.SmegCollection;

    // Note that the 'smegVar' is an IEnumerable 
    var smegVar = from bh in smegs
                      where bh.Name.Equals(smegName,   
                                StringComparison.OrdinalIgnoreCase)
                      select bh; 
    Smeg smeg = smegVar.FirstOrDefault();

    return smeg;
}

private Smeg FindSmeg2(Project project, string smegName)
{
    SpellRoot spellRoot = SpellRoot.Get(project);
    SmegCollection smegs = spellRoot.SmegCollection;

    // Declaring a Func type lambda expression
    // A good way to learn how to form correct lambda expressions
    Func smegSelector = 
        bh => bh.Name.Equals(smegName, StringComparison.OrdinalIgnoreCase);
    Smeg smeg = smegs.FirstOrDefault(smegSelector);

    return smeg;
}

private Smeg FindSmeg3(Project project, string smegName)
{
    SpellRoot spellRoot = SpellRoot.Get(project);
    SmegCollection smegs = spellRoot.SmegCollection;

    // Inline lambda expression
    Smeg smeg = smegs.FirstOrDefault(
        bh => bh.Name.Equals(smegName, StringComparison.OrdinalIgnoreCase));

    return smeg;
}

Simple examples

Count() - Get count of items in an enumeration
IEnumerable smegs = ...
int count = smegs.Count();
ToArray() - enumeration to an array
IEnumerable smegs = ...
Smeg smegArr = smegs.ToArray();
ToList() - enumeration to a list
IEnumerable smegs = ...
IList smegList = smegs.ToList();
Where() - This is a general purpose filter, the function in the Where clause performs the filtering
File.ReadLines( @"D:\Users\ukrb\Docs\SpcPressures.txt" ).
    Where(li => li.Contains(" PRESSURE")). // Filter out any line NOT containing the specified string (" PRESSURE")
    Dump();
Select() - Allows you to Select portions of/Convert each enumerated item to an item of another type (not by casting but by extraction or conversion). Anonymous types can be used for conversion to simple intermediate types
// This parses a file of data where each line contains a number of samples, their average, maximum, minimum, etc.
File.ReadLines( @"D:\Users\ukrb\Docs\PRESSURE 214289.DAT" ).
    Select(li => ParseLine(li)).   // ParseLine is a function returning a specific class type instance
    Select(pe => pe.ToV10Form()).  // Now convert it to another more readable string of only data that is interesting
    Dump(); 
Single() - Returns the single matching element in the enumeration, if there is not exactly one match an 'InvalidOperationException' exception is thrown.
IEnumerable smegs = ...
Smeg first = smegs.Single();
First() - first element in an enumeration, be careful an exception is thrown if the enumeration is empty! If your enumeration maybe empty use FirstOrDefault
IEnumerable smegs = ...
Smeg first = smegs.First();
FirstOrDefault() - first element in an enumeration, and when it is empty, the default value of the enumerated type (which is always null for a reference type)
IEnumerable smegs = ...
Smeg first = smegs.FirstOrDefault();
Last() - last element in an enumeration, be careful an exception is thrown if the enumeration is empty!
IEnumerable smegs = ...
Smeg last = smegs.Last();
Skip() - skip the first n elements in an enumeration and return what is left, be careful an exception is thrown if the enumeration has less than n items
string[] allArgs = Environment.GetCommandLineArgs();
IEnumerable<string> args = allArgs.Skip(1); // First argument is the exe path
OfType() - extract from an enumeration all objects of the given type. Safe way of converting an enumeration of one type to another, it uses the 'is' operator. An excellent way to filter out null objects in a sequence. There is the "Cast<>()" operator but the trouble with this is that it will throw an exception if one of the objects of the enumeration is not of the given type so only use that when you know that all the elements of the enumeration will cast to the new type
IEnumerable smegs = ...
int numSquares = smegs.OfType().Count();
Cast() - Casts all items in the enumeration to the given type. When an item can not be cast to the new type then an exception is thrown. Useful to convert old style enumerables of known types. For example:
StringCollection sc = this.settingsService.GetProperty
      <StringCollection>(SourceDirectoriesSetting) ?? new StringCollection();
if (sc.Count > 0)
{
  // Cast the string collection 'sc' entries to strings
  ObservableCollection<string> oc = new ObservableCollection<string>(sc.Cast<string>());
  ...
}
Using the XXXOrDefault (First, Single, Last, ElementAt) option:
In some cases when an IEnumerable returns no entries at all the Linq operator will throw an exception using the "OrDefault" option will circumvent this problem. In the case that there are no entries returned from an XXXOrDefault operator, Linq will return the default value for the generic parameter. In the case of a reference type this will be null. For a value type it will return the default value for that value type.

SelectMany() - SelectMany flatten nested enumerables, see here for a good example

Linq Set operators:
  • Union - Simply appends one IEnumerable to another
  • Intersect - Finds items common to 2 IEnumerables
  • Except - Subtracts one IEnumerable from another
  • Distinct - Removes duplicate items from a single IEnumerable (Operates on a single IEnumerable!)

November 12, 2009

Math.Round

Math.Round() can be made to work in the conventional manner for rounding numbers using the 'MidpointRounding.AwayFromZero' argument eg
// Round to 2 decimal places. 
public double RoundUpTo2Dp(double arg)
{
  // so xx.xx5 becomes xx.x(x+1)0 where x is a digit in a double number
  return Math.Round(arg, 2, MidpointRounding.AwayFromZero); 
}

October 7, 2009

@ Character In Identifiers

The c# language specification says The "@" character is allowed as a prefix to enable keywords to be used as identifiers.. Hence the following is possible:
public class Case {};

public class XXXX
{
    private Case m_Case;

    public XXXX(Case @case)
    {
        m_Case = @case;
    }
}
Useful for events:
  var @event = new Event(...);

August 7, 2009

C++/CLI Casting Basics

C++/CLI Casting Basics
  • reinterpret_cast<> unsafe standard C++ cast
  • static_cast<> relies only on compile time information
  • const_cast<> is used to remove the const, volatile, and __unaligned
  • dynamic_cast<> relies both on compile time and run time information. if the cast is unsafe then this the cast returns NULL
  • __try_cast<> same as dynamic cast except it throws an exception if the cast fails
Recommendation for downcasting

If you are absolutely sure that the cast is going to be safe, you can use any of the four cast operators above, but I'd suggest that you use static_cast because that'd be the most efficient way of casting. If you are even a microscopic percentage unsure as to the safety of your cast, you must simply *avoid* static_cast and reinterpret_cast both of which are quite dangerous here. You may use either dynamic_cast or __try_cast depending on whether you like to check for NULL or you like to have an exception raised and handled.

Recommendations for upcasting

In most situations upcasting should be quite safe except when you have a bad derived class pointer (bad in the sense that it points to the wrong object). Therefore my recommendation for upcasting is to use static_cast which should be the most efficient. If your upcasts are unsafe it's probably time for you to sit down and figure out what's going wrong in your code rather than using dynamic_cast or __try_cast. In addition keep in kind that upcasting would probably be implicitly done in most situations.

Friend Assemblies

'InternalsVisibleToAttribute' indicates that all internal types in that assembly would be visible to another assembly, whose name is specified in the attribute constructor. In other words, that assembly becomes a friend assembly. The usage would be something like:
[assembly:InternalsVisibleToAttribute("MyFriendAssembly”)]
Or (for a strong-named friend)
[assembly:InternalsVisibleToAttribute("MyFriendAssembly, PublicKeyToken=45cb56a45e0a69a1")]

This entry goes in "AssemblyInfo.cs" of the assembly whose internal classes are being exposed. The assembly mentioned in the attribute is the one that is being given permission to access those internal definitions.
For example if Assembly A is a business logic assembly and assembly B is a unit test assembly requiring access to the internals of assembly A then the attribute definition is placed inside assembly A mentioning assembly B inside the attribute so that it may have the required access.

This has changed from .NET 5.0

Add the following to you target project, the one with internals that need to be exposed for unit testing:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
      <_Parameter1>UnitTestProject</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

Standby, Hibernate or Shut Down In .NET

See Standby or Hibernate Windows Programmatically
Using Windows forms static methods is the fastes way
Suspend is:
System.Windows.Forms.Application.SetSuspendState(PowerState.Suspend, false, false);
Hibernate is:
System.Windows.Forms.Application.SetSuspendState(PowerState.Hibernate, true, true);
Alternatively invoke the underlying API SetSuspendState directly.
To shut windows down
[Flags]
public enum ExitWindows : uint
{
    // ONE of the following five:
    LogOff = 0x00,
    ShutDown = 0x01,
    Reboot = 0x02,
    PowerOff = 0x08,
    RestartApps = 0x40,
    // plus AT MOST ONE of the following two:
    Force = 0x04,
    ForceIfHung = 0x10,
}

[Flags]
enum ShutdownReason : uint
{
    MajorApplication = 0x00040000,
    MajorHardware = 0x00010000,
    MajorLegacyApi = 0x00070000,
    MajorOperatingSystem = 0x00020000,
    MajorOther = 0x00000000,
    MajorPower = 0x00060000,
    MajorSoftware = 0x00030000,
    MajorSystem = 0x00050000,

    MinorBlueScreen = 0x0000000F,
    MinorCordUnplugged = 0x0000000b,
    MinorDisk = 0x00000007,
    MinorEnvironment = 0x0000000c,
    MinorHardwareDriver = 0x0000000d,
    MinorHotfix = 0x00000011,
    MinorHung = 0x00000005,
    MinorInstallation = 0x00000002,
    MinorMaintenance = 0x00000001,
    MinorMMC = 0x00000019,
    MinorNetworkConnectivity = 0x00000014,
    MinorNetworkCard = 0x00000009,
    MinorOther = 0x00000000,
    MinorOtherDriver = 0x0000000e,
    MinorPowerSupply = 0x0000000a,
    MinorProcessor = 0x00000008,
    MinorReconfig = 0x00000004,
    MinorSecurity = 0x00000013,
    MinorSecurityFix = 0x00000012,
    MinorSecurityFixUninstall = 0x00000018,
    MinorServicePack = 0x00000010,
    MinorServicePackUninstall = 0x00000016,
    MinorTermSrv = 0x00000020,
    MinorUnstable = 0x00000006,
    MinorUpgrade = 0x00000003,
    MinorWMI = 0x00000015,

    FlagUserDefined = 0x40000000,
    FlagPlanned = 0x80000000
}

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);

internal void ShutDownWindows()
{
    AddShutDownPrivilegeToApp();
    bool res = ExitWindowsEx(
        ExitWindows.ShutDown | ExitWindows.Force, 
        ShutdownReason.MajorOther | ShutdownReason.MinorOther);
}
taken from PInvoke
Trouble is the application must have the correct privileges:
#region Adjust Priveleges

//This snippet is tested on WinXP and Vista, only needed in Vista when using SetTimeZoneInformation
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
phtok);

[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name,
ref long pluid);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
    public int Count;
    public long Luid;
    public int Attr;
}

internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
internal const string SE_TIME_ZONE_NAMETEXT = "SeTimeZonePrivilege"; //http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

private bool AddShutDownPrivilegeToApp()
{
    try
    {
        bool retVal;
        TokPriv1Luid tp;
        IntPtr hproc = GetCurrentProcess();
        IntPtr htok = IntPtr.Zero;
        retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
        tp.Count = 1;
        tp.Luid = 0;
        tp.Attr = SE_PRIVILEGE_ENABLED;
        retVal = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
        retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
        return retVal;
    }
    catch (Exception ex)
    {
        //throw;
        return false;
    }

}
#endregion

Again taken from PInvoke a great web-site

July 29, 2009

Extension Methods On IEnumerable

The 'System.Linq' namespace adds a bunch of useful IEnumerable extension methods. These are used in Linq expressions but can alos be used seperately.

A reference to the 'System.Core' assembly is required. For example performing a count with an enumerator:
using System.Linq;
...
//This saves performing a foreach statement on the enumeration and counting the number of elements
IEnumerable enumKeywords = editor.Sections.RunSpec.GetAll("SMOG");
bool metricUnits = enumKeywords.Count() > 0;
// or
bool metricUnits = editor.Sections.RunSpec.GetAll("SMOG").Count() > 0;
// or (even shorter)
bool metricUnits = editor.Sections.RunSpec.GetAll("SMOG").Any();
There are lots of other useful extensions 'ToList', 'Cast', 'Contains', 'OfType', 'First', 'Last', 'Reverse', 'Union', 'Intersect', 'Aggregate', 'Average', ... For more information, try the following Search

February 6, 2009

System.Drawing.Image Extension Class

Adds simple methods for redrawing images with a given interpolation mode whilst maintaining the aspect ratio.
/// <summary>
/// System.Drawing.Image Extender
/// </summary>
public static class ImageExtender
{

  /// <summary>
  /// Resize the given image to the targetSize using the given interpolation mode
  /// Keeps the existing aspect ratio of the image
  /// </summary>
  /// <param name="srcImage"></param>
  /// <param name="targetSize"></param>
  /// <param name="im"></param>
  /// <returns></returns>
  public static Image ResizeImage(this Image srcImage, Size targetSize, InterpolationMode im)
  {
    Rectangle srcRect = new Rectangle(0, 0, srcImage.Width, srcImage.Height);

    Size sizeToFit = CalcSizeToFit(srcImage.Size, targetSize);
    Rectangle destRect = new Rectangle(0, 0, sizeToFit.Width, sizeToFit.Height);

    Bitmap resizedImage = new Bitmap(sizeToFit.Width, sizeToFit.Height, PixelFormat.Format24bppRgb);
    resizedImage.SetResolution(srcImage.HorizontalResolution, srcImage.VerticalResolution);

    Graphics imageAsCanvas = Graphics.FromImage(resizedImage);
    imageAsCanvas.Clear(Color.White);
    //imageAsCanvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
    imageAsCanvas.InterpolationMode = im;

    imageAsCanvas.DrawImage(srcImage,
      destRect,
      srcRect,
      GraphicsUnit.Pixel);

    imageAsCanvas.Dispose();
    return resizedImage;
  }

  /// <summary>
  /// Resize the given image to the targetSize using bicubic interpolation
  /// Keeps the existing aspect ratio of the image
  /// </summary>
  /// <param name="srcImage"></param>
  /// <param name="targetSize"></param>
  /// <param name="im"></param>
  /// <returns></returns>
  public static Image ResizeImageHighQuality(this Image srcImage, Size targetSize)
  {
    Rectangle srcRect = new Rectangle(0, 0, srcImage.Width, srcImage.Height);

    Size sizeToFit = CalcSizeToFit(srcImage.Size, targetSize);
    Rectangle destRect = new Rectangle(0, 0, sizeToFit.Width, sizeToFit.Height);

    Bitmap resizedImage = new Bitmap(sizeToFit.Width, sizeToFit.Height,
            PixelFormat.Format24bppRgb);
    resizedImage.SetResolution(srcImage.HorizontalResolution,
            srcImage.VerticalResolution);

    using (Graphics imageAsCanvas = Graphics.FromImage(resizedImage))
    {
      imageAsCanvas.Clear(Color.White);
      imageAsCanvas.InterpolationMode = InterpolationMode.HighQualityBicubic;

      imageAsCanvas.DrawImage(srcImage,
          destRect,
          srcRect,
          GraphicsUnit.Pixel);

    }
    return resizedImage;
  }


  /// <summary>
  /// Calculate the best fit of the source size to the target 
  /// size that maintains the aspect ratio
  /// </summary>
  /// <param name="src"></param>
  /// <param name="target"></param>
  /// <returns></returns>
  static public Size CalcSizeToFit(Size src, Size target)
  {
    float sfh = (float)target.Height / (float)src.Height;
    float sfw = (float)target.Width / (float)src.Width;
    float sf = Math.Min(sfh, sfw);
    Size sizeToFit = new Size((int)Math.Round((double)src.Width * sf),
      (int)Math.Round((double)src.Height * sf));
    return sizeToFit;
  }
}

February 5, 2009

Using Application Commands

These are standard application related commands, see here In Xaml:
  <Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Close"
                    Executed="CloseCommandHandler"
                    CanExecute="CanExecuteHandler"
                    />
  </Window.CommandBindings>
...
  <Button Command="ApplicationCommands.Close" 
            Content="Close File" />
and in code:
// Executed event handler.
private void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
    // Calls a method to close the file and release resources.
    CloseFile();
}

// CanExecute event handler.
private void CanExecuteHandler(object sender, CanExecuteRoutedEventArgs e)
{
    // Call a method to determine if there is a file open.
    // If there is a file open, then set CanExecute to true.
    if (IsFileOpened())
    {
        e.CanExecute = true;
    }
    // if there is not a file open, then set CanExecute to false.
    else
    {
        e.CanExecute = false;
    }
}

January 31, 2009

Pinning Arrays

Example of pinning an array While pinned the array stays locked in memory at its current location
 byte[] bytes = new byte[100];
 bytes[0] = 1;
 bytes[1] = 2;
 bytes[2] = 3;
 bytes[3] = 4;

fixed (byte* pBytes = &bytes[0]) 
{
...
}

January 18, 2009

Using Reflection To Get Method Name

Output test class and method name:
string classAndMethodName =
  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString() +
  "." + System.Reflection.MethodBase.GetCurrentMethod().Name.ToString());
Now in Visual C# compiler versions 6, to get the class name we can use:
  string className = nameof(someClass);
and to get the method name
...
public static string GetCurrentMethodName([System.Runtime.CompilerServices.CallerMemberName] string name = "")
{
    return name;
}
...
  string methodName = GetCurrentMethodName()

Useful Byte Array Debugging Classes

Some useful debugging classes for debugging byte arrays. Useful for unit tests.
public static class ByteArrayHelper
{
  // Output the byte array as a C# style byte array variable declaration 
  // where the variable name of the byte array is passed as a parameter
  public static string ToCSharpByteArrayDeclrn(
      this byte[] bytes, string name)
  {
    string res = "byte[] " + name + " = new byte["
        + bytes.Length.ToString() + "] { ";
    int ix = 0;
    for (; ix < bytes.Length - 1; ix++)
    {
      res += "0x" + bytes[ix].ToString("X2") + ", ";
    }
    for (; ix < bytes.Length; ix++)
    {
      res += "0x" + bytes[ix].ToString("X2");
    }
    res += " };";
    return res;
  }

  // Checks whether 2 byte arrays are exactly the same, ie. they have 
  // the same length and the same values at each array entry
  public static bool AreTheSame(this byte[] bytes1, byte[] bytes2)
  {
    bool areTheSame = (bytes1.Length == bytes2.Length);
    for (int ix = 0; (ix < bytes1.Length) && areTheSame; ix++)
    {
      areTheSame = bytes1[ix] == bytes2[ix];
    }
    return areTheSame;
  }

  // XOR together 2 byte arrays
  public static byte[] XOr(this byte[] bytes, byte[] xorBytes)
  {
    Debug.Assert(bytes.Length == xorBytes.Length,
      $"Byte arrays are different sizes: first is {bytes.Length} " +
      $"and the second is {xorBytes.Length}");
    byte[] res = new byte[bytes.Length];
    int len = xorBytes.Length;
    for (int ix = 0; ix < bytes.Length; ix++)
    {
      res[ix] = (byte)(bytes[ix] ^ xorBytes[ix % len]);
    }
    return res;
  }
}

January 1, 2009

WPF Dispatcher

See here for an example
// Similar to Winforms Control.BeginInvoke
Dispatcher.BeginInvoke(DispatcherPriority.Background,
  (SendOrPostCallback)delegate 
  {  
    Progress.SetValue(ProgressBar.ValueProperty, progress); 
  }, 
null);

Converting a Winform Icon to a WPF Icon

private static ImageSource WinFormIconToWpfIcon(System.Drawing.Icon icon)
{
    System.IO.MemoryStream iconStream = new System.IO.MemoryStream();
    icon.Save(iconStream);
    iconStream.Seek(0, System.IO.SeekOrigin.Begin);
    IconBitmapDecoder ibd = new IconBitmapDecoder(iconStream, BitmapCreateOptions.None, BitmapCacheOption.Default);
    return ibd.Frames[0];
}

Access Settings/Resource in c#

Settings take the following form:
// eg. When the setting is a string
$AppNamespace$.Properties.Settings.Default.$PropertyName$ = "somechange"; 
$AppNamespace$.Properties.Settings.Default.Save();
OR
// see the Settings.Designer.cs file for the namespace
using $SomeNamespace$.Properties$
...
// eg. When the setting is a string
Settings.Default.$PropertyName$ = "somechange"; 
Settings.Default.Save();

// to use
myTextBox.Text = Settings.Default.$PropertyName$
Can only save "User Settings" and they do not get saved to the local config file but to: $Drive$:\Documents and Settings\$UserAccount$\Local Settings\Application Data\$ApplicationName$\...

To Access a Resource from a ".resx" file:

var $VariableName$ = Properties.Resources.$ResourceName$