Visual Studio

Visual Studio is Microsoft’s Integrated Development Environment (IDE) used for building software for Windows and the .NET platform.

Interactive showdown: csi.exe verses fsi.exe

Visual Studio 2015 Update 1 brings with it a nice little utility called C# Interactive which you can access from the View menu, but we’re going to have a look at the command line version which you can run from the Developer Command Prompt for VS2015.

Using this tool you can quickly run C# using a REPL environment – which is a fast and convenient way to explorer APIs, frameworks, and script existing code from .NET assemblies in a non-compiled way.

While this is new to Visual Studio and C#, we have enjoyed this functionality for a long time with F#.

(Technically this has been around for a while, but it’s officially shipping now!)

I decided to take a look at the new csi.exe application, and compare it to how I already use fsi.exe and see if it’s enough to make me switch my default command line tool.

C# Interactive

For me the most important way I’d use C# Interactive is via the command line, so it’s important to know what it’s capable of, even though you may not need to use the advanced features right away.

To find out the current version and get a list of the command line options in C# Interactive, just add the /? switch and read the output:

PS> csi /?
Microsoft (R) Visual C# Interactive Compiler version 1.2.0.51106
Copyright (C) Microsoft Corporation. All rights reserved.

Usage: csi [option] ... [script-file.csx] [script-argument] ...

Options

/help Display this usage message (alternative form: /?)
/i Drop to REPL after executing the specified script.
/r:<file> Reference metadata from the specified assembly file (alternative form: /reference)
/r:<file list> Reference metadata from the specified assembly files (alternative form: /reference)
/lib:<path list> List of directories where to look for libraries specified by #r directive. (alternative forms: /libPath /libPaths)
/u:<namespace> Define global namespace using (alternative forms: /using, /usings, /import, /imports)
@<file> Read response file for more options
-- Indicates that the remaining arguments should not be treated as options.

Form a first look, I can see that csi.exe has all of the command line options I really want in normal use – I especially find /i to be useful – but we’ll come to that shortly.

F# Interactive

F# Interactive has been around for a lot longer, and is built on different technology under the hood – so there are a more options going on here, but we can take a look by providing a similar -? switch:

PS> fsi -?
Microsoft (R) F# Interactive version 14.0.23413.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

Usage: fsi.exe <options> [script.fsx [<arguments>]]...

Input Files

--use:<file> Use the given file on startup as initial input
--load:<file> #load the given file on startup
--reference:<file> Reference an assembly (Short form: -r)
-- ... Treat remaining arguments as command line arguments, accessed using fsi.CommandLineArgs

Code Generation

--debug[+|-] Emit debug information (Short form: -g)
--debug:{full|pdbonly} Specify debugging type: full, pdbonly. ('full' is the default and enables attaching a debugger to a running program).
--optimize[+|-] Enable optimizations (Short form: -O)
--tailcalls[+|-] Enable or disable tailcalls
--crossoptimize[+|-] Enable or disable cross-module optimizations

Errors and Warnings

--warnaserror[+|-] Report all warnings as errors
--warnaserror[+|-]:<warn;...> Report specific warnings as errors
--warn:<n> Set a warning level (0-5)
--nowarn:<warn;...> Disable specific warning messages
--warnon:<warn;...> Enable specific warnings that may be off by default
--consolecolors[+|-] Output warning and error messages in color

Language

--checked[+|-]Generate overflow checks

--define:<string> Define conditional compilation symbols (Short form: -d)
--mlcompatibility Ignore ML compatibility warnings

Miscellaneous

--nologo Suppress compiler copyright message
--help Display this usage message (Short form: -?)

Advanced

--codepage:<n> Specify the codepage used to read source files
--utf8output Output messages in UTF-8 encoding
--fullpaths Output messages with fully qualified paths
--lib:<dir;...> Specify a directory for the include path which is used to resolve source files and assemblies (Short form: -I)
--noframework Do not reference the default CLI assemblies by default
--exec Exit fsi after loading the files or running the .fsx script given on the command line
--gui[+|-] Execute interactions on a Windows Forms event loop (on by default)
--quiet Suppress fsi writing to stdout
--readline[+|-] Support TAB completion in console (on by default)
--quotations-debug[+|-] Emit debug information in quotations
--shadowcopyreferences[+|-] Prevents references from being locked by the F# Interactive process

