Category Archives: Technology

Test Driven Development (TDD) and Windows Phone 7

Kylen, my 6 year old son, is really into world flags. At home we have a sheet of around 200 flags from across the globe, and he’s pretty close at reciting all of them (and certainly much better than Mom and Dad!).

Spending a couple of hours over labor day last month, I set myself a task of building a “Flag Matching” application for Windows Phone 7 (WP7). My goal was twofold: Build a simple application that he can use (and that I can offer on the marketplace), and at the same time, look into some of the TDD best practices for developing a WP7 application.

imageThe application itself is simple enough. As shown above, the player gets presented with a picture of a flag, and four possible countries (of which only one is correct). A game consists of 20 flags, and the application maintains a high score table.

During development of the application, this is what I found:

1. Setting up TDD for Windows Phone 7

As a new developer for Windows Phone 7, one of the first things you’ll quickly discover is that there is no option for a test project within the IDE. After creating a WP7 solution, I searched for the “WP7 Test Project” template, but to no avail…

imageA quick search on the Web will offer up a few alternatives and chances are, you’ll quickly reach Jeff Wilcox’s session on Unit Testing Silverlight & Windows Phone Applications from MIX10. This is a really good session, however the recommended approach (using a Silverlight-based unit test framework) can be somewhat limited.

In my opinion, although it works well for small numbers of tests, not having unit tests outside the emulator makes it difficult for large test suites, using any continuous integration, and integrating with the IDE.

If unit tests in the emulator don’t work for you either, here’s a workaround:

In your solution, create a new project of type Windows Phone Class Library.

imageName it appropriately (I called mine FlagMatch.Test) and include a reference to the original Windows Phone project (FlagMatch). Add the NUnit unit test framework library as a reference (I’m using v2.0.50727) and write your tests as you normally would (of course, specific to the NUnit syntax).

[TestFixture]
public class FlagModelTests
{
    [Test]
    public void TestFourRandomFlags_AllUnique()
    {
        Assert.AreEqual(4, Flag.FourRandom.GroupBy(f => f.Name).Select(f => f).Count());
    }
}

Once you have a set of tests, you can then integrate these within Visual Studio. I’ve had reasonable luck with Visual NUnit, a free IDE plug in that works well with many versions of Visual Studio.

imageAlternatively, if you use ReSharper, you’ll find that their IDE integration works great also.

imageMy preference is to use ReSharper as it works well with with another JetBrains product called dotCover – for which you can use to analyze test code coverage in your Windows Phone application.

Although you’ll find the majority of your unit tests will work great, you may well come across some strange errors. Most of these will be related to operations on the phone that cannot be replicated outside the emulator. For example, accessing isolated storage or referring to embedded resources/images as part of the project works well within the emulator, but not so much from a class library.

To get around this, you’ll need to create some mock objects to handle these operations. In my test project, I have a MockStorageProvider that I use in place of calls to isolated storage:

[Test]
public void TestResumeButton_NotVisibleOnStartup()
{
    MainViewModel viewModel = new MainViewModel(new MockStorageProvider());
    Assert.AreEqual(Visibility.Collapsed, viewModel.ResumeGameButtonVisibility);
}

As you can see, I pass the mock object to the view model (more on this in the next section) as an optional constructor parameter. All storage operations then use this MockStorageProvider instead of writing to isolated storage (which would have generated an exception during the tests). This also has the advantage that I can add additional tests within the mock object to ensure that the storage provider is being called correctly from the application.

2. Using MVVM with WP7

For anyone with experience of testing Silverlight projects, you’ll know that although XAML provides a code separation layer, testing parts of the UI (e.g. actions when a button is pressed) can still be difficult. This can be overcome by using a pattern called MVVM (Model View ViewModel). I’m not going to go into the details of MVVM here (there are plenty of other resources that do a great job) other than to say it can be used for WP7 applications with a little tweaking. The core reason is that WP7 is based largely on the SL3 codebase, which does not contain a complete commanding event model.

There are a couple of approaches in order to get MVVM working on WP7. The first would be to reuse one of the existing samples/libraries available today. Your mileage may vary (as I found some were designed for pre-RTM versions), although I’ve heard good reviews about Laurent Bugnion’s MVVMLite project.

