<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bo Wu&#039;s IT Lab &#187; Microsoft</title>
	<atom:link href="http://www.bowu.org/category/microsoft/feed" rel="self" type="application/rss+xml" />
	<link>http://www.bowu.org</link>
	<description>If winter comes, can spring be far behind?</description>
	<lastBuildDate>Thu, 29 Dec 2011 18:09:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>CEO Friday: Why we don’t hire .NET programmers</title>
		<link>http://www.bowu.org/microsoft/net/dont-hire-net-programmers.html</link>
		<comments>http://www.bowu.org/microsoft/net/dont-hire-net-programmers.html#comments</comments>
		<pubDate>Fri, 23 Dec 2011 17:38:24 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=596</guid>
		<description><![CDATA[Written by David Barrett March 25, 2011 at 7:00 am Posted in CEO Friday, Job Original Post URL: http://blog.expensify.com/2011/03/25/ceo-friday-why-we-dont-hire-net-programmers/ As you might know, we’re hiring the best programmers in the world. Sure, everyone says that. But my coders will beat up your coders, any day of the week. For example, Mich is barely 5 foot [...]]]></description>
			<content:encoded><![CDATA[<p>Written by David Barrett<br />
March 25, 2011 at 7:00 am<br />
Posted in CEO Friday, Job<br />
Original Post URL: http://blog.expensify.com/2011/03/25/ceo-friday-why-we-dont-hire-net-programmers/</p>
<hr />
<p><img class="alignnone" title="Microsoft .NET" src="http://www.ssdntech.com/images/dotnet.png" alt="dotnet CEO Friday: Why we don’t hire .NET programmers" width="419" height="269" /></p>
<p>As you might know, we’re hiring the best programmers in the world.  Sure, everyone says that.  But my coders will beat up your coders, any day of the week.  For example, Mich is barely 5 foot tall, but is a competitive fencer.  Witold is a 6’3″ former professional hockey player.  Nate practices knife fighting for fun.  And they’re pretty decent programmers, too.</p>
<p>But finding such people is more than a full time job.  Indeed, I spend about half my time on it, while Lisa spends about all hers.  And on top of that we have an army of recruiters out scouring the globe, leaving no resume unturned.  Taken all together, this creates a lot of resumes.  So many that we don’t look at them, because resumes — let’s be honest — are totally worthless.  Rather, we pay all our attention to a few key questions we ask every candidate, each aiming at uncovering a single key point: is this someone we really want to work with?</p>
<p>See, experience is cheap.  All it takes is time.  Skill is harder, but really only requires hard work — a lot of people can get that.  But attitude.  You either have it, or you don’t.  The right sort of person is so passionate about coding, they can’t be stopped from doing it.  They typically started before high school — sometimes before middle school — and never looked back.  They write everything from assembly to jQuery, on PCs to mobile phones, doing hard core computer graphics to high level social networking.  They’ve tried everything.</p>
<p>Everything, that is, but .NET.</p>
<p>Now let me clarify — .NET is a dandy language.  It’s modern, it’s fancy, it’s got all the bells and whistles.  And if you’re doing Windows Mobile 7 apps (which the stats suggest you aren’t), it’s your only choice.  But choosing .NET is a choice, and whenever anybody does it, I can’t help but ask “why?”</p>
<p>Don’t get me wrong: .NET on your resume isn’t an instant showstopper.  But it will definitely raise questions during the phone screen, for reasons that are best explained by simile:</p>
<p>Programming with .NET is like cooking in a McDonalds kitchen.  It is full of amazing tools that automate absolutely everything.  Just press the right button and follow the beeping lights, and you can churn out flawless 1.6 oz burgers faster than anybody else on the planet.</p>
<p>However, if you need to make a 1.7 oz burger, you simply can’t.  There’s no button for it.  The patties are pre-formed in the wrong size.  They start out frozen so they can’t be smushed up and reformed, and the thawing machine is so tightly integrated with the cooking machine that there’s no way to intercept it between the two.  A McDonalds kitchen makes exactly what’s on the McDonalds menu — and does so in an absolutely foolproof fashion.  But it can’t go off the menu, and any attempt to bend the machine to your will just breaks it such that it needs to be sent back to the factory for repairs.</p>
<p>Instead, we look for a very different sort of person.  The sort of person who grew up cooking squirrels over a campfire with sharpened sticks — squirrels they caught and skinned while scavenging in the deep forests for survival.  We don’t want a short order chef, we want a Lord of the Flies, carried by wolves into civilization and raised in a French kitchen full of copper-bottomed pots and fresh-picked herbs.  We need people who can not only cook burgers, but cook anything, from scratch.</p>
<p>See, Microsoft very intentionally (and very successfully) created .NET to be as different as possible from everything else out there, keeping the programmer far away from the details such that they’re wholly and utterly dependent on Microsoft’s truly amazing suite of programming tools to do all the thinking for them.  Microsoft started down this path when they were the only game in town, explicitly to maintain their monopoly by making it as hard as possible to either port Windows apps to non-Windows platforms, or to even conceive of how to do it in the first place.</p>
<p>This decision — or this mandate for incompatibility, perhaps — has produced countless ramifications.  Small things, like using backslashes in file paths rather than forward slashes like any dignified OS., or using a left-handed coordinate system with DirectX instead of right-handed as was used since the dawn of computer graphics.  Big things, like obscuring the networking stack under so many countless layers of abstraction that it’s virtually impossible to even imagine what bytes are actually going over the wire.  And a thousand other things in between: programming tools that generate a dozen complex files before you even write your first line of code, expensive servers that force a remote GUI terminal on you to do essentially anything despite a few keystrokes being perfectly adequate for everybody else,  a programming culture almost allergic to open source licensing.  The list goes on and on.</p>
<p>None of this makes you a “bad programmer”.  All these differences are perfectly irrelevant if you just want to make 1.6 oz burgers as fast as possible, and commit the rest of your career to an endless series of McDonalds menus.  But every day spent in that kitchen is a day NOT spent in a real kitchen, learning how to cook real food, and write real code.</p>
<p>Even worse, every day spent learning a Microsoft kitchen takes TWO days to unlearn, meaning once you get a reasonable way down the .NET career path, there is almost no going back.  You become so steeped in tools and techniques that have absolutely no relevance outside of .NET that you are actually less valuable to a startup than had you just taken a long nap.</p>
<p>So what’s the moral of this whole story?  Two things:</p>
<p>If you ever want to work in a startup, avoid .NET.  It does you no favors.<br />
If you are a startup looking to hire really excellent people, take notice of .NET on a resume, and ask why it’s there.</p>
<p>It might sound harsh, and it is.  But sometimes we only have squirrels to eat, and we need them to taste good.</p>
<p>-david (Follow us at https://twitter.com/expensify)</p>
<p>Saturday edit: Wow, this post has hit quite a nerve.  Had I known it was going to take the internet by storm I probably would have been a bit more careful with my word choice (especially referring to .NET as a language, doh!).  But just to clarify a couple points, 24-hours into the storm:</p>
<p>Yes, .NET developers are great at what they do. It’s the most modern platform for application development on the planet.  Microsoft has always produced the best tools for building internal business applications, and .NET is their masterpiece.  There’s a reason why they own that space; they earned it.  That space employs millions of people, and those people are unquestionably the masters at what they do.<br />
But what they do is very, very rarely startups. I’m sorry if that sounds offensive, but that’s a simple fact.  You can measure this yourself: go to any list of startups, maybe look at YCombinator’s recent graduate class, or Scoble’s list of picks for 2010, or Sequoia’s list of seed companies — or  go find a list you like better.  Do a curl (or your .NET equivalent) on each domain, and see how many are running a Windows server: I think you’ll find the fraction very small.  Don’t get me wrong: there are a lot of people who aren’t interested in working at a startup, for a lot of very valid reasons.  But if you are the odd person who is interested, it’s worth asking: why do so few use .NET?<br />
Because .NET is designed to extend, not disrupt. The same could largely be said about J2EE, but in general anybody who “grows up” with these self-contained, highly-automated platforms can’t help but view computers in a different way than those who start from a lower, less automated, more difficult level.  (As one of the coherent commentators says below, Joel Spolsky himself laments schools teaching Java with the same basic reasoning of my article above, albeit more diplomatically stated.)  .NET is designed to tightly integrate with and seamlessly extend the Microsoft stack in extremely powerful but ultimately incremental ways.  Again, there’s nothing wrong about that if that’s what you want to do.  But if that’s not what you want to do, then .NET probably isn’t the right choice, as evidenced by how few people in the startup world choose it.</p>
<p>Again, this isn’t a rant against .NET — it’s fine.  It’s not even a rant against .NET developers being incapable of learning — they can learn as well as anyone.  It’s a rant against .NET teaching the wrong things for startups.  And about how people who use it for too long, can’t help but learn those things.  This is a rant about how startups, by definition, need to think of things from new angles, and those angles typically don’t involve .NET.</p>
<p>Anyway, I was going to leave all this to blow over before making any comments in a follow-up post next Friday.  Indeed, for all the outrage and fury, this is actually common knowledge amongst startups, and I was going to support that with a bit more data to win over the skeptics (at least, those who were open to listening).</p>
<p>But I’ve seen some recent comments that this post might have upset and offended the SMB community that we serve, and that I cannot abide.  For that, I’m truly sorry.  As someone who grew up using and ultimately becoming frustrated with the limitations of Microsoft tools, and grew up submitting and hating small-business expense reports, I hope I can convince you that we’re fighting for the same goals.  Even if our tools and techniques might differ wildly.</p>
<p>Sunday edit: Incredible that this post is still going strong, on a weekend no less.  But what’s most interesting is how the comments have gradually shifted over time.  Granted, me even pointing this out will probably have an effect on comments going forward, but the general trend has been:</p>
<p>First wave: Raw, incoherent hate, constructed from near-pure profanity.  I took the liberty of deleting most of this, as this is a PG-13 site.  Perhaps 1% of the first wave agreed with me.<br />
Second wave: “Reasoned” hate, though most of that reasoning was done by extrapolating my misuse of one word (“language” instead of “platform”) into every conceivable sin.  I’d say maybe 15% of the second wave agreed with me (if weighted by actual coherent text).<br />
Third wave: A very heated discussion.  It would appear that every possible insult had already been slung so there was nothing left to do but actually discuss the merits of the post.  I’d say maybe 25% of the third wave agreed with me.</p>
<p>It’s harder to get a sense of agreement/disagreement from Twitter as most people just retweet without comment.  But I’d say those who do make comments have fit the rough curve above.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/net/dont-hire-net-programmers.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tips on using Windows PC</title>
		<link>http://www.bowu.org/microsoft/windows/tips-windows-pc.html</link>
		<comments>http://www.bowu.org/microsoft/windows/tips-windows-pc.html#comments</comments>
		<pubDate>Mon, 20 Jun 2011 19:30:13 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=567</guid>
		<description><![CDATA[1. Concatenate Multiple Text Files in Windows: You have a directory full of log files that you want to import into Excel or a database so you can do some processing on them… but there are hundreds of files… how do you make them into a single file? copy /a *.log aggregate.txt 2. How to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.wdtvc.com/wp-content/uploads/2009/04/windows_logo.jpg" alt="windows logo Tips on using Windows PC"  title="Tips on using Windows PC" /></p>
<p><strong>1. Concatenate Multiple Text Files in Windows:</strong></p>
<p>You have a directory full of log files that you want to import into Excel or a database so you can do some processing on them… but there are hundreds of files… how do you make them into a single file?</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">copy /a *.log aggregate.txt</div></div>
<p><strong>2. How to delete a large folder of a large number of files?</strong><br />
(1) Command Line:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rmdir /s /q &quot;My Apps&quot;<br />
rmdir /s /q &quot;My Documents&quot;<br />
rmdir /s /q &quot;My Pictures&quot;<br />
rmdir /s /q &quot;My Work Files”</div></div>
<p>(2) Windows Explorer:<br />
Select the folder and then hold down the Shift key and then Delete. You&#8217;ll be prompted about permanently deleting the files. No recycle bin should speed this up.</p>
<p><strong>3. How to change Windows Command Line Prompt Default Location?</strong><br />
Run &#8211;> regedit.exe</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">HKEY_CURRENT_USER \ Software \ Microsoft \ Command Processor<br />
Add a new String Value in the right pane:<br />
Name: Autorun<br />
Value: CD /d C:\foldername</div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/windows/tips-windows-pc.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serialization in .NET Programming</title>
		<link>http://www.bowu.org/microsoft/net/serialization-net-programming.html</link>
		<comments>http://www.bowu.org/microsoft/net/serialization-net-programming.html#comments</comments>
		<pubDate>Thu, 19 Aug 2010 23:23:18 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[Serializable]]></category>
		<category><![CDATA[Serialization]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=440</guid>
		<description><![CDATA[If you want to Binary or XML Serialization in .NET Programming and you are using C#, you can use following code. using System; using System.IO; using System.Collections; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; using System.Web.Mail; namespace npuInfoCS.Utilities { &#160; &#160; public class Serialization &#160; &#160; { &#160; &#160; &#160; &#160; public enum SerializationFormat {Xml, Binary} [...]]]></description>
			<content:encoded><![CDATA[<p>If you want to Binary or XML Serialization in .NET Programming and you are using C#, you can use following code.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">using System;<br />
using System.IO;<br />
using System.Collections;<br />
using System.Runtime.Serialization;<br />
using System.Runtime.Serialization.Formatters;<br />
using System.Runtime.Serialization.Formatters.Binary;<br />
using System.Web.Mail;<br />
<br />
namespace npuInfoCS.Utilities<br />
{<br />
&nbsp; &nbsp; public class Serialization<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; public enum SerializationFormat {Xml, Binary}<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static System.Boolean SerializeToDisk(string path, object request, SerializationFormat format) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.IO.MemoryStream oStream = Serialize(request, format);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(System.IO.File.Exists(path)) System.IO.File.Delete(path);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.IO.FileStream output = System.IO.File.Open(path, System.IO.FileMode.CreateNew);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.Write(oStream.ToArray(),0,Convert.ToInt32(oStream.Length));<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oStream.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch(Exception e)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static object DeSerializeFromDisk(string path, SerializationFormat format) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(System.IO.File.Exists(path)) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.IO.FileStream input = System.IO.File.Open(path, System.IO.FileMode.Open);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byte[] filecontents=new byte[Convert.ToInt32(input.Length)];<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; input.Read(filecontents, 0, Convert.ToInt32(input.Length));<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; input.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //System.IO.File.Delete(path);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.IO.MemoryStream inStream = new System.IO.MemoryStream(filecontents);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object newObj = DeSerialize(inStream, format);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; inStream.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return newObj;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch(Exception e) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; #region wrappers for binary and xml serialization<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static System.IO.MemoryStream Serialize(object request, SerializationFormat format) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(format==SerializationFormat.Binary)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return SerializeBinary(request);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return SerializeSOAP(request);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static object DeSerialize(System.IO.MemoryStream memStream, SerializationFormat format) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(format==SerializationFormat.Binary)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return DeSerializeBinary(memStream);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return DeSerializeSOAP(memStream);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; #region Binary Serializers<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static System.IO.MemoryStream SerializeBinary(object request) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.IO.MemoryStream memStream = new System.IO.MemoryStream();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; serializer.Serialize(memStream, request);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return memStream;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static object DeSerializeBinary(System.IO.MemoryStream memStream) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; memStream.Position=0;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.Runtime.Serialization.Formatters.Binary.BinaryFormatter deserializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object newobj = deserializer.Deserialize(memStream);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; memStream.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return newobj;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; #region XML Serializers<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static System.IO.MemoryStream SerializeSOAP(object request) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.Runtime.Serialization.Formatters.Soap.SoapFormatter serializer = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.IO.MemoryStream memStream = new System.IO.MemoryStream();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; serializer.Serialize(memStream, request);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return memStream;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static object DeSerializeSOAP(System.IO.MemoryStream memStream) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; object sr;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.Runtime.Serialization.Formatters.Soap.SoapFormatter deserializer = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; memStream.Position=0;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sr = deserializer.Deserialize(memStream);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; memStream.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return sr;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; #region miscel<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static string ConvertStreamToString(System.IO.Stream theStream) <br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string theString=&quot;&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; theStream.Position=0;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; using (System.IO.StreamReader sr = new System.IO.StreamReader(theStream) ) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; theString = sr.ReadToEnd();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Close and clean up the StreamReader<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sr.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return theString;<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; }<br />
}</div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/net/serialization-net-programming.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unable to get the project file from the Web server</title>
		<link>http://www.bowu.org/microsoft/net/unable-project-file-web-server.html</link>
		<comments>http://www.bowu.org/microsoft/net/unable-project-file-web-server.html#comments</comments>
		<pubDate>Thu, 19 Aug 2010 23:12:10 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[Visual Studio 2003]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=453</guid>
		<description><![CDATA[My environment: OS: Windows XP Web Server: IIS 5 .NET Framework: 1.1 IDE: Visual Studio 2003 After moving or copying my code directory, when I tried to open the solution in the Visual Studio 2003, I got an error: &#8220;Unable to get the project file form the Web server&#8221; as following screenshot. The reason is [...]]]></description>
			<content:encoded><![CDATA[<p>My environment:<br />
OS: Windows XP<br />
Web Server: IIS 5<br />
.NET Framework: 1.1<br />
IDE: Visual Studio 2003</p>
<p>After moving or copying my code directory, when I tried to open the solution in the Visual Studio 2003, I got an error: &#8220;Unable to get the project file form the Web server&#8221; as following screenshot.</p>
<p><img src="http://www.bowu.org/wp-content/uploads/2010/08/unable_get_project_file.jpg" alt="unable get project file Unable to get the project file from the Web server" title="unable_get_project_file" width="323" height="126" class="alignnone size-full wp-image-454" /></p>
<p>The reason is the Visual Studio cannot open the project file, which is http://localhost/projectName.csproj.  I checked all settings of the IIS and permission of files and found nothing was wrong.  After several hours struggling, I finally figured out following solution.</p>
<p>I deleted the all files under VSWebCache folder which is under C:\Documents and Settings\my_user_name\.  The screenshot is as below.  The possible reason is when I copied or moved the code folder, the previously generated runtime chache conflicts with the new code folder&#8217;s location.</p>
<p><img src="http://www.bowu.org/wp-content/uploads/2010/08/unable_get_project_file_1.jpg" alt="unable get project file 1 Unable to get the project file from the Web server" title="unable_get_project_file_1" width="571" height="202" class="alignnone size-full wp-image-455" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/net/unable-project-file-web-server.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IIS: Creating Multiple Web Sites within IIS on (2000 and XP Pro)</title>
		<link>http://www.bowu.org/microsoft/windows/iis-multiple-web-sites.html</link>
		<comments>http://www.bowu.org/microsoft/windows/iis-multiple-web-sites.html#comments</comments>
		<pubDate>Wed, 18 Aug 2010 02:22:48 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[Internet Information Services]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=444</guid>
		<description><![CDATA[In the server versions of Windows, you can have multiple versions of web sites installed into IIS and running simultaneously. You can install and run more than one web site within IIS in the professional version of Windows XP or Windows 2000. You just have to pull a trick to modify the IIS metabase to [...]]]></description>
			<content:encoded><![CDATA[<p>In the server versions of Windows, you can have multiple versions of web sites installed into IIS and running simultaneously. You can install and run more than one web site within IIS in the professional version of Windows XP or Windows 2000. You just have to pull a trick to modify the IIS metabase to that it is aware of the additional sites. The user interface does not support creating more than one web site. Also, you still will not be able to have more than one site running at the same time.</p>
<p>To create the second web site:</p>
<ul>
<li>Create a command prompt window.
<li>Type &#8220;cd \Inetpub\Adminscripts&#8221; and press enter.
<li>Find out what the highest numbered site you currently have is. You can do that by typing
</ul>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">adsutil.vbs ENUM /P W3SVC</div></div>
<p>If you have never done this process before, the highest numbered site should be 1.</p>
<ul>
<li>Add one to the highest numbered site. Then run this command:
</ul>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">adsutil.vbs COPY W3SVC/1 W3SVC/x</div></div>
<p>Where x is replaced by the new numbered site. For example if you run the enum command and the highest numbered site is 4, then type this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">adsutil.vbs COPY W3SVC/1 W3SVC/5</div></div>
<ul>
<li>Run the IIS Manager. You should find a new site has been created. It will be an exact copy of site #1, so you will need to change a few things. Go into the properties for the web site. Change the site name, and the virtual directory for the root of the web site to point to another location on the hard disk. Usually, you will create a new subdirectory under Inetpub and point the virtual directory at that.
<li>To use the site, you must first stop the currently running site, then start the new site.
</ul>
<p>To delete a site, first stop it if it is running (bad things happen if you don&#8217;t!). Then type:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">adsutil.vbs DELETE W3SVC/x</div></div>
<p>Where x is the number of the site you want to delete.</p>
<p>You can find the number for an existing web site in IIS Manager by enabling logging and examining the logging properties. The web site number is at the bottom of the dialog.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/windows/iis-multiple-web-sites.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sending email from ASP.NET MVC through MVC and MSMQ Part 2</title>
		<link>http://www.bowu.org/microsoft/net/email-asp-net-mvc-msmq-2.html</link>
		<comments>http://www.bowu.org/microsoft/net/email-asp-net-mvc-msmq-2.html#comments</comments>
		<pubDate>Thu, 05 Aug 2010 23:55:03 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[batch]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[message queue]]></category>
		<category><![CDATA[msmq]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[smtp]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=415</guid>
		<description><![CDATA[Original Post: http://dotnetslackers.com/articles/aspnet/Sending-email-from-ASP-NET-MVC-through-MVC-and-MSMQ-Part2.aspx By: Andrew Siemer In this article you will learn how to send emails using ASP.NET MVC and MSMQ. Contents Introduction Setting up a private queue MSMQ in Windows 7 MSMQ in Windows 2008 Creating an MSMQ Service Update your web application to use MSMQ instead of SMTP Draining the queue A quick [...]]]></description>
			<content:encoded><![CDATA[<p>Original Post: <a href="http://dotnetslackers.com/articles/aspnet/Sending-email-from-ASP-NET-MVC-through-MVC-and-MSMQ-Part2.aspx" target="_blank">http://dotnetslackers.com/articles/aspnet/Sending-email-from-ASP-NET-MVC-through-MVC-and-MSMQ-Part2.aspx</a></p>
<p>By: Andrew Siemer</p>
<p>In this article you will learn how to send emails using ASP.NET MVC and MSMQ.</p>
<p><strong>Contents</strong></p>
<ol>
<li>Introduction
<li>Setting up a private queue
<ol>
<li>MSMQ in Windows 7
<li>MSMQ in Windows 2008
</ol>
<li>Creating an MSMQ Service
<li>Update your web application to use MSMQ instead of SMTP
<li>Draining the queue
<ol>
<li>A quick refactor of the queue guard code
</ol>
<li>Sending the emails
<ol>
<li>Relocating the SerializeMessage method
</ol>
<li>Creating an installable Windows Service to drain the queue
<ol>
<li>A quick refactor of our console applciation
</ol>
<li>Finishing up the Windows Service
<ol>
<li>Adding a Timer
<li>Making the service installable
</ol>
<li>Installing your website email queue processing service
<li>Summary
</ol>
<p>Sending email from ASP.NET MVC through MVC and MSMQ Part Series</p>
<ul>
<li><a href="./email-asp-net-mvc-msmq-1.html">Part 1</a>
<li>Part 2
</ul>
<p><strong>Introduction</strong></p>
<p>In the previous article we discussed some of the downfalls of sending email directly from a web page and worker process that served that request. The biggest issue that we discussed was the fact that the user that initiated an email to be sent would be stuck waiting for the code to connect to the mail server and deliver the message. But we also discussed that for important emails we would also need a logging component to keep track of all the customer communications that we send. We then built out an example ASP.NET MVC application that sends email in a direct from the page fashion. We also built out a logging component so that all the messages that we intended to send would be serialized and stored in a logging database using LINQ to SQL.</p>
<p>In this article we will now refactor the previously created code base (make sure you grab a copy of the first articles application if you want to work along with this article) to take advantage of MSMQ. We will modify our EmailService so that rather than speaking directly with System.Net.Mail and SMTP we will instead utilize System.Messaging and MSMQ. Once our web application is converted to send its email communications to MSMQ we will then need to create a queue processing application. We will start by creating this in the form of a console application that clears the queue and sends email via our existing EmailService. Once the console application is working we will convert it into a more reliable Windows Service.</p>
<p><strong>Setting up a private queue</strong></p>
<p>To get started we will first create a new queue. There are many options when creating a queue. Take a look at &#8220;Reliable Messaging with MSMQ and .NET&#8221; for a good in depth discussion of MSMQ concepts. We are going to create a simple non-transactional private queue for this example. You need to first make sure that you have MSMQ installed on your machine.</p>
<p>I will quickly describe how to install MSMQ in Windows 7 and Windows 2008. You can use MSMQ on any of today&#8217;s current versions of Windows (just google for some MSMQ installation help if you don&#8217;t know what to do).</p>
<p><strong>MSMQ in Windows 7</strong></p>
<p>Go to Control Panel\Programs and select &#8220;Turn Windows features on or off&#8221;. In the Windows Features window that pops up, scroll down to Microsoft Message Queue (MSMQ) Server and select that box. Just leave the default selection as that will get us through this demonstration. Then click OK.</p>
<p>Then navigate to the Computer Management console. You should be able to expand Services and Applications and see a Message Queuing entry. Expand that entry and right click on Private Queues. Select new private queue. In the New Private Queue window that opens enter WebsiteEmails. This will make the path to your private queue &#8220;{ComputerName}\private$\WebsiteEmails&#8221;.</p>
<p><strong>MSMQ in Windows 2008</strong></p>
<p>In the Server Manager window, navigate to the Features node. Then click on Add Features. In the Add Features Wizard scroll down to Message Queuing. Then click through the wizard buttons to complete the installation.</p>
<p>Back in the Features node of Server Manger you should now have a Message Queue node. Inside of there you will see a Private Queues node. Right click on Private Queues and select new private queue. Give your queue the same name as above WebsiteEmails. This will make the path to your private queue &#8220;{ComputerName}\private$\WebsiteEmails&#8221;.</p>
<p><strong>Creating an MSMQ Service</strong></p>
<p>Now that we have a queue to dump our EmailMessages into, let&#8217;s write some code that will allow us to do just that. Start by creating a QueueService class in your Services folder. Then we will create a method named QueueMessage that will take in an EmailMessage object.</p>
<p>Listing 1: QueueService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class QueueService<br />
{<br />
&nbsp; &nbsp; public void QueueMessage(EmailMessage message)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p>Now let&#8217;s add a reference to System.Messaging to our BusinessLayer project. Then we will add the code that we need to connect to our private queue and insert a new message.</p>
<p>Listing 2: QueueService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class QueueService<br />
{<br />
&nbsp; &nbsp; public void QueueMessage(EmailMessage message)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; Message msg = new Message();<br />
&nbsp; &nbsp; &nbsp; &nbsp; msg.Body = message;<br />
&nbsp; &nbsp; &nbsp; &nbsp; msg.Recoverable = true;<br />
&nbsp; &nbsp; &nbsp; &nbsp; msg.Formatter = new BinaryMessageFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; string queuePath = @&quot;.\private$\WebsiteEmails&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; MessageQueue msgQ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; //if this queue doesn't exist we will create it<br />
&nbsp; &nbsp; &nbsp; &nbsp; if(!MessageQueue.Exists(queuePath))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MessageQueue.Create(queuePath);<br />
&nbsp; &nbsp; &nbsp; &nbsp; msgQ = new MessageQueue(queuePath);<br />
&nbsp; &nbsp; &nbsp; &nbsp; msgQ.Formatter = new BinaryMessageFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; msgQ.Send(msg);<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p><strong>Update your web application to use MSMQ instead of SMTP</strong></p>
<p>All that we need to do to get our web site to use MSMQ instead of SMTP is to comment out (or delete) the call to our EmailService and replace it with a call to our QueueService.</p>
<p>Listing 3: HomeController.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[HttpPost]<br />
public ActionResult Index(string id)<br />
{<br />
&nbsp; &nbsp; EmailMessage em = new EmailMessage();<br />
&nbsp; &nbsp; em.Subject = &quot;test message&quot;;<br />
&nbsp; &nbsp; em.Message = &quot;howdy from asp.net mvc&quot;;<br />
&nbsp; &nbsp; em.From = &quot;asiemer@andrewsiemer.com&quot;;<br />
&nbsp; &nbsp; em.To = &quot;asiemer@andrewsiemer.com&quot;;<br />
&nbsp; &nbsp; //new EmailService().SendMessage(em,<br />
&nbsp; &nbsp; // &nbsp; &nbsp;&quot;{email address}&quot;,<br />
&nbsp; &nbsp; // &nbsp; &nbsp;&quot;{password}&quot;,<br />
&nbsp; &nbsp; // &nbsp; &nbsp;&quot;smtp.gmail.com&quot;,<br />
&nbsp; &nbsp; // &nbsp; &nbsp;587,<br />
&nbsp; &nbsp; // &nbsp; &nbsp;true,<br />
&nbsp; &nbsp; // &nbsp; &nbsp;new LoggingRepository());<br />
&nbsp; &nbsp; new QueueService().QueueMessage(em);<br />
&nbsp; &nbsp; return View();<br />
}</div></div>
<p>You should now be able to build and run your application. Clicking the Send Email button should now store messages in your new private queue. More importantly, the time it takes from when you click the button until the page returns should be considerably faster!</p>
<p>After clicking the button a few times you should be able to open up your MSMQ management window and see some messages in the queue.</p>
<p>Also, if you double click one of those messages to open it up, you should be able to see all sorts of data about the message. And you can see the original email that was sent!<br />
Draining the queue</p>
<p>Now that we have our web site converted to send emails to a queue, we need to create an application that can read from the queue, deserialize our messages, and send out the emails as intended. We will start building this application as a console app. Once that is working as expected we can convert it to a Windows Service.</p>
<p>Add a new Console Application to your solution named WebsiteEmailProcessor. Then add two references to that project. The first reference is to the BusinessLayer project. The second reference is to the System.Messaging namespace.</p>
<p>Next we need to add a way for our application to read from the queue. This process is fairly straightforward. We will need the Main method in our console application to get us started. But we are also going to need an event handler to keep processing messages as they come into the queue.</p>
<p>Listing 4: Program.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Program<br />
{<br />
&nbsp; &nbsp; private static MessageQueue msgQ = null;<br />
&nbsp; &nbsp; private static object lockObject = new object();<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; static void Main(string[] args)<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string queuePath = @&quot;.\private$\WebsiteEmails&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ = new MessageQueue(queuePath);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.Formatter = new BinaryMessageFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.MessageReadPropertyFilter.SetAll();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.ReceiveCompleted += new ReceiveCompletedEventHandler(msgQ_ReceiveCompleted);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.BeginReceive();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (Console.ReadKey().Key != ConsoleKey.Q)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Press q to exit.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;static void msgQ_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lock (lockObject)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// The message is plain text.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EmailMessage msg = (EmailMessage)e.Message.Body;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Console.WriteLine(&quot;Message received: &quot; + msg.Message);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Listen for the next message.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgQ.BeginReceive();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
}</div></div>
<p>With what we have so far you can now run both the web application and the console application. When you click the Send Email button on the web application you should see a message go through your queue and through the processor. Give it a try!</p>
<p><strong>A quick refactor of the queue guard code</strong></p>
<p>You may have noticed that our console application is currently making an assumption that a queue exists. This is lazy! Let&#8217;s refactor some code in our QueueService to check that the queue exists and make the queue in the case that it doesn&#8217;t.</p>
<p>Listing 5: QueueService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public static void InsureQueueExists(string queuePath)<br />
{<br />
&nbsp; &nbsp; //if this queue doesn't exist we will create it<br />
&nbsp; &nbsp; if (!MessageQueue.Exists(queuePath))<br />
&nbsp; &nbsp; &nbsp; &nbsp; MessageQueue.Create(queuePath);<br />
}</div></div>
<p>And then we can replace this check in our QueueService.QueueMessage method.</p>
<p>Listing 6: QueueService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">MessageQueue msgQ;<br />
InsureQueueExists(queuePath);<br />
msgQ = new MessageQueue(queuePath);</div></div>
<p>Now we are ready to update our console app so that it makes this check as well.</p>
<p>Listing 7: Program.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Program<br />
{<br />
&nbsp; &nbsp; private static MessageQueue msgQ = null;<br />
&nbsp; &nbsp; private static object lockObject = new object();<br />
&nbsp; &nbsp; static void Main(string[] args)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; string queuePath = @&quot;.\private$\WebsiteEmails&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; QueueService.InsureQueueExists(queuePath);<br />
&nbsp; &nbsp; &nbsp; &nbsp; msgQ = new MessageQueue(queuePath);<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p><strong>Sending the emails</strong></p>
<p>Now that the core guts of this thing are working we can now integrate our EmailService back into the picture. We will add this to our msgQ_RecieveCompleted event handler.</p>
<p>Listing 8: Program.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">static void msgQ_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)<br />
{<br />
&nbsp; &nbsp;lock (lockObject)<br />
&nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; // The message is plain text.<br />
&nbsp; &nbsp; &nbsp; &nbsp; EmailMessage msg = (EmailMessage)e.Message.Body;<br />
&nbsp; &nbsp; &nbsp; &nbsp; new EmailService().SendMessage(msg,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;{username}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;{password}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;{host}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 587,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new LoggingRepository());<br />
&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(&quot;Message received: &quot; + msg.Message);<br />
&nbsp; &nbsp;}<br />
&nbsp; &nbsp;// Listen for the next message.<br />
&nbsp; &nbsp;msgQ.BeginReceive();<br />
}</div></div>
<p>Now when we run the web application and the console application we can click the SendEmail button, see the messages get queued up in the MSMQ manager, see the console application process the queue, see in the database that our log is being added too, and see in our email client that the emails are getting sent too!<br />
Relocating the SerializeMessage method</p>
<p>This looks pretty good so far. But it no longer makes sense to keep our SerializeMessage method in the EmailService. Let&#8217;s move it to its own class now and then we can come back to update the QueueService. We need to create a new Serializer class. Then if you are using ReShaper you can simply put your mouse over the SerializeMessage method name and press [ctrl][shift][r] to refactor the method. Then you can choose Move to another Type from the list that pops up. If you don&#8217;t have ReShaper then you can copy/paste! Don&#8217;t forget to update your EmailService to use the relocated Serializer.SerializeMessage method (ReSharper does this for you!).</p>
<p>Listing 9: Serializer.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">namespace AndrewSiemer.BusinessLayer.Services<br />
{<br />
&nbsp; &nbsp; public class Serializer<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static string SerializeMessage(EmailMessage message)<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StringWriter outStream = new StringWriter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; XmlSerializer s = new XmlSerializer(typeof(EmailMessage));<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s.Serialize(outStream, message);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return outStream.ToString();<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p><strong>Creating an installable Windows Service to drain the queue</strong></p>
<p>To complete our distributed application we need to take the console application and beef it up a bit. While we could technically leave our queue processor in the console application and just leave the console application running all day, this is not a very &#8220;enterprise&#8221; way of doing things! For that reason we will create one last project. This time we will create a Windows Service project that can be installed on a server and left to run forever after.</p>
<p>Let&#8217;s start by adding a new Windows Service project called WebsiteEmailService to our solution. Then set the ServiceName (in the properties window) to something you will recognize in your Services MMC. I am calling my service WebsiteEmailQueueProcessor.<br />
A quick refactor of our console applciation</p>
<p>Then we need to do a quick refactor of our console application. We need to pull the code that we wrote there up into our BusinessLayer project. We will do this by adding a QueueProcessor class to our Services folder. Inside that class we will add all the code from our Project.cs file so that it can be referenced by both the console application and the service.</p>
<p>Listing 10: QueueProcessor.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Messaging;<br />
using System.Text;<br />
using AndrewSiemer.BusinessLayer.DataAccess;<br />
using AndrewSiemer.BusinessLayer.Domain;<br />
namespace AndrewSiemer.BusinessLayer.Services<br />
{<br />
&nbsp; &nbsp; public class QueueProcessor<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; private static MessageQueue msgQ = null;<br />
&nbsp; &nbsp; &nbsp; &nbsp; private static object lockObject = new object();<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static void StartProcessing()<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string queuePath = @&quot;.\private$\WebsiteEmails&quot;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; QueueService.InsureQueueExists(queuePath);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ = new MessageQueue(queuePath);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.Formatter = new BinaryMessageFormatter();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.MessageReadPropertyFilter.SetAll();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.ReceiveCompleted += new ReceiveCompletedEventHandler(msgQ_ReceiveCompleted);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.BeginReceive();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (Console.ReadKey().Key != ConsoleKey.Q)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Press q to exit.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.Sleep(0);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; static void msgQ_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lock (lockObject)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // The message is plain text.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EmailMessage msg = (EmailMessage)e.Message.Body;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new EmailService().SendMessage(msg,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;{username}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;{password}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;{host}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 587,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; true,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new LoggingRepository());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(&quot;Message received: &quot; + msg.Message);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Listen for the next message.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgQ.BeginReceive();<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; public static void StopProcessing()<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msgQ.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p>From there we can update our Program class in the console application to use this code which will make it much smaller and easier to read!</p>
<p>Listing 11: Program.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Program<br />
{<br />
&nbsp; &nbsp; static void Main(string[] args)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; QueueProcessor.StartProcessing();<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p>We also need to move the while loop out of the QueueProcessor as that implementation will only work when ran from the Console Application. It will give us errors if ran from the Windows Service. For that reason we will relocate that looping logic to our console app like this.</p>
<p>Listing 12: Program.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Program<br />
{<br />
&nbsp; &nbsp; static void Main(string[] args)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; QueueProcessor.StartProcessing();<br />
&nbsp; &nbsp; &nbsp; &nbsp; while (Console.ReadKey().Key != ConsoleKey.Q)<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Press q to exit.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.Sleep(0);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p><strong>Finishing up the Windows Service</strong></p>
<p>Now that our code is accessible for both the Windows Service and the Console Application we can complete the service. In the design surface for your service click the &#8220;click here to switch to code view&#8221; link.</p>
<p><strong>Adding a Timer</strong></p>
<p>One of the first things that we need to do when building up our service is to add a Timer to keep track of how often our service does its job. Every time the Timer&#8217;s interval completes it will fire an event that we will capture to perform our queue processing. To do this we first need to declare a private Timer instance.</p>
<p>Listing 13: Service1.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public partial class WebsiteEmailQueueProcessor : ServiceBase<br />
{<br />
&nbsp; &nbsp; Timer timer = new Timer();<br />
}</div></div>
<p>Then we need to initialize our timer in the OnStart method.</p>
<p>Listing 14: Service1.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">protected override void OnStart(string[] args)<br />
{<br />
&nbsp; &nbsp; timer.Interval = 1000;<br />
&nbsp; &nbsp; timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);<br />
&nbsp; &nbsp; timer.AutoReset = true;<br />
&nbsp; &nbsp; timer.Enabled = true;<br />
&nbsp; &nbsp; timer.Start();<br />
}</div></div>
<p>Next, we need to create our even handler which will actually kick off the processor.</p>
<p>Listing 15: Service1.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">void timer_Elapsed(object sender, ElapsedEventArgs e)<br />
{<br />
&nbsp; &nbsp; QueueProcessor.StartProcessing();<br />
}</div></div>
<p>Lastly, we need to add some code to the OnStop method of our service that will stop the timer and free the resources in our QueueProcessor.</p>
<p>Listing 16: Service1.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">protected override void OnStop()<br />
{<br />
&nbsp; &nbsp; QueueProcessor.StopProcessing();<br />
&nbsp; &nbsp; timer.AutoReset = false;<br />
&nbsp; &nbsp; timer.Enabled = false; &nbsp; <br />
}</div></div>
<p><strong>Logging makes building a service much easier!</strong></p>
<p>I didn&#8217;t want to bog down our code examples with logging code. But in the code download for this article you will find that I have added some error handling and logging code. This will allow you to look into what is going on with the service when you attempt to install it, run it, etc. which will ultimately help you track down problems in your service. My logging implementation just appends text to a text file in the root of your C drive. You may want to update this to run from somewhere else!</p>
<p><strong>Making the service installable</strong></p>
<p>Now that we have everything ready for testing we have a few more steps to perform to get our service installed and running. To make an installer for our service you need to go the design surface of your service. Then right click in the grey area and select add installer. This will add two components to your design surface, a service process installer, and a service installer. You might want to rename these to something more descriptive to your project. I prefixed both of them with WebsiteEmailQueueProcessor.</p>
<p>In the service installer you will want to give your service a description and name that means something to you when looking at the service in the Services MMC. I named my service &#8220;Website Email Queue Processor&#8221; and gave it a description of &#8220;Website email queue processing service&#8221;.</p>
<p>Then in the process installer you will want to change the Account that your service will run under by default to &#8220;LocalSystem&#8221;. This should give your service enough rights to run after the basic install process (described shortly).</p>
<p>The last and most important step of all this is to navigate to the properties window for your windows service project. In the application tab make sure that you set the Startup Object to the Program class in your service project.</p>
<p>Now you can build the entire solution (cross your fingers). Once everything builds ok we can get this puppy installed and running.</p>
<p><strong>Installing your website email queue processing service</strong></p>
<p>To get your service installed you need to open the Visual Studio command prompt in administrator mode. Then navigate to the directory that contains your service executable. This is most likely in the bin/debug folder of your service project. Then you can run installutil and the executable name to install your service. </p>
<p>Run these commands in the Visual Studio command prompt.</p>
<p>Listing 17: Visual Studio Command Prompt in Administrator Mode</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cd /d {drive letter where your code is}:<br />
cd &quot;{full path to project}\bin\debug\&quot;<br />
installutil {name of executable}.exe<br />
<br />
Microsoft (R) .NET Framework Installation utility Version 4.0.30319.1<br />
Copyright (c) Microsoft Corporation. &nbsp;All rights reserved.<br />
<br />
Running a transacted installation.<br />
<br />
.........<br />
<br />
The Commit phase completed successfully.<br />
The transacted install has completed.</div></div>
<p>If you want to remove a service, you can type following command in the Visual Studio command prompt:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">installutil /u {name of executable}.exe</div></div>
<p>If you find that you are having issues getting your service installed, you can always check the folder that contains your executable. After running the installutil you will have a couple of log files that will give you the details of your installation. Check there for more clues and google for the answer!</p>
<p>With any luck everything should be installed and at this point. You will then need to go to the Services MMC and start your service. You should now be able to run your web application and click the magical Send Email button. And after a few seconds that email should arrive in your inbox!</p>
<p><strong>Summary</strong></p>
<p>In our previous article we discussed why sending email directly from a website upon a user&#8217;s request might be a bad idea. We then discussed some of the options for getting around these various forms of evil. We then created a demo application that sent email directly from the website. In this article we refactored our initial code base so that it would use a distributed method of sending email using an MSMQ private queue and a Windows Service to drain that queue and do the heavy lifting of sending email.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/net/email-asp-net-mvc-msmq-2.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sending email from ASP.NET MVC through MVC and MSMQ Part 1</title>
		<link>http://www.bowu.org/microsoft/net/email-asp-net-mvc-msmq-1.html</link>
		<comments>http://www.bowu.org/microsoft/net/email-asp-net-mvc-msmq-1.html#comments</comments>
		<pubDate>Sun, 01 Aug 2010 00:29:21 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[batch]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[message queue]]></category>
		<category><![CDATA[msmq]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[smtp]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=408</guid>
		<description><![CDATA[Original Post: http://dotnetslackers.com/articles/aspnet/Sending-email-from-ASP-NET-MVC-through-MVC-and-MSMQ-Part1.aspx Published: 22 Mar 2010 By: Andrew Siemer In this article you will learn how to send emails using ASP.NET MVC and MSMQ. Contents Introduction An example of sending mail directly to SMTP Creating the ASP.NET MVC web application Creating the email logging database Creating a quick business layer Adding LINQ to SQL [...]]]></description>
			<content:encoded><![CDATA[<p>Original Post: <a href="http://dotnetslackers.com/articles/aspnet/Sending-email-from-ASP-NET-MVC-through-MVC-and-MSMQ-Part1.aspx" target="_blank">http://dotnetslackers.com/articles/aspnet/Sending-email-from-ASP-NET-MVC-through-MVC-and-MSMQ-Part1.aspx</a></p>
<p>Published: 22 Mar 2010<br />
By: Andrew Siemer</p>
<p>In this article you will learn how to send emails using ASP.NET MVC and MSMQ.</p>
<p><strong>Contents</strong></p>
<ol>
<li>Introduction
<li>An example of sending mail directly to SMTP
<ol>
<li>Creating the ASP.NET MVC web application
<li>Creating the email logging database
<li>Creating a quick business layer
<li>Adding LINQ to SQL support for data access
<li>Creating an email wrapper
<li>Logging to the database
<li>Hooking up our web page
<li>Ready to send an email?
</ol>
<li>Summary
</ol>
<p>Sending email from ASP.NET MVC through MVC and MSMQ Part Series</p>
<ul>
<li>Part 1
<li><a href="./email-asp-net-mvc-msmq-2.html">Part 2</a>
</ul>
<p><strong>Introduction</strong></p>
<p>I have worked in a lot of different web environments ranging from high traffic social networking sites to high transaction ecommerce sites. One thing every site has in common regardless of the industry that it serves is that at some point in time it will need to send an email communication to someone. In the case of a community site you might send an email to a user when they comment on a friend&#8217;s profile. For ecommerce sites you might send a confirmation email when someone purchases a product from your site.</p>
<p>Regardless of the reason that the email is being sent, sending it directly from your web sites worker process is generally a bad idea. Connecting to an SMTP server, especially one on a separate server, can be a long blocking process. Adding insult to injury, the poor guy that performed the initial button click of some kind is now stuck waiting for the next web page to return. And if you work in an environment that needs to log every communication with its customers (a common requirements these days), the customer may have to endure the wait for the sending of the email as well as a dip to an email logging database. Luckily for your customer there is a better method!</p>
<p>In this article we will take a look at all the normal steps required to send an email directly from an ASP.NET MVC web page. We will also discuss how to log all of our communications by serializing our email communications to a logging database with LINQ to SQL. Once we complete this article we will have a working codebase that we can then refactor to send email in a more efficient and disconnected manner through MSMQ.<br />
An example of sending mail directly to SMTP</p>
<p>In the majority of consulting gigs I have been a part of I almost always come across a web page that connects directly to an SMTP server. It creates an instance of MailMessage, populates various properties of that message, spins up an instance of SmtpClient, and attempts to send the message. If the message was sent successfully then we can log it to a database. If the message doesn&#8217;t send then we can log the failed attempt too.<br />
Creating the ASP.NET MVC web application</p>
<p><strong>Let&#8217;s create a quick web application</strong></p>
<p>that works in this fashion. To start we will create an ASP.NET MVC 2 application (in Visual Studio 2010). I am going to place mine in a source folder and call the application &#8220;Web Application&#8221; (clever eh?).</p>
<p><strong>Creating the email logging database</strong></p>
<p>Then we need to create the database for the logging side of our application. Right click on the App_Data folder in your MVC application and choose to add a new item. Then select a SQL Server Database (you need SQL Express installed for this to work). Name the database EmailLogging.mdf and click Add. The new database should then show up in the App_Data folder as well as under your Data Connections section of the Server Explorer.</p>
<p>Expand the database in the Data Connections window. Right click on the Tables folder and select add new table. Add a column named EmailLogID with an int data type and don&#8217;t allow nulls. Then mark that column as a primary key (click the key above). Then scroll down in the Column Properties and set the (Is Identity) filed under the Identity Specification to Yes.</p>
<p>Then add a SentSuccessfully field with a data type of bit and don&#8217;t allow nulls.</p>
<p>Next we will add a SentDate field with a data type<br />
of date (about time we got this data type!).</p>
<p>And lastly we will add a Message field with a data type of varchar(500).</p>
<p>Now you can save your table. Name the table EmailLogs in the window that pops up.</p>
<p><strong>Creating a quick business layer</strong></p>
<p>Now we can add a new class library to manage our data access and business logic. Do this by right clicking on your solution and selecting to add a new project. Choose to add a new Class Library project. Name this project BusinessLayer. Then add a reference from your WebApplication project to your BusinessLayer project. This can be done by right clicking on the WebApplication project and selecting add reference. In the project tab, select the BusinessLayer project.</p>
<p><strong>Adding LINQ to SQL support for data access</strong></p>
<p>The quickest way to achieve data access these days is through the uses of LINQ to SQL! Add a folder to the BusinessLayer project called Domain. Then right click on that folder and choose to add a new item. Then add a LINQ to SQL Classes item and call it Logging.dbml.</p>
<p><strong>NOTE</strong></p>
<p>The name you choose here will be used to generate a {nameYouPick}DataContext class. If you choose AndrewsEmailLoggingContext.dbml you will end up with an AndrewsEmailLoggingContextDataContext class that you have to do all your data access through. Buyer beware!</p>
<p>Now you can drag the EmailLogs table we create out of the Data Connections->EmailLogging.mdf->Tables section of the Server Explorer on to the design surface of your Logging.dbml. This will generate an EmailLogging class for you. Now save your Logging.dbml file. Then build your project so that your LoggingDataContext will be created for you as we will need it in upcoming steps.</p>
<p><strong>Why did you put the LINQ to SQL classes in the Domain folder?</strong></p>
<p>Good question. The LINQ to SQL classes item sort of leaks it&#8217;s concerns throughout your application so you have to know how to pick the lesser of two evils when deciding where to put this thing. LINQ to SQL performs (at least) two functions for you. 1) It creates the classes that represent your database objects. 2) It provides you with the tools you need to query the database with.</p>
<p>What this means to you from a code organization perspective is that you either have Domain objects that live in a DataAccess folder (ugly) or code that you never directly reference in your application that lives in your Domain folder. What I mean to say is that you will use a Repository class that you create and that Repository class will have a reference to Domain.LoggingDataContext. Equally ugly but you only have to touch it when building the repositories.</p>
<p>If this discussion is boring you then it doesn&#8217;t apply to you. If this discussion has you thinking then you should probably use the Entity Framework or NHibernate! <img src='http://www.bowu.org/wp-includes/images/smilies/icon_razz.gif' alt="icon razz Sending email from ASP.NET MVC through MVC and MSMQ Part 1" class='wp-smiley' title="Sending email from ASP.NET MVC through MVC and MSMQ Part 1" /> </p>
<p><strong>Creating an email wrapper</strong></p>
<p>Next we need to create a quick wrapper class that will handle sending email for us. We will do this by creating a new folder in our BusinessLayer project called Services. Inside that we can create an EmailService class. We will use this class as the entry point into sending our email directly through SMTP. Make this class public and add a method called SendMessage.</p>
<p>Listing 1: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void SendMessage(EmailMessage message, string username, string password, string host, int port)<br />
{<br />
}</div></div>
<p><strong>Use ReShaper to save you some time!</strong></p>
<p>If you are a big ReSharper fan you might just implement the usage of the EmailMessage directly in the SendMessage method and then use ReSharper to create the EmailMessage class for you (must faster).</p>
<p>Now go to the Domain folder and create a new class called EmailMessage.<br />
Listing 2: EmailMessage.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">namespace AndrewSiemer.BusinessLayer.Domain<br />
{<br />
&nbsp; public class EmailMessage<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; public string To { get; set; }<br />
&nbsp; &nbsp; public string From { get; set; }<br />
&nbsp; &nbsp; public string Subject { get; set; }<br />
&nbsp; &nbsp; public string Message { get; set; }<br />
&nbsp; &nbsp; }<br />
}</div></div>
<p>Back in your EmailService we can now map our EmailMessage properties into the constructor of a MailMessage instance.</p>
<p>Listing 3: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">MailMessage mm = new MailMessage(message.From, message.To, message.Subject, message.Message);</div></div>
<p>After that we can create an instance of NetworkCredential with the passed in username and password. And then we can create an instance of SmtpClient with the host and port. And then we can bring those two together by passing in the credentials to the SmtpClient.</p>
<p>Listing 4: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void SendMessage(EmailMessage message, string username, string password, string host, int port, bool enableSsl)<br />
{<br />
MailMessage mm = new MailMessage(message.From, message.To, message.Subject, message.Message);<br />
NetworkCredential credentials = new NetworkCredential(username, password);<br />
SmtpClient sc = new SmtpClient(host, port);<br />
sc.EnableSsl = enableSsl;<br />
sc.Credentials = credentials;<br />
}</div></div>
<p>Once this is completed we are ready to try to send our message with a call to SmtpClient.Send().</p>
<p>Listing 5: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">try<br />
{<br />
sc.Send(mm);<br />
//add to logging db<br />
}<br />
catch (Exception)<br />
{<br />
//add to logging db<br />
throw;<br />
}<br />
SmtpClient.SendAsync()</div></div>
<p>If you really just want to send email from your page &#8220;because that is how you have always done it&#8221; you should at least upgrade to .NET 4 and use the SendAssync method (http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx)</p>
<p>Now we can create one last method to serialize a mail message for us which we can then pass into our logging database.<br />
Listing 6: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public static string SerializeMessage(EmailMessage message)<br />
{<br />
string result = &quot;&quot;;<br />
StreamWriter tw = new StreamWriter(result);<br />
XmlSerializer x = new XmlSerializer(message.GetType());<br />
x.Serialize(tw, message);<br />
return tw.ToString();<br />
}</div></div>
<p>And now we can serialize our mail message to be logged by adding this line to our SendMessage method.</p>
<p>Listing 7: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void SendMessage(EmailMessage message, string username, string password, string host, int port)<br />
{<br />
&nbsp; &nbsp; string serializedMessage = SerializeMessage(message);<br />
&nbsp; &nbsp; MailMessage mm = new MailMessage(message.From, message.To, message.Subject, message.Message);<br />
}</div></div>
<p><strong>Logging to the database</strong></p>
<p>Now we are ready to build up a repository for our logging purposes. Add a new folder to the business layer called DataAccess. Then add a class called LoggingRepository. Then add a method called LogMessage. In this method we will connect to our database and insert our serialized message.</p>
<p>Listing 8: LoggingRepository.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class LoggingRepository<br />
{<br />
public void LogMessage(string message, bool sentSuccessfully)<br />
{<br />
string connectionString =<br />
@&quot;Data Source=.\SQLEXPRESS;AttachDbFilename={pathToDatabase}\EmailLogging.mdf;Integrated Security=True;User Instance=True&quot;;<br />
using(LoggingDataContext dc = new LoggingDataContext(connectionString))<br />
{<br />
EmailLog el = new EmailLog();<br />
el.Message = message;<br />
el.SentDate = DateTime.Now;<br />
el.SentSuccessfully = sentSuccessfully;<br />
dc.EmailLogs.InsertOnSubmit(el);<br />
dc.SubmitChanges();<br />
}<br />
}<br />
}</div></div>
<p>Now we can return to the EmailSerivce and wire up our LoggingRepository. Start by adding another parameter to our SendMessage method that takes in an instance of our new LoggingRepository. Then replace the &#8220;//add to logging db&#8221; comments with a call to the LoggingRepository.LogMessage method.</p>
<p>Listing 9: EmailService.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">try<br />
{<br />
sc.Send(mm);<br />
repository.LogMessage(serializedMessage, true);<br />
}<br />
catch (Exception)<br />
{<br />
repository.LogMessage(serializedMessage, false);<br />
throw;<br />
}</div></div>
<p><strong>Hooking up our web page</strong></p>
<p>Now we can return to our web application. Open the Views/Home folder and then open the Index.aspx view page. We are going to add a form with a button that will allow us to catch a post to an action that will attempt to send an email for us.</p>
<p>Listing 10: Index.aspx</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;% Html.BeginForm(&quot;Index&quot;, &quot;Home&quot;); %&gt;<br />
&lt;input type=&quot;submit&quot; value=&quot;SendEmail&quot; /&gt;<br />
&lt;% Html.EndForm(); %&gt;</div></div>
<p>With this in place we can then navigate to our HomeController. In the HomeController we need to add a new action to catch the form submission from the Index view. Make sure that you specify the HttpPost attribute! Without it our form post won&#8217;t find this new action.</p>
<p>Listing 11: HomeController.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[HttpPost]<br />
public ActionResult Index(string id)<br />
{<br />
return View();<br />
}</div></div>
<p>Once we have our new action in place we can then wire up our email sending code! We need to create a new instance of a MailMessage. Then we need to populate the various properties of our MailMessage. From there we can create an instance of EmailService and pass in all the various properties that your SMTP server requires.</p>
<p>Listing 12: HomeController.cs</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[HttpPost]<br />
public ActionResult Index(string id)<br />
{<br />
EmailMessage em = new EmailMessage();<br />
em.Subject = &quot;test message&quot;;<br />
em.Message = &quot;howdy from asp.net mvc&quot;;<br />
em.From = &quot;asiemer@andrewsiemer.com&quot;;<br />
em.To = &quot;asiemer@andrewsiemer.com&quot;;<br />
new EmailService().SendMessage(em,<br />
&quot;{email account}&quot;,<br />
&quot;{password}&quot;,<br />
&quot;{smtp server address}&quot;,<br />
{smtp port},<br />
{ssl or not},<br />
new LoggingRepository());<br />
return View();<br />
}</div></div>
<p><strong>Ready to send an email?</strong></p>
<p>With all of these steps completed you should now be able to hit F5 and run your web application. When it pops open you will have a &#8220;SendEmail&#8221; button on your form just begging to be clicked. When you click it an email should be sent (or not depending on lots of things). And regardless of the status of your email being sent you should get a serialized EmailMessage logged into your database. If the email was sent you will probably notice that it took at least several seconds to perform its operation. If your email server was not available then you would have noticed that the server took around a minute (give or take) to tell you that it wasn&#8217;t available for sending messages. Add to that the latency of logging the message into the database and you have a slow process no matter how successful it was!</p>
<p>Listing 13: Serialized EmailMessage from the EmailLogs table</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:550px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;<br />
&lt;EmailMessage xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;<br />
&lt;To&gt;asiemer@andrewsiemer.com&lt;/To&gt;<br />
&lt;From&gt;asiemer@andrewsiemer.com&lt;/From&gt;<br />
&lt;Subject&gt;test message&lt;/Subject&gt;<br />
&lt;Message&gt;howdy from asp.net mvc&lt;/Message&gt;<br />
&lt;/EmailMessage&gt;</div></div>
<p><strong>Summary</strong></p>
<p>In this article we discussed some of the issues with sending email directly out of a page in your web application. We then jumped into creating an example ASP.NET MVC application that would send email in this manner. Our example also serialized all of our communications and logged them into a logging database using LINQ to SQL.</p>
<p>In the next article we will take a look at the steps required to move away from this thread blocking way of sending email. We will then implement a disconnected method of sending email communications using MSMQ.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/net/email-asp-net-mvc-msmq-1.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>9 Must Known Websites for .NET Developers</title>
		<link>http://www.bowu.org/microsoft/net/9-websites-net-developers.html</link>
		<comments>http://www.bowu.org/microsoft/net/9-websites-net-developers.html#comments</comments>
		<pubDate>Wed, 09 Jun 2010 21:36:52 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=369</guid>
		<description><![CDATA[As an .NET application developer, the following 9 websites are my most frequently visited websites. 1. ASP.net I learned .NET and get a lot of resources from this website. 2. MSDN MSDN&#8217;s primary web presence at msdn.microsoft.com is a collection of sites for the developer community that provide information, documentation, and discussion which is authored [...]]]></description>
			<content:encoded><![CDATA[<p>As an .NET application developer, the following 9 websites are my most frequently visited websites.</p>
<p>1. <a href="http://www.asp.net" target="_blank&quot;">ASP.net</a></p>
<p><a href="http://www.asp.net" target="_blank"><img class="alignnone" title="asp.net" src="http://i2.asp.net/common/header/logo.png" alt="logo 9 Must Known Websites for .NET Developers" width="108" height="44" /></a></p>
<p>I learned .NET and get a lot of resources from this website.</p>
<p>2. <a href="http://msdn.microsoft.com/en-us/default.aspx" target="_blank">MSDN</a></p>
<p><a href="http://msdn.microsoft.com/en-us/default.aspx"><img class="alignnone" title="MSDN" src="http://creativemahi.blog.com/files/2010/03/msdn-logo.jpg" alt="msdn logo 9 Must Known Websites for .NET Developers" width="200" /></a></p>
<p>MSDN&#8217;s primary web presence at msdn.microsoft.com is a collection of sites for the developer community that provide information, documentation, and discussion which is authored both by Microsoft and by the community at large. Recent emphasis on and incorporation of applications such as forums, blogs, library annotations, and social bookmarking are changing the nature of the MSDN site from a one-way information service to an open dialog between Microsoft and the developer community.</p>
<p>3. <a href="http://www.codeproject.com/">CodeProject</a></p>
<p><a href="http://www.codeproject.com/"><img class="alignnone" title="CodeProject" src="http://s.codeproject.com/App_Themes/Std/Img/logo225x90.gif" alt="logo225x90 9 Must Known Websites for .NET Developers" width="225" /></a></p>
<p>I downloaded many source code from this website.  There are also many very good articles.</p>
<p>4. <a href="http://www.dotnetnuke.com/">DotNetNuke</a></p>
<p><a href="http://www.dotnetnuke.com/"><img class="alignnone" title="DotNetNuke" src="http://www.dotnetnuke.com/Portals/_default/Skins/Ultimo/images/DotNetNuke-Logo.gif" alt="DotNetNuke Logo 9 Must Known Websites for .NET Developers" width="367" /></a></p>
<p>5. <a href="http://www.4guysfromrolla.com/">4GuysFromRolla.com</a></p>
<p><a href="http://www.4guysfromrolla.com/"><img class="alignnone" title="4 Guys From Rolla.com" src="http://www.4guysfromrolla.com/img/4guyslogo.gif" alt="4guyslogo 9 Must Known Websites for .NET Developers" width="405" height="85" /></a></p>
<p>6. <a href="http://www.devsource.com/" target="_blank">DevSource</a></p>
<p><a href="http://www.devsource.com/" target="_blank"><img class="alignnone" title="DevSource" src="http://images.51cto.com/files/uploadimg/20090625/0905593.jpg" alt="0905593 9 Must Known Websites for .NET Developers" width="340" height="105" /></a></p>
<p>7. <a href="http://www.devx.com/" target="_blank">DevX</a></p>
<p><a href="http://www.devx.com/" target="_blank"><img class="alignnone" title="DevX" src="http://assets.devx.com/devx/7819.gif" alt="7819 9 Must Known Websites for .NET Developers" width="317" height="70" /></a></p>
<p>8. <a href="http://channel9.msdn.com/&lt;/a&gt;" target="_blank">Chanel 9</a></p>
<p><a href="http://channel9.msdn.com/&lt;/a&gt;" target="_blank"><img class="alignnone" title="Channel 9" src="http://images.51cto.com/files/uploadimg/20090625/0905595.jpg" alt="0905595 9 Must Known Websites for .NET Developers" width="189" height="116" /></a></p>
<p>Many videos introducing very cool and latest Microsoft technologies.</p>
<p>9. <a href="http://weblogs.asp.net/scottgu/" target="_blank">ScottGu&#8217;s Glog</p>
<p><img alt="0905596 9 Must Known Websites for .NET Developers" src="http://images.51cto.com/files/uploadimg/20090625/0905596.jpg" title="ScottGu&#039;s Blog" class="alignnone" width="314" height="186" /><br />
</a><br />
The About Me Page of this blog:</p>
<p>My name is Scott Guthrie, and I am a Corporate Vice President in the Microsoft Developer Division. I run the development teams that build the following products/technologies:</p>
<p>    * CLR and the core .NET Base Class Libraries<br />
    * ASP.NET<br />
    * Silverlight<br />
    * WPF<br />
    * IIS 7.0<br />
    * Visual Studio Tools for ASP.NET, WPF, Silverlight and Mobile</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/net/9-websites-net-developers.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP on IIS6 with MS SQL Server 2005</title>
		<link>http://www.bowu.org/microsoft/php-iis6-mssql-server-2005.html</link>
		<comments>http://www.bowu.org/microsoft/php-iis6-mssql-server-2005.html#comments</comments>
		<pubDate>Thu, 15 Apr 2010 02:58:59 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[FreeTDS]]></category>
		<category><![CDATA[IIS6]]></category>
		<category><![CDATA[Moodle]]></category>
		<category><![CDATA[MS SQL Server 2005]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[ODBC]]></category>
		<category><![CDATA[ODBTP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=264</guid>
		<description><![CDATA[Although I think that running PHP and MySQL applications on Linux is more natural and easy to be implemented, sometimes I am still asked to install PHP applications on Windows and use MS SQL Server as database. My environment is: Windows 2003R2 in VirtualBox IIS 6 MS SQL Server 2005 1. Install PHP on IIS: [...]]]></description>
			<content:encoded><![CDATA[<p>Although I think that running PHP and MySQL applications on Linux is more natural and easy to be implemented, sometimes I am still asked to install PHP applications on Windows and use MS SQL Server as database.</p>
<p>My environment is:</p>
<ul>
<li> Windows 2003R2 in VirtualBox</li>
<li> IIS 6</li>
<li> MS SQL Server 2005</li>
</ul>
<p><strong>1. Install PHP on IIS:</strong><br />
<strong>1.1 Download the PHP:</strong></p>
<p><strong>1.1.1</strong> For the latest version of PHP for Windows, please go to:<br />
<a href="http://windows.php.net/download/" target="_blank">http://windows.php.net/download/</a></p>
<p><strong>1.1.2 </strong>For the older version of PHP, please go to:<br />
<a href="http://www.php.net/releases/" target="_blank">http://www.php.net/releases/</a></p>
<p>Because I need to install ODBTP Database Connector to connect to MS SQL Server, and the ODBTP said that it only support several version of PHP including 5.1.1, I have to install PHP 5.1.1 instead of the latest version.</p>
<p>When you download, you need to select <strong>Wi</strong><strong>ndows binary</strong>.</p>
<p><strong>1.2 Unzip the the file downloaded and rename move it to a folder under C drive called:</strong><br />
C:\php511</p>
<p>In case you want to test another version of PHP, you can download another one and name it as:<br />
C:\php532 or similar.  But you need to change other configuration as below to make it work.</p>
<p><strong>1.3 Setup System Environment:</strong><br />
<strong>1.3.1</strong> Right click &#8220;My Computer&#8221; and select &#8220;Properties&#8221;, or go to &#8220;Start&#8221; &#8211;&gt; &#8220;Run&#8221; &#8211;&gt; Type: sysdm.cpl, a &#8220;System Properties&#8221; window will pop up.</p>
<p>Select &#8220;Advanced&#8221; &#8211;&gt; &#8220;Environment Variables&#8221;.  At &#8220;System variables&#8221;, click &#8220;Path&#8221;, then click &#8220;Edit&#8221;, add &#8220;C:\php511&#8243; (same as the path in above (2)) at the end.  It should be like:<br />
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\php511</p>
<p><strong>The purpose of this variable is telling system the location of the PHP&#8217;s Dl</strong><strong>ls and Executable files.</strong></p>
<p><strong>1.3.2 </strong>You also need to add a new System variable here.  Please click &#8220;New&#8221;, type the &#8220;Variable name&#8221; as &#8220;PHPRC&#8221;, &#8220;Variable value&#8221; as &#8220;C:\php511&#8243;.</p>
<p><strong>The purpose of this variable is telling the location of php.ini (PHP Configuration File) to the system.</strong></p>
<p><strong>1.4 Install and Configure IIS Extension to run PHP:</strong><br />
There are 3 options to run PHP on IIS: CGI, ISAPI and FastCGI.  Here is the comparison of the three:</p>
<p>Performance (from low to high): CGI &lt; FastCGI &lt; ISAPI<br />
Stability (from low to high): ISAPI &lt; FastCGI &lt; CGI</p>
<p>It is very obvious that the FastCGI is the most balanced option.  FastCGI is an IIS Extension provided by Microsoft to make IIS more supportive to PHP and other Open Source applications.</p>
<p><strong>1.4.1 Download and Install FastCGI:</strong></p>
<p>Go to: <a href="http://www.server7.iis.net/download/FastCGI" target="_blank">http://www.server7.iis.net/download/FastCGI</a> to download the x86 or x64 version installation file according to your computer&#8217;s architecture.</p>
<p>Click the installation file fcgisetup_1.5_rtw_x86.msi and follow the instruction to install it.</p>
<p><strong>1.4.2 Configure the FastCGI to make it work with the PHP you installed:</strong></p>
<p><strong>1.4.2.1 Web Service Extensions &#8211;&gt; FastCGI Handler</strong></p>
<p>Open your IIS Manager which is located in &#8220;Administrative Tools&#8221;, or you can just run &#8220;inetmgr&#8221;.  In the &#8220;Web Service Extensions&#8221;, you will see a &#8220;FastCGI Handler&#8221; was already there, also it was &#8220;Allowed&#8221;.  It should be always allowed, otherwise your PHP and FastCGI will not work.</p>
<p><a href="http://www.bowu.org/wp-content/uploads/2010/04/php_iis_5.png"><img class="alignnone size-full wp-image-295" title="php_iis_5" src="http://www.bowu.org/wp-content/uploads/2010/04/php_iis_5.png" alt="php iis 5 PHP on IIS6 with MS SQL Server 2005" width="679" height="357" /></a></p>
<p><strong>1.4.2.2 Add .php Application Extensions Mapping:</strong></p>
<p>In the same IIS Manager, <strong>right click</strong> the &#8220;Web Sites&#8221;, select &#8220;Properties&#8221; &#8211;&gt; &#8220;Home Directory&#8221; &#8211;&gt; &#8220;Configuration&#8221; &#8211;&gt; &#8220;Mapping&#8221;,</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/php-iis6-mssql-server-2005.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Run Commands</title>
		<link>http://www.bowu.org/microsoft/windows/windows-run-commands.html</link>
		<comments>http://www.bowu.org/microsoft/windows/windows-run-commands.html#comments</comments>
		<pubDate>Wed, 14 Apr 2010 21:22:38 +0000</pubDate>
		<dc:creator>bo</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[Command]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[Windows 2000]]></category>
		<category><![CDATA[Windows 2003]]></category>
		<category><![CDATA[Windows 2008]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://www.bowu.org/?p=278</guid>
		<description><![CDATA[Windows has a lot of useful commands accessible from Run menu. To invoke the Run box, click on Start button and choose Run, or hold down the Windows key and hit R. Run commands allows simply run applications by typing their name instead of click on an icon. Remember these commands. They can save a [...]]]></description>
			<content:encoded><![CDATA[<p>Windows has a lot of useful commands accessible from Run menu. To invoke the Run box, click on Start button and choose Run, or hold down the Windows key and hit R. Run commands allows simply run applications by typing their name instead of click on an icon. Remember these commands. They can save a lot of your time.</p>
<p>P.S. Some commands may be missed in your system.</p>
<p><a href="http://www.bowu.org/wp-content/uploads/2010/04/run.png"><img class="alignnone size-full wp-image-279" title="run" src="http://www.bowu.org/wp-content/uploads/2010/04/run.png" alt="run Windows Run Commands" width="347" height="186" /></a></p>
<table border="0" cellspacing="1" cellpadding="3" width="100%">
<tbody>
<tr>
<td bgcolor="#e0e0e0"><strong>Command</strong></td>
<td bgcolor="#e0e0e0"><strong>Short description</strong></td>
</tr>
<tr>
<td>%allusersprofile%</td>
<td>c:\documents and settings\all users</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">%appdata%</td>
<td bgcolor="#f0f0f0">c:\documents and  settings\%username%\application data</td>
</tr>
<tr>
<td>%comspec%</td>
<td>command line</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">%homedrive%</td>
<td bgcolor="#f0f0f0">installation disk</td>
</tr>
<tr>
<td>%homepath%</td>
<td>user profile directory (documents and  settings\%username%)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">%path%</td>
<td bgcolor="#f0f0f0">system default directories</td>
</tr>
<tr>
<td>%programfiles%</td>
<td>program files directory</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">%systemdrive%</td>
<td bgcolor="#f0f0f0">drive containing the windows root  directory</td>
</tr>
<tr>
<td>%systemroot%</td>
<td>windows directory</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">%temp% or %tmp%</td>
<td bgcolor="#f0f0f0">temporary directory, usually  c:\documents and settings\%username%\local settings\temp</td>
</tr>
<tr>
<td>%userprofile%</td>
<td>user profile directory</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">%windir%</td>
<td bgcolor="#f0f0f0">windows folder</td>
</tr>
<tr>
<td>\</td>
<td>system drive</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ac3filter.cpl</td>
<td bgcolor="#f0f0f0">ac3filter</td>
</tr>
<tr>
<td>access.cpl</td>
<td>accessibility option control</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">accwiz</td>
<td bgcolor="#f0f0f0">accessibility wizard</td>
</tr>
<tr>
<td>acrobat</td>
<td>adobe acrobat</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">acrodist</td>
<td bgcolor="#f0f0f0">adobe distiller</td>
</tr>
<tr>
<td>adaptertroubleshooter</td>
<td>display adapter troubleshooter</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">appwiz.cpl</td>
<td bgcolor="#f0f0f0">add/remove programs control</td>
</tr>
<tr>
<td>azman.msc</td>
<td>authorization manager</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">bitlockerwizard</td>
<td bgcolor="#f0f0f0">bitlocker wizard</td>
</tr>
<tr>
<td>calc</td>
<td>calculator</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">certmgr.msc</td>
<td bgcolor="#f0f0f0">certificate manager</td>
</tr>
<tr>
<td>charmap</td>
<td>character map</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">chkdsk</td>
<td bgcolor="#f0f0f0">check disk utility</td>
</tr>
<tr>
<td>ciadv.msc</td>
<td>indexing service</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">cleanmgr</td>
<td bgcolor="#f0f0f0">disk cleanup utility</td>
</tr>
<tr>
<td>cliconfg</td>
<td>sql client configaration</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">clipbrd</td>
<td bgcolor="#f0f0f0">clipboard viewer</td>
</tr>
<tr>
<td>cmd</td>
<td>command prompt</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">colorcpl</td>
<td bgcolor="#f0f0f0">color management</td>
</tr>
<tr>
<td>compmgmt.msc</td>
<td>computer management</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">compmgmtlauncher</td>
<td bgcolor="#f0f0f0">computer management launcher</td>
</tr>
<tr>
<td>conf</td>
<td>netmeeting</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control access.cpl</td>
<td bgcolor="#f0f0f0">accessibility options</td>
</tr>
<tr>
<td>control admintools</td>
<td>administrative tools</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control appwiz.cpl,,1</td>
<td bgcolor="#f0f0f0">add/remove programs w/add new programs  preselected</td>
</tr>
<tr>
<td>control appwiz.cpl,,2</td>
<td>add/remove programs w/add remove windows components  preselected</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control appwiz.cpl,,3</td>
<td bgcolor="#f0f0f0">add/remove programs w/set program  access &amp; defaults preselected</td>
</tr>
<tr>
<td>control color</td>
<td>display properties (w/appearance tab preselected)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control</td>
<td bgcolor="#f0f0f0">control panel</td>
</tr>
<tr>
<td>control desktop</td>
<td>desktop properties</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control folders</td>
<td bgcolor="#f0f0f0">folder properties</td>
</tr>
<tr>
<td>control fonts</td>
<td>fonts</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control keyboard</td>
<td bgcolor="#f0f0f0">keyboard properties</td>
</tr>
<tr>
<td>control mouse</td>
<td>mouse properties</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control netconnections</td>
<td bgcolor="#f0f0f0">network connections</td>
</tr>
<tr>
<td>control printers</td>
<td>printer and fax options</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">control schedtasks</td>
<td bgcolor="#f0f0f0">scheduled tasks</td>
</tr>
<tr>
<td>control userpassword2</td>
<td>user accounts</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">credwiz</td>
<td bgcolor="#f0f0f0">credential backup and restore wizard</td>
</tr>
<tr>
<td>dcomcnfg</td>
<td>component services</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ddeshare</td>
<td bgcolor="#f0f0f0">dde share</td>
</tr>
<tr>
<td>desk.cpl</td>
<td>display properties</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">devmgmt.msc</td>
<td bgcolor="#f0f0f0">device manager</td>
</tr>
<tr>
<td>dfrg.msc</td>
<td>disk defragment</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">dfrgui</td>
<td bgcolor="#f0f0f0">defragment user interface</td>
</tr>
<tr>
<td>dialer</td>
<td>phone dialer</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">directx.cpl</td>
<td bgcolor="#f0f0f0">directx control panel</td>
</tr>
<tr>
<td>diskmgmt.msc</td>
<td>disk management</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">diskpart</td>
<td bgcolor="#f0f0f0">disk partition manager</td>
</tr>
<tr>
<td>dpinst</td>
<td>driver package installer</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">dpiscaling</td>
<td bgcolor="#f0f0f0">dpi scaling</td>
</tr>
<tr>
<td>drwtsn32</td>
<td>dr. watson system troubleshooting utility</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">dvdplay</td>
<td bgcolor="#f0f0f0">dvd player</td>
</tr>
<tr>
<td>dxdiag</td>
<td>direct x troubleshooter</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">eudcedit</td>
<td bgcolor="#f0f0f0">private character editor</td>
</tr>
<tr>
<td>eventvwr</td>
<td>event viewer</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">excel</td>
<td bgcolor="#f0f0f0">microsoft excel</td>
</tr>
<tr>
<td>explorer</td>
<td>windows explorer</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">findfast.cpl</td>
<td bgcolor="#f0f0f0">findfast</td>
</tr>
<tr>
<td>firefox</td>
<td>firefox browser</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">firewall.cpl</td>
<td bgcolor="#f0f0f0">windows firewall</td>
</tr>
<tr>
<td>firewallcontrolpanel</td>
<td>firewall control panel</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">firewallsettings</td>
<td bgcolor="#f0f0f0">firewall settings</td>
</tr>
<tr>
<td>fonts</td>
<td>fonts folder</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">freecell</td>
<td bgcolor="#f0f0f0">free cell card game</td>
</tr>
<tr>
<td>frontpg</td>
<td>microsoft frontpage</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">fsmgmt.msc</td>
<td bgcolor="#f0f0f0">shared folders</td>
</tr>
<tr>
<td>fsquirt</td>
<td>bluetooth transfer wizard</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">fvenotify</td>
<td bgcolor="#f0f0f0">bitlocker notifier</td>
</tr>
<tr>
<td>fxscover</td>
<td>fax cover sheet editor</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">gpedit.msc</td>
<td bgcolor="#f0f0f0">group policy editor</td>
</tr>
<tr>
<td>hdwwiz.cpl</td>
<td>add new hardware wizard</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">helpctr</td>
<td bgcolor="#f0f0f0">help and support center</td>
</tr>
<tr>
<td>helppane</td>
<td>help pane</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">hypertrm</td>
<td bgcolor="#f0f0f0">hyperterminal</td>
</tr>
<tr>
<td>icwconn1</td>
<td>internet connection wizard</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">iexplore</td>
<td bgcolor="#f0f0f0">internet explorer</td>
</tr>
<tr>
<td>iexpress</td>
<td>iexpress wizard (self extracting package creator)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">imageready</td>
<td bgcolor="#f0f0f0">adobe imageready</td>
</tr>
<tr>
<td>inetcpl.cpl</td>
<td>internet properties</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">inetwiz</td>
<td bgcolor="#f0f0f0">internet setup wizard</td>
</tr>
<tr>
<td>intl.cpl</td>
<td>regional and language options</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ipconfig /all</td>
<td bgcolor="#f0f0f0">ip configuration (display connection  configuration)</td>
</tr>
<tr>
<td>ipconfig /displaydns</td>
<td>ip configuration (display dns cache contents)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ipconfig /flushdns</td>
<td bgcolor="#f0f0f0">ip configuration (delete dns cache  contents)</td>
</tr>
<tr>
<td>ipconfig /registerdns</td>
<td>ip configuration (refreshes dhcp &amp; re-registers dns)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ipconfig /release</td>
<td bgcolor="#f0f0f0">ip configuration (release all  connections)</td>
</tr>
<tr>
<td>ipconfig /renew</td>
<td>ip configuration (renew all connections)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ipconfig /setclassid</td>
<td bgcolor="#f0f0f0">ip configuration (modifies dhcp class  id)</td>
</tr>
<tr>
<td>ipconfig /showclassid</td>
<td>ip configuration (display dhcp class id)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">iscsicpl</td>
<td bgcolor="#f0f0f0">iscsi initiator</td>
</tr>
<tr>
<td>javaws</td>
<td>java control panel</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">joy.cpl</td>
<td bgcolor="#f0f0f0">game controllers</td>
</tr>
<tr>
<td>jpicpl32.cpl</td>
<td>java control panel</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">logoff</td>
<td bgcolor="#f0f0f0">logoff from windows</td>
</tr>
<tr>
<td>lpksetup</td>
<td>language pack installer</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">lusrmgr.msc</td>
<td bgcolor="#f0f0f0">local users and groups</td>
</tr>
<tr>
<td>magnify</td>
<td>windows magnifier</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">mailto</td>
<td bgcolor="#f0f0f0">opens default email client</td>
</tr>
<tr>
<td>main.cpl</td>
<td>mouse properties</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">mblctr</td>
<td bgcolor="#f0f0f0">windows mobility center</td>
</tr>
<tr>
<td>migwiz</td>
<td>files and settings transfer tool</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">mmsys.cpl</td>
<td bgcolor="#f0f0f0">multimedia properties control</td>
</tr>
<tr>
<td>mobsync</td>
<td>microsoft synchronization center</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">moviemk</td>
<td bgcolor="#f0f0f0">microsoft movie maker</td>
</tr>
<tr>
<td>mrt</td>
<td>malicious software removal tool</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">msaccess</td>
<td bgcolor="#f0f0f0">microsoft access</td>
</tr>
<tr>
<td>msconfig</td>
<td>system configuration utility</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">msdt</td>
<td bgcolor="#f0f0f0">microsoft support diagnostic tool</td>
</tr>
<tr>
<td>mshearts</td>
<td>hearts card game</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">msimn</td>
<td bgcolor="#f0f0f0">outlook express</td>
</tr>
<tr>
<td>msinfo32</td>
<td>system information</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">msmsgs</td>
<td bgcolor="#f0f0f0">windows messenger</td>
</tr>
<tr>
<td>mspaint</td>
<td>microsoft paint</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">msra</td>
<td bgcolor="#f0f0f0">remote assistance</td>
</tr>
<tr>
<td>mstsc</td>
<td>remote desktop</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ncpa.cpl</td>
<td bgcolor="#f0f0f0">network connections</td>
</tr>
<tr>
<td>nero</td>
<td>nero</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">netplwiz</td>
<td bgcolor="#f0f0f0">user accounts</td>
</tr>
<tr>
<td>netsetup.cpl</td>
<td>network setup wizard</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">notepad</td>
<td bgcolor="#f0f0f0">notepad</td>
</tr>
<tr>
<td>ntbackup</td>
<td>windows backup utility</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">ntmsmgr.msc</td>
<td bgcolor="#f0f0f0">removable storage</td>
</tr>
<tr>
<td>ntmsoprq.msc</td>
<td>removable storage operator requests</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">nusrmgr.cpl</td>
<td bgcolor="#f0f0f0">user account management</td>
</tr>
<tr>
<td>nvtuicpl.cpl</td>
<td>nview desktop manager</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">odbccp32.cpl</td>
<td bgcolor="#f0f0f0">odbc data source administrator</td>
</tr>
<tr>
<td>optionalfeatures</td>
<td>optional features manager</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">osk</td>
<td bgcolor="#f0f0f0">on screen keyboard</td>
</tr>
<tr>
<td>p2phost</td>
<td>people near me</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">packager</td>
<td bgcolor="#f0f0f0">object packager</td>
</tr>
<tr>
<td>password.cpl</td>
<td>password properties</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">pbrush</td>
<td bgcolor="#f0f0f0">paint</td>
</tr>
<tr>
<td>perfmon</td>
<td>performance monitor</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">photoshop</td>
<td bgcolor="#f0f0f0">adobe photoshop</td>
</tr>
<tr>
<td>pinball</td>
<td>pinball game</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">powercfg.cpl</td>
<td bgcolor="#f0f0f0">power configuration</td>
</tr>
<tr>
<td>powerpnt</td>
<td>microsoft powerpoint</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">prefetch</td>
<td bgcolor="#f0f0f0">windows prefetcher</td>
</tr>
<tr>
<td>presentationsettings</td>
<td>presentation settings</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">printbrmui</td>
<td bgcolor="#f0f0f0">printer migration</td>
</tr>
<tr>
<td>printers</td>
<td>printers folder</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">quicktime.cpl</td>
<td bgcolor="#f0f0f0">quicktime</td>
</tr>
<tr>
<td>quicktimeplayer</td>
<td>quicktime player</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">rasphone</td>
<td bgcolor="#f0f0f0">remote access phonebook</td>
</tr>
<tr>
<td>realplay</td>
<td>real player</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">regedit</td>
<td bgcolor="#f0f0f0">registry editor</td>
</tr>
<tr>
<td>regedit32</td>
<td>registry editor (Windows 2000)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">rekeywiz</td>
<td bgcolor="#f0f0f0">encryption file system</td>
</tr>
<tr>
<td>rsop.msc</td>
<td>resultant set of policies</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sdclt</td>
<td bgcolor="#f0f0f0">windows backup utility</td>
</tr>
<tr>
<td>secpol.msc</td>
<td>local security settings</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">services.msc</td>
<td bgcolor="#f0f0f0">list of services</td>
</tr>
<tr>
<td>sethc</td>
<td>accessibility settings</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sfc /cachesize=x</td>
<td bgcolor="#f0f0f0">system file checker utility (set cache  size to size x)</td>
</tr>
<tr>
<td>sfc /purgecache</td>
<td>system file checker utility (purge file cache)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sfc /revert</td>
<td bgcolor="#f0f0f0">system file checker utility (return  scan setting to default)</td>
</tr>
<tr>
<td>sfc /scanboot</td>
<td>system file checker utility (scan on every boot)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sfc /scannow</td>
<td bgcolor="#f0f0f0">system file checker utility (scan  immediately)</td>
</tr>
<tr>
<td>sfc /scanonce</td>
<td>system file checker utility (scan once at next boot)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">shrpubw</td>
<td bgcolor="#f0f0f0">windows share creation wizard</td>
</tr>
<tr>
<td>shutdown</td>
<td>shuts down windows</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sigverif</td>
<td bgcolor="#f0f0f0">file signature verification tool</td>
</tr>
<tr>
<td>slui</td>
<td>software licensing/windows activation</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sndvol</td>
<td bgcolor="#f0f0f0">sound volume</td>
</tr>
<tr>
<td>snippingtool</td>
<td>snipping tool (an advanced print screen function)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">soundrecorder</td>
<td bgcolor="#f0f0f0">sound recorder</td>
</tr>
<tr>
<td>spider</td>
<td>spider solitaire card game</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sticpl.cpl</td>
<td bgcolor="#f0f0f0">scanner and camera control</td>
</tr>
<tr>
<td>stikynot</td>
<td>sticky notes</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">sysdm.cpl</td>
<td bgcolor="#f0f0f0">system properties</td>
</tr>
<tr>
<td>sysedit</td>
<td>system configuration editor</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">syskey</td>
<td bgcolor="#f0f0f0">windows system security tool</td>
</tr>
<tr>
<td>system.ini</td>
<td>windows loading information</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">systempropertiesadvanced</td>
<td bgcolor="#f0f0f0">system properties (advanced  preselected)</td>
</tr>
<tr>
<td>systempropertiescomputername</td>
<td>system properties (computer name preselected)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">systempropertiesdataexecutionprevention</td>
<td bgcolor="#f0f0f0">system properties (data execution  prevention preselected)</td>
</tr>
<tr>
<td>systempropertieshardware</td>
<td>system properties (hardware preselected)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">systempropertiesperformance</td>
<td bgcolor="#f0f0f0">system properties (performance  preselected)</td>
</tr>
<tr>
<td>systempropertiesprotection</td>
<td>system properties (protection preselected)</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">systempropertiesremote</td>
<td bgcolor="#f0f0f0">system properties (remote preselected)</td>
</tr>
<tr>
<td>tabcal</td>
<td>digitizer calibration tool</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">taskmgr</td>
<td bgcolor="#f0f0f0">task manager</td>
</tr>
<tr>
<td>tcptest</td>
<td>tcp tester</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">telephon.cpl</td>
<td bgcolor="#f0f0f0">phone and modem options</td>
</tr>
<tr>
<td>telnet</td>
<td>telnet client</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">timedate.cpl</td>
<td bgcolor="#f0f0f0">date and time properties</td>
</tr>
<tr>
<td>tourstart</td>
<td>windows xp tour wizard</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">tpminit</td>
<td bgcolor="#f0f0f0">trusted platform module</td>
</tr>
<tr>
<td>tweakui</td>
<td>tweak ui</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">utilman</td>
<td bgcolor="#f0f0f0">utility manager</td>
</tr>
<tr>
<td>verifier</td>
<td>driver verifier utility</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">waaucpl.cpl</td>
<td bgcolor="#f0f0f0">automatic updates</td>
</tr>
<tr>
<td>wab</td>
<td>windows address book</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">wabmig</td>
<td bgcolor="#f0f0f0">windows address book import utility</td>
</tr>
<tr>
<td>wercon</td>
<td>problem reports and solutions</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">wf.msc</td>
<td bgcolor="#f0f0f0">windows firewall with advanced  security</td>
</tr>
<tr>
<td>wfs</td>
<td>windows fax and scan</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">wiaacmgr</td>
<td bgcolor="#f0f0f0">windows picture import wizard</td>
</tr>
<tr>
<td>win.ini</td>
<td>windows loading information</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">winchat</td>
<td bgcolor="#f0f0f0">microsoft chat</td>
</tr>
<tr>
<td>winmine</td>
<td>minesweeper game</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">winver</td>
<td bgcolor="#f0f0f0">windows version</td>
</tr>
<tr>
<td>winword</td>
<td>microsoft word</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">wmimgmt.msc</td>
<td bgcolor="#f0f0f0">windows management infrastructure</td>
</tr>
<tr>
<td>wmplayer</td>
<td>windows media player</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">write</td>
<td bgcolor="#f0f0f0">wordpad</td>
</tr>
<tr>
<td>wscui.cpl</td>
<td>security center</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">wuapp</td>
<td bgcolor="#f0f0f0">windows update app manager</td>
</tr>
<tr>
<td>wupdmgr</td>
<td>windows update launches</td>
</tr>
<tr>
<td bgcolor="#f0f0f0">wusa</td>
<td bgcolor="#f0f0f0">windows standalone update manager</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.bowu.org/microsoft/windows/windows-run-commands.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
