Submitting/Posting Files and Fields to an HTTP Form using C#/.NET

Awhile back, I had to integrate a C# program with a web system that allowed the user to upload a few files and include some misc. data. I Googled around and didn't find a comprehensive solution.

I did use some code I found on the internet, unfortunately I don't remember where, so I can't give proper attribution. If you know, please let me know; it's the code relevant to the MimePart class. I added the form values code and packaged it up into the HttpForm sugar.

Here is the code:

public class HttpForm {

    private Dictionary<string, string> _files = new Dictionary<string, string>();
    private Dictionary<string, string> _values = new Dictionary<string, string>();

    public HttpForm(string url) {
        this.Url = url;
        this.Method = "POST";
    }

    public string Method { get; set; }
    public string Url { get; set; }

    //return self so that we can chain
    public HttpForm AttachFile(string field, string fileName) {
        _files[field] = fileName;
        return this;
    }

    public HttpForm ResetForm(){
        _files.Clear();
        _values.Clear();
        return this;
    }

    //return self so that we can chain
    public HttpForm SetValue(string field, string value) {
        _values[field] = value;
        return this;
    }

    public HttpWebResponse Submit() {
        return this.UploadFiles(_files, _values);
    }


    private HttpWebResponse UploadFiles(Dictionary<string, string> files, Dictionary<string, string> otherValues) {
        var req = (HttpWebRequest)WebRequest.Create(this.Url);

        req.Timeout = 10000 * 1000;
        req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        req.AllowAutoRedirect = false;

        var mimeParts = new List<MimePart>();
        try {
            if (otherValues != null) {
                foreach (var fieldName in otherValues.Keys) {
                    var part = new MimePart();

                    part.Headers["Content-Disposition"] = "form-data; name=\"" + fieldName + "\"";
                    part.Data = new MemoryStream(Encoding.UTF8.GetBytes(otherValues[fieldName]));

                    mimeParts.Add(part);
                }
            }

            if (files != null) {
                foreach (var fieldName in files.Keys) {
                    var part = new MimePart();

                    part.Headers["Content-Disposition"] = "form-data; name=\"" + fieldName + "\"; filename=\"" + files[fieldName] + "\"";
                    part.Headers["Content-Type"] = "application/octet-stream";
                    part.Data = File.OpenRead(files[fieldName]);

                    mimeParts.Add(part);
                }
            }

            string boundary = "----------" + DateTime.Now.Ticks.ToString("x");

            req.ContentType = "multipart/form-data; boundary=" + boundary;
            req.Method = this.Method;

            long contentLength = 0;

            byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");

            foreach (MimePart part in mimeParts) {
                contentLength += part.GenerateHeaderFooterData(boundary);
            }

            req.ContentLength = contentLength + _footer.Length;

            byte[] buffer = new byte[8192];
            byte[] afterFile = Encoding.UTF8.GetBytes("\r\n");
            int read;

            using (Stream s = req.GetRequestStream()) {
                foreach (MimePart part in mimeParts) {
                    s.Write(part.Header, 0, part.Header.Length);

                    while ((read = part.Data.Read(buffer, 0, buffer.Length)) > 0)
                        s.Write(buffer, 0, read);

                    part.Data.Dispose();

                    s.Write(afterFile, 0, afterFile.Length);
                }

                s.Write(_footer, 0, _footer.Length);
            }

            var res = (HttpWebResponse)req.GetResponse();

            return res;
        } catch (Exception ex) {
            Console.WriteLine(ex.Message);
            foreach (MimePart part in mimeParts)
                if (part.Data != null)
                    part.Data.Dispose();

            return (HttpWebResponse)req.GetResponse();
        }
    }

    private class MimePart {
        private NameValueCollection _headers = new NameValueCollection();
        public NameValueCollection Headers { get { return _headers; } }

        public byte[] Header { get; protected set; }

        public long GenerateHeaderFooterData(string boundary) {
            StringBuilder sb = new StringBuilder();

            sb.Append("--");
            sb.Append(boundary);
            sb.AppendLine();
            foreach (string key in _headers.AllKeys) {
                sb.Append(key);
                sb.Append(": ");
                sb.AppendLine(_headers[key]);
            }
            sb.AppendLine();

            Header = Encoding.UTF8.GetBytes(sb.ToString());

            return Header.Length + Data.Length + 2;
        }

