<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Inveigled By Design » Blog</title>
	
	<link>http://www.inveigledsoftware.com</link>
	<description>The art of persuasive design</description>
	<lastBuildDate>Sat, 12 Dec 2009 20:41:31 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/InveigledByDesign" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="inveigledbydesign" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">InveigledByDesign</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Silverlight 4: Integrating With COM</title>
		<link>http://www.inveigledsoftware.com/2009/12/silverlight-4-integrating-with-com/</link>
		<comments>http://www.inveigledsoftware.com/2009/12/silverlight-4-integrating-with-com/#comments</comments>
		<pubDate>Sat, 12 Dec 2009 18:39:34 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[csharp]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=599</guid>
		<description><![CDATA[
One new feature introduced in the Silverlight 4 beta that caught my eye was the ability to communicate with a Silverlight app via COM.  It definitely opens up some powerful ways to interact with the Windows desktop environment in Silverlight.  I mocked up this quick demo just to see how it might work [...]]]></description>
			<content:encoded><![CDATA[<p><code><!-- ckey="60917B82" --></code><br />
One new feature introduced in the Silverlight 4 beta that caught my eye was the ability to communicate with a Silverlight app via COM.  It definitely opens up some powerful ways to interact with the Windows desktop environment in Silverlight.  I mocked up this quick demo just to see how it might work and hope it&#8217;s useful to someone else trying to figure out how to do this.</p>
<p>Here are the tools you need to get started:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx">Visual Studio 2010 Beta</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=177508">Silverlight 4 Beta Tools for Visual Studio 2010</a></li>
<li>Administrator privileges on your development machine</li>
</ul>
<p>The Silverlight 4 Beta Tools will give you the Silverlight 4 runtime, integrated project support in Visual Studio, and the Silverlight 4 SDK.  Remember that these are beta tools, so I do not recommend installing them on a production developer machine just yet.</p>
<p>There&#8217;s more information on getting set up with Silverlight 4 here:<br />
<a href="http://silverlight.net/getstarted/silverlight-4-beta/#tools">Silverlight 4 Beta Information</a></p>
<h3>Get the Code:</h3>
<p>Download the code here:<br />
<a href="http://www.inveigledsoftware.com/wp-content/files/blog/downloads/SilverlightComDemo.zip">SilverlightComDemo.zip</a></p>
<p><span id="more-599"></span></p>
<p>A Preview:</p>
<p>In this article, we&#8217;ll build a simple COM library that will display a user interface with four buttons and a Silverlight app displaying a simple circle inside a grid.  The user will be able to move the circle in the Silverlight app by pressing the buttons being displayed by the COM library.  This demonstrates the concept of interacting with Silverlight apps via COM.  </p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/finishedApp.png" ><img alt="" src="/wp-content/files/blog/cominterop/finishedApp.png" class="alignleft"  height="200" /></a></p>
<p>While this application is very simple and not that useful, the same techniques can be applied to interact with custom hardware, office applications, or other COM components on the user&#8217;s system.</p>
<h3>Step 1:  Create the COM Library</h3>
<p>Your COM Library may be a c++ library, or something like Excel or Word that already exist.  For purposes of this demo, I&#8217;ll create the COM library in .Net.  There are some good references for how to do this on <a href="http://www.codeproject.com">CodeProject</a> if you need more information.</p>
<p>Before you fire up Visual Studio 2010, note that if you are running Windows Vista or Windows 7, you have to right-click on Visual Studio and choose &#8220;Run as administrator&#8221; to create the project.  This is because we are going to configure Visual Studio to register our COM library automatically, which requires administrator privileges.</p>
<p>Here are the steps to get started:</p>
<ul>
<li>Create an empty solution in Visual Studio and name it SilverlightComDemo.</li>
<li>Create a new C# class library called ComDemoLib.</li>
<li> Right-click on the project in Solution Explorer and choose Properties and then the Build tab.  </li>
<li>Check the &#8220;Register for COM interop&#8221; checkbox.  When you build the library, Visual Studio will register the com library so that it can be accessed by the Silverlight app we&#8217;ll create below.</li>
<li>Click on the Signing tab and check the &#8220;Sign the assembly&#8221; checkbox and create a new key that our assembly will be signed with.  You will not be able to register the COM library unless the assembly has a strong name (is signed with a key).</li>
</ul>
<p>Setting up .NET classes so that they can be seen as COM objects requires using the System.Runtime.InteropServices library and decorating your classes and interfaces with some attributes.  I found this article to be a good reference for seeing how to set things up:<br />
<a href="http://www.codeproject.com/KB/cs/cs_com_obj_for_javascript.aspx">C# COM Object for Use in Javascript</a>.</p>
<p>Continuing on:</p>
<ul>
<li>Remove the Class1 class that is created by default in the ComDemoLib project</li>
<li>Right-click the ComDemoLib project and add a reference to the .Net System.Windows.Forms assembly.</li>
<li>Add a windows form to the project and call it DemoForm</li>
</ul>
<p>Now add four buttons so that DemoForm looks like this:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/demoForm.png" ><img alt="" src="/wp-content/files/blog/cominterop/demoForm.png" class="alignleft"  height="200" /></a></p>
<p>The code behind defines four directional events and hooks up the button click handlers to fire them:</p>
<pre class="brush: csharp;">
using System;
using System.Windows.Forms;

namespace ComDemoLib
{
    public partial class DemoForm : Form
    {
        public event EventHandler&lt;EventArgs&gt; MoveUp;
        public event EventHandler&lt;EventArgs&gt; MoveDown;
        public event EventHandler&lt;EventArgs&gt; MoveRight;
        public event EventHandler&lt;EventArgs&gt; MoveLeft;

        public DemoForm()
        {
            InitializeComponent();
        }

        private void button_up_Click(object sender, EventArgs e)
        {
            fire(MoveUp);
        }

        private void button_right_Click(object sender, EventArgs e)
        {
            fire(MoveRight);
        }

        private void button_left_Click(object sender, EventArgs e)
        {
            fire(MoveLeft);
        }

        private void button_down_Click(object sender, EventArgs e)
        {
            fire(MoveDown);
        }

        private void fire(EventHandler&lt;EventArgs&gt; eventToFire)
        {
            EventHandler&lt;EventArgs&gt; temp = eventToFire;

            if (temp != null)
                temp(this, EventArgs.Empty);
        }
    }
}
</pre>
<p>Now create three classes:  </p>
<ul>
<li>ComDemoClass will be our main COM object that the Silverlight app will interact with</li>
<li>IComDemoClass defines a very simple interface for our ComDemoClass</li>
<li>IComDemoClassEvents defines an interface for our COM events that the Silverlight app will receive</li>
</ul>
<p>In order to register with COM, our ComDemoClass and interfaces must be public and have Guids assigned to them via the Guid attribute.  When I tried to access &#8220;Create GUID&#8221; from the Tools menu in Visual Studio 2010 beta, it was grayed out.  If this is true for you as well, you can access the Guid Generator tool by typing &#8220;guidgen&#8221; at the Visual Studio 2010 command prompt.  If you run this project on your machine, you should generate new guids for any new classes that you create.</p>
<p>Our ComDemoClass will have two methods:  ShowForm and HideForm that control the visibility of the demo form we created above.  It will also fire the directional events that will tell the Silverlight app which button was pushed.</p>
<p>Here is the code for the ComDemoClass:</p>
<pre class="brush: csharp;">
using System;
using System.Runtime.InteropServices;

namespace ComDemoLib
{
    [Guid(&quot;C920762D-5819-4B06-A9FE-F42EA615771D&quot;)]
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IComDemoClassEvents))]
    public class ComDemoClass : IComDemoClass
    {
        private DemoForm m_form;

        [ComVisible(false)]
        public delegate void moveEventSignature();

        public event moveEventSignature Left;
        public event moveEventSignature Right;
        public event moveEventSignature Up;
        public event moveEventSignature Down;

        public void ShowForm()
        {
            if (m_form == null)
            {
                m_form = new DemoForm();
                m_form.MoveLeft += form_Left;
                m_form.MoveRight += form_Right;
                m_form.MoveUp += form_Up;
                m_form.MoveDown += form_Down;
                m_form.Show();
            }
        }

        public void HideForm()
        {
            if (m_form != null)
            {
                m_form.MoveLeft -= form_Left;
                m_form.MoveRight -= form_Right;
                m_form.MoveUp -= form_Up;
                m_form.MoveDown -= form_Down;
                m_form.Dispose();
                m_form = null;
            }
        }

        private void form_Left(object sender, EventArgs e)
        {
            fire(Left);
        }

        private void form_Right(object sender, EventArgs e)
        {
            fire(Right);
        }

        private void form_Up(object sender, EventArgs e)
        {
            fire(Up);
        }

        private void form_Down(object sender, EventArgs e)
        {
            fire(Down);
        }

        private void fire(moveEventSignature eventToFire)
        {
            moveEventSignature temp = eventToFire;

            if (temp != null)
                temp();
        }
    }
}
</pre>
<p>This is pretty simple.  It creates a demo form and then fires events when the user presses the buttons on the form.  Note that for COM, our events have to be defined in a separate interface and our class declares the interface via the ComSourceInterfaces attribute.</p>
<p>Here is the code for the IComDemoClass interface:</p>
<pre class="brush: csharp;">
using System.Runtime.InteropServices;

namespace ComDemoLib
{
    [Guid(&quot;3BCA5655-05EC-42D8-A046-5C0567DB7901&quot;)]
    [ComVisible(true)]
    interface IComDemoClass
    {
        [DispId(0x10000001)]
        void HideForm();

        [DispId(0x10000002)]
        void ShowForm();
    }
}
</pre>
<p>And finally the IComDemoClassEvents inteface:</p>
<pre class="brush: csharp;">
using System.Runtime.InteropServices;

