Scott Hanselman

How to automatically notify the user that it's time to upgrade a Windows App

March 19, '14 Comments [51] Posted in Musings
Sponsored By

imageBack in 2007 I did a post called Making your Application Automatically Update Itself. Yesterday I was pairing on a little startup I'm doing on the side with Greg Shackles and it was time do the setup application. I thought about WiX, I thought about InstallShield, but then discovered a wonderful little gem of a setup application called Inno Setup by Jordan Russell. It's free, but it's a joy and you should donate if you use it.

It took me just 15 minutes to make a simple installer, and it's clear that this tool is deep and broad in its support. However, there's no free lunch when it comes to auto-updating. Inno Setup will upgrade my app from build to build when I run a new setup over the top of an old one. I still need my app to notify the user that it's time to upgrade.

This is our little 10 minute solution, but it's actually working very nicely. Inside the latest.txt files is a simple version string like 0.9.9.4.

var http = new HttpClient();
string versionString = await http.GetStringAsync(new Uri("http://www.hanselman.com/SecretStartup/latest.txt"));
Version latestVersion = new Version(versionString);

//get my own version to compare against latest.
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
Version myVersion = new Version(fvi.ProductVersion);

if (latestVersion > myVersion)
{
if (System.Windows.MessageBox.Show(String.Format("You've got version {0} of SecretStartup for Windows. Would you like to update to the latest version {1}?", myVersion, latestVersion), "Update SecretStartup?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Process.Start("http://www.hanselman.com/blog");
}
}

I'm thinking:

  • We'll add an SSL certificate and confirm its identity on the HTTP call as a little added security.
  • Error Handling, natch.
  • One could also download the setup app to %temp%, check it's SHA hash, launch it and close myself. Not sure I like it this automatic, though.
  • Maybe only check the version once a day or once every few days.

Comments?


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

AngleBrackets open web conference in Florida - April 2014

March 19, '14 Comments [7] Posted in Musings
Sponsored By

imageWe had a blast last year at AngleBrackets in Vegas. Next month we're heading to family-friendly Orlando with our friends ScottGu, Denise Jacobs, Douglas Crockford, John Papa, Dan Wahlin, and lots more.

There's some great optional workshops/pre-cons and post-cons that are a fantastic opportunity to get some one-on-one training with experts in the field. It's deep web technologies with a focus on practicality, open source, and creative problem solving. Check this out, get your boss to sign off and bring your laptop!

  • PRECON12: AngularJS SPA Development - 0 to 60 (Sunday, April 13) Hands-on Bring your own Laptop - John Papa
  • PRECON08: Architecting Applications for Multiple UIs (Sunday, April 13) - Paul Sheriff
  • On the Metal: Essential HTML 5, CSS 3 and JavaScript for All Developers (Sunday, April 13) - Todd Anglin
  • Service Orientation Technologies Designing, Developing and Implementing WCF and the WEB API (Sunday, April 13) - Miguel Castro
  • PRECON07: The Architecture Clinic - (Sunday, April 13) - Juval Lowy
  • POSTCON08: Building Data-Centric Single Page Applications with Durandal, Knockout, Breeze and Web API (Thursday, April 17) - Brian Noyes
  • POSTCON03: Experimental Design for User Interfaces (Thursday, April 17) - Billy Hollis
  • POSTCON09: Hacking the Creative Brain (Thursday, April 17) - Denise R. Jacobs

AngleBrackets is a conference that's "co-located" with the DevIntersections conference. That means that you can move between the two conferences and attend the sessions you want. You can move between MongoDB, Ruby, and node.js sessions and even (gasp!) SharePoint sessions at the other conference. It's a great way to get your boss to send you to a conference while you learn all aspects of web development.

Here's a few cool session I'm tracking for myself, just to give you a taste of the diversity of topics.

Managing Asynchronicity with RQ - Douglas Crockford

Turn based servers are now joining turn based browsers in providing race-free and deadlock-free interactivity. The event-driven model has long been popular in UI systems, but the nature of work in servers presents some new challenges. Functional programming provides solutions, including monads, arrows, promises, and various flavors of FRP. This is another such solution, intended to enhance ease of use with constructs that support parallel and sequential operations.

The Art of Disciplined Creativity - Denise Jacobs

As tech industry professionals, we rarely experience a shortage of projects that necessitate our creative thinking. While everyone has moments of being on fire with creativity, all too often the time of being in the state of creative flow is too short. Additionally, sometimes we get stuck: we lack inspiration, our creative confidence wanes, and the generation of ideas comes to a standstill. Much like elite athletes, we need to exercise discipline to be able to get into the creative "zone" at at will and produce consistently great results. Let's explore ideas and practices for regularly gathering sources of inspiration, eliminating blocks to more easily access creative states, prolong them, and leverage their power to develop and execute great work.

Grunt-ify Your Front-End Web Development - Elijah Manor

There are a lot of manual processes that front-end developers tend to perform in order to get their job done. Wouldn't it be nice if there was some way to automate all the things? Well, thanks to Grunt you can :) In this session we will introduce Grunt and showcase some common workflows to automate building, live reloading, CSS processing, unit testing, deploying, as well as making your own custom plugins. Along the way, we will discuss some tips and tricks when using Grunt.

There's also other optional PreCons at DevIntersections on SQL, C, ALM, Disaster Recovery, Rosylin and CodeGen and more. Check out the great line-up we have this year at AngleBrackets and I'll see you there!


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

OneNote and Microsoft's quiet API revolution

March 17, '14 Comments [20] Posted in Musings
Sponsored By

imageMicrosoft just released OneNote for Mac today. They also made OneNote for PC free, which means there's a free OneNote app on Windows, Windows Phone, iOS, Mac, Android and a really full featured HTML5 web version at http://www.office.com. This is all very cool of course, but I'm interested in the APIs.

Now, to be clear, I have worked for Microsoft for the last few years on ASP.NET and Azure, but I don't know anyone in the Office team. I am not privy to any secret info and I get most of my news from The Verge, just like you.

But from my perspective, the real story here is that Microsoft has woken up to the power of the API. Some may argue that they've always had powerful web APIs, which is true, however the breadth and scope of these APIs and their ubiquity seems to have accelerated in recent years. They are clearer, more open, simpler, and more cross-platform than ever before.

The Azure cloud and the Azure HTML5 Portal where folks manage their apps uses a REST API, and the SDKs to use them - as well as a cross platform nodejs command line application - are on GitHub. If you use the main portal, write your own, or use Visual Studio, it all calls the same open API. Duh.

Exchange has APIs, Microsoft IDs use OAuth, Azure's Portal has an API and uses it themselves, SharePoint is one giant REST/OData API, Office 365 has been quietly releasing APIs for Mail, Calendar, and Contacts, and even now Lync has a REST Web API now.

Today when the Office team launched OneNote for Mac, they also launched http://dev.onenote.com along with integration partners like Feedly, JotNot, IFTTT, Weave News Reader and more all integrating with their REST API.

The moral of the story here is - if you have no API then you have no story.

Using the OneNote API

There's even more evidence of a change in thinking inside the big house. It's clearly of note that the API example in the OneNote API documentation on MSDN used Objective-C. They also link to a OneNote interactive Console at Apigee.

The API appears to be basically RESTful, with a POST of HTML to https://www.onenote.com/api/v1.0/pages creating a new OneNote page in your authenticated notebook.

You authenticate with your Microsoft ID using the SDK, get the token from the SDK object to be used in the authentication header then POST.

What has surprised me is that they have tutorials and samples across all platforms:

And, heck, the samples are all on GitHub too: https://github.com/OneNoteDev.

It looks like the focus for this initial launch is POST/Create for capture apps, photos, text, clippers, etc, but all the verbs are coming, clearly at the top of their backlog.

I like this direction, and to me, it's representative of a larger shift to recognize that the world doesn't always run Windows. I've said it before, and I'll said it again - The Web will always win.

Related Links


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Exploring FAKE, an F# Build System for all of .NET

March 14, '14 Comments [24] Posted in Open Source
Sponsored By

I've been orbiting around F# - but not really jumping in - for a while now. In fact, I looked at F# in 2008 almost 6 years ago and more recently talked to Richard Minerich and Phillip Trelford on Hanselminutes Podcast #311 "Why F#?"

Last week I looked at using ScriptCS, literally C# as a Scripting language, to drive browser automation. Today I'm exploring a make system called FAKE. It's F# Make, a build automation system similar to Make (which is 38 years old next month!) or Rake (which uses Ruby).

Fake is a Domain Specific Language that you can use without knowing F#, but if and when you outgrow it you can keep heading down the F# road. In all cases you've got all of .NET at your command.

Here's their Hello World example, a basic deploy script:

#r "tools/FAKE/tools/FakeLib.dll" // include Fake lib
open Fake


Target "Test" (fun _ ->
trace "Testing stuff..."
)

Target "Deploy" (fun _ ->
trace "Deploy stuff..."
)

"Test" // define the dependencies
==> "Deploy"

Run "Deploy"

Note that Deploy depends on Test.

FAKE uses F# but you can use it go build whatever. These are some C# OSS projects that use FAKE to build themselves:

FAKE isn't new, it's actually been around for 4 years with 55 contributors so far! It works not only on .NET but also on Linux and Mac under Mono - it works everywhere. Because it's all .NET you can use it on your Continuous Integration Servers like TeamCity or Travis CI.

image

Getting Started with FAKE

Check out their Calculator sample, a .NET project you'll extend to build itself with FAKE. Just download the zip, unblock it, and unzip. Then run build.bat from a developer command prompt.

The build.net is a bootstrapper. It could be powershell or a shell script if you like, of course.

@echo off
cls
"tools\nuget\nuget.exe" "install" "FAKE" "-OutputDirectory" "tools" "-ExcludeVersion"
"tools\FAKE\tools\Fake.exe" build.fsx
pause

This batch file uses NuGet to get FAKE, just as npm install restores node_modules, or gem gets ruby libraries. Then it calls Fake on the build.fsx file. Follow their Getting Started instructions to slowly expand the responsibilities of the build.fsx file.

FAKE has a lot of Helpers in their API documentation. Hundreds, and there's a whole community making others that you can call upon. For example, the built in FileHelper has things like CleanDir to remove files and subdirs.

Here we Clean before we build by making Clean a dependency of Default. BuildDir here is a property that's shared.

// include Fake lib
#r "tools/FAKE/tools/FakeLib.dll"
open Fake

// Properties
let buildDir = "./build/"

// Targets
Target "Clean" (fun _ ->
CleanDir buildDir
)

Target "Default" (fun _ ->
trace "Hello World from FAKE"
)

// Dependencies
"Clean"
==> "Default"

// start build
RunTargetOrDefault "Default"

Jumping to the end of the tutorial, the syntax gets a little more tricky, butu once you get the |> format, it makes sense.

Some cool things to note and file away as interesting at in the script below.

  • the use of !! to include files
  • the use of -- to exclude a file spec after a !! operator
  • Zip is built-in as a helper and zips up the results of the build.
  • the options passed into NUnit
  • The dependency chain
  • #r for referencing .NET DLLs
// include Fake lib
#r "tools/FAKE/tools/FakeLib.dll"
open Fake

RestorePackages()

// Properties
let buildDir = "./build/"
let testDir = "./test/"
let deployDir = "./deploy/"

// version info
let version = "0.2" // or retrieve from CI server

// Targets
Target "Clean" (fun _ ->
CleanDirs [buildDir; testDir; deployDir]
)

Target "BuildApp" (fun _ ->
!! "src/app/**/*.csproj"
|> MSBuildRelease buildDir "Build"
|> Log "AppBuild-Output: "
)

Target "BuildTest" (fun _ ->
!! "src/test/**/*.csproj"
|> MSBuildDebug testDir "Build"
|> Log "TestBuild-Output: "
)

Target "Test" (fun _ ->
!! (testDir + "/NUnit.Test.*.dll")
|> NUnit (fun p ->
{p with
DisableShadowCopy = true;
OutputFile = testDir + "TestResults.xml" })
)

Target "Zip" (fun _ ->
!! (buildDir + "/**/*.*")
-- "*.zip"
|> Zip buildDir (deployDir + "Calculator." + version + ".zip")
)

Target "Default" (fun _ ->
trace "Hello World from FAKE"
)

// Dependencies
"Clean"
==> "BuildApp"
==> "BuildTest"
==> "Test"
==> "Zip"
==> "Default"

// start build
RunTargetOrDefault "Default"

You can do virtually anything and there's a great community out there to help.

Here's a more complex dependency chain with an optional parameter:

// Build order
"Clean"
==> "BuildApp"
==> "BuildTest"
==> "FxCop"
==> "NUnitTest"
=?> ("xUnitTest",hasBuildParam "xUnitTest") // runs the target only if FAKE was called with parameter xUnitTest
==> "Deploy"

There's a rich FAKE world out there with support for Octopus Deploy, all Unit Test systems, Xamarin's xpkg format and much more. Thanks to Steffan Forkmann for helping me explore this. ;)

Related Links


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Back to Basics: Assert your assumptions and diff your source code

March 13, '14 Comments [20] Posted in ASP.NET | Back to Basics
Sponsored By

I've done a whole series of "Back to Basics" posts that I encourage you to check out. Sometimes I'll do a post as a result of a reader emailing me for help and this is one such post.

A person emailed me with an ASP.NET app was behaving differently on his computer vs. another developer's computer.

On his machine when he hit a protected page foo.aspx?returnurl=http://mymachine.domain.com

he would get a FORM element like this:

<form action="foo.aspx?returnurl=http://mymachine.domain.com">

but on everyone else's machines their HTML was:

<form action="foo.aspx">

They debugging and were frustrated and eventually reached out. They said:

1. there's nothing going on in the aspx of login.aspx that would append the querystring.

2. there's nothing going on in the code-behind of the aspx that manipulates Form.Action or messes with the Page.Render in any way.

So, I'm stumped, because the querystring is included on my machine, but not on others. I've tried comparing IIS components, web.config differences, application pool runtime type, machine.config differences, possible differences in Modules for IIS (IISrewrite), but nothing is giving me love. 

I suggested that they assert assumptions and start diffing everything. You can see in the last paragraph that they're comparing stuff but I think you really have to diff everything.

When something "works here but not there" my answer is always, what has changed? What's different? If the answer is "nothing is different" I'm just gonna say it again:

"What's different?"

What are some things we can check?

  • Code
    • Do you know what's on disk?
    • Do you know what ended up in memory? These are different things.
  • Configuration
    • There's local and machine-wide config to check
  • Network Traffic
    • This is often overlooked. The Internet is not a black box, but you'd be surprised how few people hook up a packet sniffer or even just Fiddler to look at HTTP traffic.
    • I've talked to developers who have said "well, that's under SSL so I can't see it." Oh, my friend, if you only knew.

I had them do a sniff and see if there was a difference in HTTP traffic. My assumption was that the HTTP_REFERER HTTP header was different and there was some code that was causing the page to render differently.

We went back and forth over a few days and my reader became frustrated and just added this line in their app's Page_Load:

this.Form.Action = Request.Url.ToString();

Here they are basically reasserting the Form action by pulling it from the URL. It's gross and it's a hack. It's a Band-Aid on Cancer.

They then started looking at the source for ASP.NET proper and then decided to disassemble the code that was running on the other person's machine. They then started to assert their assumptions.

Is the code running what's on disk? For a compiled language, do the binaries reflect the source?

They looked in Temporary ASP.NET files at the compiled ASPX markup pages and found this.

//ExternalSource("D:\WebApplications\Foo\login.aspx",27)
__ctrl.Method = "post";

//ExternalSource("D:\WebApplications\Foo\login.aspx",27)
__ctrl.Action = "login.aspx";

What? Why is someone setting the FORM Action manually? And there's a line number.

They had diff compared all the source code but not the markup/views/html.

Their markup:

<form id="Form1" method="post" runat="server">

Other person's markup:

<form id="Form1" method="post" runat="server" action="Login.aspx">

The other person had hard-coded the action in their source markup. They'd been diffing everything but the markup.

When you are comparing two code-bases, make sure to compare everything or you might just lose a day or two like this person.

Thanks to my reader for sharing this and letting me in on this debugging adventure.

Related Links:


Sponsor: Big thanks to Red Gate for sponsoring the blog feed this week. Check out the Free Starter Edition of their release management tool! Deploy your SQL Server databases, .NET apps and services in a single, repeatable process with Red Gate’s Deployment Manager. Get started now with the free Starter Edition.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.