        public Stream Data { get; set; }
    }
}

You can easily use it like so:

var file1 = @"C:\file";
var file2 = @"C:\file2";

var yourUrl = "http://yourdomain.com/process.php";
var httpForm = new HttpForm(yourUrl);
httpForm.AttachFile("file1", file1).AttachFile("file2", file2);
httpForm.setValue("foo", "some foo").setValue("blah", "rarrr!");
httpForm.Submit();

Do you use Git? If so, checkout Gitpilot to make using Git thoughtless.

Follow me on Twitter: @jprichardson.

-JP Richardson

FridayThe13th the Best JSON Parser for Silverlight and C#/.NET

Up until a couple of months ago I was writing most of my code using WPF. Recently, a project came up where Silverlight made more sense to use. I’d thought that wouldn’t be a problem since I’d just use JavaScriptSerializer [wrote about it here] like I did for my WPF project.

Uh oh. It turns out that Silverlight doesn’t have JavaScriptSerializer. Never fear! DataContractJsonSerializer is here! Or so I thought.

It turns out that if you want to use DataContractJsonSerializer you must actually create POCOs to backup this “data contract.” I didn’t want to do that.

I wanted to turn this…

{
	"some_number": 108.541,
	"date_time": "2011-04-13T15:34:09Z",
	"serial_number": "SN1234"
	"more_data": {
		"field1": 1.0
		"field2": "hello"
	}
}

into..

using System.Web.Script.Serialization;

var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<dynamic>(jsonText);

Console.WriteLine(dict["some_number"]); //outputs 108.541
Console.WriteLine(dict["more_data"]["field2"]); //outputs hello

So I set out to write my own JSON parser. I call it FridayThe13th… how fitting huh? Now, using either Silverlight or .NET 4.0, you can parse the previous JSON into the following:

using FridayThe13th;

var jsonText = File.ReadAllText("mydata.json");

var jsp = new JsonParser(){CamelizeProperties = true};
dynamic json = jsp.Parse(jsonText);

Console.WriteLine(json.SomeNumber); //outputs 108.541
Console.WriteLine(json.MoreData.Field2); //outputs hello

Since I work with a lot of Ruby on Rails backends, I want to add a property “CamelizeProperties” to turn “some_number” into “SomeNumber”… it’s more .NET like.

Try it! You can find it on Github. Oh yeah… it’s also faster than that other .NET JSON library that everyone uses.

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

If you made it this far, read my blog on software entrepreneurship and follow me on Twitter: @jprichardson.

-JP

Missing DockPanel? Add DockPanel for Silverlight 4 or Silverlight 5

When I first created a demo project for Silverlight 5, I opened the XAML code to start editing. I started typing “DockPanel” but then I noticed that intellisense didn’t show anything. It turns out that DockPanel and some other controls aren’t included in the default installation of Silverlight 4 or Silverlight 5 beta.

Here’s what you need to do:

  1. Download the Silverlight 4 Toolkit. Install it. (Yes, this will work with Silverlight 5 beta)
  2. Add a reference to “System.Windows.Controls.Toolkit”. In Silverlight 5, you will need to navigate to the file:
    %ProgramFiles%\Microsoft SDKs\Silverlight\v4.0\Toolkit\Apr10\Bin\System.Windows.Controls.Toolkit.dll
  3. Add the following attribute to your UserControl: xmlns:tk=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit”
  4. So your code might look like:

    <UserControl x:Class="Project1.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    	xmlns:tk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">
    
        <Grid x:Name="LayoutRoot" Background="White">
    		<tk:DockPanel>
    			
    		</tk:DockPanel>
        </Grid>
    	
    </UserControl>
    

    Enjoy.

    Advertisement:
    Make Git simple. Let Gitpilot show you the right way to Git things done. Gitpilot will help you write software faster.

    Follow me on Twitter: @jprichardson and read my blog on software entrepreneurship: Techneur

    -JP

Linear Regression in C#/.NET Using Least Squares

I had a class that handled the regression of my data sets, but it had too many business rules. It was necessary for me to refactor the code.

Here’s how you can use it:

double[] X = { 75.0, 83, 85, 85, 92, 97, 99 };
double[] Y = { 16.0, 20, 25, 27, 32, 48, 48 };
var ds = new XYDataSet(X, Y);