namespace ComDemoLib
{
    [Guid(&quot;9942C070-D524-420F-AEBA-30A50D5A5291&quot;)]
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IComDemoClassEvents
    {
        [DispId(0x00000001)]
        void Left();

        [DispId(0x00000002)]
        void Right();

        [DispId(0x00000003)]
        void Up();

        [DispId(0x00000004)]
        void Down();
    }
}
</pre>
<p>Now build the library and verify that it was registered on the system.  Any messages about failures to register will be logged to the output window.  Once the build succeeds, if you right-click on the ComDemoLib project and choose &#8220;Add Reference&#8221;, you should see ComDemoLib listed in the COM tab (this is for verification only, hit cancel and don&#8217;t actually add the reference).</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/comRegisteredLib.png" ><img alt="" src="/wp-content/files/blog/cominterop/comRegisteredLib.png" class="alignleft"  height="300" /></a></p>
<h3>Step 2:  Create and Configure the Silverlight Application</h3>
<p>Now that we have the COM library ready to go, we need a silverlight application that can interact with it.  Add a new Silverlight Application project to the solution and name it &#8220;SilverlightComDemo&#8221;.  Allow Visual Studio to create a web hosting project (SilverlightComDemo.Web) and ensure that you are using Silverlight 4.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/newSilverlightApp.png" ><img alt="" src="/wp-content/files/blog/cominterop/newSilverlightApp.png" class="alignleft"  height="350" /></a></p>
<p>In order to interact with COM, the Silverlight app needs to run out of browser and have elevated permissions on the user&#8217;s system.  In order to use COM, it also needs to reference the Microsoft.CSharp.dll. To configure this:</p>
<ul>
<li>Right-click on the SilverlightComDemo project and choose properties</li>
<li>On the Silverlight tab, check the &#8220;Enable running application out of the browser&#8221; box</li>
<li>Press the &#8220;Out-of-Browser Settings&#8221; button.  At the bottom of the window, check the &#8220;Require elevated trust when running outside the browser&#8221; checkbox.</li>
<li>Right-click the SilverlightComDemo project again and choose &#8220;Add Reference&#8221;.  Click on the &#8220;Browse&#8221; tab and then add a reference to the Microsoft.CSharp library, which was installed as part of the Silverlight 4 SDK.  The default path is here:<br />
C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\Microsoft.CSharp.dll</li>
</ul>
<p>Our MainPage will be pretty simple.  It includes some installation stuff (that will only show when the app is not installed or not running outside the browser) and the grid with the circle in it whose position will be controlled via the COM library:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/MainPageXaml.png" ><img alt="" src="/wp-content/files/blog/cominterop/MainPageXaml.png" class="alignleft"  height="200" /></a></p>
<p>Here&#8217;s the xaml for the page:</p>
<pre class="brush: xml;">
&lt;UserControl
    x:Class=&quot;SilverlightComDemo.MainPage&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot;
    d:DesignHeight=&quot;300&quot;
    d:DesignWidth=&quot;400&quot;
    Loaded=&quot;UserControl_Loaded&quot;&gt;

    &lt;Grid x:Name=&quot;LayoutRoot&quot; Background=&quot;Navy&quot;&gt;
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;Auto&quot; /&gt;
            &lt;RowDefinition Height=&quot;*&quot; /&gt;
            &lt;RowDefinition Height=&quot;Auto&quot; /&gt;
        &lt;/Grid.RowDefinitions&gt;
        &lt;TextBlock Foreground=&quot;White&quot; Text=&quot;Silverlight Com Demo&quot;
            Grid.Row=&quot;0&quot;  FontSize=&quot;20&quot; Margin=&quot;20&quot; VerticalAlignment=&quot;Center&quot; HorizontalAlignment=&quot;Center&quot;/&gt;
        &lt;Grid Name=&quot;demoGrid&quot; Grid.Row=&quot;1&quot; &gt;
            &lt;Grid.RowDefinitions&gt;
                &lt;RowDefinition Height=&quot;*&quot; /&gt;
                &lt;RowDefinition Height=&quot;*&quot; /&gt;
                &lt;RowDefinition Height=&quot;*&quot; /&gt;
            &lt;/Grid.RowDefinitions&gt;
            &lt;Grid.ColumnDefinitions&gt;
                &lt;ColumnDefinition Width=&quot;*&quot;/&gt;
                &lt;ColumnDefinition Width=&quot;*&quot;/&gt;
                &lt;ColumnDefinition Width=&quot;*&quot;/&gt;
            &lt;/Grid.ColumnDefinitions&gt;
            &lt;Ellipse Name=&quot;ellipseControl&quot; Grid.Row=&quot;1&quot; Grid.Column=&quot;1&quot; Fill=&quot;Yellow&quot; Width=&quot;40&quot; Height=&quot;40&quot;/&gt;
        &lt;/Grid&gt;
        &lt;StackPanel x:Name=&quot;installationControls&quot; Grid.Row=&quot;2&quot;&gt;
            &lt;TextBlock x:Name=&quot;installText&quot; Text=&quot;Please run in out of browser mode&quot;
                Width=&quot;200&quot; Visibility=&quot;Collapsed&quot; TextWrapping=&quot;Wrap&quot; TextAlignment=&quot;Center&quot; FontSize=&quot;14&quot; Foreground=&quot;Red&quot; /&gt;
            &lt;Button x:Name=&quot;installButton&quot; Click=&quot;installButton_Click&quot; Content=&quot;install&quot;
                Margin=&quot;80, 5&quot; Height=&quot;40&quot; Foreground=&quot;Red&quot; FontSize=&quot;18&quot; /&gt;
        &lt;/StackPanel&gt;
    &lt;/Grid&gt;
&lt;/UserControl&gt;
</pre>
<p>Here&#8217;s the full code for the MainPage.xaml.cs code behind file, which I&#8217;ll discuss below:</p>
<pre class="brush: csharp;">
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;

namespace SilverlightComDemo
{
    public partial class MainPage : UserControl
    {
        private dynamic m_comDemoClass;

        delegate void motionEventDelegate();

        public MainPage()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            bool ready = true;

            demoGrid.Visibility = Visibility.Visible;
            installationControls.Visibility = Visibility.Collapsed;

            #region installation Checks

            // see if the app is installed
            if (App.Current.InstallState != InstallState.Installed)
            {
                ready = false;
                installText.Text = &quot;Please install the application&quot;;
            }

            // make sure the app is running out of browser
            if (!App.Current.IsRunningOutOfBrowser)
            {
                ready = false;
            }

            if (!ready)
            {
                demoGrid.Visibility = Visibility.Collapsed;
                installationControls.Visibility = Visibility.Visible;
                return;
            }

            #endregion   

            // we want to hide the form when the app exits
            App.Current.Exit += application_exit;

            // if we got here, we're ready to go, create the com object
            m_comDemoClass = ComAutomationFactory.CreateObject(&quot;ComDemoLib.ComDemoClass&quot;);

            // if the class was created, show our control form
            if (m_comDemoClass != null)
            {
                m_comDemoClass.ShowForm();

                m_comDemoClass.Left += new motionEventDelegate(moveLeft);
                m_comDemoClass.Right += new motionEventDelegate(moveRight);
                m_comDemoClass.Up += new motionEventDelegate(moveUp);
                m_comDemoClass.Down += new motionEventDelegate(moveDown);
            }
        }

        private void installButton_Click(object sender, RoutedEventArgs e)
        {
            App.Current.Install();
        }

        private void application_exit(object sender, EventArgs e)
        {
            if (m_comDemoClass != null)
            {
                m_comDemoClass.Left -= new motionEventDelegate(moveLeft);
                m_comDemoClass.Right -= new motionEventDelegate(moveRight);
                m_comDemoClass.Up -= new motionEventDelegate(moveUp);
                m_comDemoClass.Down -= new motionEventDelegate(moveDown);
                m_comDemoClass.HideForm();
            }
        }

        private void moveLeft()
        {
            int currentColumn = Grid.GetColumn(ellipseControl);

            if (currentColumn-- == 0)
                currentColumn = 2;

            Grid.SetColumn(ellipseControl, currentColumn);
        }

        private void moveRight()
        {
            int currentColumn = Grid.GetColumn(ellipseControl);

            if (currentColumn++ == 2)
                currentColumn = 0;

            Grid.SetColumn(ellipseControl, currentColumn);
        }

        private void moveUp()
        {
            int currentRow = Grid.GetRow(ellipseControl);

            if (currentRow-- == 0)
                currentRow = 2;

            Grid.SetRow(ellipseControl, currentRow);
        }

        private void moveDown()
        {
            int currentRow = Grid.GetRow(ellipseControl);

            if (currentRow++ == 2)
                currentRow = 0;

            Grid.SetRow(ellipseControl, currentRow);
        }
    }
}
</pre>
<p>In order to set the app up for debugging and interacting with COM, we need to get it installed on the system.  Build the app and run it.  It should open up your default web browser and show you the installation controls:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/installApp.png" ><img alt="" src="/wp-content/files/blog/cominterop/installApp.png" class="alignleft"  height="200" /></a></p>
<p>Go ahead and press the &#8220;install&#8221; button.  You&#8217;ll get a popup window that lets you choose where to put shortcuts for the app and warns you that the app will have potentially dangerous access to your system.  Your users will see this same warning whenever you deploy a Silverlight application that requires elevated trust on a user&#8217;s system.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/cominterop/installWarningWindow.png" ><img alt="" src="/wp-content/files/blog/cominterop/installWarningWindow.png" class="alignleft"  height="300" /></a></p>
<p>Now that the app is installed, you can configure it for easy debugging by following the directions here:<br />
<a href="http://johnpapa.net/silverlight/10-steps-to-debug-silverlight-out-of-browser-applications-without-attaching/">Debug Silverlight OOB Applications Without Attaching</a></p>
<h3>Step 3:  Integrate the COM Library into the Silverlight Application</h3>
<p>From the code listing for MainPage.xaml.cs above, you&#8217;ll see that we created an object from our COM library (m_comDemoClass) by declaring a dynamic type.  This tells the compiler that it is a type that will be defined at runtime.</p>
<p>The code to create the object and set up the event handlers is here:</p>
<pre class="brush: csharp;">
 // if we got here, we're ready to go, create the com object
            m_comDemoClass = ComAutomationFactory.CreateObject(&quot;ComDemoLib.ComDemoClass&quot;);

            // if the class was created, show our control form
            if (m_comDemoClass != null)
            {
                m_comDemoClass.ShowForm();

                m_comDemoClass.Left += new motionEventDelegate(moveLeft);
                m_comDemoClass.Right += new motionEventDelegate(moveRight);
                m_comDemoClass.Up += new motionEventDelegate(moveUp);
                m_comDemoClass.Down += new motionEventDelegate(moveDown);
            }