If instead you’d like to learn how implement this yourself, here is how I achieved it:

First, you should create a view model base. Assuming you are going to have multiple view models (I ended up with one per page), it’s a good idea.

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Next, create your view model, inheriting from ViewModelBase.

public class MainViewModel : ViewModelBase
{
    public string NewGameButtonTitle
    {
        get { return AppResources.NewGameButtonTitle; }
    }

    public NewGameCommand NewGameButton
    {
        get
        {
            return new NewGameCommand();
        }
    }
}

For the purposes of this sample code, let’s imagine that we have a single page with a “New Game” button. As you can see above, the view model contains two properties – one for the title of the button, the second for the command that this button will be bound to.

In order to implement the commands, you’ll need a couple of things. The first is a command service:

public static class CommandService
{
    private static readonly DependencyProperty _commandProperty;

    static CommandService()
    {
        _commandProperty = DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(CommandService),
        new PropertyMetadata(OnCommandChanged));
    }

    public static ICommand GetCommand(DependencyObject dependencyObject)
    {
        return (ICommand)dependencyObject.GetValue(_commandProperty);
    }

    public static void SetCommand(DependencyObject dependencyObject, ICommand value)
    {
        dependencyObject.SetValue(_commandProperty, value);
    }

    private static void OnCommandChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dpceArgs)
    {
        if (dependencyObject is Button)
        {
            string parameter = dependencyObject.GetValue(_commandProperty).ToString();
            Button button = (Button)dependencyObject;
            ICommand command = (ICommand)dpceArgs.NewValue;
            button.Click += delegate(object sender, RoutedEventArgs arg) { command.Execute(parameter); };
        }
    }
}

There are a good number of examples of this around (just search for MVVM) – this one I found in a great post from the Coding Solutions blog.

After this, you’ll need to create event handlers. Here’s a simple handler for when the new button is pressed.

public class CommandEvents
{
    public static EventHandler NewGameButtonPressed;
}

Your command itself simply implements the ICommand interface:

public class NewGameCommand : ICommand
{
    public NewGameCommand()
    {
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        if (this.CanExecute(null))
        {
            if (CommandEvents.NewGameButtonPressed != null)
            {
                CommandEvents.NewGameButtonPressed(this, new EventArgs());
            }
        }
    }
}

With all these in place, you can now bind the command to the actual button in your XAML file. On your XAML page, you’ll need to add the following namespace:

xmlns:Commands="clr-namespace:FlagMatch.Commands"

And on the button itself, simply bind to the command using the following:

button name="button1" margin="134,505,0,0" verticalalignment="Top" commands:commandservice.command="{Binding Path=NewGameButton}" content="{Binding NewGameButtonTitle}" height="72" horizontalalignment="Left" width="227"

Notice how the content of the button is bound to the NewGameButtonTitle in the view model, and the command is bound to the NewGameButton command. More importantly, notice also how there are no traditional event handlers needed here.

The final piece of the puzzle is to register the view model and the button event handler in the XAML code behind. To do this, in the code behind, we create an instance of the view model:

private readonly MainViewModel _mainViewModel = new MainViewModel();

Then in the constructor, bind the view model to the datacontext and register the button event handler.

LayoutRoot.DataContext = _mainViewModel;

CommandEvents.NewGameButtonPressed += new EventHandler(StartGame);

The StartGame method simply performs a navigate action for us. This is something that just can’t be moved into the view model.

private void StartGame(object sender, EventArgs e)
{
    NavigationService.Navigate(new Uri("/GamePage.xaml", UriKind.Relative));
}

Other than that, there is no additional UI logic required in code behind – which means for a slightly more complex implementation, but one that provides great test coverage.

A final point worth noting is designer support. As you start building out controls using the MVVM paradigm, you’ll likely find that the designer ends up being difficult to use.

imageBecause we are binding content directly to the view model, the designer doesn’t know where to pick up values to be shown at design time. Fortunately, there is a way around this. Simply add a reference to the view model in your App.xaml file:

Rebuild the project, and you’ll see that the designer picks up the default values from a instance of the view model class:

image3. Localization and MVVM

Finally, I wanted to make sure that my MVVM model could be used for multiple languages.