Console.WriteLine(Math.Round(ds.Slope,2)); //1.45
Console.WriteLine(Math.Round(ds.YIntercept,2)); //-96.85
ConsoleWriteLine(Math.Round(ds.ComputeRSquared(), 3)); //0.927

The source is in my .NET CommonLib library.
XYDataSet.cs: https://github.com/jprichardson/CommonLib/blob/master/CommonLib/Numerical/XYDataSet.cs
XYDataSetTest.cs: https://github.com/jprichardson/CommonLib/blob/master/TestCommonLib/Numerical/XYDataSetTest.cs

Here is the source for XYDataSet.cs:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using CommonLib.Geometry;

namespace CommonLib.Numerical
{
	public class XYDataSet : IList<PointD>
	{
		
		private List<PointD> _internalList = new List<PointD>();

		public XYDataSet() : this(null, null) { }

		public XYDataSet(IEnumerable<PointD> points) {
			ResetValues();

			foreach (var point in points)
				Add(point);
		}

		public XYDataSet(IEnumerable<double> Xs, IEnumerable<double> Ys) {
			ResetValues();
			
			if (Xs != null || Ys != null) {
				if (Xs.Count() != Ys.Count())
					throw new Exception("X count must be the same as the Y count.");

				for (int i = 0; i < Xs.Count(); ++i)
					Add(Xs.ElementAt(i), Ys.ElementAt(i));
			}
		}

		public int Count { get { return _internalList.Count; } }

		public bool IsReadOnly { get { return false; } }

		private double _maxX = Double.NegativeInfinity;
		public double XMax { get { return _internalList[XMaxIndex].X; } }
		private double _minX = Double.PositiveInfinity;
		public double XMin { get { return _internalList[XMinIndex].X; } }
		public int XMaxIndex { get; protected set; }
		public int XMinIndex { get; protected set; }

		private double _maxY = Double.NegativeInfinity;
		public double YMax { get { return _internalList[YMaxIndex].Y; } }
		private double _minY = Double.PositiveInfinity;
		public double YMin { get { return _internalList[YMinIndex].Y; } }
		public int YMaxIndex { get; protected set; }
		public int YMinIndex { get; protected set; }

		public double XMean { get { return XSum / Count; } }
		public double YMean { get { return YSum / Count; } }

		public double RSquare { get; protected set; }

		public PointD RegressionPoint0 { get; protected set; }
		public PointD RegressionPointN { get; protected set; }

		public double Slope { get; protected set; }

		public double XSum { get; set; }
		public double YSum { get; set; }
		public double XSquaredSum { get; set; }
		public double XYProductSum { get; set; }

		public double XIntercept { get { return -YIntercept / Slope; } }
		public double YIntercept { get; protected set; }


		public PointD this[int index] {
			get { return _internalList[index]; }
			set {
				var p = value;
				var old = _internalList[index];
				_internalList[index] = p;

				ComputeSums(old, SumMode.Subtract);
				ComputeSums(p, SumMode.Add);
				ComputeMinAndMax();
				ComputeSlopeAndYIntercept();
			}
		}

		public void Add(double x, double y) {
			Add(new PointD(x, y));
		}

		public void Add(PointD p) {
			_internalList.Add(p);
			RSquare = double.NaN;

			ComputeSums(p, SumMode.Add);
			ComputeMinAndMax(Count - 1, p);
			ComputeSlopeAndYIntercept();
		}

		public void Clear() {
			_internalList.Clear();
			ResetValues();
		}

		public void ComputeSlopeAndYIntercept() {
			double delta = Count * XSquaredSum - Math.Pow(XSum, 2.0);
			YIntercept = (1.0 / delta) * (XSquaredSum * YSum - XSum * XYProductSum);
			Slope = (1.0 / delta) * (Count * XYProductSum - XSum * YSum);

			RegressionPoint0.X = XMin;
			RegressionPoint0.Y = Slope * XMin + YIntercept;
			RegressionPointN.X = XMax;
			RegressionPointN.Y = Slope * XMax + YIntercept;
		}

		public double ComputeRSquared() {
			var SStot = _internalList.Sum(p => Math.Pow(p.Y - YMean, 2.0));
			var SSerr = _internalList.Sum(p => Math.Pow(p.Y - (Slope * p.X + YIntercept), 2.0));
			RSquare = 1.0 - SSerr / SStot;
			return RSquare;
		}