</pre>
<p>Since we don&#8217;t have a direct reference to the COM library, we have to create the object using the ComAutomationFactory.CreateObject call.  This is defined in the System.Windows.Interop library.  We create the object and then hook up listeners for each of the events.</p>
<p>We also hooked up a listener to the application_exit event so that we can clean up the COM class when the application is closing:</p>
<pre class="brush: csharp;">
     private void application_exit(object sender, EventArgs e)
     {
            if (m_comDemoClass != null)
            {
                m_comDemoClass.Left -= new motionEventDelegate(moveLeft);
                m_comDemoClass.Right -= new motionEventDelegate(moveRight);
                m_comDemoClass.Up -= new motionEventDelegate(moveUp);
                m_comDemoClass.Down -= new motionEventDelegate(moveDown);
                m_comDemoClass.HideForm();
            }
        }
</pre>
<p>And that&#8217;s it!  Now when you run the app, you should see the DemoForm window pop up.  When you click on any of the buttons, the yellow circle&#8217;s position should move around according to which button you clicked.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=x9JTlIAxfuc:lICJIKXFxNE:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=x9JTlIAxfuc:lICJIKXFxNE:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/x9JTlIAxfuc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/12/silverlight-4-integrating-with-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit-Testing WebClient Dependencies in Silverlight</title>
		<link>http://www.inveigledsoftware.com/2009/11/unit-testing-webclient-dependencies-in-silverlight/</link>
		<comments>http://www.inveigledsoftware.com/2009/11/unit-testing-webclient-dependencies-in-silverlight/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 23:21:33 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Unit Testing]]></category>
		<category><![CDATA[Rhino Mocks]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=539</guid>
		<description><![CDATA[
If you are going to be interfacing with web services in Silverlight, there&#8217;s a good chance you&#8217;ll have classes that are dependent on System.Net.WebClient.  Unfortunately, because of some of the security restrictions in Silverlight, you cannot mock or stub the System.Net.WebClient class.  In addition, the constructor for DownloadStringAsyncCompleteEventArgs is internal, making it difficult [...]]]></description>
			<content:encoded><![CDATA[<p><code><!-- ckey="60917B82" --></code><br />
If you are going to be interfacing with web services in Silverlight, there&#8217;s a good chance you&#8217;ll have classes that are dependent on System.Net.WebClient.  Unfortunately, because of some of the security restrictions in Silverlight, you cannot mock or stub the System.Net.WebClient class.  In addition, the constructor for DownloadStringAsyncCompleteEventArgs is internal, making it difficult to simulate the web client completing a call.</p>
<p>I started trying to test this completely within Silverlight by creating an interface and testable wrapper around the WebClient class.  I ran into a dead end, though, when I tried to create the EventArgs classes.  Silverlight will not let you create an instance of a class with an internal constructor via reflection because of the security restrictions.<br />
<span id="more-539"></span></p>
<p>I have chosen to deal with this particular issue by working around it by using a non-silverlight class library to run the tests.  I&#8217;ll demo this with a fairly simple WebClient-dependent class but it will demonstrate the techniques for testing it.  </p>
<p>First create a Silverlight Class Library that will contain the WebClient-dependent class.  This is the class library you will use in your final Silverlight application.  I called mine WebClientDependencyProject for this demo. </p>
<p>Then I added a simple class that is dependent on a WebClient.  Note that it is not complete and does not deal with thread safety, but was concocted for demonstration purposes:</p>
<pre class="brush: csharp;">
using System;
using System.Net;

namespace WebClientDependencyProject
{
    /// &lt;summary&gt;
    /// makes calls to a web service
    /// &lt;/summary&gt;
    public class WebClientDependentClass : IDisposable
    {
        /// &lt;summary&gt;
        /// fired when a call is completed
        /// &lt;/summary&gt;
        public event EventHandler&lt;DownloadStringCompletedEventArgs&gt; CallCompleted;

        private WebClient m_webClient;

        /// &lt;summary&gt;
        /// constructor
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;webClient&quot;&gt;the web client class to use&lt;/param&gt;
        public WebClientDependentClass(WebClient webClient)
        {
            m_webClient = webClient;

            if (m_webClient == null)
                throw new ArgumentNullException(&quot;webClient&quot;, &quot;webClient cannot be null&quot;);

            m_webClient.DownloadStringCompleted += webClient_DownloadStringCompleted;
        }

        /// &lt;summary&gt;
        /// cancel the current web client call
        /// &lt;/summary&gt;
        public void CancelCall()
        {
            m_webClient.CancelAsync();
        }

        /// &lt;summary&gt;
        /// clean up
        /// &lt;/summary&gt;
        public void Dispose()
        {
            m_webClient.DownloadStringCompleted -= webClient_DownloadStringCompleted;
        }

        /// &lt;summary&gt;
        /// makes a call on the web client to the specified uri
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;uri&quot;&gt;the uri to use in the web call&lt;/param&gt;
        /// &lt;param name=&quot;key&quot;&gt;the key to return with the results&lt;/param&gt;
        public void MakeCall(Uri uri, Guid key)
        {
            m_webClient.DownloadStringAsync(uri, key);
        }

        private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            EventHandler&lt;DownloadStringCompletedEventArgs&gt; temp = CallCompleted;

            if (temp != null)
                temp(this, e);
        }
    }
}
</pre>
<p>To test this class, create a new Windows (not Silverlight) Class Library. </p>
<p><img src="http://www.inveigledsoftware.com/wp-content/files/blog/unitTestWebClient/createWindowsClassLibrary.png" alt="Create windows class library project" width = "600"/></p>
<p>I chose to name this library the same name as the Silverlight version, but added .WPF to the end of the name (WebClientDependencyProject.WPF) so that I could distinguish it from the Silverlight version.  </p>
<p>Now right-click the new project and choose Add -> ExistingItem.  In the Window that comes up, browse to the folder containing the Silverlight class library and select your WebClient-dependent class.  Instead of choosing the Add button, click the arrow to the right side of the Add button and choose Add As Link.  This will add a link to the Silverlight file rather than copying it:</p>
<p><img src="http://www.inveigledsoftware.com/wp-content/files/blog/unitTestWebClient/addClassAsLink.png" alt="Add a class as a link" width="600"/></p>
<p>Now you have the same code, but it will use the full .net framework classes and security settings rather then utilizing the restricted Silverlight versions.  This opens up mocking the WebClient class as well as creating DownloadStringAsyncCompleteEventArgs instances.</p>
<p>In order to mock the WebClient class, I use <a href="http://www.ayende.com/projects/rhino-mocks/downloads.aspx">Rhino Mocks 3.5</a>.</p>
<p>Now you need to add one last project to your solution.  This should be another windows (non-silverlight) class library that will contain the tests.  I called mine WebClientDependencyProject_Tests:</p>
<p><img src="http://www.inveigledsoftware.com/wp-content/files/blog/unitTestWebClient/solutionExplorer.png" alt="Solution Explorer"/></p>
<p>Add a reference to the Rhino.Mocks library as well as the Microsoft.VisualStudio.QualityTools.UnitTestFramework.  </p>
<p>Within this library you also have access to the full .net framework capabilities and do not have the Silverlight security restrictions, so mocking the WebClient class and simulating the DownloadStringCompleted events becomes fairly straightforward:</p>
<pre class="brush: csharp;">
using System;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using WebClientDependencyProject;

namespace WebClientDependency_Tests
{
    [TestClass]
    public class WebClientDependencyClass_Tests
    {
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ConstructorShouldThrowOnNullWebClient()
        {
            WebClientDependentClass dependentClass = new WebClientDependentClass(null);
        }

        [TestMethod]
        public void ConstructorShouldSubscribeToDownloadStringCompletedEvent()
        {
            WebClient webClient;
            WebClientDependentClass dependentClass;

            webClient = MockRepository.GenerateMock&lt;WebClient&gt;();

            dependentClass = new WebClientDependentClass(webClient);

            webClient.AssertWasCalled(
                x =&gt; x.DownloadStringCompleted += Arg&lt;DownloadStringCompletedEventHandler&gt;.Is.NotNull);
            dependentClass.Dispose();
        }

        [TestMethod]
        public void DisposeShouldUnsubscribeFromEvent()
        {
            WebClient webClient;
            WebClientDependentClass dependentClass;

            webClient = MockRepository.GenerateMock&lt;WebClient&gt;();

            dependentClass = new WebClientDependentClass(webClient);

            webClient.AssertWasCalled(
                x =&gt; x.DownloadStringCompleted += Arg&lt;DownloadStringCompletedEventHandler&gt;.Is.NotNull);

            dependentClass.Dispose();

            webClient.AssertWasCalled(
                x =&gt; x.DownloadStringCompleted -= Arg&lt;DownloadStringCompletedEventHandler&gt;.Is.NotNull);

            dependentClass.Dispose();
        }

        [TestMethod]
        public void MakeCallShouldCallDownloadStringAsync()
        {
            WebClient webClient;
            WebClientDependentClass dependentClass;
            Uri uri;
            Guid key = Guid.NewGuid();

            webClient = MockRepository.GenerateMock&lt;WebClient&gt;();

            uri = new Uri(&quot;http://www.inveigledsoftware.com&quot;);
            dependentClass = new WebClientDependentClass(webClient);

            dependentClass.MakeCall(uri, key);
            Thread.Sleep(300);

            webClient.AssertWasCalled(x =&gt; x.DownloadStringAsync(uri, key));
            dependentClass.Dispose();
        }

        [TestMethod]
        public void CancelProcessingShouldCallCancelAsync()
        {
            WebClient webClient;
            WebClientDependentClass dependentClass;
            Uri uri;
            Guid key = Guid.NewGuid();

            webClient = MockRepository.GenerateMock&lt;WebClient&gt;();

            uri = new Uri(&quot;http://www.inveigledsoftware.com&quot;);
            dependentClass = new WebClientDependentClass(webClient);

            dependentClass.MakeCall(uri, key);
            Thread.Sleep(300);

            webClient.AssertWasCalled(x =&gt; x.DownloadStringAsync(uri, key));

            dependentClass.CancelCall();

            Thread.Sleep(300);
            webClient.AssertWasCalled(x =&gt; x.CancelAsync());
            dependentClass.Dispose();
        }

        [TestMethod]
        public void DownloadStringCompletedFiresEvent()
        {
            WebClient webClient;
            WebClientDependentClass dependentClass;
            Uri uri;
            ConstructorInfo[] constructors;
            ConstructorInfo constructor;
            bool wasCalled = false;
            DownloadStringCompletedEventArgs returnedArgs = null;
            DownloadStringCompletedEventArgs readArgs = null;
            Guid key = Guid.NewGuid();

            webClient = MockRepository.GenerateMock&lt;WebClient&gt;();

            webClient.DownloadStringCompleted += (sender, e) =&gt;
            {
                wasCalled = true;
                returnedArgs = e;
            };

            constructors =
                typeof(DownloadStringCompletedEventArgs).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
            Debug.Assert(constructors != null);
            constructor = constructors[0];
            object args = constructor.Invoke(new object[] { null, null, false, key });
            Debug.Assert(args != null);
            readArgs = (DownloadStringCompletedEventArgs)args;

            uri = new Uri(&quot;http://www.google.com&quot;);
            dependentClass = new WebClientDependentClass(webClient);

            dependentClass.MakeCall(uri, key);
            Thread.Sleep(300);

            webClient.AssertWasCalled(x =&gt; x.DownloadStringAsync(uri, key));

            dependentClass.CallCompleted += dependentClass_callCompleted;

            webClient.Raise(x =&gt; x.DownloadStringCompleted += null, this, readArgs);

            Assert.IsTrue(wasCalled);
            Assert.IsNotNull(returnedArgs);

            Assert.IsTrue(m_eventRaised);
            Assert.AreEqual(m_args, readArgs);
            Assert.AreEqual(key, m_args.UserState);

            dependentClass.CallCompleted -= dependentClass_callCompleted;

            dependentClass.Dispose();
        }

        private bool m_eventRaised;
        private DownloadStringCompletedEventArgs m_args;
        private void dependentClass_callCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            m_eventRaised = true;
            m_args = e;
        }
    }
}
</pre>
<p>If you end up sharing many files between class libraries, Microsoft has created the Project Linker tool to help keep the WPF/Silverlight projects that share files in sync:<br />
<a href="http://msdn.microsoft.com/en-us/library/dd458870.aspx">Project Linker</a></p>
<p>UPDATE  Dec. 4, 2009:</p>
<p>In Silverlight4/Visual Studio 2010, it looks like you will not have to make duplicate WPF projects to allow testing your Silverlight libraries.  This would eliminate having to create the WebClientDependencyProject.WPF project in the above example.  More information here:<br />
<a href="http://blogs.msdn.com/clrteam/archive/2009/12/01/sharing-silverlight-assemblies-with-net-apps.aspx">Sharing Silverlight Assemblies with .NET Apps</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=nTLrYZvBENM:huhl6oM0sqE:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=nTLrYZvBENM:huhl6oM0sqE:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/nTLrYZvBENM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/11/unit-testing-webclient-dependencies-in-silverlight/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning Silverlight: Auto-run a Storyboard in Sketchflow</title>
		<link>http://www.inveigledsoftware.com/2009/10/learning-silverlight-auto-run-a-storyboard-in-sketchflow/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/learning-silverlight-auto-run-a-storyboard-in-sketchflow/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 22:25:39 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Sketchflow]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=474</guid>
		<description><![CDATA[
One thing I want to have in the project prototype I&#8217;m working on in Sketchflow is the ability to run a storyboard automatically when a form loads.  This is a fairly straightforward process.  I&#8217;ll demonstrate it using a progress bar whose value progresses from 0 to 100 after the screen loads.  Click [...]]]></description>
			<content:encoded><![CDATA[<p><!-- ckey="1F9651B7" --><br />
One thing I want to have in the project prototype I&#8217;m working on in Sketchflow is the ability to run a storyboard automatically when a form loads.  This is a fairly straightforward process.  I&#8217;ll demonstrate it using a progress bar whose value progresses from 0 to 100 after the screen loads.  Click this link for a sneak peak at the functionality:</p>
<h3><a href="http://silverlight.inveigledsoftware.com/sketchflow/autoRunStoryboard/TestPage.html" target="_blank">Auto Run a Storyboard Demo</a></h3>
<p><br/></p>
<h3> Step 1:  Create a Progress Bar on the Sketchflow Screen:</h3>
<p>Open Blend and create a new Silverlight 3 Sketchflow Application.  Display the SketchStyles assets by clicking on the Assets tab on the left column of the Blend window, expanding the Styles list, and choosing SketchStyles:<br />
<span id="more-474"></span><br />
<a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/showSketchAssets.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/showSketchAssets.png" class="alignleft"  height="400" /></a></p>
<p>Drag a progress bar to the screen Sketchflow created for you and set its properties on the right column of the Blend window in the Layout section as shown below:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/drawProgressBar.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/drawProgressBar.png" class="alignleft" width="650" /></a></p>
<h3> Step 2:  Create a Storyboard to Animate the Progress Bar:</h3>
<p>You can create animations in Silverlight and WPF using Storyboards to change the values of the user interface controls over time.  For this demonstration, you&#8217;ll animate the value of the progress bar.  About half-way down the left column of the Blend window, in the Objects and Timeline section, click on the plus sign to add a new storyboard.  Name the new storyboard progressBarValue:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/createStoryboard.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/createStoryboard.png" class="alignleft"  /></a></p>
<p>In the newly-created storyboard you&#8217;ll see a timeline with a 0, 1, and 2 at the top. Make sure the screen edit window is highlighted in red and the message &#8220;progressBarValue timeline recording is on&#8221; appears at the top.  You&#8217;ll be animating the value of the progress bar as the storyboard progresses from 0 to 2.  </p>
<p>Click on the number 1 so that the line below it appears in yellow.  Click on the progress bar to make sure it&#8217;s selected and then in the right column of the Blend window in the Common Properties section, set the Value of the progress bar to 50.  You&#8217;ll see the bar turn gray half way across:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/progress50Percent.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/progress50Percent.png" class="alignleft" width="650" /></a></p>
<p>Now click on the 2 at the top of the storyboard layout so that the line below it turns yellow.  In the Common Properties section, set the progress bar Value to 100.  The bar should be solid gray now:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/progress100Percent.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/progress100Percent.png" class="alignleft" width="650" /></a></p>
<p>Click Close in the Objects and Timeline section of the left column of the Sketchflow window to close the storyboard.</p>
<h3>Step 3:  Create a Behavior to Auto-Run the Storyboard:</h3>
<p>You can use a Behavior that is triggered by an event to trigger the storyboard to start running.  The behaviors are located in the Assets tab in the left column of the Blend window.  Select the behavior called ControlStoryboardAction:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/addControlStoryboardBehavior.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/addControlStoryboardBehavior.png" class="alignleft"  width="650"/></a></p>
<p>Drag the ControlStoryboardAction to the Objects and Timeline section and drop it on the object named LayoutRoot.  LayoutRoot is the default grid that Sketchflow created on the screen that contains the progress bar you created.  Now you should see ControlStoryboardAction nested under LayoutRoot in the Objects and Timeline section:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/layoutRootStoryboardAction.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/layoutRootStoryboardAction.png" class="alignleft"  /></a></p>
<p>Click on the ControlStoryBoard action to make sure it is selected.  In the right column of the Blend window on the Properties tab, edit the properties of the action so that Trigger event name is Loaded and the ControlStoryboardOption is Play.  Select progressBarValue from the Storyboard list to run the storyboard we created for the progress bar.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/editControlStoryboardAction.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/editControlStoryboardAction.png" class="alignleft"  /></a></p>
<p>At this point you can run the project to view the results.  Unfortunately, you&#8217;ll discover that by the time Silverlight loads in the test page, the animation will have already started and likely completed running.  This will be evident because the progress bar will be completely gray.</p>
<h3>Step 4: Adjust the Timing of the Storyboard:</h3>
<p>In the middle column of the Blend window where the screen display is, look for a button with <> on it toward the top right of the artboard.  This will change the display to show you the xaml that is being used to create the display.  For the progressBarValue storyboard change the StartTime to 00:00:04 to delay the start until 4 seconds after the LayoutRoot is loaded.  You can adjust this value to whatever delay you would like.  You can also adjust the two keytimes to control the speed of the animation:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/sketchflow/automatingStoryboard/editXamlTiming.png" ><img alt="" src="/wp-content/files/blog/sketchflow/automatingStoryboard/editXamlTiming.png" class="alignleft"  /></a></p>
<p>Now when you run the project, you should see the screen load and then within a second or two, the progress bar will gradually change from 0 to 100 over a few seconds.</p>
<p>That&#8217;s all there is to it.  You can use many different events and controls to run a storyboard either automatically, or in response to a user action.    </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=3RLy6fG9Mxo:8MU9c1VoP4Y:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=3RLy6fG9Mxo:8MU9c1VoP4Y:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/3RLy6fG9Mxo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/learning-silverlight-auto-run-a-storyboard-in-sketchflow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing XAMPP on Windows 7</title>
		<link>http://www.inveigledsoftware.com/2009/10/installing-xampp-on-windows-7/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/installing-xampp-on-windows-7/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 14:21:06 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Windows 7]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=388</guid>
		<description><![CDATA[I just switched over to using Windows 7 with a full development setup including IIS 7 and Sql Server 2008 (including reporting services).  I also use Apache to edit a local copy of my blog and websites.  I decided to let apache run on the default port 80.  In order to do [...]]]></description>
			<content:encoded><![CDATA[<p>I just switched over to using Windows 7 with a full development setup including IIS 7 and Sql Server 2008 (including reporting services).  I also use Apache to edit a local copy of my blog and websites.  I decided to let apache run on the default port 80.  In order to do this, I installed XAMPP Lite, which was pretty straightforward, but getting it running was not.  Here&#8217;s what got it working for me:</p>
<h3>Step 1: Download and install XAMPP:</h3>
<p>Download and install one of the XAMPP exe files from here:<br />
<a href="http://www.apachefriends.org/en/xampp-windows.html" target="_blank">Apache Friends &#8211; XAMPP For Windows</a><br />
<span id="more-388"></span></p>
<p>You can use XAMPP or XAMPP Lite, whichever suits your needs, but be sure to get the EXE rather than the ZIP file.  I used XAMPP Lite version 1.7.2 for this installation.</p>
<p>Double-click the installer and let it run.  I chose to let it install on the default C: destination folder:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/xamppLiteInstall.png" ><img alt="" src="/wp-content/files/blog/apache/xamppLiteInstall.png" class="alignleft"  /></a></p>
<p>I&#8217;ve read that it can&#8217;t be run on the same partition as the operating system, that it has to be run as administrator and in compatibility mode, but I didn&#8217;t find any of that to be true.  Windows 7 sometimes pops up a message at the end of the install saying it didn&#8217;t install properly.  I just hit the &#8220;The program installed correctly&#8221; button.</p>
<h3>Step 2: Change the port that IIS is running on:</h3>
<p>By default, IIS and Sql Server use port 80, so first you have to move IIS to a new port. Click on the Start button and in the &#8220;Search programs and files&#8221; box, type in &#8220;iis&#8221;, and hit Enter.  This will start up the Internet Information Services Manager.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/launchIISManager.png" ><img alt="" src="/wp-content/files/blog/apache/launchIISManager.png" class="alignleft" height="400" /></a></p>
<p>Under &#8220;Connections&#8221; on the left, expand the entry for your PC name, then Sites and click on Default Web Site under Sites (this may have a different name if you have named your default site):</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/iisSelectDefaultWebSite.png" ><img alt="" src="/wp-content/files/blog/apache/iisSelectDefaultWebSite.png" class="alignleft" width="600" /></a></p>
<p>Now with the Default Web Site selected, click on Bindings on the right side of the window.  In the bindings window, click on the first entry, hit the edit button and enter the new port you want IIS to run on. (I chose 8080).</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/IISPort.png" ><img alt="" src="/wp-content/files/blog/apache/IISPort.png" class="alignleft"  /></a></p>
<p>Click &#8220;Ok&#8221;, &#8220;Close&#8221;, and then on the right side of the Internet Information Services Manager, under Manage Web Site, click on Restart.  Close the Internet Information Services Manager.  You can verify that IIS is now running on port 8080 by opening a browser and typing http:/localhost:8080 into the address bar:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/IISLocalhost.png" ><img alt="" src="/wp-content/files/blog/apache/IISLocalhost.png" class="alignleft"  height="250" /></a></p>
<h3>Step 3:  Moving Sql Server Reporting Services:</h3>
<p>Now you can try running the XXAMP Control Panel and running Apache.  In my case, it appeared to start, but then would stop immediately.  In order to figure out what else is running on port 80, you need to run the Command Prompt as an administrator.  </p>
<p>Click on the Start button and go to All Program -> Accessories -> Command Prompt.   Right click on Command Prompt and choose Run As Administrator.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/commandPrompt.png" ><img alt="" src="/wp-content/files/blog/apache/commandPrompt.png" class="alignleft" height="350" /></a></p>
<p>Once the command prompt opens, type in “netsh http show servicestate” (without the quotes).  This will show you what is running on what ports on the system.  In my case, it was REPORTS and<br />
REPORTSERVER that were on port 80:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/commandNetstat.png" ><img alt="" src="/wp-content/files/blog/apache/commandNetstat.png" class="alignleft" height="400" /></a></p>
<p>These are both SQL Server Reporting Services, which I want to use, but I&#8217;ll also move to port 8080.  To configure the Reporting Services, launch the Reporting Services Configuration Manager.  This is located under Start -> All Programs -> Microsoft Sql Server 2008 -> Configuration Tools:</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/runReportingConfig.png" ><img alt="" src="/wp-content/files/blog/apache/runReportingConfig.png" class="alignleft"  /></a></p>
<p>Click on Web Service URL in the left panel and change the TCP Port to 8080.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/reportingChangePort.png" ><img alt="" src="/wp-content/files/blog/apache/reportingChangePort.png" class="alignleft" width="600" /></a></p>
<p>Now choose Report Manager Url from the left panel and Click Advanced.</p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/reportsConfigure.png" ><img alt="" src="/wp-content/files/blog/apache/reportsConfigure.png" class="alignleft" width="600" /></a></p>
<p> Change the TCP Port to 8080 and click OK.  </p>
<p><a href="http://www.inveigledsoftware.com/wp-content/files/blog/apache/reportManagerEditPort.png" ><img alt="" src="/wp-content/files/blog/apache/reportManagerEditPort.png" class="alignleft"  /></a></p>
<p>Close out the Reporting Services Configuration Manager.</p>
<p>Now if you open the XAMPP Control panel and run Apache, it should stay running.  If it doesn&#8217;t work at this point, reboot the system and try again.</p>
<p><img alt="" src="/wp-content/files/blog/apache/apacheRunning.png" class="alignleft"  /></p>
<p>Now you can verify that apache is working by opening a browser and typing http://localhost into the address bar:</p>
<p><img alt="" src="/wp-content/files/blog/apache/xamppLocalhost.png" class="alignleft" width="400" /></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=RJMadKozXKg:qhdivaAcKaY:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=RJMadKozXKg:qhdivaAcKaY:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/RJMadKozXKg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/installing-xampp-on-windows-7/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Setting SketchStyles in SketchFlow</title>
		<link>http://www.inveigledsoftware.com/2009/10/learning-silverlight-setting-sketchstyles-in-sketchflow/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/learning-silverlight-setting-sketchstyles-in-sketchflow/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 13:23:51 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Sketchflow]]></category>
		<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=367</guid>
		<description><![CDATA[When I first started up SketchFlow to create a prototype, by default all of the controls were styled using the standard controls styles rather than the sketch-like style I had seen in the SketchFlow demos.  It wasn&#8217;t obvious to me how to use the sketch style and I didn&#8217;t find it easily, so here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>When I first started up SketchFlow to create a prototype, by default all of the controls were styled using the standard controls styles rather than the sketch-like style I had seen in the SketchFlow demos.  It wasn&#8217;t obvious to me how to use the sketch style and I didn&#8217;t find it easily, so here&#8217;s how to do it:</p>
<h3>Create a new SketchFlow project:</h3>
<p>You can create one for Silverlight or WPF:<br />
<br/><br />
<img alt="" src="/wp-content/files/blog/CreateSketchflowSilverlightProject.png" class="alignleft"  /><br />
<span id="more-367"></span></p>
<h3>Display the project assets:</h3>
<p>Click on the &#8220;Assets&#8221; button toward the bottom of the toolbar on the left and expand the Styles:<br />
<br/><br />
<img alt="" src="/wp-content/files/blog/ShowAssets.png" class="alignleft"  /><br />
<br/></p>
<h3>Select SketchStyles as default:</h3>
<p>Under Styles, right click on SketchStyles and select &#8220;Set as Default Style&#8221; from the context menu.<br />
<br/><br />
<img alt="" src="/wp-content/files/blog/SelectSketchStyles.png" class="alignleft"  /><br />
<br/></p>
<h3>Create controls:</h3>
<p>Now when you add controls to your screens they will be styled as sketches:<br />
<br/><br />
<img alt="" src="/wp-content/files/blog/SketchflowButton.png" class="alignleft"  /></p>
<h3>Alternative:</h3>
<p>Alternatively, you can pick the sketchflow controls directly by selecting the Assets tab on the left side of the screen, expanding the Styles option, and clicking on SketchStyles.  You can then click on any of the Sketch controls and utilize them in your screens:<br />
<br/><br />
<img alt="" src="/wp-content/files/blog/SketchFlowSketchStylesAssets.png" class="alignleft"  /></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=xUuM1y6XElY:3-KDQ_yQ3tY:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=xUuM1y6XElY:3-KDQ_yQ3tY:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/xUuM1y6XElY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/learning-silverlight-setting-sketchstyles-in-sketchflow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning Silverlight:  Hosting Silverlight Content</title>
		<link>http://www.inveigledsoftware.com/2009/10/learning-silverlight-hosting-silverlight-content/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/learning-silverlight-hosting-silverlight-content/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 14:08:41 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Silverlight]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=250</guid>
		<description><![CDATA[One of my latest quests is to learn more about Silverlight.

One of the first things I wanted to figure out is how, if I&#8217;m going to be developing Silverlight apps, can I publish them on my site so I can share them.  So far I&#8217;ve found three ways to do it.  For purposes [...]]]></description>
			<content:encoded><![CDATA[<p>One of my latest quests is to learn more about <a href="http://silverlight.net/" target="_blank">Silverlight</a>.<br />
<br/><br />
One of the first things I wanted to figure out is how, if I&#8217;m going to be developing Silverlight apps, can I publish them on my site so I can share them.  So far I&#8217;ve found three ways to do it.  For purposes of this demo, I created a very simple silverlight app that just has a single button.  Each time you click the button, the text toggles between &#8220;Click Me&#8221; and &#8220;Reset&#8221;.  </p>
<h3>Embedding Silverlight Content in an HTML page</h3>
<p><br/><br />
Since I plan on posting a series of Silverlight projects as I learn more about what can be done with it, I thought one way to show them was to give each one it&#8217;s own html page.  This involves using the object element and setting its source property to point to the .xap file that&#8217;s generated when you compile your silverlight app.<br />
<span id="more-250"></span><br />
Here&#8217;s what the html code looks like (my .xap file is called Hello.xap and it lives in the same directory as the web page):</p>
<pre class="brush: xml;">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
    &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
   &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=iso-8859-1&quot;&gt;
   &lt;meta name=&quot;GENERATOR&quot; content=&quot;Arachnophilia 3.9&quot;&gt;
   &lt;meta name=&quot;description&quot; content=&quot;Embedding Silverlight in HTML.&quot;&gt;
   &lt;meta name=&quot;keywords&quot; content=&quot;Silverlight, HTML&quot;&gt;
   &lt;title&gt;Embedding Silverlight in HTML:&lt;/title&gt;

   &lt;style type=&quot;text/css&quot;&gt;
    html, body {
        height: 100%;
        overflow: auto;
    }
    body {
        padding: 0;
        margin: 0;
    }
    #silverlightControlHost {
        height: 100%;
        text-align:center;
    }
    &lt;/style&gt;

    &lt;script type=&quot;text/javascript&quot;&gt;
        function onSilverlightError(sender, args) {
            var appSource = &quot;&quot;;
            if (sender != null &amp;&amp; sender != 0) {
                appSource = sender.getHost().Source;
            }

            var errorType = args.ErrorType;
            var iErrorCode = args.ErrorCode;

            if (errorType == &quot;ImageError&quot; ||
                errorType == &quot;MediaError&quot;) {
              return;
            }

            var errMsg = &quot;Unhandled Error in Silverlight Application &quot;
                + appSource + &quot;\n&quot;;

            errMsg += &quot;Code: &quot; + iErrorCode + &quot;    \n&quot;;
            errMsg += &quot;Category: &quot; + errorType + &quot;       \n&quot;;
            errMsg += &quot;Message: &quot; + args.ErrorMessage + &quot;     \n&quot;;

            if (errorType == &quot;ParserError&quot;) {
                errMsg += &quot;File: &quot; + args.xamlFile + &quot;     \n&quot;;
                errMsg += &quot;Line: &quot; + args.lineNumber + &quot;     \n&quot;;
                errMsg += &quot;Position: &quot; + args.charPosition + &quot;     \n&quot;;
            }
            else if (errorType == &quot;RuntimeError&quot;) {
                if (args.lineNumber != 0) {
                    errMsg += &quot;Line: &quot; + args.lineNumber + &quot;     \n&quot;;
                    errMsg += &quot;Position: &quot; + args.charPosition +
                        &quot;     \n&quot;;
                }
                errMsg += &quot;MethodName: &quot; + args.methodName + &quot;     \n&quot;;
            }

            throw new Error(errMsg);
        }
    &lt;/script&gt;

&lt;/head&gt;
  &lt;body&gt;
    &lt;h2&gt;Embedding Silverlight in HTML:&lt;/h2&gt;

    &lt;div id=&quot;silverlightControlHost&quot;&gt;
        &lt;object width=&quot;100%&quot; height=&quot;100%&quot;
            type=&quot;application/x-silverlight-2&quot;
            data=&quot;data:application/x-silverlight-2,&quot; &gt;
            &lt;param name=&quot;source&quot; value=&quot;Hello.xap&quot;/&gt;
            &lt;param name=&quot;onerror&quot; value=&quot;onSilverlightError&quot; /&gt;
            &lt;param name=&quot;background&quot; value=&quot;white&quot; /&gt;
            &lt;param name=&quot;minRuntimeVersion&quot; value=&quot;3.0.40624.0&quot; /&gt;
            &lt;param name=&quot;autoUpgrade&quot; value=&quot;true&quot; /&gt;
            &lt;a href=&quot;http://go.microsoft.com/fwlink/?LinkID=149156&quot;
                style=&quot;text-decoration: none;&quot;&gt;
                &lt;img
                    src=&quot;http://go.microsoft.com/fwlink/?LinkId=108181&quot;
                    alt=&quot;Get Microsoft Silverlight&quot;
                    style=&quot;border-style: none&quot;/&gt;
            &lt;/a&gt;
        &lt;/object&gt;
        &lt;iframe id=&quot;_sl_historyFrame&quot;
            style='visibility:hidden;height:0px;width:0px;border:0px'&gt;
        &lt;/iframe&gt;
    &lt;/div&gt;

  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>You can view this page with the embedded app here:  <a href="http://silverlight.inveigledsoftware.com/hello/hello.html">Hello</a><br />
<br />
There&#8217;s alot to more to learn before this is ready for a production deployment, but it gets the job done for now.  Here are some resources for learning more:</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/cc189089(VS.95).aspx" target="_blank">How to Add Silverlight to a Web Page</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/cc189043(VS.95).aspx" target="_blank">Sizing the Silverlight Plugin</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/cc838268(VS.95).aspx" target="_blank">Properties of the Silverlight HTML Object</a></li>
<li><a href="http://www.microsoft.com/downloads/details.aspx?displaylang=en&#038;FamilyID=961e96e8-9a7f-4b70-947a-97f0973cb38c" target="_blank">Silverlight Installation Experience White Paper</a></li>
</ul>
<p></p>
<h3>Embedding Silverlight Content in a Wordpress Blog</h3>
<p>
Thanks to people sharing their code, this one is easy.  There&#8217;s a plugin for WordPress that allows you to embed your application in a blog post very easily.  You can get the plug in <a href="http://wordpress.org/extend/plugins/silverlight-for-wordpress/" target="_blank">Here</a>.  Thanks to <a href="http://timheuer.com/blog/" target="_blank">Tim Heuer</a> for this great plugin.<br />
<br />
Embedding the app in this blog post is this easy (enclose this in brackets):</p>
<pre class="brush: xml;">
silverlight: http://www.inveigledsoftware.com/wp-content/files/silverlight/Hello.xap
</pre>
<p>
Here&#8217;s the result:<br />
<div id="silverlightControlHost"><object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100" height="100"><param name="source" value="http://www.inveigledsoftware.com/wp-content/files/silverlight/Hello.xap"/><param name="background" value="white" /><param name="minRuntimeVersion" value="3.0.40723.0" /><param name="autoupgrade" value="true" /><param name="enableHtmlAccess" value="true" /><a href="http://go.microsoft.com/fwlink/?LinkID=149156" style="text-decoration: none;"><img src="http://storage.timheuer.com/sl4wp-ph.png" alt="Install Microsoft Silverlight" style="border-style: none; width:400px; height:200px"/></a></object><iframe style="visibility:hidden;height:0;width:0;border:0px" id="_sl_historyFrame"></iframe></div><br /><br />
</p>
<h3>Embedding Silverlight Content Using the Silverlight Streaming Service</h3>
<p>
I haven&#8217;t uploaded anything to the <a href="http://silverlight.live.com/" target="_blank">Silverlight Streaming Service</a> but it&#8217;s currently free (and may remain so if you don&#8217;t mind some advertising).<br />
<br />
Embedding content deployed to the streaming service involves using an iframe like so:</p>
<pre class="brush: xml;">
&lt;iframe src=&quot;http://silverlight.services.live.com/invoke/32/SlLogo/iframe.html&quot;
        frameborder=&quot;0&quot; width=&quot;258&quot; height=&quot;100&quot; scrolling=&quot;no&quot; &gt;&lt;/iframe&gt;
</pre>
<p>
This ends up looking like this:</p>
<p><iframe src="http://silverlight.services.live.com/invoke/32/SlLogo/iframe.html"<br />
        frameborder="0" width="258" height="100" scrolling="no" ></iframe></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=pu1nQ1qpqmw:8xNaOa8mk0k:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=pu1nQ1qpqmw:8xNaOa8mk0k:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/pu1nQ1qpqmw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/learning-silverlight-hosting-silverlight-content/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Git and OpenSSH for Windows Development</title>
		<link>http://www.inveigledsoftware.com/2009/10/using-git-and-openssh-for-windows-development/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/using-git-and-openssh-for-windows-development/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 13:57:24 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[general programming]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Vista]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=194</guid>
		<description><![CDATA[

I have a linux server I&#8217;m hosting over at Linode that I use to host this blog along with a git repository for my development projects.  I found that there are many guides on configuring git for use with your own remote repositories on linux, but getting things set up on windows was a [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://www.inveigledsoftware.com/wp-content/files/blog/openSSH.png" /></p>
<p><br/><br />
I have a linux server I&#8217;m hosting over at <a href="http://www.linode.com">Linode</a> that I use to host this blog along with a git repository for my development projects.  I found that there are many guides on configuring git for use with your own remote repositories on linux, but getting things set up on windows was a little different.<br />
<br/></p>
<h2>A few notes:  </h2>
<ul>
<li>I&#8217;m using Windows Vista, though the set up should be very similar (if not the same) for XP or Windows 7.</li>
<li>  I won&#8217;t cover installing git on the server, since there are already many resources on that around the web.  If you&#8217;re running one of the Debian linux families it&#8217;s as simple as sudo apt-get install git</li>
<li>I also won&#8217;t cover how to generate a key for use with openssh, but you can find instructions here: <a href="http://sial.org/howto/openssh/publickey-auth/">Public key authentication</a></li>
</ul>
<p><br/></p>
<h2>Configuring OpenSSH:</h2>
<p><br/><br />
First you need to download and install <a href="http://code.google.com/p/msysgit/downloads/list">Msysgit</a>.  I&#8217;m using version Git-1.6.4-preview20090730.exe.  During the installation I accepted all of the defaults.  You can choose other options, but be sure to select OpenSSH as your SSH executable.<br />
<span id="more-194"></span><br />
If you don&#8217;t have an ssh authentication key for working with your server yet, generate your key and upload the public key to the server. There are instructions here:  <a href="http://sial.org/howto/openssh/publickey-auth/">OpenSSH Public Key Authentication</a><br />
<br/><br />
Now you want to configure your OpenSSH so that it&#8217;s easy to work with the server.  You&#8217;ll need to create a new directory to hold the configuration files.  If you used the default installation path for msysgit, open the folder C:\Program Files\Git\etc and create a new folder inside of it named &#8220;ssh&#8221;.  Vista requires admin authentication to write to this folder, so you&#8217;ll see the UAC prompts if you have that turned on.  Now you should have a ssh configuration folder here:  C:\Program Files\Git\etc\ssh.<br />
<br/><br />
I found that it&#8217;s much more convenient to use OpenSSH if you create a config file to hold all of the server settings.  That way when you access the server you can use a convenient name like &#8220;linode&#8221; instead of the ip address.  Run Notepad or another text editor as admin (required on Vista so we can save it to the ssh directory).  The contents of the file should look like this (fill in the information in [brackets] with your own server information):<br />
<br/></p>
<pre class="brush: plain;">
Host [yourhostname]
HostName [serverIpAddress]
User [serverLoginName]
Port [sshPort]
IdentityFile [privateKeyPath]
</pre>
<p><br/><br />
<strong>yourhostname:</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this can be any name you want to use when you access the server via ssh<br />
<strong>serverIpAddress:</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the ip address of the server where your git repository is located<br />
<strong>serverLoginName:</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the user name you use to access your server via ssh<br />
<strong>sshPort:</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the port your server is using for ssh  (This is not required if you are using the default port)<br />
<strong>privateKeyPath:</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the path to the private key file you generated previously (likely called id_rsa or something similar).  If the path has any spaces in it, you need to enclose it in quotes.<br />
<br/><br />
Save the file in your ssh directory with the name &#8220;ssh_config&#8221;.  Be sure the filename does not have an extension (notepad tends to append .txt &#8211; you don&#8217;t want that).<br />
<br/>Now you should be able to test your open ssh setup.  Open Git Bash (part of msysgit) and type:</p>
<pre class="brush: plain;">
ssh [yourhostname]
</pre>
<p>and you should be logged into your server.  If you private key was password protected, you&#8217;ll be prompted for the password.  The only issue I had initially was that the path to my private key had a space in it, but once I added quotes around the path, it all went smoothly.<br />
<br/></p>
<h2>Setting Up a Project</h2>
<p><br/><br />
There are two steps to setting up a project for use with git.  First you need to create a folder on the server that will act as the git repository for your project.  You can choose whatever path you prefer, but it should not be in a public folder.  Create the folder you want to use as the repository on the server and then in the command prompt type:</p>
<pre class="brush: plain;">
git --bare init
</pre>
<p><br/><br />
It&#8217;s that easy to set up the server side, now for the windows project.  If you&#8217;re using Visual Studio, go ahead and create a project and let Visual Studio put in in a folder for you.  If you already have a project set up, you can skip that step.  Now you&#8217;ll want to tell Git to ignore some of the build folders and Resharper stuff if you&#8217;re using that.  You do that by using Notepad or another text editor to create a file inside the project folder named .gitignore.  Here&#8217;s what mine looks like:</p>
<pre class="brush: plain;">
obj
bin
_ReSharper.*
*.csproj.user
*.resharper.user
*.resharper
*.suo
*.cache
*~
*.swp
</pre>
<p><br/><br />
If you&#8217;re using some other development tools, these files may vary.  Full documentation of the gitignore syntax is available on the <a href="http://ftp.df.lth.se/%2F/pub/software/scm/git/docs/gitignore.html">man page</a>.  Now open a Git Bash prompt and navigate to the folder where your project is on the windows box.  Once you&#8217;re inside the folder, initialize it as a git repository:</p>
<pre class="brush: plain;">
git --bare init
</pre>
<p><br/><br />
In order to sync the repository with the server, you&#8217;ll need to add a remote origin.  In order to do that you&#8217;ll need the [yourHostName] you used from the ssh_config file above and the path to the folder you are using on the server (that you initialized with git &#8211;bare init).  Enter yourHostName without the brackets.  Add the connection by using git remote add:</p>
<pre class="brush: plain;">
git remote add origin ssh://[yourHostName]/pathToTheServerFolder
</pre>
<p><br/><br />
Now all that&#8217;s left is to add your project to the git repository and push the files to the server:</p>
<pre class="brush: plain;">
git add .
git commit -m &quot;initial commit&quot;
git push origin master
</pre>
<p><br/><br />
To pull files from the server you&#8217;ll use:</p>
<pre class="brush: plain;">
git pull origin master
</pre>
<p><br/><br />
There&#8217;s much more to using git, but that should get you started!<br />
<br/></p>
<h3>Git resources:</h3>
<p><a href="http://kernel.org/pub/software/scm/git/docs/v1.2.6/tutorial.html">A tutorial introduction to git</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=wPTYn4M6n5s:Hz53OiHp4DI:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=wPTYn4M6n5s:Hz53OiHp4DI:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/wPTYn4M6n5s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/using-git-and-openssh-for-windows-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Silverlight Development: IE Cannot Display the web page</title>
		<link>http://www.inveigledsoftware.com/2009/10/silverlight-development-ie-cannot-display-the-web-page/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/silverlight-development-ie-cannot-display-the-web-page/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 05:36:34 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[Vista]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=184</guid>
		<description><![CDATA[I&#8217;ve been playing around with Silverlight 3 on Vista and having problems getting the test pages to display in IE 8.  IE had the very helpful message &#8220;Internet Explorer cannot display the page&#8221;.

Thanks to Vijay Kodali I was able to find the answer.

Go to c:\Windows\System32\drivers\etc\  and open the hosts file.  You have [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing around with Silverlight 3 on Vista and having problems getting the test pages to display in IE 8.  IE had the very helpful message &#8220;Internet Explorer cannot display the page&#8221;.<br />
<br/><br />
Thanks to <a href="http://www.vijaykodali.com/post/2009/03/Visual-studio-Development-Server-problem-in-Vista.aspx">Vijay Kodali</a> I was able to find the answer.<br />
<br/><br />
Go to c:\Windows\System32\drivers\etc\  and open the hosts file.  You have to open it as admin to be able to save it, so the easiest thing to do is to click the start button and right click on Notepad to Run as Administrator.  Then open the file via the file menu and you&#8217;ll be able to save.<br />
<br/><br />
Look for the line with &#8220;::1            localhost&#8221;  and change it to &#8220;:::1            localhost&#8221; by adding an extra &#8220;:&#8221; before the 1.  That fixed it on my machine.<br />
<br/><br />
Thanks Vijay!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=jVCxPSmvyr0:nVSSzT262s8:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=jVCxPSmvyr0:nVSSzT262s8:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/jVCxPSmvyr0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/silverlight-development-ie-cannot-display-the-web-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rewriting a location in Nginx</title>
		<link>http://www.inveigledsoftware.com/2009/10/rewriting-a-location-in-nginx/</link>
		<comments>http://www.inveigledsoftware.com/2009/10/rewriting-a-location-in-nginx/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 04:15:03 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[server setup]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=179</guid>
		<description><![CDATA[For some reason I had a tough time finding this one, so for my own future use and in case it helps anyone else, here&#8217;s how you rewrite a url inside an nginx config file.
Calling the old url OldUrl and the url to map to newUrl, here it is:

server {
   listen 80;
  [...]]]></description>
			<content:encoded><![CDATA[<p>For some reason I had a tough time finding this one, so for my own future use and in case it helps anyone else, here&#8217;s how you rewrite a url inside an nginx config file.</p>
<p>Calling the old url OldUrl and the url to map to newUrl, here it is:</p>
<pre class="brush: cpp;">
server {
   listen 80;
   server_name siteName;

    ... (other configuration)

    location oldUrl
    {
         rewrite oldUrl
         newUrl permanent;
     }
}
</pre>
<p>Not that hard, but hard to find <img src='http://www.inveigledsoftware.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=k8kSvLDElVQ:hUZMrDDSMi4:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=k8kSvLDElVQ:hUZMrDDSMi4:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/k8kSvLDElVQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/10/rewriting-a-location-in-nginx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up and Testing Php on Nginx</title>
		<link>http://www.inveigledsoftware.com/2009/08/setting-up-and-testing-php-on-nginx/</link>
		<comments>http://www.inveigledsoftware.com/2009/08/setting-up-and-testing-php-on-nginx/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 14:34:41 +0000</pubDate>
		<dc:creator>bg</dc:creator>
				<category><![CDATA[server setup]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://www.inveigledsoftware.com/?p=131</guid>
		<description><![CDATA[

In the previous article, we set up Nginx with Ruby Enterprise Edition and Passenger support.  Now we need to get php running if we want to run wordpress or drupal or other php-based sites.  We&#8217;ll also add mysql so we have a database back end for these sites
Installing mysql:
This is pretty simple, do [...]]]></description>
			<content:encoded><![CDATA[<p><img alt="" src="http://www.inveigledsoftware.com/wp-content/files/blog/php.png" class="alignleft" width="200" height="50" /><br />
<br/></p>
<p>In the <a href="http://www.inveigledsoftware.com/2009/07/setting-up-nginx-with-ruby-on-rails-using-passenger-and-ruby-enterprise-edition/">previous article</a>, we set up Nginx with Ruby Enterprise Edition and Passenger support.  Now we need to get php running if we want to run wordpress or drupal or other php-based sites.  We&#8217;ll also add mysql so we have a database back end for these sites</p>
<h3>Installing mysql:</h3>
<p>This is pretty simple, do the installation:</p>
<pre class="brush: plain;">sudo aptitude install mysql-server mysql-client libmysqlclient15-dev</pre>
<p>You will be asked to supply a root password.  Make sure you store it so it doesn&#8217;t get lost.<br/><br/></p>
<p>Since this is a production server, it should be secured:</p>
<pre class="brush: plain;">sudo mysql_secure_installation</pre>
<h3>Setting up Php:</h3>
<p>First the installation:</p>
<pre class="brush: plain;">sudo aptitude install php5-cgi php5-mysql</pre>
<p>Note that if you need to access the php.ini file, it will be located here:  /etc/php5/cgi/php.ini<br/><br />
<span id="more-131"></span><br />
Now we need a few scripts and configuration files.  I got these from <a href="http://forum.slicehost.com/comments.php?DiscussionID=1987&#038;page=1#Item_2">here</a>, but I&#8217;ll post the contents here for completeness.</p>
<p>First the init script:</p>
<pre class="brush: plain;">sudo nano /etc/init.d/php-fastcgi</pre>
<p>Copy and paste this in the file:</p>
<pre class="brush: plain;">
#! /bin/sh
### BEGIN INIT INFO
# Provides: php-fastcgi
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop php-cgi in external FASTCGI mode
# Description: Start and stop php-cgi in external FASTCGI mode
### END INIT INFO

# Author: Kurt Zankl &amp;lt;[EMAIL PROTECTED]&amp;gt;

# Do NOT &amp;quot;set -e&amp;quot;

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC=&amp;quot;php-cgi in external FASTCGI mode&amp;quot;
NAME=php-fastcgi
DAEMON=/usr/bin/php-cgi
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
PHP_CONFIG_FILE=/etc/php5/cgi/php.ini

# Exit if the package is not installed
[ -x &amp;quot;$DAEMON&amp;quot; ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] &amp;amp;amp;&amp;amp;amp; . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (&amp;gt;= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

# If the daemon is not enabled, give the user a warning and then exit,
# unless we are stopping the daemon
if [ &amp;quot;$START&amp;quot; != &amp;quot;yes&amp;quot; -a &amp;quot;$1&amp;quot; != &amp;quot;stop&amp;quot; ]; then
log_warning_msg &amp;quot;To enable $NAME, edit /etc/default/$NAME and set START=yes&amp;quot;
exit 0
fi

# Process configuration
export PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS
DAEMON_ARGS=&amp;quot;-q -b $FCGI_HOST:$FCGI_PORT -c $PHP_CONFIG_FILE&amp;quot;

do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test &amp;gt; /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON \
--background --make-pidfile --chuid $EXEC_AS_USER --startas $DAEMON -- \
$DAEMON_ARGS \
|| return 2
}

do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE &amp;gt; /dev/null # --name $DAEMON
RETVAL=&amp;quot;$?&amp;quot;
[ &amp;quot;$RETVAL&amp;quot; = 2 ] &amp;amp;amp;&amp;amp;amp; return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ &amp;quot;$?&amp;quot; = 2 ] &amp;amp;amp;&amp;amp;amp; return 2
# Many daemons donâ^À^Ùt delete their pidfiles when they exit.
rm -f $PIDFILE
return &amp;quot;$RETVAL&amp;quot;
}
case &amp;quot;$1&amp;quot; in
start)
[ &amp;quot;$VERBOSE&amp;quot; != no ] &amp;amp;amp;&amp;amp;amp; log_daemon_msg &amp;quot;Starting $DESC&amp;quot; &amp;quot;$NAME&amp;quot;
do_start
case &amp;quot;$?&amp;quot; in
0|1) [ &amp;quot;$VERBOSE&amp;quot; != no ] &amp;amp;amp;&amp;amp;amp; log_end_msg 0 ;;
2) [ &amp;quot;$VERBOSE&amp;quot; != no ] &amp;amp;amp;&amp;amp;amp; log_end_msg 1 ;;
esac
;;
stop)
[ &amp;quot;$VERBOSE&amp;quot; != no ] &amp;amp;amp;&amp;amp;amp; log_daemon_msg &amp;quot;Stopping $DESC&amp;quot; &amp;quot;$NAME&amp;quot;
do_stop
case &amp;quot;$?&amp;quot; in
0|1) [ &amp;quot;$VERBOSE&amp;quot; != no ] &amp;amp;amp;&amp;amp;amp; log_end_msg 0 ;;
2) [ &amp;quot;$VERBOSE&amp;quot; != no ] &amp;amp;amp;&amp;amp;amp; log_end_msg 1 ;;
esac
;;
restart|force-reload)
log_daemon_msg &amp;quot;Restarting $DESC&amp;quot; &amp;quot;$NAME&amp;quot;
do_stop
case &amp;quot;$?&amp;quot; in
0|1)
do_start
case &amp;quot;$?&amp;quot; in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo &amp;quot;Usage: $SCRIPTNAME {start|stop|restart|force-reload}&amp;quot; &amp;gt;&amp;amp;amp;2
exit 3
;;
esac
</pre>
<p>Now the defaults:</p>
<pre class="brush: plain;">sudo nano /etc/default/php-fastcgi</pre>
<p>Copy and paste this into the file:</p>
<pre class="brush: plain;">
START=yes

# Which user runs PHP? (default: www-data)

EXEC_AS_USER=www-data

# Host and TCP port for FASTCGI-Listener (default: localhost:9000)

FCGI_HOST=localhost
FCGI_PORT=10005

# Environment variables, which are processed by PHP

PHP_FCGI_CHILDREN=4
PHP_FCGI_MAX_REQUESTS=1000
</pre>
<p>Note that we&#8217;re running php as the www-data user, which is how we configured Nginx.<br/><br/></p>
<p>And now the configuration:</p>
<pre class="brush: plain;">
sudo mkdir /etc/nginx
sudo nano /etc/nginx/fcgi.conf
</pre>
<p>Copy and paste this into the file:</p>
<pre class="brush: plain;">
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;

fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;

fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;

fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
</pre>
<p>Make the init script executable and start it:</p>
<pre class="brush: plain;">
sudo chmod +x /etc/init.d/php-fastcgi
sudo /etc/init.d/php-fastcgi start
</pre>
<h3>Testing php:</h3>
<p>Verify that it is running:</p>
<pre class="brush: plain;">sudo ps ax | grep php</pre>
<p>Now we want to make sure it starts on reboot:</p>
<pre class="brush: plain;">sudo update-rc.d php-fastcgi defaults 21 23</pre>
<p>Just to be sure, test the reboot:</p>
<pre class="brush: plain;">
sudo reboot
sudo ps ax | grep php
</pre>
<h3>Make a php info test site:</h3>
<p>Often it is useful to be able to view the output of phpinfo(), but it is not something you want to have available on the internet all the time for security reasons.  To solve this problem, I made a site with just the phpinfo file that I can enable/disable with scripts.</p>
<p><br/></p>
<p>First, we need to set up our sites directory.  People often put their sites in their home directories or in /public_html or various other configurations.</p>
<p><br/></p>
<p>Substitute the path to your sites root folder for &#8220;pathToSitesRoot&#8221; and your domain name for &#8220;yourDomainName&#8221;, both without the quotes.  Depending on where you want your sites root folder, you may have to set some permissions to make this work.</p>
<p>Make the directory:</p>
<pre class="brush: plain;">
mkdir &amp;quot;pathToSitesRoot&amp;quot;
mkdir &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/public
mkdir &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/log
</pre>
<p>Now make the file that will display the php information:</p>
<pre class="brush: plain;">
nano &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/public/index.php
</pre>
<p>Add this one line to the file and save it:</p>
<pre class="brush: plain;">
&amp;lt;?php echo phpinfo(); ?&amp;gt;
</pre>
<p>Now set up a host for the site in the Nginx sites-available folder:</p>
<pre class="brush: plain;">
sudo nano /usr/local/nginx/sites-available/php.&amp;quot;yourDomainName&amp;quot;.com
</pre>
<p>Copy and paste this into the file (adjusting your domain name and path to your sites where applicable):</p>
<pre class="brush: plain;">
server {
   listen 80;
   server_name php.&amp;quot;yourDomainName&amp;quot;.com;

   access_log &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/log/access.log;
   error_log &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/log/error.log;

    location / {
     root &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/public;
     index index.html index.htm index.php;

    }

    # .php and .php5 sent to php5
    location ~ .*\.php[345]?$ {
      include /etc/nginx/fcgi.conf;
      fastcgi_pass 127.0.0.1:10005;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME &amp;quot;pathToSitesRoot&amp;quot;/php.&amp;quot;yourDomainName&amp;quot;.com/public$fastcgi_script_name;
    }
}
</pre>
<p>Now to test, enable the site in Nginx:</p>
<pre class="brush: plain;">
sudo ln -s /usr/local/nginx/sites-available/php.&amp;quot;yourDomainName&amp;quot;.com /usr/local/nginx/sites-enabled/php.&amp;quot;yourDomainName&amp;quot;.com
</pre>
<p>Now restart Nginx to enable the site:</p>
<pre class="brush: plain;">
sudo /etc/init.d/nginx restart
</pre>
<p>You should be able to browse in your web browser to http://php.&#8221;yourDomainName&#8221;.com and see the php info page.  It will tell you what you have installed and the version numbers.  I&#8217;ve often found this helpful when troubleshooting problems with WordPress and Drupal.<br />
<br/><br />
To make it easy to enable and disable the site, create a few scripts.  I prefer to store them under my user folder:</p>
<pre class="brush: plain;">
cd ~
mkdir scripts
cd scripts
</pre>
<p>First the enable script:</p>
<pre class="brush: plain;">nano enablephp</pre>
<p>Copy and paste this into the file (your domain name where applicable):</p>
<pre class="brush: plain;">
# !/bin/sh

ln -s /usr/local/nginx/sites-available/php.&amp;quot;yourDomainName&amp;quot;.com /usr/local/nginx/sites-enabled/php.&amp;quot;yourDomainName&amp;quot;.com

/etc/init.d/nginx restart
</pre>
<p>Now the disable script:</p>
<pre class="brush: plain;">nano disablephp</pre>
<p>Copy and paste this into the file (substituting your domain name where applicable):</p>
<pre class="brush: plain;">
#! /bin/sh

rm /usr/local/nginx/sites-enabled/php.inveigledsoftware.com
/etc/init.d/nginx restart
</pre>
<p>Now make the scripts executable:</p>
<pre class="brush: plain;">
chmod +x enablephp
chmod +x disablephp
</pre>
<p>Now you can enable the site with sudo enablephp and disable it with sudo disablephp.  Be sure to always execute disablephp when you are done examining the php information to prevent broadcasting your installation information on the internet.<br />
<br/><br />
Now with mysql and php running you are ready to install php-based applications like Drupal or WordPress.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/InveigledByDesign?a=e2q1mQzNiW4:F6n45PoYWvM:3QFJfmc7Om4"><img src="http://feeds.feedburner.com/~ff/InveigledByDesign?i=e2q1mQzNiW4:F6n45PoYWvM:3QFJfmc7Om4" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/InveigledByDesign/~4/e2q1mQzNiW4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.inveigledsoftware.com/2009/08/setting-up-and-testing-php-on-nginx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
