Presentation: Introduction to Windows 8.1 App Development

A huge thanks to the crowd at the San Diego .NET Developers Group! You guys were an awesome crowd. Congrats on the 20 year anniversary of the group as well. It’s great to know we have a deep culture of helping and teaching each other in the area. Keep it up!

For those that couldn’t make it we discussed how to handle Page Navigation and App Lifecycle for the first hour then moved into Location Services for the last 30min. Theses are some critical topics for Windows 8.1 App Development that I think a lot of people could use some help with. I only say that because many apps I use behave badly. I hope you find the recording of the session useful. Please leave some comments on what you think!

Materials

 

Again, thanks a bunch! And we’ll catch you next time!

Getting Started with PHP On Windows

Intro

For the four-or-so years that I’ve been writing code, it’s always been with a Microsoft technology; starting with VBScript, moving to VB.Net, and eventually C#, Silverlight, and WPF. I’ve been meaning to dive in to the cross-platform, open source world of Web Development, and I have explored the various aspects of it at different times, so I’m going to do an end-to-end, cross platform “Address Book” based on web technologies…HTML 5, CSS, and JavaScript for the front end, PHP for server side scripting, and MySQL for my database. However, I will still be using a Microsoft product…IIS as my web server, for the sake of familiarity. This walkthrough will help you get PHP installed on your Windows machine, and IIS configured to work with PHP.

Preparing IIS

PHP is very well documented, and I suggest you browse through the manual at http://www.php.net/manual/en/index.php to get familiar with the language before diving right in to the preparation and installation. The steps I list below are for IIS 7, on Windows Vista SP1, Windows 7, or Windows 8, and are based on the instructions in the manual I linked to above.

  1. Assuming you already have IIS 7 installed ( go do that, if you don’t), we need to enable FastCGI on IIS. To do this, open Control Panel, and select Programs and Features. In the column on the left side, click “Turn Windows features on or off”. In the Windows Features dialog, expand Internet Information Services, then expand World Wide Web Services, Application Development Features, and select the check box next to CGI. You should see something like this…..
  2. Click Ok, and Windows will do the installation.

Installing PHP

The actual process of installing PHP requires a bit of reading, because you have to set up the config file once you’ve downloaded and extracted the correct build of PHP. Here is a link to the full process… http://www.php.net/manual/en/install.windows.manual.php . Once you download and extract PHP, and get your config file set up, we’ll need to tell IIS how to process PHP requests.

Configuring IIS to Process PHP

These last steps will guide you through using the IIS Manager UI to create a handler mapping for PHP, and, again are based on the steps in http://www.php.net/manual/en/install.windows.iis7.php . I recommend you take a look at their manual after doing this simple UI setup, as they have detailed information on how to use the command line tool, and information about impersonation and file system access.

  1. Open Control Panel, select Administrative Tools, and double click IIS Manager.
  2. Select the Server node in the tree view on the left side, and then double click the Handler Mappings icon in the IIS section of the Features View. It should look similar to this…    
  3. In the Actions pane on the right, click “Add Module Mapping…” 
  4. Enter the following information in the “Add Module Mapping” dialog…
  • Request path: *.php
  • Module: FastCgiModule
  • Executable: C:\[Path to PHP installation]\php-cgi.exe
  • Name: PHP_via_FastCGI

5.  Click “Request Restrictions” button and then configure the mapping to invoke handler only if request is mapped to a file or a folder;

6.  Click OK on all the dialogs to save the configuration.

Test

If everything went according to plan, your default website is now configured to process PHP requests. Here’s how we test it…

  1. Open up Notepad and enter the following line of text, without the quotation marks surrounding it…”<?php echo ‘Hello World’; ?> “
  2. Click File, Save As…, and save the file as Test.php ( be sure to set the file type to All Files) in your My Documents folder.
  3. Copy the Test.php file to C:\inetpub\wwwroot.
  4. Finally, open a web browser and browse to localhost/test.php. You should see your Hello World output.

Conclusion / Now What?

This walkthrough covered the very basics of getting PHP installed, and setting up IIS to process PHP requests. It didn’t begin to touch on the actual language, syntax, or usage of PHP, but there is great documentation and plenty of walkthroughs at php.net to get you started on using PHP. My next blogs will be about setting up MySQL ( Spoiler: it was infinitely easier than my first attempts at installing and configuring Microsoft SQL Server ) and connecting to it from PHP, and how to use browser detection to detect mobile devices and load appropriate css sheets.