		public bool Contains(PointD p) {
			return _internalList.Contains(p);
		}

		public void CopyTo(PointD[] points, int index) {
			_internalList.CopyTo(points, index);
		}

		public IEnumerator<PointD> GetEnumerator() {
			return _internalList.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator() {
			return _internalList.GetEnumerator();
		}

		public int IndexOf(PointD p) {
			return _internalList.IndexOf(p);
		}

		public void Insert(int index, PointD p) {
			_internalList.Insert(index, p);
			RSquare = double.NaN;

			ComputeSums(p, SumMode.Add);
			ComputeMinAndMax();
			ComputeSlopeAndYIntercept();
		}

		public bool Remove(PointD p) {
			var success = _internalList.Remove(p);
			if (success) {
				RSquare = double.NaN;
				ComputeSums(p, SumMode.Subtract);
				ComputeMinAndMax();
				ComputeSlopeAndYIntercept();
			}
			return success;
		}

		public void RemoveAt(int index) {
			var old = _internalList[index];
			_internalList.RemoveAt(index);
			RSquare = double.NaN;

			ComputeSums(old, SumMode.Subtract);
			ComputeMinAndMax();
			ComputeSlopeAndYIntercept();
		}

		protected void ComputeMinAndMax() { //methods that call this, Insert, 
			ResetMinAndMax();

			for (int i = 0; i < _internalList.Count; ++i)
				ComputeMinAndMax(i, _internalList[i]);
		}

		protected void ComputeMinAndMax(int index, PointD newPoint) {
			if (newPoint.X <= _minX) {
				_minX = newPoint.X;
				XMinIndex = index;
			}

			if (newPoint.X >= _maxX) {
				_maxX = newPoint.X;
				XMaxIndex = index;
			}

			if (newPoint.Y <= _minY) {
				_minY = newPoint.Y;
				YMinIndex = index;
			}

			if (newPoint.Y >= _maxY) {
				_maxY = newPoint.Y;
				YMaxIndex = index;
			}
		}

		protected enum SumMode { Add, Subtract };
		protected void ComputeSums(PointD p, SumMode mode) {
			if (mode == SumMode.Add) {
				XSum += p.X;
				YSum += p.Y;
				XSquaredSum += Math.Pow(p.X, 2.0);
				XYProductSum += (p.X * p.Y);
			}
			else if (mode == SumMode.Subtract) {
				XSum -= p.X;
				YSum -= p.Y;
				XSquaredSum -= Math.Pow(p.X, 2.0);
				XYProductSum -= (p.X * p.Y);
			}
		}

		protected void ResetMinAndMax() {
			_maxX = double.NegativeInfinity;
			_maxY = double.NegativeInfinity;
			_minX = double.PositiveInfinity;
			_minY = double.PositiveInfinity;
		}

		protected void ResetValues() {
			ResetMinAndMax();

			RegressionPoint0 = new PointD();
			RegressionPointN = new PointD();

			RSquare = double.NaN;

			Slope = double.NaN;
			YIntercept = double.NaN;

			XSum = 0.0;
			YSum = 0.0;
			XSquaredSum = 0.0;
			XYProductSum = 0.0;

			XMaxIndex = -1;
			YMaxIndex = -1;
			XMinIndex = -1;
			YMinIndex = -1;
		}
		
	}
}

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Follow me on Twitter: @jprichardson and read my blog on software entrepreneurship: Techneur

-JP

Quick JSON Serialization/Deserialization in C#

*This outdated*. You should use FridayThe13th the best JSON parser for Silverlight and .NET 4.0.

You don’t need to download an additional libraryto serialize/deserialize your objects to/from JSON. Since .NET 3.5, .NET can do it natively.

Add a reference to your project to “System.Web.Extensions.dll”

Let’s look at this example JSON string:

{
	"some_number": 108.541, 
	"date_time": "2011-04-13T15:34:09Z", 
	"serial_number": "SN1234"
}

You can deserialize the previous JSON into a dictionary like so:

using System.Web.Script.Serialization;

var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string,string>>(jsonText);

Console.WriteLine(dict["some_number"]); //outputs 108.541

So what if your JSON is a bit more complex?

{
	"some_number": 108.541, 
	"date_time": "2011-04-13T15:34:09Z", 
	"serial_number": "SN1234"
	"more_data": {
		"field1": 1.0
		"field2": "hello"	
	}
}

Deserialize like so…

using System.Web.Script.Serialization;

var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string,dynamic>>(jsonText);

Console.WriteLine(dict["some_number"]); //outputs 108.541
Console.WriteLine(dict["more_data"]["field2"]); //outputs hello

The field “more_data” gets deserialized into a Dictionary<string, object>.

You can actually just just deserialize like so:

using System.Web.Script.Serialization;

var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<dynamic>(jsonText);

Console.WriteLine(dict["some_number"]); //outputs 108.541
Console.WriteLine(dict["more_data"]["field2"]); //outputs hello

And everything still works the same. The only caveat is that you lose intellisense by using the “dynamic” data type.

Serialization is just as easy:

using System.Web.Script.Serialization;

var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<dynamic>(jsonText);

var json = jss.Serialize(dict);
Console.WriteLine(json);

Outputs…

{
	"some_number": 108.541, 
	"date_time": "2011-04-13T15:34:09Z", 
	"serial_number": "SN1234"
	"more_data": {
		"field1": 1.0
		"field2": "hello"	
	}
}

Do you use Git? If so, checkout Gitpilot to make project management and collaborating on projects seamless.

If you made it this far, read my blog on software entrepreneurship and follow me on Twitter: @jprichardson.

-JP

StreamWriter Share Read Access in Another Process

I have two applications, one is the main application that generates a log file, the other is an application that reads the log file to compute statistics.

I want my app that reads the log file to be able to read the file while the other app is running and generating the log file. If you just use the default StreamWriter and StreamReader constructors you will get a file access in error in one of the processes.

Log file generator: (1st process)

static void Main(string[] args) {
	var file = @"C:\logfile.txt";
	var sw = new StreamWriter(file);
	sw.AutoFlush = true;
	sw.WriteLine("some data");
	sw.WriteLine("some data2"); //set breakpoint here
	
	sw.Close();
}

Log file reader: (2nd process)

static void Main(string[] args) {
	var file = @"C:\logfile.txt";
	var sr = new StreamReader(file);

	var l1 = sr.ReadLine();
	var l2 = sr.ReadLine(); //set breakpoint here

	sr.Close();
}

Startup the “log file generator” app and then startup the “log file reader” app, you’ll get an IOException.
Here’s how you can fix this:

Log file generator: (1st process)

static void Main(string[] args) {
	var file = @"C:\logfile.txt";
	var fs = File.Open(file, FileMode.Append, FileAccess.Write, FileShare.Read);
	var sw = new StreamWriter(fs);
	sw.AutoFlush = true;
	sw.WriteLine("some data");
	sw.WriteLine("some data2"); //set breakpoint here
	
	sw.Close();
}

Log file reader: (2nd process)

static void Main(string[] args) {
	var file = @"C:\logfile.txt";
	var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
	var sr = new StreamReader(fs);

	var l1 = sr.ReadLine();
	var l2 = sr.ReadLine(); //set breakpoint here

	sr.Close();
}

You’ll notice that the breakpoint on the 2nd process will now work without getting an IOException. In short this works because the FileShare permissions are set properly. You can also read more about the enum FileMode.

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Follow me on Twitter: @jprichardson and read my blog on entrepreneurship.

-JP

WPF Application Wide Exception Handling

What do you do if you want to catch all unhandled exceptions in an application?

In App.xaml:

<Application x:Class="MyApp.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DispatcherUnhandledException="UnhandledException"
>

Add “DispatcherUnhandledException” to App.xaml. Then in your App.xaml.cs file:

private void UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) {
	var time = DateTime.Now;
	File.AppendAllText(@"C:\exps.csv", string.Format("{0},{1}", time, e.Exception.Message));
	File.AppendAllText(@"C:\sts.txt", time + ":\n" + e.Exception.StackTrace + "\n");
	e.Handled = false; //we want the user to experience the crash
}