You may have noticed that in the previous code sample, the title of the button is returned as AppResources.NewGameButtonTitle (instead of returning “New Game”).

public string NewGameButtonTitle
{
    get { return AppResources.NewGameButtonTitle; }
}

This is to make localization easy (well… easier!). Under my Locales namespace there are two files:

imageAppResources.resx is a resource file that contains default (in my case English) string values. In there, you’ll find that NewGameButtonTitle refers to a string called “New Game”.

As you may have guessed, AppResources.es-ES.resx is the Spanish version of this resource file. In there, you’ll find that NewGameButtonTitle refers to a string called “Nuevo Juego”

In order to enable the Spanish localized version, we need to do a few things:

Firstly, create separate resource files for all your languages, using the AppResources.[lang].resx format as stated above.

Next, in the .resx file, ensure that the access modifier is set to public.

image(Otherwise, you’ll find that it just doesn’t offer the localized version).

Them edit your .csproj file outside Visual Studio (using Notepad or similar). Add the supported country code in the SupportedCultures tag.

es-ES

Save the file and reload the project in Visual Studio.

Once this is done, deploy the application to the emulator, and set the language of the emulator appropriately (Settings / Region and Language / Display Language). The emulator will restart.

Finally, test your application. You should find that the new language strings are now used:

image(My Spanish isn’t that good, so apologies for any mistakes above!).

One word of caution: The testing process on the Windows Phone Marketplace is strict when it comes to supporting multiple languages. If you submit an application that supports multiple languages, you really need to make sure that all strings are localized (and you provide localized screenshots and product descriptions) in order to pass the testing certification.

*** Update: I’ve recently moved the source code for the project – you can now find it on http://github.com/simonguest/flagmatch ***


  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Speaking at JavaOne 2010!

I recently found out that I will be speaking at JavaOne again this year!  I’ll be participating on a quick-fire demo panel called Taking Java to the Sky:  Cloud Computing 2010 Expert Panel together with representatives from Oracle, Salesforce, and Amazon.  Raghavan Srinivas will again be doing a wonderful job by moderating the session, and you can find the details by looking up code S313962 – it will be on Monday 20th at 11.30am.

JavaOne is one of my favorite conferences, so I’m really looking forward to returning this year.  Although I spoke last year, my favorite JavaOne was in 2005, where my session on Advanced Web Services Interoperability (co-presented with Raghavan) was one of the top ten of the conference!  I have a beautiful glass trophy with a Java logo in my office – quite a rarity on the Microsoft campus!

File:Duke Wave.png

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Cloud Computing Interoperability

Over the past few weeks I’ve been working with Jean Paoli’s team at Microsoft to create an application that runs across multiple cloud vendors.  Jean’s team has been working on a number of SDKs for PHP and Java, and I wanted to create a sample that demonstrated all of them working together.

The result is a small application that calculates every prime number between 1 and 10,000,000 in a minute or less, with the calculation performed by a set of PHP pages running on Windows Azure, a Java Servlet running on Google AppEngine, and an ASP.NET application running on Amazon EC2.  All of the results are stored in a central SQL Azure database, and I used the .NET Service Bus to coordinate messages across the three cloud applications.

I presented this for the first time at TechEd Europe last week in Berlin and this week at QCon in San Francisco.  Both presentations seemed to strike a chord with the audience, especially the attendees looking for how interoperability works in the cloud.

For those that weren’t able to make it to my sessions, I’ve recorded a short screencast of the demo in action – you can find it here

If you are after more information, here you can find a longer (50 minute) screencast that goes into the details of how this works.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Online Talks from TechEd 2009

Just before heading home from TechEd 2009 in LA, I recorded a couple of online interviews, which are now available:

Patterns for Moving to the Cloud:  Recorded with Denny Boynton, host of ARCast, we chat about where applications live, and what applications make sense for the cloud.  We also cover a set of patterns that was shown in my previous session.

Demystifying the Cloud:  In this talk, I chat with Kevin Remde on what cloud computing means for IT managers, and some of the considerations for moving applications to the cloud.

These were fun to put together; hope you find them useful. 

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Slides from TechEd 2009