CES 2014 – My Presentation and Invite to a Private Party (VIP Reception)

ces

I am pretty excited (and honored to be invited back) to speak at CES International in Las Vegas again this year.  My presentation details are below in case you are going to CES and can attend.

But, I’m also keynoting a VIP Reception that same night.  it’s a private event with a party (cocktails / food) after.  It should be totally fun.  It’s sponsored by the Microsoft Perspective Pixel Team, Avnet, and hosted at The Integration Center.  It’s free and transportation to and from the CES conference center is provided.  I have provided the Details and registration link and private code below.

Details:

Register to Attend VIP Reception at CES 2014

You are invited to attend a VIP reception at CES 2014 hosted by Perceptive Pixel (PPI) by Microsoft and Avnet. The International CES Conference covers all things groundbreaking, market-leading and pioneering in the consumer electronics (CE) industry and PPI will be there to showcase how you can leverage our devices to redefine your meeting experiences.

The reception hosted at the Integration Center in Las Vegas brings together industry-leading companies and ideas under one roof. The event will kick off with a special keynote presentation from Tim Huckaby  on “The Engaging User Experience & the Natural User Interface”. This demo focused keynote will take an amusing look at the past and take an impressive look at some of the best NUI software being built today and into the immediate future and will even delve into the NUI of the future.

A cocktail reception will immediately follow the keynote, where you will have the opportunity to meet with key executives from Microsoft and Avnet to learn more about how we are working together to drive innovation and collaboration in the industry while networking with fellow CES attendees. You will also have an opportunity to see demos and learn how PPI is enabling organizations to spark creativity, ignite collaborative power, showcase their best.

Space for the reception is limited, use the link below to RSVP and secure your space to attend. Registration closes Friday,

When& Where:

Wednesday, January 8th

4:30 – 5:30 PM – Keynote Presentation The inNEVation Center

5:30 – 7:30 PM – Cocktail Reception The Integration Center

6795 Edmond Street, Las Vegas, NV 89118

(702) 605-9800

Transportation:

Shuttles will pick up attendees at 4:00 PM at the Venetian Resort Hotel Bus & Tour Lobby

Shuttles will depart the Integration center at 7:30 PM to return to the Venetian Resort 

Link to Register:

https://msevents.microsoft.com/CUI/InviteOnly.aspx?EventID=C0-41-DD-A3-8F-29-24-BF-A0-2D-85-33-19-6A-99-72&Culture=en-US&community=0

RSVP Code:

521DAE

Please note that registration requires a Microsoft account to register. If you use Hotmail, SkyDrive, Xbox LIVE, or a number of other products you already have a Microsoft Account. Don’t have a Microsoft account? Sign up now to create your profile and save time for future registrations.

Reception Co-Hosted By

clip_image001 clip_image003clip_image005


Details on my Presentation at CES:
January 8, 2014

Session: User Interface Innovation: What’s on the Horizon?

Gesture control has moved from videogame consoles to PCs and TVs and it is setting its sights on your car’s dashboard. Is 2014 the year of gesture? Will kinetics, facial recognition, eye tracking and brain control make the cut or die on the vine?

Location:LVCC, North Hall

Room:N259

Time:2:00 PM – 3:00 PM

Role:Moderator

Text On A Path With Alignment

Click here to download code and sample project

In past WPF projects, design specifications given by artists are sometimes challenging to attempt to implement. One scenario I have ran into multiple times was trying to display custom text around a curved object. Most of the time this problem was avoided by the artist providing the content as images, but, fortunately, this was only feasible because the text was finite and static. Recently I came across this same scenario again except this time the incoming text could be dynamic. The immediate reaction was to simply read the text as images stored in a folder provided by the customer. This solution tends to create problems in the future because:

  • The user must be familiar with some image editing tool
  • If not accustomed to any, then the user has to be trained
  • The user must be aware of the exact font, weight, and color the artist intended
  • The user must also have the same eye for lining up text as the original artist intended (which many tools can aid in)

With all these issues, it would be better to assume that if a user could get something wrong then they will, which will result in an application that seems off. Not happy with this path I decided to look into creating text on a path.