That’s it. So now if the app crashes on your users, you don’t have to ask your users what steps they did to cause the crash. You can just look at the logs!

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Follow me on Twitter @jprichardson or read my blog on software entrepreneurship.

-JP

Memcached Alternative for C#/.NET

I’m currently developing a software package that has to retrieve large amounts of data from a server. This data is needed frequently throughout the application and doesn’t change much in a given day. This sounds like a perfect use case for Memcached, or so I thought. After I installed the .NET Memcached adapters, I was in for a big surprise. Memcached has a 1 MB value limit!

So, like any good developer I wrote my own tool. First, two caveats, as I don’t want to waste your time.
1) I wouldn’t use this in a production environment. It just hasn’t had enough rigorous testing. YMMV.
2) It only works on the same machine that the app resides on. Yes, I realize that this is a huge caveat.

Why?

So, what was my use case? I follow a loose Agile process of delivering every week. Well, as the production went on, more data would accumulate on the server. I needed a quick way to cache this data locally without rewriting my algorithms in the short term. Thus, MemMapCache was born.

How Does It Work?

It uses memory mapped files that are new in .NET 4.0 (they just wrap the Win32 API). The client creates a key and persists the object value to a memory mapped file using the said key. It then passes the key onto the server so that the server can keep the reference. This prevents the .NET garbage collector from cleaning up the memory mapped file so that upon a new instance of the client, it can still retrieve the data.