Today is my last day at TechEd 2009 in LA, and as promised, I’ve uploaded the presentations from the three talks that I’ve given this week.  Thanks again to everyone that attended my talks, and I really enjoyed speaking with many of you after the presentations. 

PRC02 – Demystifying the Cloud

This is the presentation that I gave as part of the architecture preconference on Sunday 10th.  It’s a high level look at cloud computing and covers the definition of running applications on premise, in a hosted environment, and in the cloud, together with many of the considerations for doing so. 

image

Click here to view the presentation on SlideShare.

Click here to download the presentation.

ISB204 – Impact of the Cloud for IT Managers

This presentation was delivered on Monday at 4.30pm and covers much of the pre-conference material from PRC02, but through the eyes of an IT Manager.  When I was putting the decks together I realized that there were many common concerns shared between the IT Manager (from an operations perspective) and the IT Architect (from a design perspective), in which I try to surface in this deck.

image

Click here to view the presentation on SlideShare.

Click here to download the presentation.

ARC308 – Patterns for Moving to the Cloud

This is my presentation from Tuesday at 8.30am that covered a series of patterns for moving to the cloud.  In this presentation I look at the differences between on premise, hosted, and the cloud, describe some applications that you may find running on premise in a large organization, and then cover five patterns for running these applications in the cloud.  The patterns I cover are:  Transference – moving applications from on premise to the cloud, Scalable Web / Multi Tenancy – cloud application that can scale on the web front end, Burst Compute – cloud applications that have the ability to dial up / dial down compute resources as necessary, Elastic Storage – looking at how the cloud can provide for storage that can grow on demand, and Inter-Org Communications – sharing how part of the cloud can be used to connect multiple organizations through a service bus and workflow.

As you can imagine, with the space being so new, these are not a definitive or exhaustive list of all patterns for cloud computing, but I hope they were useful in introducing the different types of applications running in the cloud.

image

Click here to view the presentation on SlideShare.

Click here to download the presentation.

I believe two of the three sessions (ISB204 and ARC308) were also recorded and will be online soon.  Once I get hold of them, I’ll update with the link.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Using SketchFlow to Create Better Prototypes

I recently put together this article for InfoQ on using SketchFlow to create better prototypes. 

In case you haven’t run across it yet, SketchFlow is a feature of Microsoft Expression 3, announced during the MIX09 conference in March this year.  In this article I cover the importance of prototyping (I’ve often said that we don’t do enough prototyping in IT), and take the reader on a walkthrough of using SketchFlow to build a prototype shopping store for InfoQ.

Hope you enjoy the article – feedback always welcomed!

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Displaying XPS Documents in Silverlight

I’ve recently been involved on a project that has a requirement to create and view XPS documents in Silverlight.  The application needs to display the XPS file in a full screen window together with zoom and navigation features.

After a little searching on how to do this, I was able to get a head start with this great post from David Anson, which includes sample code for viewing XPS files in Silverlight 2 beta 2.  As his updated post attests to however, there were a few issues with Silverlight 2 due to a breaking change with the ways that font resources could be referenced from within a Silverlight assembly.  Fortunately, this post from Li Chen pointed me in the right direction, separating out the ODTTF fonts into separate XAP files which can be referenced at runtime. 

The sample code provided by Li Chen works well with the sample XPS files provided, but I couldn’t get it working with an XPS file generated using Microsoft Word.  After a little debugging this weekend, I found a few subtleties with how the code dealt with XPS files geneated from Microsoft Word:

Firstly, the root document of the XPS file is called FixedDoc.fdoc instead of FixedDocument.fdoc (which is the name when using the XPS Printer Driver).  This was fairly easy to correct using a simple check:

// Added to support "Save as XPS" from Microsoft Word
if (resourceInfo == null)
{
    resourceInfo = Application.GetResourceStream(_streamResourceInfo, ConvertPartName("/Documents/1/FixedDoc.fdoc"));
}

Secondly, the .fdoc file refers to pages using relative links.  Instead of the absolute link (e.g. /Documents/1/Pages/1.page), a relative link (e.g. /Page/1.page) was causing the sample to be unable to find the pages.  A small piece of code to append the full path quickly fixes this also.