As you can see there’s a lot more options for F#, but many of them are not needed for every day use.

Quick Interactive Use

It’s fairly common that I use F# Interactive just to test out how part of the Framework behaves.

In this instance, I’ll use HttpUtility.HtmlEncode method to see see what output I get when one of my emoticons is encoded into HTML-friendly characters.

PS> fsi

Microsoft (R) F# Interactive version 14.0.23413.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> open System.Web;;
> let encode s = HttpUtility.HtmlEncode(s);;

val encode : s:string -> string

> encode "<(>_<)>";;
val it : string = "&lt;(&gt;_&lt;)&gt;"
>

This is how I’d do it in F# – we could call the HtmlEncode function directly, but creating functions is so easy with F# that we might as well shorten the name to make it nice and easy if we need to run it multiple times.

The function encode actually returns a string rather than printing it to the screen, but F# is setting that output to a special value called it – a special identifier which is used for displaying the value of the last expression on the screen. It’s handy, and you’ll see why.

Alright so here’s my first attempt to do something similar in C# Interactive.

PS> csi
Microsoft (R) Visual C# Interactive Compiler version 1.1.0.51109
Copyright (C) Microsoft Corporation. All rights reserved.

Type "#help" for more information.
> using System.Web;
> HttpUtility.HtmlEncode("<(>_<)>");
(1,1): error CS0103: The name 'HttpUtility' does not exist in the current context
>

Ah. HttpUtility is missing because it hasn’t loaded the clases from the System.Web.dll assembly. I didn’t notice on the first line becuase of the way namespaces work – the namespace exists, but not the class we want. No problem, we just reference it using #r – you reference assemblies this way in F# too!

> #r "System.Web"
> HttpUtility.HtmlEncode("<(>_<)>");
>

This worked and we have access to the static HttpUtility class and the HtmlEncode method – however the output has not been displayed to the screen because C# Interactive doesn’t have that the specal it value F# had.

I didn’t realise this at first but in the absense of the it value F# has, the C# Interactive prompt introduces a slightly different syntax for when you want to see the value.

> HttpUtility.HtmlEncode("<(>_<)>");
> HttpUtility.HtmlEncode("<(>_<)>")
"&lt;(&gt;_&lt;)&gt;"
>

Notice the difference a semicolon makes? This is important, and something I missed when first trying out C# Interactive. Avoiding the semicolon would normally result in invalid C#, but this is a great way to view the output as if you’re typing it into the Immediate Window in Visual Studio.

Let’s also create a function using normal C# syntax so that we don’t have so much typing to do. Notice that I’m going to call this function without the semicolon so that I can see the output.

> string encode(string s) { return HttpUtility.HtmlEncode(s); }
> encode("<(>_<)>")
"&lt;(&gt;_&lt;)&gt;"
>

Loading Scripts

Let’s keep things simple, we’ll take the functions we just created in each langauge, and create a script file so that they can be loaded up when we start an interactive session.

First of all, let’s do it with F#. Here’s the content of encode.fsx:

open System.Web
 
let encode s =
    HttpUtility.HtmlEncode(s)

And then we can run it from the command line using the --use switch. This will drop us into an interactive prompt after the code file has been loaded.

PS> fsi --use:.\encode.fsx

Microsoft (R) F# Interactive version 14.0.23413.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

>
val encode : s:string -> string

> encode "<(>_<)>";;
val it : string = "&lt;(&gt;_&lt;)&gt;"
> encode "<(^o^)>";;
val it : string = "&lt;(^o^)&gt;"
> encode "<(T_T)>";;
val it : string = "&lt;(T_T)&gt;"
>

Not bad at all. So let’s do the same thing with the C# interactive, using a file called encode.csx:

#r "System.Web"
using System.Web;
 
string encode(string s)
{
    return HttpUtility.HtmlEncode(s);
}

I love that they used a similar extension! And again, we can run the code file and then get an interactive prompt as above using the /i switch.

PS> csi /i .\encode.csx
> encode("<(>_<)>");
&lt;(&gt;_&lt;)&gt;
> encode("<(^o^)>");
&lt;(^o^)&gt;
> encode("<(T_T)>");
&lt;(T_T)&gt;
>