How do you use it?

Go clone this project: https://github.com/jprichardson/MemMapCache and then add MemMapCacheLib to your project. You’ll need to make sure that MemMapCache.exe is running on your system.

var cache = new MemMapCache();
cache.Connect();

var col = new Dictionary<string, int>();
col.Add("hello", 5);
col.Add("hi", 2);

cache.Set("myKey", col);

var newCol = cache.Get<Dictionary<string,int>>("myKey");

//you can pass in an expiration time as DateTime or TimeSpan
cache.Set("newKey", "some data", DateTime.Now.AddMinutes(4)); 

//hypothetical large data repository that returns IEnumerable<double>
var dataRepo = new DataRepository(); 

//you can even call one function to retrieve the last value for a key, if it doesn't exist set a new value
IEnumerable<double> largeDataSet = cache.TryGetThenSet("dataSetKey", () => dataRepo.LoadLargeDataSet());

//you can also specify for the cache to always miss, in case you have it deeply embedded in your code and you want to run unit tests that aren't cache dependent
cache.CacheHitAlwaysMiss = true

That’s it. It’s come in handy for me during development. If you find this useful please leave a comment.

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Follow me on Twitter @jprichardson or read my blog on entrepreneurship: Techneur

-JP

Forcing Single Instance for WPF Apps

Sometimes you may not want to allow multiple instances for your WPF apps. You can use a Mutex to accomplish this. Credit goes to this StackOverflow question: “What is the correct way to create a single instance application?” for mashing these ideas together.

public partial class App : Application
{
	[DllImport("user32.dll")]
	private static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
	private const int SW_MAXIMIZE = 3;
	private const int SW_SHOWNORMAL = 1;

	private static Mutex singleInstanceMutex = new Mutex(true, "AnyUniqueStringToYourApp");

	protected override void OnStartup(StartupEventArgs e) {
		base.OnStartup(e);
		if (singleInstanceMutex.WaitOne(TimeSpan.Zero, true))
			Program.OnStartup();
		else {
			var procs = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
			foreach (var p in procs.Where(p => p.MainWindowHandle != IntPtr.Zero)) {
				ShowWindow(p.MainWindowHandle, SW_MAXIMIZE);
					Application.Current.Shutdown();
					return;
				}
			}	
		}
	}
}

The basic idea is that the startup code checks the mutex and maximizes the application if the app isn’t already open. You can view the MSDN docs for ShowWindow and pass any of the associated constants to alter the behavior of the window if it is already running.

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Read my blog on entrepreneurship and follow me on Twitter.

-JP

Including More than One ResourceDictionary in Your Xaml

I have one giant Xaml ResourceDictionary that’s becoming unwieldy to manage. The solution is simple. Use MergedDictionaries.

Snippet:

<Window.Resources>
	<ResourceDictionary>
		<ResourceDictionary.MergedDictionaries>
			<ResourceDictionary Source="FileResources1.xaml" />
			<ResourceDictionary Source="FileResources2.xaml" />
		</ResourceDictionary.MergedDictionaries>
	</ResourceDictionary>
</Window.Resources>

Are you a Git user? Let me help you make project management with Git simple. Checkout Gitpilot.

Follow me on Twitter @jprichardson and read my blog on entrepreneurship.

-JP

Follow

Get every new post delivered to your Inbox.