Fortunately, a majority of the work had already been developed by Charles Petzold described in his article Render Text On A Path With WPF.

The article provides a comprehensive description of his algorithm for placing text on a path. It is worth a read to get an in-depth understanding of how the algorithm works. To try and sum it up though, the algorithm uses a PathFigure object to shape the path the text will render and the class comes equipped with a method to help simplify calculations. In sizing the text font onto the path, the text is scaled to fit entirely on the length of the path. For the best performance, we render the text as DrawingVisual objects so they only need to be created once when the text changed. The result comes out as this:

Fantastic! This worked well for what I wanted, except for one problem; the text scaling. I knew the path I wanted my text to render, but not the length of the text since that could change dynamically. When attempting to apply this algorithm to a path I had in mind, the results were less than pleasing (red curve represents the path for the text):

I needed the text to render the same size despite the length of the path, but the current algorithm would require me to resize the path dynamically based on the size of the text. This did not seem reasonable, especially since I would prefer the text to rest on the center of the path.

So, in order to accomplish this the first thing I needed was a Dependency Property of type HorizontalAlignment to set the content alignment. Setting the alignment to Stretch will keep the original behavior of the algorithm by resizing the text to fit the path. Then we need another Dependency Property for font size, which will only get applied if the content alignment was not Stretch. Now, when calculating the text length we need to substitute our font size over the default 100

private void OnTextPropertyChanged()
{
    _formattedChars.Clear();
    _textLength = 0;

    if (!String.IsNullOrEmpty(Text))
    {
        foreach (char ch in Text)
        {
            var fontSize = ContentAlignment == HorizontalAlignment.Stretch ? 100 : FontSize;

            var formattedText =
                new FormattedText(ch.ToString(), CultureInfo.CurrentCulture,
                    FlowDirection.LeftToRight, _typeface, fontSize, Foreground);

            _formattedChars.Add(formattedText);
            _textLength += formattedText.WidthIncludingTrailingWhitespace;
        }

        GenerateVisualChildren();
    }
}

Then we move onto our TransformVisualChildren method and make sure the scaling factor stays at 1 since we no longer want the text to rescale to the path

private void TransformVisualChildren()
{
    ...
    var scalingFactor = ContentAlignment == HorizontalAlignment.Stretch ? _pathLength / _textLength : 1;
    ...
}

Since content alignment can be set as Center, or Right aligned, the initial progress will need adjusting to push the text further along the path

private void TransformVisualChildren()
{
    ...
    double progress = 0;

    switch (ContentAlignment)
    {
        case HorizontalAlignment.Left:
        case HorizontalAlignment.Stretch:
            progress = 0;
            break;
        case HorizontalAlignment.Center:
            progress = Math.Abs(_pathLength - _textLength) / 2 / _pathLength;
            break;
        case HorizontalAlignment.Right:
            progress = Math.Abs(_pathLength - _textLength) / _pathLength;
            break;
    }
    ...
}

And that is all we have to do since the scaling factor will be set to 1 if content is not stretched. Here is the result with content alignment set to Center. Also, you can see all the various alignments applied:

Although I was very satisfied with the results, a change in the scope of our project made this solution obsolete. Just another day in the life of a programmer.

Future of Enterprise Software Services

Over the Thanksgiving Holiday I did a lot of thinking about what the future looks like for software as it relates to services provided to clients. I am lucky enough to work at a cutting edge software development firm that constantly looks to innovate what it is that we provide to customers. This notion was again brought to my attention when I read an article on Microsoft’s Quarterly results. In the article, one of the conclusions was, “The company is increasingly focusing on the enterprise’s needs in a more integrated way as the company continues to increase/improve its Cloud and Data Center offerings integration.” To me, I read this as Microsoft is focusing on the enterprises as a whole, and how to fulfill the needs of customers who are shifting from licensing software to hardware neutral solutions and integrating platforms.

Cloud and Data Center integration make it possible for people to work from anywhere, but how does a company make this appealing to their employees and customize that experience? I think the answer is that it is up to companies to develop experiences that is customized to their employees. This service has a large amount of value as it essentially “consumerizes” employees to a point. For example, how many times have you been on a website and a personalized ad pops up on the border of your browser? Those ads are derived from data that you have put on there, i.e. web searches, purchases, internet history, etc. Companies can harness the same power by looking at the work flows of their employees and personalizing their experiences through cloud services such as O365 Home Premium and how they are navigating those solutions. If an employer is able to customize their employees experience while they are working remotely, I believe that productivity would increase and you would have much happier workers.