// Update the page names for "Save as XPS" from Microsoft Word
List<string> _newPageNames = new List<string>();
foreach (String pageName in _pageNames)
{
    if (pageName.StartsWith("Page"))
    {
        _newPageNames.Add("/Documents/1/" + pageName);
    }
}

Finally, it looks like Word includes a page attribute called BidiLevel, which isn’t recognized by the Canvas element.  Adding an additional exclusion line into the sample code quickly fixed it.

_elementAttributesToRemove.Add("Glyphs", new List<string> { "BidiLevel" });

The result seems to work quite well, with an XPS file saved from Microsoft Word viewable within Silverlight.  

image

If you are interested in trying this yourself, I’ve posted a version of the sample code here which contains the above modifications.  To use the modified sample with your own XPS file, do the following: 

1.  Go into Microsoft Word and “Save as / XPS” to create a new XPS file.

2.  Download and compile the sample (note: only works in Visual Studio 2008). 

3.  Copy the XPS into your Visual Studio project, in the SimpleSilverlightXpsViewer_Web project. 

4.  In Windows Explorer, rename the original XPS file to a ZIP file.  Ignore the warning about changing the file extension.

5.  Open the zip file and go into the /Resources directory.  Look for font files ending in ODTTF – these are embedded font files for the XPS file and must be referenced separately in the Silverlight project.  Copy all of these ODTTF files to the SampleWordGenerated project in the solution.  Also note that the ODTTF files are dynamically named when the XPS file is generated.  This means that although you may have already imported the correct ODTTF files for previous XPS file that use the same fonts, you’ll still need to re-import the fonts again to handle a new XPS file. 

6.  Edit default.html in SimpleSilverlightXpsViewer_Web and on line 70 change the xpsDocument=SampleWordGenerated.xps to the correct name of your XPS file. 

7.  F5 to run and you should see your XPS document displayed within a Silverlight control!

There is still a bit of work to do with the sample code, which I think would be worth taking into a CodePlex project.  For example, the code should initially read the XPS root file (FixedDocSeq.fdseq) instead of looking or FixedDoc.fdoc or FixedDocument.fdoc directly.  It would also be great to figure out a better way of extracting the fonts more dynamically at runtime.  Other than that though I found this to be a good solution to display XPS files in Silverlight applications, especially useful as Silverlight doesn’t support the FlowDocument element (which is commonly used in WPF applications for creating documents and report generation).

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Cloud Computing Talks at TechEd 2009

I wanted to share the details of two cloud computing sessions that I will be presenting at TechEd 2009 in Los Angeles next month: 

ISB204:  The Impact of the Cloud and Software as a Service – 5/11/2009 4:30PM-5:45PM

ARC308:  Patterns for Moving to the Cloud – 5/12/2009 8:30AM-9:45AM

The first session (ISB204) is part of the IT Manager track.  The goal of this 200 level session is to explore the significance of cloud computing for IT decision makers.  This will include looking at different types of applications and understanding whether they make sense for the cloud, and why – and then investigating some of the tradeoffs and risks for moving certain applications to the cloud. 

The second session (ARC308) is the next level deeper:  an architect/developer focused session that will cover a collection of design and implementation patterns for cloud based applications.  For example, how the cloud can enable parallelization across multiple machines, blob storage in the cloud, and some of the finer points of identity management within applications.

We are still a few weeks away from the event, so if there are questions that would like to see answered or other items that you think would make sense in either presentation, do get in touch and let me know. 

And to those that will be attending TechEd 2009, I look forward to seeing you there!

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Twitter for Office Communicator

One of my observations from MIX09 last week was the sheer number of attendees using Twitter at the event.  In addition to the “flotzam” wall (a realtime display of tweets) during the keynote session, I couldn’t turn a corner without running into someone tweeting about something. 

Although I must admit that “I still don’t get twitter”, on the plane ride back to Seattle, I thought it would be interesting to create a twitter client that works in conjunction with Office Communicator

As you may know, Office Communicator provides the ability to set presence information as part of the UI.  Presence information is useful for out of the office details such as “At Chicago office today”.

image

After having used this in the past, I wondered how easy it would be to take this presence information and publish it to Twitter.  i.e. When I update the presence text in Office Communicator it would also update my twitter account with the same information.  That way I can provide short presence information in one place and have it published to both internal users of Office Communicator and my (small number of) followers on Twitter. 