We have the same end result, though like before the actual functions behave slightly differently. C# Interactive gives a cleaner output here, though you can always clean up the F# Interactive prompt a little bit by using the --nologo switch.

Use Inside PowerShell

Because I want to get access to both of these utilities as fast as possible, I have added a few lines to my PowerShell profile which will ease their use.

I’ve mentioned doing this kind of thing before – and I highly that developers using Windows spend a good amount of time learning PowerShell – but here’s a little snippet that may be useful.

$PROGFILES32 = "C:\Program Files (x86)\"
 
# create an alias to the full path of the executable
Set-Alias fsi "$PROGFILES32\Microsoft SDKs\F#\4.0\Framework\v4.0\fsi.exe"
Set-Alias csi "$PROGFILES32\MSBuild\14.0\Bin\amd64\csi.exe"
 
# add helpers which include common switches
function fsu ($fsx) { fsi --nologo --use:$fsx }
function csu ($csx) { csi /i $csx }

Adding this to my profile means I can just run them using fsu encode.fsx or csu encode.csx respectively. Very easy.

Highlights from Build 2015

The Build 2015 conference has just taken place in San Francisco.

Like last year, this has been another huge event for Microsoft, and a big deal for the people who build solutions using their technologies.

There have been way more interesting things happening than I can possibly cover in one article, but I have decided to cover the three most important to me:

.NET, Windows and Azure.

An exciting future for .NET and Open Source

The future of .NET is the continued push to an open source .NET Core, which is at the centre of both the latest ASP.NET runtime and the Universal Windows app platform. In the future, this will expand and include other application types. In my opinion, they’ve picked the right place to start.

Applications running on the CoreCLR can be developed and deployed on cloud and server-based infrastructures running different operating systems including Windows, Linux and OS X. I have been watching the development efforts on GitHub for a while now, and I’ve set it up on my own machines running both Windows and Linux. It sure is a sight to see.

As well as the core runtime itself going open source, other technologies like Roslyn have enabled products that many wouldn’t have guessed would see the light of day. Having an open source compiler platform has enabled Visual Studio Code – a new cross platform text editor with Intellisense – to be built.

I was lucky enough to see Visual Studio Code before it was announced, and it changed the way I thought about collaboration with Mac users instantly. I’ll have more on this new text editor soon.

Visual Studio Code

With the RC of Visual Studio 2015 there have been some big improvements in the languages supported including both the more traditional C# and Visual Basic, and (my personal favourite) F#.

The Visual F# improvements in ‘every day’ activities are dramatic for anyone who has been using the language. This is all thanks to the new open source attitude, and the amazing community around F# who have helped to develop the Visual F# tools on GitHub.

This new world of cross-platform and open source .NET technology is going to enable some amazing scenarios for .NET developers like myself.

Windows 10’s application platform takes shape

The aforementioned Universal Windows app platform is really taking shape now. Gone are the days of very prescriptive (and maybe too forward-looking) design patterns of Windows 8, and in is the ‘do what’s right for your applications‘ model that has been working well for some for a while.

Universal Windows apps scale from the smallest phones and Internet of Things devices up to the large screens of the Xbox One and the Surface Hub. The most ‘universal’ of these apps are built with just one binary which includes a scalable UI. This allows you to even have the ‘desktop’ app experience when used on a landscape 5.7 inch phone, or when plugged into an external screen using an amazing new Continuum for Phones feature.

For app developers there are some interesting (and controversial) new ways for software venders to build for Windows. The biggest of which are the bridges from Android and iOS. These two are extremely important for the phone and work especially well for iOS games which don’t rely too heavily on the operating specific UI elements. Combined with the bridges for ‘classic windows’ apps and websites using Microsoft Edge, the Store should get a lot more apps on this Windows 10 wave of releases.

From a user’s view, Windows 10 has really rounded out, with the latest Insider Preview feeling a lot more polished than any of the previous builds. Seeing HoloLens run standard Windows Universal apps was a big deal too.

I’ll have more thoughts on these in the future as the Insider Preview continues, and more information for HoloLoens is released at E3.

Microsoft <3 Docker and other Azure improvements

Azure, and the Microsoft Cloud in general, continue to amaze me. Microsoft has managed to embrace this new way of building (and selling) software in at breakneck speed. Additional services were added throughout the platform all the way from storage and networking, to analytics and machine learning. Way too many for this article.

Two of the biggest highlights were the ability to run the complete Azure Stack locally, and Azure’s new Data Lake features too, something which Amazon has had a lot of success with.

Microsoft <3 Docker

For me though, the most interesting changes were around Docker support across Windows and Azure. Docker has been on my radar for a while, but I have yet to use it in production. I have plans to do so in the not too distant future.

Remote Desktop to the Cloud

Remote Desktop for Windows Desktop

For the last six months I’ve been using an Windows 8.1 virtual machine running in Microsoft Azure for various day-to-day developer activities. It has ended up being extremely useful to have a full Windows machine that’s accessible from any place and any device.

Azure

The VM I’m using is A2 Standard and running Windows 8.1, set up with my Microsoft account so all my apps are working on it properly – from Windows Store to Office 365.

Most importantly it also provides an always-on development platform for all my applications even when my main PC is being reinstalled with the Windows 10 technical preview builds. I have access to Visual Studio, F# Interactive, Node.js and all my usual scripting tools in PowerShell at any time.

Remote Desktop for Windows Phone

The remote desktop client for Windows Phone is truly brilliant too, with support for a virtual mouse pad enabling me to get access to applications like Visual Studio or Outlook at any time. True it’s a little fiddly, but it’s really powerful.

Azure’s Virtual Machines suite me as I have a number of credits every month, and nowhere at home to keep a server that could be on 24/7. Overall I’m really pleased with the service.

String Hashing in F#

I recently wrote a small program to convert some strings into a ‘unique enough‘ hash which could be used as a short reference.

Whenever I’m trying to come up with an idea of how to handle these kinds of functions, I tend to turn to my favourite language, F#. This allows me to do rapid prototyping in a very functional way.

Below is the prototype version of this hashing program:

open System
open System.Text
open System.Security.Cryptography

let encode (alpha:string, number:int) =

    let b = alpha.Length

    let rec enc (s:string, n:int) =
        match n with
        | x when x <= 0 -> s
        | _ -> enc (s + alpha.[n % b].ToString(), n / b)

    match number with
    | 0 -> alpha.[0].ToString()
    | _ -> enc ("", number)

let md5Int (input:string) =

    let clean (str:string) =
        str.ToLowerInvariant()
           .Trim()

    let computeHash (str:string) =
        let bytes = Encoding.Unicode.GetBytes(str)
        use crypto = new MD5CryptoServiceProvider()
        crypto.ComputeHash(bytes)

    let convert (bytes:byte[]) =
        let i = BitConverter.ToInt32(bytes, 0)
        Math.Abs(i)

    convert (computeHash (clean input))

let hash (input:string) =

    let a = "ABCDFGHJKLMNPQRSTVWXYZ0123456789"
    let i = md5Int input

    encode(a, i)

Once I have this program created, it’s very easy to use in F# Interactive like so:

> hash "Here is a test string!";;
val it : string = "1W2ALLB"
> hash "The hash is much smaller, which is great.";;
val it : string = "5DAF5T"
>

It’s a great time to be a Microsoft-focused software developer

The Build 2014 conference took place in San Francisco last week, where thousands of developers and designers came together to learn all the latest information about what it means to use Microsoft development tools, and build solutions that run on Microsoft platforms.

I have over 137 GB of videos yet to watch, but I can already say that it has been one of the best Microsoft developer conferences to date.

Here are my thoughts so far, with a few links to some of my highlights.

.NET is alive and well – and becoming more open

build-2014-4

There was a general feeling that .NET developers had been left behind in recent years. A strong push to using HTML and JavaScript really got some people worried when Windows 8 was announced – but at Build 2014 the message was loud and clear. The .NET platform is alive and well.

It’s almost as if they asked .NET developers what would make them really happy, and set about doing all those things. For me, personally, I was most excited by the promise of open-sourcing even more of the framework, including the brand-new compiler platform (Roslyn) that has been years in the making.

Initiatives like .NET Native will allow applications built with C# and Visual Basic to get much closer performance to applications created with C++. Starting first with Windows Store apps, these architecture specific binaries will increase performance at runtime without losing the productivity of developing with the architecture-agnostic .NET Framework.

Roslyn and .NET Native are in preview, and won’t be completed until the next version of Visual Studio. But there have also been a wide range of updates to the ASP.NET web platform, MVC, Entity Framework and way more – most of which are either available now with Visual Studio 2013 Update 2, or can be downloaded using packages from NuGet.

You can tell Windows is under new leadership

build-2014-1

Cortana – the new assistant built into Windows Phone 8.1 – was the highlight of the show. There had been rumours of Microsoft’s answer to Siri and Google Now for quite some time, so a lot of the information had already come out. But still, it was great to see Joe Belfiore talking to her publicly for the first time, confirming what Halo fans were waiting for: yes she is called Cortana, and yes, she sounds like Cortana.

As Cortana is such a huge step for Microsoft, I’ll be going in depth on what I think over the next few weeks.

Cortana wasn’t the only addition to Windows Phone 8.1, there were hundreds of new features and tweaks to the UI that will take weeks to be documented – the new calendar is just one of these. I’ve tried it in the emulator and it’s really great. The developer preview is due this month.

As a developer, the news of Universal Apps was very welcome. This allows high amounts of code sharing between applications designed for both Windows and Windows Phone. I can’t wait to try this stuff out, especially with the new JavaScript support.

Windows 8.1 has some new features too. The much-leaked Windows 8.1 Update includes changes to how the operating system behaves with a keyboard and mouse – though these changes are only the start of the improvements that are coming.

Azure is the future, and already here

build-2014-3

Microsoft’s cloud platform has improved tremendously over the last few years and this year was no exception – in fact, there were so many new features I can’t even begin to go through them all. Some I probably won’t even use (Java? No thanks.) but I know the option is there, which will inform my decisions for cloud hosting in the future.

Scott Guthrie and his team talked at great length about new features that will improve productivity for ‘DevOps’ tasks significantly. For example, the new Azure Portal includes the ability to view statistics, create new infrastructure, build new virtual machines, deploy websites and even do code changes with Git source control – all from one UI.

I already use Azure as part for my personal projects, as well as Visual Studio online as my source code repository. I plan on using it even more in the future – so I’m pleased to see Microsoft lead in this area. And they really are leading.

It doesn’t have to be Windows & .NET

build-2014-2

Times have certainly changed, and PCs that run Windows are no longer the most popular computing devices. As a predominantly Microsoft developer, this makes me wonder about the future. This year’s Build has continued the recent trend of Microsoft supporting other platforms in new ways – plus with partnerships with like likes of Xamarin, I see no reason to even contemplate switching over to Android (the most popular platform) in the foreseeable future.

While I was hoping that there would be the announcement of a Xamarin acquisition, they didn’t disappoint. It was great to see Maguel even joining Anders on stage during the keynote. Both of these guys are very smart, and I look forward to what else the partnership can bring. Being able to develop universal apps that also target iOS and Android is not very far away at all.

Querying TFS with TFPT.EXE and PowerShell

At Branded3 we use Team Foundation Server for source control, task managment, and various other tracking purposes. One of the benefits of this is being able to run queries with WIQL to pull off reports.

As is usually the case with me, I have set up a couple of PowerShell scripts that use TFPT.EXE from the Team Foundation Server Power Tools to make life a little simpler for myself…

Viewing Open WorkItems

$TFSSERVER   = "hq-tfs08-01.branded3.net"

Function Get-WorkItem
{
    $query = "SELECT [System.Id], [System.Title] FROM WorkItems " +
             "WHERE [System.AssignedTo] = 'Julian Kay' " +
             "AND [System.State] <> 'Closed' " +
             "AND [System.State] <> 'Resolved' " +
             "ORDER BY [System.Id]"

    tfpt query /collection:$TFSSERVER /wiql:$query /include:data
}

This little script gets a list of WorkItems which are not closed or resolved from TFS. I find this much faster than opening a copy of Visual Studio to find out which tasks I have assigned to me. True you could run this kind of script by using a batch file, but I like the fact I can use this in conjunction with the various Outlook scripts I use for PowerShell with simple one-liners like foreach ($workItem in Get-WorkItem) { Add-OutlookTask “$workItem” }

Getting Work Hours

Function Get-WorkItemHours
{
    $month = (Get-Date).ToString("MMMM")
    $year  = (Get-Date).Year
    $query = "SELECT [Completed Work] FROM WorkItems " +
             "WHERE [System.AssignedTo] = 'Julian Kay' " +
             "AND [Assigned Month] = '$month' " +
             "AND [Assigned Year] = '$year'"

    $hours = tfpt query /collection:$TFSSERVER /wiql:$query /include:data
    $total = 0.0
    foreach ($hour in $hours)
    {
       $total += $hour
    }
    $total
}

We also have custom fields which help us keep track of the hours we’ve spent on a project, and as shown above, we can even see how many hours have been spent in a month. By running this simple script I can be sure that all my time is correctly recorded to enable us to both bill correctly, and keep track of how long things really take.

Naturally, everyone has their own requirements for scripts like this, but PowerShell gives me the flexibility to create these simple utilities with very little development work.

Writing and Running F# Scripts with Vim

When I’m writing software for the .NET Framework I tend to have a copy of F# Interactive open. This lets me run commands directly like so…

This is fine for simple stuff, but if you’re writing something a little more complex it’s better to write a script. In the past I’ve done this by having another copy of Visual Studio open and running the script that way. This works really well, and includes colour coding, intellisense and all the other good stuff you expect.

However there are times that having yet another copy of Visual Studio is a little heavy for just keeping track of a script. Enter Vim, the de facto command line editor for Unix and other operating systems.

  1. Set up Vim to work with PowerShell
  2. Grab yourself a copy of the F# Syntax file
  3. Save it into your Vim plugins directory
  4. Add the following lines to your vimrc file…
au BufRead,BufNewFile *.fs set filetype=fs
au BufRead,BufNewFile *.fsx set filetype=fs

Now when you create a .fsx file, you can run it directly from F# Interactive by using Vim’s shell execution feature.

:!fsi %

This will run your script in F# Interactive and present you with the results. The :! Vim command is for running the external program, and the % represents the filename of the currently open document.

Note that you’ll need to have set up F# Interactive by either adding it to the path or setting an alias in PowerShell. If you haven’t done this already, you can do it by adding the following lines to your PowerShell profile:

$FSIPATH     = "C:\Program Files (x86)\Microsoft F#\v4.0\Fsi.exe"

Set-Alias fsi  $FSIPATH

Build your own Astrolight app

Astrolight is a simple red flashlight application which you can get in the Windows Phone Marketplace, it’s so simple that I’m going to tell you how you can create one too. With two lines of code.

Assuming you’re all up and running with the free Visual Studio Express for Windows Phone, we just need to start a new Windows Phone Game project…

Then we double click the Game1.cs file and find the Draw method. Here we need to change replace one line with two:

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
    graphics.IsFullScreen = true;
    graphics.GraphicsDevice.Clear(Color.Red);

    base.Draw(gameTime);
}

Press play and watch your brand new app on the Windows Phone Emulator!

Five Favourite Visual Studio 2010 Extensions

Productivity Power Tools

Probably the best code focused extension for Visual Studio 2010 is the amazing Productivity Power Tools. It includes such gems as the Solution Navigator which lets you navigate to classes and members, search for references, and filter your solution to show only checked out files.

NuGet Package Manager

NuGet is an awesome open source package manager for the .NET platform, which includes a very large amount of third party libraries ready to use in a couple of clicks. Or, if you fancy, by using a PowerShell console. They totally get extra points for the PowerShell integration…

F# Outlining

The name pretty much describes what it does. Visual Studio 2010 was a pretty massive release for Microsoft, including F# for the first time. This is why I totally forgive them for not implementing outlining support for this fledgling language. Fortunately someone else did their job for them.

Spell Checker

Everyone wants to have properly spelt comments, especially when you’re using the XML comment features in the .NET languages to produce documentation for your customers. While this plugin is pretty simple, it works a treat and even supports custom dictionaries.

Python Tools for Visual Studio

Not just an extension, but a whole bunch of Python related win for Visual Studio. This latest version works with both CPython and IronPython which really increases the scope for these tools.

Don’t forget to couple these guys with the Microsoft Web Platform Installer for great justice.