In the future of providing services to enterprise software, we must tune in and listen to what our customers needs are and how best to deliver these services. Creating an innovative and intuitive experience is paramount but also keeping the end user in mind and their preferences should be integrated as well.

ContentControl “bug” in WinRT

Background

I was recently on a WinRT project that required showing a hierarchy of assets that the user could browse through, ultimately leading to an “asset details” view where they can interact with the selected asset. One of the interactive features was to have a toggle button that would hide/show a details pane with the asset description. Throughout the asset hierarchy, the data templates would bind to Name and ImageUri properties on the assets to display them. When I got down to the asset details level, I needed to wrap the asset in a ViewModel to support the command that I needed to implement the description toggle.

Implementation

After messing around with the built in Transition API trying to get my description pane to animate in, I realized that I needed to expose a separate Asset property on my VM so my description pane could bind to it via a ContentControl with a ContentThemeTransition, and to do the toggling I would just null the object in the VM and let the Transition work its magic. I tested this without the ContentTemplate set on the ContentControl (just bound directly to the extra Asset property I added to my VM), and it worked as I expected…..the description pane was hidden, and when i clicked the toggle button the pane animated in and showed that it was bound to an Asset object.

Problem

The problem started when I added the DataTemplate that was bound to the ImageUri and Name of that Asset property. When I tested it, the description pane was instantly visible before I clicked the toggle button.

Solution

After a lot of breakpoints and head scratching, my theory was that, even though the Content property of the ContentControl was bound to this seperate Asset that I added to the VM, it still looked up the tree to find those properties when the object was null. Since the VM itself had those same properties, the DataTemplate was binding to that and displaying the pane when it shouldn’t have been. Sure enough, I made a separate little class to hold the Name and Description properties, and named them differently, and it worked fine. The surprise for me here was that the ContentControl was looking up the tree for property binding when it’s content was null, and it only did it when a DataTemplate was defined. I’m not sure if this is a bug, or by design, but it can cause a headache if you’re not expecting it.

EmguCV: Rotating face images to align eyes

Sometimes to increase accuracy of face recognition algorithms it’s important to make sure the face is upright. For instance, in this image of Arnold, he is tilting his head, which may make it difficult to recognize him:

One way to pre-process this image is to rotate the it so the face is upright. The fastest way to do that is to find the eyes using a cascade classifier and then finding the angle between the eyes. This method AlignEyes will take an image and return one that is rotated upright:

public static Image<Gray, byte> AlignEyes(Image<Gray, byte> image)
{
     Rectangle[] eyes = EyeClassifier.DetectMultiScale(image, 1.4, 0, new Size(1, 1), new Size(50, 50));
     var unifiedEyes = CombineOverlappingRectangles(eyes).OrderBy(r => r.X).ToList();
     if (unifiedEyes.Count == 2)
     {
           var deltaY = (unifiedEyes[1].Y + unifiedEyes[1].Height/2) - (unifiedEyes[0].Y + unifiedEyes[0].Height/2);
           var deltaX = (unifiedEyes[1].X + unifiedEyes[1].Width/2) - (unifiedEyes[0].X + unifiedEyes[0].Width/2);
           double degrees = Math.Atan2(deltaY, deltaX)*180/Math.PI;
           if (Math.Abs(degrees) < 35)
           {
                   image = image.Rotate(-degrees, new Gray(0));
           }
     }
     return image;
}

EyeClassifier is a cascade classifier using the training file included with EmguCV called “haarcascade_eye_tree_eyeglasses.xml”. You can use whatever training you find works best.

And here is the result (the face has been cropped and masked in this image):

Automatic UI Transitions in Windows Store apps

Basics

When you’re making apps intended for modern touch hardware, it’s important that your UI feels alive, fluid, and in motion. Some of Microsoft’s XAML controls will give you this motion for free, like Panorama in Windows Phone and the FlipView in WinRT,  but other than that it was very difficult to duplicate the built-in animations and transitions of those respective platforms. The WinRT platform introduces the Transition API that applies to Controls and Containers that can apply a built in animation in a response to a predetermined trigger. Transitions are applied to individual controls using the Transitions property, and to Panels using the ChildrenTransitions property. For example, adding an EntranceThemeTransition to the ChildrenTransitions collection of a Grid will cause all children of the Grid to automatically slide in from the right when they first appear. Getting the default subtle slide in from the right is this simple…….

Adding Transitions via Designer Instead of XAML

Back when Visual Studio and Blend both served completely different purposes, I always preferred doing UI related  in Blend so that I can see all the Properties right in front of me and set them visually. In Visual Studio 2012, a lot of that ability to see and set Properties visually was added from Blend, and it makes setting and customizing Transitions very simple. Here’s how…

First

If you don’t already have the Document Outline and Properties Window visible ( they usually aren’t ), go up to View, click Properties Window, then go back to View, Other Windows, Document Outline. Here’s what mine looks like…

 

Next

All we need need to do is select the Grid in the document and, in the Properties window on the right, click the small ellipse button next to the ChildrenTransitions. You should see a new dialog window to add ChildrenTransitions with a DropDown at the bottom. Select EntranceThemeTransition and click Add. You should see the following window, which will allow you to configure the Transition properties. You should see this window if you’re in the right place….

 

Conclusion

The new Transitions API is an easy, flexible way to add predefined system animations to your UI. I’ve barely scratched the surface of what can be done with this system, but I will be using them where appropriate and will make more posts when I figure out some of the more advanced features.

Send Your Automated Build via Hightail (Formerly YouSendIt)

Here at InterKnowlogy we are always looking for ways to optimize our business. We’ve been using automated builds for sometime now. They are seriously one of the best things since sliced bread! Who doesn’t love to see a giant green checkmark stating their check-in succeeded. Or yelling names down the hallway when someone else causes a huge red ‘X’ to show up due to a failed check-in. As long as those names are aimed at you that is… We’ve been struggling with one problem lately with our release builds. If we have someone working offsite and they need to get the build after it completes they have to VPN into our network, go to the build directory, and copy the deliverable to their local machine. We do a lot of really cool graphically intense applications, which can mean large deliverables. This then turns into a really long difficult process to get a single deliverable. After a lot of discussions we come up with a really cool idea to use Hightail.

Hightail (Formerly YouSendIt)

We use Hightail for sending and receiving large files as I’m sure many of you do. We love the feature allowing us to specify an expiration date on a file so it will no longer take up space on our account. I did a lot of research on DropBox, Box, SkyDrive, and a few other options and each had pros and cons. In the end, Hightail was superior. It supports expiration dates, emails, and an easy API.

BuildSendService

We created a REST service that lives on our build server named the BuildSendService. This service is responsible for accepting a file path, expiration date, and details for sending the email with a link to the file. Information received is immediately added to a queue and which is then processed asynchronously. This allows the caller of the service to continue on to do more work instead of waiting for the file to be hightailed. The service asynchronously processes each item in the queue using the Hightail API, which is brain dead simple! It’s really great! Hightail takes care of the email for us once the file is uploaded. Recipients can then quickly download the file from their inbox! AWESOME!

SendBuild Custom Build Action

In order to leverage the BuildSendService most efficiently we built a Custom Build Action named SendBuild. In our Build Process Template, after the build has completed all other tasks and the final deliverable is ready for use in the final build directory, the SendBuild action contacts the BuildSendService to hightail the build to all desired recipients. It is not a mandatory action and is ignored if no recipients are specified. We wanted this action to be as fast as possible. That is why the BuildSendService accepts the parameters and queues the information immediately. This frees up our build server to process the next request immediately instead of waiting for a large deliverable to be uploaded to Hightail.

Conclusion

While this process is still new to us here at InterKnowlogy it is showing promise. Overtime, I’m sure we’ll tweak the current implementation to make it better and help use run more effectively and efficiently. Also, Hightail is just awesome! They have been super helpful answering all of our questions and pointing me in the right direction for development. They have a .NET sample application, which as far as I can tell implements each of their APIs. That was the best source of information. Their documentation is mostly good, but could use some extra explanations. If you want to do something similar for your build process let me know. I’m happy to help where I can.

Windows Services: File Watcher Implementation

File Watcher

File Watcher is an application that continuously monitor your files. You can define files or a whole directory to look after, and have a custom action that notifies you every time those files/directory have been changed (created, deleted, renamed or error had occurred).

Simple Implementation Steps:

1. Create a new FileWatcher and define values for its properties

FileWatcher watcher = new FileWatcher();
watcher.Path = Path.GetDirectoryName(file); 
watcher.Filter = Path.GetFileName(file);
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
           | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  • Path of the directory to be monitored.
  • Filter: “.txt” only watch text files, “GetFileName(file)” only watch that specific file.
  • NotifyFilter: watch for changes in LastAccess, LastWrite, FileName, DirectoryName

2. Subscribe to Event Handlers
These will notify the user if there are changes to the file/directory the FileWatcher is watching.

watcher.Changed += FileChanged;
watcher.Renamed += FileRenamed;
watcher.Created += FileChanged;
watcher.Deleted += FileChanged;
private void FileRenamed( object sender, RenamedEventArgs e )
{
 Debug.WriteLine( string.Format( " {0} renamed to {1} at {2}", e.OldFullPath, e.FullPath, DateTime.Now.ToString( "MM/dd/yy H:mm:ss" ) ) );
}

private void FileChanged( object sender, FileSystemEventArgs e )
{
 Debug.WriteLine( string.Format( "{0} with path {1} has been {2} at {3}", e.Name, e.FullPath, e.ChangeType, DateTime.Now.ToString( "MM/dd/yy H:mm:ss" ));
}

3. Enable the FileWatcher.
NOTE: When Path is not set and EnableRaisingEvent is not set to true, specified file/directory will not be watched.

watcher.EnableRaisingEvents = true;

FileWatcher + Windows Services

Windows Services allows us to run assembly in the background. They are very suitable for the times when you need to continuously listen to incoming network connections, or monitor a directory or files.
Let’s make a Windows Service project by doing File -> New Project -> Windows Service
Do not forget to inherit from ServiceBase().

  • By default, we already have the Run() in Program.cs that creates an instance of our FileWatcherService class.
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
       {
          new FileWatcherService()
       };
    ServiceBase.Run(ServicesToRun);
    
  • When we start our service, the service will call the OnStart() inside our FileWatcherService().

  • Like what was described above this post, we create an instance of the FileWatcher on OnStart() and subscribe to the events.
    OnStop(), we dispose the FileWatcher instance and unsubscribe to the events.

    protected override void OnStart( string[] args )
    {
    _fileWatcher = new FileWatcher( currentDirectory );
    _fileWatcher.Changed += FileChanged;
    _fileWatcher.EnableRaisingEvents = true;
    }
    
    protected override void OnStop()
    {
    _fileWatcher.Changed -= FileChanged;
    _fileWatcher.EnableRaisingEvents = false;
    _fileWatcher.Dispose();
    }
    
  • a. Create an Installer: Add -> new Class
    b. After creating a new class, inherit the class from Installer [add reference to System.Configuration.Install]
    c. Create a new ServiceProcessInstaller() and ServiceInstaller — These install an executable that extend ServiceBase(), which is our FileWatcherService.
    d. Set the properties: ServiceName, Account, StartType, DisplayName, etc.
    NOTE: Set the ServiceName to be the same as the value of the ServiceName on the service itself.
    e. Add the 2 installers to the Installers collection.

    ServiceProcessInstaller processInstaller = new ServiceProcessInstaller();
    ServiceInstaller serviceInstaller = new ServiceInstaller();
    processInstaller.Account = ServiceAccount.NetworkService;
    serviceInstaller.DisplayName = "File Watcher Service";
    serviceInstaller.StartType = ServiceStartMode.Manual;
    serviceInstaller.ServiceName = "File Watcher Service";
    Installers.AddRange(new Installer[]
    {
      processInstaller, serviceInstaller
    });
    
  • Install the service and start running it!
    a. Run Command Prompt [Visual Studio Command Prompt or Windows SDK Command Prompt] as Administrator.
    b. Go to the directory where the Windows Service executable is at.
    c. Type installutil {name of the service} (e.g. installutil FileWatcherService.exe).
    d. On Success, you will be able to see the Service on your Local Services list.
    Windows Service

    Windows Service successfully installed


    e. To uninstall: type installutil /u {name of the service}