The result is Twitter4OC, a small client app that runs in the background and listens for presence updates from Office Communicator, creating new tweets as appropriate.  If you are interested in seeing how it works, you can find the binaries here and the sample code here

Twitter4OC uses the OCSDKWrapper libraries from this excellent project on codeplex to listen to status changes in Office Communicator. 

MOCAutomation _moc = null;

if (_moc == null)
{
    _moc = MOCAutomation.Instance;
    _moc.MyStatusChange += new EventHandler<OCSDKWrapper.MOCEventArgs.MyStatusChangeEventArgs>(_moc_MyStatusChange);
}

If it detects that the presence information has been updated, it firsts calls the TinyURL API to change any URLs into a smaller format, and then makes a call to the Twitter API to tweet the updated status. 

    private string Post(string url, string username, string password, string data)
    {
        // Prevents HTTP-417 error code from API
        ServicePointManager.Expect100Continue = false;

        // Construct the WebRequest
        WebRequest request = WebRequest.Create(url);
        request.Credentials = new NetworkCredential(username, password);
        request.ContentType = "application/x-www-form-urlencoded";
        request.Method = "POST";

        byte[] bytes = Encoding.UTF8.GetBytes(data);
        request.ContentLength = bytes.Length;
        using (Stream requestStream = request.GetRequestStream())
        {
            requestStream.Write(bytes, 0, bytes.Length);

            using (WebResponse response = request.GetResponse())
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }

    public string Update(string username, string password, string presence)
    {
        // First tinyfy the URLs
        presence = TinyURL.TinyfyPresence(presence);

        // Check the length of the status < 140 chars
        if (presence.Length > 140) throw new StatusTooLongException();

        try
        {
            string url = TWITTER_UPDATE_URL;
            string data = string.Format("status={0}", HttpUtility.UrlEncode(presence));
            return Post(url, username, password, data);
        }
        catch (Exception e)
        {
            throw new UpdateFailedException(e.ToString());
        }
    }
}

The application runs as a small exe that can be launched at startup and takes parameters via a simple credential form or via settings in the App.Config file.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Using Windows 7 to host PHP applications in 5 easy steps!

A few people have asked me recently whether it’s possible to setup Windows 7 as a PHP server (for development purposes).  The answer is absolutely yes, and it’s a breeze to setup.  Follow these five simple steps to get PHP up and running in minutes:

1.  In the Programs and Features control panel, click on the Turn Windows features on or off link:

image

2.  In the list of Windows Features, expand Internet Information Services, World Wide Web Services, and the Application Deployment Features.  If it’s not already, select the CGI checkbox and click OK.  (The most reliable way of hosting PHP applications on Windows 7 is to use the built in FastCGI interface for IIS – checking this box installs it together with any pre-requisites.)

image

3.  Download the non-thread-safe (NTS) version of PHP from http://www.php.net/downloads.php.  The current version (as of time of writing is 5.2.9).  (The thread safe (TS) version will also work, but generally NTS is faster, and thread safety is not an issue under FastCGI).  Expand the zip to an installation directory of your choice – e.g. c:devphp

4.  Copy the php.ini-recommended file to php.ini in the PHP directory.  Edit the php.ini file and add correctly configure extension_dir, pointing to the PHP extensions directory (normally the .ext folder of the PHP installation – e.g c:devphpext).  You can also configure other php.ini options and modules here if required.

5.  Run Internet Information Services Manager by typing inetmgr in the Start menu.  You can either set the global settings of the server, or (recommended) add a new web site to run the PHP applications.  Once you’ve done this, double click on the Handler Mappings for the site and add a new module mapping with the following settings:

image

Request path should be set to *.php.  Module should be FastCgiModule.  Executable should be {php_install_dir}php-cgi.exe.  Name can be anything – I use “PHP via Fast CGI”.

That’s it! Simply start/restart IIS and you are ready to go.  The easiest way to test that everything is working is to create a simple info.php file with a single line:

<?php phpinfo(); ?>

When you access this page from a browser (e.g. http://localhost:8081/info.php), you should see the PHP info screen:

image

Validate that the server API is using CGI/FastCGI and that the loaded configuration file is the one in your installation directory.

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS