Scott Hanselman

Prompts and Directories - Even Better Git (and Mercurial) with PowerShell

February 1, '12 Comments [36] Posted in Open Source | PowerShell
Sponsored By

posh-git with custom directoryI love PowerShell and spent years and years working with it since it first came out. I've actually got 15 or so pages of PowerShell posts on this blog going way back.

PowerShell is insanely powerful. I would even go so far as to say it was (is) ahead of its time. PowerShell is totally dynamic and is almost like having JavaScript at the command line, but even more thoughtfully designed. I appreciate folks that love their bash shells and what not, but PowerShell can do some wonderful things.

A long time ago (2009) Mark Embling blogged about a nice prompt with TabExpansion that he'd made to make working with PowerShell and Git (his favorite source control system) nicer. Later, Jeremy Skinner added TabExpansion for common commands. A little while later Keith Dahlby started with their code (with their blessing) and posh-git was born. Expanding even more, Jeremy later created posh-hg (for Mercurial, my favorite source control system).

All of these are currently in use in various forms. Just recently (days ago, even) while I was trying figure out how to get these two separate but similar PowerShell scripts to live together when Keith created a small shared function that makes sharing prompts easier.

I think that Git Bash on Windows needs to go away. It's just not useful to say that a Windows user has to run Bash in order to use Git. PowerShell with Git (or your favorite VCS) is demonstrably better for Windows folks. I also feel that the installation for posh-git, while it uses PsGet (think NuGet for PowerShell, which is INSANELY awesome), just could be easier.

I happened to be tweeting about this and ended up doing a Skype+Join.me 3-way pair programming session with Keith and Paul Betts to explore some ideas on the topic. While a customized prompt is cool, I wouldn't rest until we'd modified "dir/ls" to show source control status. I'm not talking about a PowerShell Provider, I'm talking about extending the View for the result of a dir (get-childitem and a FileInfo) itself.

I want to be able to take a fresh machine and fresh PowerShell installation, invoke one PsGet command and get Git and Hg (and whoever else) integration with PowerShell, a new prompt AND new (yet to be written at this point) directory listing support.

We did some pairing as I sat in a pub and drove while Keith and Paul told me I was a lousy typist. We got a nice prototype working and I went home. After the kids went to sleep I was asking questions on a mailing list and ended up getting an answer from James Brundage, noted PowerShell expert. I'd met James at a Nerd Dinner in Seattle once and gave him a book. He was kind enough to do a screen sharing session with me and refactor my directory spike (and some of posh-git) into a more useful form. It's still a spike, but Keith and I are going to merge all three of them (posh-git, posh-hg and my VCS dir stuff) into one usable and easy to install module. I'm sure we'll both blog about it when it's cleaner. I'm hoping we'll get it all integrated into a single install line:

(new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex
install-module posh-git

Here's the general idea that encapsulates a number of these ideas. Rather than scripts that are plugged into your PowerShell $profile, we'll have a module or two like this.

C:\Users\Scott\Documents\WindowsPowerShell\Modules
$ dir

Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 1/31/2012 10:37 PM Posh-Git
d---- 1/31/2012 10:37 PM Posh-GitDir
d---- 1/31/2012 12:27 AM PsGet

The Posh-Git folder is the Posh-Git source as it is, as a module and imported in your profile like this.

Import-Module Posh-Git
Import-Module Posh-GitDir

Posh-GitDir is my extension module that will change dir/ls/get-childitem and add a Git Status column. I've added extra columns with file information before in PowerShell, except in a cheesy way and I never actually overrode dir directly.

First, we'll make a post-gitdir.Types.ps1xml that adds the new ScriptProperty that pulls details for each file out of a $GitStatus variable that's added each time the prompt is drawn.

<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>System.IO.FileInfo</Name>
<Members>
<ScriptProperty>
<Name>Git</Name>
<GetScriptBlock>
$retVal = ""
if ($GitStatus.Index.Added -contains $this.Name) { $retVal += "+" } `
elseif ($GitStatus.Index.Modified -contains $this.Name) { $retVal += "~" } `
elseif ($GitStatus.Index.Unmerged -contains $this.Name) { $retVal += "!" } `
else { $retVal += " " }

$retVal += " "

if ($GitStatus.Working.Added -contains $this.Name) { $retVal += "+" } `
elseif ($GitStatus.Working.Modified -contains $this.Name) { $retVal += "~" } `
elseif ($GitStatus.Working.Unmerged -contains $this.Name) { $retVal += "!" } `
else { $retVal += " " }

$retVal
</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
<Type>
<Name>System.IO.DirectoryInfo</Name>
<Members>
<ScriptProperty>
<Name>Git</Name>
<GetScriptBlock>
""
</GetScriptBlock>
</ScriptProperty>
</Members>
</Type>
</Types>

This adds the Git column to the output as a ScriptProperty, but doesn't change the default view.

$ dir | get-member

TypeName: Get-ChildItem

Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
Create Method System.Void Create(System.Security.AccessControl.DirectorySecurity director...
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
...snip...
BaseName ScriptProperty System.Object BaseName {get=$this.Name;}
Git ScriptProperty System.Object Git {get="";}

I'd have to always select manually, which is tedious.

$ dir | select Name, Git

Name Git
---- ---
CommandType.cs ~
Connection.cs ~
ConnectionExtensions.cs ~
ConnectionManager.cs +
ConnectionScope.cs +
GuidConnectionIdFactory.cs ~

We want to change the dir "view" itself.  We have to copy the default view for a directory at: "C:\Windows\system32\WindowsPowerShell\v1.0\FileSystem.format.ps1xml" and add our new column.

<?xml version="1.0" encoding="utf-16"?>
<Configuration>
<ViewDefinitions>
<View>
<Name>Dir-Git</Name>
<ViewSelectedBy>
<TypeName>Dir-Git</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Git</Label>
<Width>4</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
...snip...
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Git</PropertyName>
</TableColumnItem>
...snip...
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>

For the design, I want the Indexed and Working files in two columns, showing Added+, Modified~ and Unmerged! files like this. Deleted files won't show up cause they aren't there.

$ dir #snipped out directories and files for clarity

Mode Git LastWriteTime Length Name
---- --- ------------- ------ ----
d---- 1/31/2012 5:14 PM Configuration
d---- 1/31/2012 5:14 PM Hosting
-a--- + 1/31/2012 5:14 PM 2170 ConnectionManager.cs
-a--- + 1/31/2012 5:14 PM 402 ConnectionScope.cs
-a--- ~ 1/31/2012 5:14 PM 280 GuidConnectionIdFactory.cs
-a--- 1/31/2012 5:14 PM 273 IConnection.cs
-a--- ~ 1/31/2012 5:14 PM 165 IConnectionIdFactory.cs
-a--- + 1/31/2012 5:14 PM 304 IConnectionManager.cs
-a--- 1/31/2012 5:14 PM 118 packages.config
-a--- ~ 1/31/2012 5:14 PM 8296 PersistentConnection.cs
-a--- + 1/31/2012 5:14 PM 1118 PersistentConnectionFactory.cs
-a--- 1/31/2012 5:14 PM 623 PersistentResponse.cs
-a--- ~ 1/31/2012 5:14 PM 1288 SignalCommand.cs
-a--- ~ 1/31/2012 5:14 PM 7386 SignalR.csproj
-a--- 1/31/2012 5:14 PM 23076 TaskAsyncHelper.cs
C:\Users\Scott\Desktop\github\SignalR\SignalR [master +1 ~0 -0 | +10 ~58 -11 !]

We import these modules in our $profile.

Import-Module Posh-Git
Import-Module Posh-GitDir

The posh-git module adds the custom prompt (if you haven't changed yours) with a new function called Write-VcsStatus that is shared between Hg and Git (and any other systems that want to play with us). It only adds the prompt if the user hasn't already customized their prompt. If they have, they'll need to incorporate Write-VcsStatus themselves.

$defaultPromptHash = "HEYStcKFSSj9jrfqnb9f+A=="

$md5 = [Security.Cryptography.MD5]::Create()
$thePrompt = [Text.Encoding]::Unicode.GetBytes((Get-Command prompt | Select-Object -ExpandProperty Definition))
$thePromptHash = [Convert]::ToBase64String($md5.ComputeHash($thePrompt))

if ($thePromptHash -eq $defaultPromptHash) #using the default prompt?
{
#recommend our own
function prompt(){
# Reset color, which can be messed up by Enable-GitColors
$Host.UI.RawUI.ForegroundColor = $GitPromptSettings.DefaultForegroundColor

Write-Host($pwd) -nonewline -foregroundcolor white

Write-VcsStatus

Write-Host ""
return "$ "
}
}
else {
Write-Debug "Make sure your prompt includes a called to Write-VcsStatus!"
}

The craziness that James Brundage came up with to override dir/ls/get-childitem was this. He said he'll do a complete tutorial on his blog with technical details for the generic case.

. ([ScriptBlock]::Create("
function Get-ChildItem {
$([Management.Automation.ProxyCommand]::GetCmdletBindingAttribute((Get-Command Get-ChildItem -CommandType Cmdlet)))
param(
$([Management.Automation.ProxyCommand]::GetParamBlock((Get-Command Get-ChildItem -CommandType Cmdlet)))
)

process {
Microsoft.PowerShell.Management\Get-ChildItem @psBoundParameters |
ForEach-Object {
`$null = `$_.pstypenames.Insert(0, 'Dir-Git')
`$_
}
}
}
"))

Tie it all up with a .psd1 file that has the list of Scripts, Types, Formats and the Module.

@{
ModuleVersion="1.0.0.0"
Author="Scott Hanselman"
Description="Posh-GitDir"
CompanyName="Hanselman and Friends"
RequiredModules="Posh-Git"
ScriptsToProcess="prompt.ps1"
TypesToProcess="posh-gitdir.Types.ps1xml"
FormatsToProcess="posh-gitdir.Format.ps1xml"
ModuleToProcess="posh-gitdir.psm1"
}

To recap, this new module requires the posh-git module, it ands our new "Dir-Git" type, adds the Git ScriptProperty in Types, and shows how to Format it, and overrides get-childitem in the psm1. If you didn't want to override dir proper, maybe you could make a dir-git or dir-hg.

Next steps are for us to integrate them into one module, bring in an inproc library to access the source info (rather than regex'ing the output of git status and hg status) which would speed it up 10x I'm sure, as well as better NuGet support.

In this screenshot you can see posh-git and posh-hg living together. The first directory is a hg repo with a 1 file not in control. The second directory is a git repo with 1 file added in the Index, 10 new added in working, 58 modified, and 11 deleted.

PowerShell with Git and Hg

Keith and Jeremy have done some amazing work. Open Source, baby. I'm looking forward to pairing with them in coming days and buttoning this up. I've been a hardcore Tortoise (Tortoise-Hg, Tortoise-SVN, Tortoise-Git) source control user, but the addition of PowerShell is shaking my faith in a good way. At leat to the point that I think it's worth my spare time to see this through.

Thoughts?

Related Links

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 ORCS Web

One ASP.NET Sneak Peek: Elegant Web Forms and Snowballs in Hell

February 1, '12 Comments [72] Posted in ASP.NET
Sponsored By

For the most part, I'm an ASP.NET developer. I don't need to specify MVC or Web Forms, because it's all One ASP.NET its core. My apps are often hybrids and include not just Web Forms or MVC but also SignalR and Web API.

Web Forms often gets picked on because of large View State, weird markup or maybe folks don't like the controls model. However, Web Forms has its place and it's getting even better with .NET 4.5. Here's a little sneak peek of some cool ideas Damian Edwards and the team have been working on for the next version of ASP.NET.

As a place to start, remember that ASP.NET routing started in MVC and moved into core ASP.NET. Routing is useful in all ASP.NET applications - MVC, Web Pages and Web Forms. Model Binding is coming to Web Forms as well, as well as Strongly Typed Data Controls and some other features that make both the code and the result pretty compelling. Dare I say, elegant. Elegant Web Forms? Madness! Who is this fool?

Here's a sortable grid with Create, Edit, Delete in Web Forms 4.5. An experiment for you, Dear Reader, would be to do the same thing I'm doing here in ASP.NET MVC or Web Pages.

Do note that this is fresh off Damian's laptop, and it's a experiment.

First, note the clean URLs. Use Routing, Web Forms people. You have no reason not to.

Clean URLs in WebForms. Scandalous.

Here's what it'll look like:

Databinding in ASP.NET Web Forms 4.5 Sneak Peek

Right now in this experiment, there is this routing table. Personally I'd like a convention for CRUD to make this one line.

Routes.MapPageRoute("CategoriesNew", "Categories/New", "~/Categories_New.aspx");
Routes.MapPageRoute("CategoriesEdit", "Categories/{id}", "~/Categories_Edit.aspx");
Routes.MapPageRoute("CategoriesDelete", "Categories/{id}/Delete", "~/Categories_Delete.aspx");
Routes.MapPageRoute("Categories", "Categories", "~/Categories.aspx");

Here's the  Grid. Now, before you declare that's too freaky, take a look and note there's a lot of functionality going on here in not too many lines. ItemType (was ModelType in the Developer Preview) is strongly typing this grid to the Category model. Notice SelectMethod. You just need to provide a method here that returns an iQueryable, in this case, GetCategories.

UPDATE with NOTE: See the comments below. Damian Edwards says: "That said, you don't need to return IQueryable. You can happily return an IEnumerable and just take in the extra parameters that the GridView will give you to ensure you can retrieve only the data for the currently requested page and sorted by the chosen column."

<asp:GridView runat="server" ID="categoriesGrid" CellSpacing="-1" GridLines="None"
ItemType="VS11Experiment.Model.Category" DataKeyNames="CategoryId"
AutoGenerateColumns="false"
AllowPaging="true" AllowSorting="true" PageSize="5"
SelectMethod="GetCategories">
<Columns>
<asp:DynamicField DataField="Name" />
<asp:DynamicField DataField="Description" />
<asp:TemplateField>
<ItemTemplate>
<a runat="server" href='<%# GetRouteUrl("CategoriesEdit", new { id = Item.CategoryId }) %>'>edit</a>
<a runat="server" href='<%# GetRouteUrl("CategoriesDelete", new { id = Item.CategoryId }) %>'>delete</a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
No categories found.
</EmptyDataTemplate>
<SortedAscendingHeaderStyle CssClass="asc" />
<SortedDescendingHeaderStyle CssClass="desc" />
<PagerStyle CssClass="pager" />
</asp:GridView>

"OK, Hanselman, what hellish code-behind are you going to show us now? What Satan's spawn have you been shining us on with all this time only to spring the nasty stuff at the last minute? I know you crafty Microsoft types, always creeping around with your Legos and your Windows Phones."

Fine, you caught me.

public partial class Categories : System.Web.UI.Page
{
private readonly DemoWhateverDataContext _db = new DemoWhateverDataContext();

public void Page_Load()
{
if (!IsPostBack)
{
// Set default sort expression
categoriesGrid.Sort("Name", SortDirection.Ascending);
}
}

public IQueryable<Category> GetCategories()
{
return _db.Categories;
}
}

Aargh! My eyes! Wait, that doesn't suck at all. Even better if I could hypothetically put the default sort on the GridView and lose the whole Page_Load.

Whatever database or repository or Web (HTTP) Service you like, as long as your data access layer returns some IQueryables and you're in a good place. Sorting happens via LINQ so your data access layer can do the work, not ASP.NET.

So listing categories in a grid is decent, what's Edit look like?

Editing with ASP.NET Web Forms 4.5

If you add Model Binding to ASP.NET WebForms you spend less time digging around in the Request object. Notice that we're not doing that all here.

See how the RouteData attribute on GetCategory pulls the id out of the URL Categories/1?

public partial class Categories_Edit : System.Web.UI.Page
{
private readonly DemoWhateverDataContext _db = new DemoWhateverDataContext();

public Category GetCategory([RouteData]int? id)
{
return _db.Categories.Find(id);
}

public int UpdateCategory(int categoryId /* Comes from the data control itself via DataKeyNames property */)
{
var category = _db.Categories.Find(categoryId);
TryUpdateModel(category);
if (ModelState.IsValid)
{
return _db.SaveChanges();
}
return 0;
}

protected void categoriesForm_ItemUpdated(object sender, FormViewUpdatedEventArgs e)
{
Response.RedirectToRoute("Categories");
}

protected void categoriesForm_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.IsCancel())
{
Response.RedirectToRoute("Categories");
}
}
}

Often folks point to ASP.NET MVC's ability to use PRG (Post Redirect Get) as a strength. Often PostBacks in WebForms are looked down upon. In this model above, we're also totally able to use the PRG interaction model in Web Forms. See how the item is updated and we redirect to a route.

And the categoryId on UpdateCategory() comes from the Form View that is HTTP posting the data back. Here's a snippet:

<asp:FormView runat="server" ID="categoriesForm" RenderOuterTable="false"
ItemType="VS11Experiment.Model.Category" DataKeyNames="CategoryId"
DefaultMode="Edit"
SelectMethod="GetCategory" UpdateMethod="UpdateCategory"
OnItemUpdated="categoriesForm_ItemUpdated"
OnItemCommand="categoriesForm_ItemCommand">

Also, you know how in ASP.NET MVC you've got unobtrusive JavaScript validation that is driven by the model class itself?

Edit Category in ASP.NET Web Forms

In ASP.NET MVC one often uses EditorFor, and in Web Forms we've got Dynamic Control. The idea being that Dates get Calendars and you can replace the UI completely using a field template. That feature actually started in Web Forms Dynamic Data and then moved to ASP.NET MVC. Features move both ways when it's all ASP.NET underneath. See what I did there?

<EditItemTemplate>
<ol>
<li><label>Name:</label>
<asp:DynamicControl runat="server" ID="name" DataField="Name" Mode="Edit" />
</li>
<li><label>Description:</label>
<asp:DynamicControl runat="server" ID="description" DataField="Description" Mode="Edit" />
</li>
</ol>
...

And when these forms are POSTed, you'll need validation. Rather than Validation Controls, in this case since we already know about the model we can use unobtrusive validation, similar to ASP.NET MVC. The idea is push the best ideas into the core of ASP.NET and make common stuff easy while letting people work the way they want to work.

public class Category
{
[ScaffoldColumn(false), Display(Name="Id")]
public long CategoryId { get; set; }

[Required, StringLength(100)]
public string Name { get; set; }

[StringLength(10000), DataType(DataType.MultilineText)]
public string Description { get; set; }
}

Sure, ASP.NET Web Forms may not be your cup of tea just like ASP.NET MVC might not be either. But remember that it's all One ASP.NET, and you've got a number of tools in your toolkit. Pick the ones that make you happy.

One ASP.NET Diagram

*And no, Hell isn't a dirty word in this context. ;)

Related Links

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 ORCS Web

From Concept to Code in 6 hours: Shipping my first Windows Phone App

January 30, '12 Comments [49] Posted in Open Source | WinPhone
Sponsored By

A screenshot of my new app Lost Phone Screen for Windows Phone 7Warning, this is long. I'll be frank with you, as I always am. I have an iPhone, a number of iPads and I like them fine. I have a Windows Phone that I use occasionally. I know C# but I do not know Objective-C.

TL;DR Version

I made my first Phone Application. I've spent about 6 hours on it. It's called Lost Phone Screen and it makes nice wallpaper. It's over at http://lostphonescreen.com. It's a simple customizable Windows Phone 7 Lockscreen. It was way easier and more fun to make than I expected. If I make a million bucks with this thing I'm GONE. You'll never see me again. :)

Introduction

I wanted to see how quickly I could make a useful Windows Phone 7 application. I'm not talking about just dragging a button onto a Hello World template and adding "press to fart." I'm talking about an MVP - Minimally Viable Product. It might not be the greatest app in the world, but it will provide value. At least to me.

Disclaimer: I don't work for the Windows Phone Team and don't really know anyone over there. I did this on my own with my personal details, personal account, as an "on the side moonlighting thing." While I work for Microsoft, I work in the Web department, not in Phones.

I honestly hadn't given the Windows Phone too much thought until the "Mango" release, when things got really interesting.

So, last week I sat down and decided to see how quickly I could come up with an app, write it, market it (make a website) and get it in the Windows Phone Marketplace. I had never done any of this stuff and my machine didn't even have any Phone development tools so I was starting from literally Step, ahem, Zero.

The Concept

I am consistently surprised at at how often someone shows me their fancy new phone - no matter what kind of phone they have - and they're using some lame default wallpaper. Folks rarely lock their phones (bad idea) and when they do, there's nothing on the lock screen wallpaper to help them get their phone back if it's ever lost.

"But Scott! I can enable this new fangled GPS and track my phone globally!"

Really? That's lovely and I'm sure ever se helpful when your phone is left in a basement pub, office building, subway or any other GPS-friendly locations. But that's not the point. Why make it hard? If your email or alternate phone number was on your lock screen - maybe even with a reward - chances are you'll get your phone back quickly and easily. Why do I say that? Because I've lost my phone twice before and had a dude call me to pick it up twice before.

I'll make an application that stamps your contact information on custom wallpaper for the Windows Phone 7. My requirements are:

  • Must create lock screen wallpapers that match the Phone's style.
    • The resulting wallpapers must look like a built-in feature
  • Must look actually designed. Correct fonts, alignment, layout.
    • No garish VB3-on-a-phone-green-background-purple-buttons for me.

Cool. I will call it LostPhoneScreen and I pay $8 for the domain. Then I get to work.

Step 0 - Get the Tools

First I go and download the Phone Development Tools. They are free to download, which is cool. To publish an app costs $99 a year though, but I don't have to pay until I decide to publish the app. I can publish up to 100 apps for that $99 and unlimited apps if I pay per app.

If I pay (which I did) I make an account at http://create.msdn.com and put in my bank account information  for when the checks come rolling in.

OK, the Windows Phone SDK is installed so I start looking around for best practices. A development environment is only as good as its community and I don't want to write a bunch of stuff myself if someone has already done the work for me.

Step 1 - Get the Essential Open Source Libraries

My app  has some requirements and some specific technical requirements. I pick these ones because I'm always irritated when apps don't do these things.

  • Must support Mango multi-tasking/quick-resuming
  • Must look nice and layout like a built-in app
  • Must notify (email?) me if a crash happens
  • Must work with light and dark theme
  • Must have a nice About Screen with release notes
  • Must have a nice website to promote that app

I started with these requirements and found these open source libraries and projects to support each requirement.These things are so important that the should have been included in the Phone SDK by default.

LittleWatson

You know when a Windows app crashes and a crash report is sent? That's done by a system called Dr. Watson. Andy Pennell made a small Error Reporting library for Windows Phone 7 called "Little Watson" that was then extended by Bjorn Kuiper and packaged into Bjorn's excellent Northern Light's WP7 Toolkit. His toolkit includes a bunch of little conveniences for serialization, logging and error handling.

It was extremely important to me as a first time app developer (and frankly, it's just important) to get notifications of crashes. I could setup a web service to catch them via HTTP but for the first version, I'll notify the user and email the call stack to me using Little Watson.

MetroGridHelper

Edit screen with transparant grid behind itI found out very quickly when doing resource on phone apps that coding is only maybe 30% of the work. The rest is design. Then layout, then more design. Even for a "trivial" app.

I'm not a designer, but I can follow the basic "Metro design guide for developers" and I see over and over that alignment is king. You know those apps where you look at them and know something's wrong? But you can't see what? Turns out it's usually font size, layout or alignment just poking at the back of your brain.

Jeff Wilcox create a useful debugging assistant that you can just drop into your application with NuGet that will make a set of red squares that are offset 12px from each other with in a page padding of 24px. As you start doing Windows Phone work you'll find that 12px is a magic number and everything looks "right" if it aligns on these boundaries.

I just need to

Install-Package MetroGridHelper

We'll also turn on the FrameRateCounter and only do these things if we are actively debugging.

// Show graphics profiling information while debugging.
if (System.Diagnostics.Debugger.IsAttached)
{
    // Display the current frame rate counters.
    Application.Current.Host.Settings.EnableFrameRateCounter = true;
 
    // Display the metro grid helper.
    MetroGridHelper.IsVisible = true;
...
}

This is so useful it should just be there by default. You'll hear me say that a lot.

SilverlightToolkit

The Silverlight Toolkit from Microsoft is up on CodePlex and also easily installed with NuGet.

Install-Package SilverlightToolkitWP

It include a pile of useful controls like DateTimePicker, LongListSelector, ProgressBar (the one I was interested in), Transitions (another that I wanted), and lots, lots more. These should be in the box. They are utterly essential.

TombstoneHelper

Tombstoning is what happens when you app gets navigated away from then navigated back to. It's how you make your app feel like it's been in the background the whole time the user was switching around, even though you were dead and then came back to life.

Install-Package WP7TombstoneHelper

There's a number of ways to save your apps state, but the I found the WP7 Tombstone Helper useful as it will automatically look at your controls and save their state away then put you right back when you're launched again. It isn't right for every scenario, but it was useful to me.

protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
this.SaveState(e);
}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
this.RestoreState();
}

YourLastAboutDialog

If you're not careful, your About dialog can get more complex than your application. I don't want that, but I do like me a tidy About Dialog. I found YLAD - Your Last About Dialog to be the best option for me. It's a single DLL that gives you a generic but highly configurable about dialog. How configurable you ask?

Look how nice that is!

My lovely about box made with YLADMy lovely history box made with YLADMy lovely credits box made with YLAD

It's entirely managed by a single data.xml file that's totally self explanatory. I especially appreciate apps with clear listings of what's changed between versions. Not enough apps do that, probably because it's hard. But no more! Use YLAD.

Windows Phone Power Tools

Often you'll want to pull files off your emulator or actual phone directly. Since my app is going to serialize settings, make photos, and the like, I'll want to access the file system directly. The Windows Phone Power Tools were essential for accessing my application's Isolated Storage files. It was useful to simulate upgrades from one version to another and to debug serialization bugs.

Windows Phone Power Tools

Another one to watch is IsoStoreSpy that lets you preview files in the app itself.

PNGOut and PNGGauntlet

You will find yourself making a LOT of PNGs when you are doing mobile development. You'll almost always want to compress them before you ship. I squish the PNGs on my blog and often get compression improvements of 30% or more. I squished all the PNGs in my app to make the resulting XAP deployment file smaller, and the PNGs smaller on the phone itself.

I highly recommend PNGGauntlet with PNGOut. No quality is lost as PNG is a lossless image format. It's also worth pointing out that I lived in Paint.NET while making this application. It's an all around great app and the best way to work with all these PNGs.

Portable Library Tools

If you're going to want to create and use some assemblies between projects, the Portable Class Library project template for Visual Studio can make it a lot easier to share code.

Screenshots.cs

It's pretty hard to take a screenshot on a Windows Phone. On an iPhone there is a special button combination, but nothing like that exists on a Windows Phone. However, application developers have to take screenshots and submit screenshots all day long. Enter "screenshots.cs" from the crazy-useful Jeff Wilcox.

install-package ScreenShots.cs

When it's running (you don't want leave it running, just have it going when you need screenshots) it will take a screenshot programmatically every 2 seconds. If you leave it running it'll fill up your phone.  ;)

NotifyPropertyWeaver

When making ViewModels for Windows Phone, you'll always end up taking a nice clean class with some properties and end up littering the properties with code like:

string givenNames;
public string GivenNames
{
get { return givenNames; }
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged("GivenNames");
OnPropertyChanged("FullName");
}
}
}
And this stresses me out. I don't want to see those OnPropertyChanged and watch my simple class full up with notification boilerplate that I don't need to see. Fortunately Simon Cropp agrees with me and created NotifyPropertyWeaver to add this code post-compilation via IL Weaving without the need for attributes, base classes or even a class reference! It's in NuGet:
install-package notifyPropertyWeaver

Or, even easier, from the Visual Studio Gallery. NotifyPropertyWeaver adds this MSBuild task automatically in your csproj:

<UsingTask TaskName="NotifyPropertyWeaverMsBuildTask.WeavingTask"
AssemblyFile="$(SolutionDir)Tools\NotifyPropertyWeaverMsBuildTask.dll" />
<Target Name="AfterCompile">
<NotifyPropertyWeaverMsBuildTask.WeavingTask/>
</Target>

I realize this whole idea is scary, but I can tell you that I added it and didn't think about INotifyPropertyChanged once in the development of my application. You just add properties and he'll take care of the OnPropertyChanged stuff. If you don't believe him (I didn't) then just open your DLL in Reflector and see for yourself.

My ViewModel class is super basic and I only had to implement INotifyPropertyChanged and the weaver did everything else automatically. Very cool and saved me a bunch of hassle. The details are up on the Google Code site for NotifyPropertyWeaver. I found it a very elegant solution to a potentially messy problem.

Coding4Fun Windows Phone Toolkit

No, the Windows Phone 7 Toolkit isn't enough. Clint and the guys over at Coding4Fun have created a toolkit of their own that adds even more awesomeness (that should have been baked into the thing from the start). Things like Color Pickers, Color Sliders, lots of different buttons and more.

Coding4Fun Windows Phone Toolkit

Drink in the awesome over at http://coding4fun.codeplex.com.

Windows Phone 7 Emulator Skin Switcher

OK, this one isn't essential but it's totally cool eye candy. Why not change your phone skin with the Windows Phone 7 Emulator Skin Switcher? Live a little. The default one that comes with the emulator is a little meh.

When you run it, be SURE to scroll to the right as there are LOTS to choose from.

WP7 Emulator Skin Switcher

It's a nice touch.

Lost Phone Screen inside a Nokia Lumia

There's a great list of other tools, libraries and tips over at Bil Simser's The Big Dummies Guide for Windows Phone Developer Resources. Bil helped me over Skype when I had dumb questions. I'm glad he called his guide the "Big Dummie's Guide" and not the Hanselman Guide because that'd make it too obvious that I was clueless when I called. Thanks, Bil!

All right. I've got the tools and I've got my idea. Now what?

Write The Application

I know C# as I'm an ASP.NET Web programmer, but I'm not a XAML guy. The last thing I wrote in XAML was BabySmash and let's just say it wasn't rocket science. I started by dragging stuff around on the visual designer, pulling in buttons, text boxes and stuff but the XAML source started getting really messy with absolute pixel values and stuff I didn't like looking at. I stared at it for a while and just decided to write the XAML manually via trial and error, convinced that the the simpler the XAML was that more likely my app was laid out correctly. This turned out to be pretty true. I made a home page and an edit page.

Visual Studio and LostPhoneScreen

I got the two pages laid out and focused on making sure everything line up on the 12's (remember the MetroGridHelper I mentioned above) and tried to "intuit" when things looked wrong. I also referred to the "Metro design guide for developers" a lot.

Adding Polish

One thing I couldn't get my head around was that the transition between the main screen and the edit screen seemed jarring. It was like "poof." Then I realized there was no animation. Windows Phone apps usually use short but subtle animations to move between screens. Not just any old animations, but ones that involve direction to indicate moving forward or backward.

I remembered the Windows Phone 7 Toolkit above had transitions, so I applied them. The XAML is scary, but I only had to copy/paste. I made a NavigationIn and a NavigationOut for both pages so that they flip cleanly between each other.

Nice Windows Phone Flip Animation

I changed the PhoneApplicationFrame in App.xaml.cs to a TransitionFrame and the rest was magic. It just worked. Nice.

private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;

//RootFrame = new PhoneApplicationFrame();
RootFrame = new TransitionFrame();

RootFrame.Navigated += CompleteInitializePhoneApplication;

// Handle navigation failures
RootFrame.NavigationFailed += RootFrame_NavigationFailed;

// Ensure we don't initialize again
phoneApplicationInitialized = true;
}

Once this was done, if I needed to add other animations, it would be trivial. This small change made the app feel more polished.

Resources (Yes, more PNGs)

I needed buttons for the ApplicationBar at the bottom but I'm not a designer. I talked to Jin Yang (a designer) to do the main icon:

This sad, tiny phone is lost and on the back of a milk carton. Won't you help him find a home?

ASIDE: If you don't understand this icon, it's because it's apparently not universal. In the US when a child was missing in the 80's and 90's they would put their picture on the back of a milk carton. The idea was that you'd be eating your cereal in the morning and you'd notice the picture and it would seep into you brain so you'd be on the alert for that child during the day. Maybe a "missing" flyer with this phone would be more culturally non-specific.

But I didn't need a full-blown expert for the standard black and white icons at the bottom. The Windows Phone SDK comes with 32 basic icons for things like download, save, stop, play, etc. Even better though are the icons at Templarian. These are hundreds of yummy icons for Windows Phone (and other phones) that are released under the Creative Commons license. The designers name is Austin Andrews and he's super talented. I mean, even when he's just drafting ideas he's awesome. If you use his icons, thank him and tell people. If you are a designer, why not join up and improve the pack for the community?

UPDATE: The 130 icons from WindowsWiki.info are also amazing and high quality. Another great place for icon inspiration is The Noun Project.

My app was so simple that I ended up only using just four of the icons that came with the SDK, but I'm going to exploit the Templarian Windows Phone Icon pack whenever I can in the future.

Interesting Gotchas (actually Got-mes)

The first time I submitted the app it was rejected within two days. Turns out that when you popup a Popup - like for my Save Button - the hardware Back button must dismiss the popup. They are really serious about this model that you move forward and the hardware Back button always moves "back."

I ended up having to close my popup like this:

protected override void OnBackKeyPress(CancelEventArgs e)
{
if (theHelpPopup != null && theHelpPopup.IsOpen == true)
{
theHelpPopup.IsOpen = false;
e.Cancel = true;
}
}

As I continue to explore Windows Phone Development I'm sure I'll find better (read: less hacky) ways to manage things like this. Frankly, I was surprised that the Popup class didn't handle this for me!

Test with Light Theme

Another important thing is to test your app with a light theme. I initially had colors with hard-coded opacity like "CC00000000" for a transparent black. However, when your theme is white-based, rather than black, things start look like crap when you hard code colors. Instead they recommend that you use StaticResources with names that will automatically look correct, regardless of theme:

<Grid Height="448" Width="480" x:Name="LayoutRoot" 
Background="{StaticResource PhoneBackgroundBrush}"
Opacity="0.8">
...

Here I'm using PhoneBackgroundBrush, which means my help Popup looks nice twice!

Lost Phone Screen with Two Themes

However, notice that the black text at the top is hard to read? More on that later. A feature to help with that will be in the next version, which should be out later this week!

Submit the Application

You log into http://create.msdn.com and go through a detailed but largely straightforward wizard. There's a long checklist but the one I spent the most time going over was the Application Artwork for Windows Phone section. You need two different icons for the phone, three different icons for the Marketplace and a panorama in case you are a Featured App. Remember earlier when I said it was less code and more PNGs? This is where the time was taken up; just making sure all the PNGs were perfect from a large source PNG.

After you submit, you wait. I waited 3 days, was rejected, fixed the Back Button issue and Submitted Again.

windowsphoenstep2

Now I've found a few more bugs and will submit an update this week. The cycle will continue.

Attention to Detail

There's so many little things from misspellings to missed pixels that you need to be on the lookout for. For example, I misspelled "wallpaper" in a screenshot - seriously - because I was working late into the night. Sloppy. And now I'll have to wait almost a week to fix it due to the way the Marketplace works. As a web programmer this will take getting used to as I'm used to "hit refresh, it's fixed" when squashing bugs for my users

Triple check everything, test and test again. Every small mistake means 3 days lost waiting for the marketplace to update. And those days can mean days of unhappy users.

Make the "Marketing" Website

Time to make myself a nice simple static website to promote my application. I could hire someone or try to make something myself, but I really just have some basic requirements.

  • The site should include screenshots
  • The site should be mostly static html but feel slightly dynamic (javascript?)
  • The site should work on a mobile device (even iPhones!) using responsive design.
  • The site should link to the Windows Phone Marketplace

I didn't want to spend much time on this, but I also didn't want to do my app a disservice with a crappy site. There are lots of mobile templates out there, but a few stand out as they are Windows Phone 7 Specific.

One is Wp7JekyllTemplates, which works nice if you are hosting your code and site on GitHub. The other is Wp7AppSite by Nick Harewood. I noticed that Wp7AppSite used the Skeleton Boilerplate, which I am a fan of. I used it on http://speakinghacks.com.  It looks great on mobile so I was sold.

It was stupid-easy to setup. I just pointed my domain my my host, setup index.html as the default document, resized the screenshots, modified the HTML and uploaded. Took about 10 minutes.

Pricing

I made it $0.99. I didn't want to make it free because I didn't want to make it free. It costs less than the foam on your latte and it will get nice updates for free. I find it funny that folks will research 99 cent apps for an hour while sipping a $5 latte. ;)

I buy lots of $1 apps because THEY ARE $1 APPS.

Find a Bug

Earlier I mentioned that some wallpapers make it so the text is hard to read depending on the theme. Tim Heuer reported this so I added a feature to invert the text color, as seen in the screenshot below:

Inverted Text in Lost Phone Screen

Notice how the A at the bottom in the Application Bar inverts depending on the color of the text. I am very happy with how that turned out.

Submit the Update

I also removed the progress bar as it was getting in the way of the screenshot process and fixed a data persistence bug where your settings don't always get saved depending on how you exit the application. This is due to my confusion about how task switching vs. application existing works in Mango. That's fixed and will be out as as a free update soon as they certify it.

I'll submit the 1.0.2 update this week that will include the smarter text coloring as seen in the screenshot above. Barring rejection, the Marketplace should notice you'll get the updates!

You can get Lost Phone Screen on the Windows Phone Marketplace and you can offer feedback and feature request on UserVoice. If you buy it, please review it on the marketplace from the About Screen.

UPDATE: Reviews

Bad Reviews hurt, even for a silly little application like mine. I've already released the 1.0.2 update with bug fixes that address many major issues folks have had with the app. Here's what you should do to keep on top of feedback and reviews:

I'll update this post with more info as I learn more. I haven't got download stats yet and I've only just released my first update.

Conclusion

I was pleasantly surprised how easy it was to get into Windows Phone 7 programming. I was also thrilled with the amount of great open source libraries, creative commons art and other resources that are available for the beginner. The marketplace process and website are still a little confusing and rough, and I don't like waiting days to find out how my app is doing, but I guess that's life with a marketplace.

Big thanks to Jin Yang for the Icon and Bil Simser for Skyping with me.

I'll keep updating my little app and trying to think of ideas for my Next App.

Enjoy!

Related Links

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 ORCS Web

Maslow's Hierarchy of Needs of Software Development

January 28, '12 Comments [28] Posted in Musings
Sponsored By

I've been experimenting with my diet a little and considering a Paleo diet. What an amazing and selfish thing, though, for me to even consider or be able to change my diet in a fundamental way. Only someone who isn't worried about their next meal could explore that aspect of their lives without fear or concern.

One doesn't get to have certain luxuries until other more basic needs are met. Here's an interpretation of Maslow's hierarchy of needs:

 

Maslow's heirarchy of needs, as a pyramid

I was talking to a customer a while back and one gentleman was deeply concerned about coding style, curly brace location, best practices in interface design and a bunch of important but arguably not urgent thing. Their unit testing wasn't well organized, their deployment was manual, their build was only marginally verifiable.

Stated differently, he was asking questions like "Am I eating enough veggies rich with Vitamin A" without asking the more fundamental "Do I have food for tonight?"

Now, apply the Hierarchy of Needs to Software and Technical Debt. Here's one, with my thanks to Phil Haack, Jon Galloway, Jonathan Wanagel, Paul Stovell for their help in brainstorming.

A proposed heirarchy of needs of software - Bragging Rights, Refactorable, Maintainable, Buildable, Revisable

Bragging Rights - Change you are proud of

Paul put it well when he said to me: "The top of Maslow's pyramid is self-actualization...in some ways I think we like to achieve self-actualization through our code, [such that] in years to come, maintenance programmers will stumble upon this architecture and exclaim, 'Wow, Scott was here.'"

Are you writing software or crafting software? When does your craft become art?

This is a noble and certainly attractive goal, but is one that should be attempted only after the basic needs are met.

Refactorable - Change without fear

Is your code/system easy able to be refactored? Can you rearrange it without fear? Does it follow all the conventions and use the appropriate idioms of your chosen language? Do you have automated unit tests?

Maintainable - Change with verification

Is it able to change at all? Are bugs fixable? When you make a change is that change verifiably correct? Any tests at all?

Buildable & Deployable - Change in production

Can you deploy your system as easily as you can build it? Continuous Integration is effectively a must in today's software systems, but moving up in importance is Continuous Deployment - with rollback!

Revisable - Change

Is your system in source control with a clear workflow that governs contributions? Can you revert changes, stamp official changes, branch and merge? What? You're using zip files? Sorry, friend, you don't get to talk about class design or move around UML diagrams until you're using source control.

The importance of leadership

This underscores the importance of a strong and appropriately self-aware leader. Creating art is the fun stuff but it isn't always what needs to be done to move the project forward. The tech lead needs to recognize the right time to be an artist and the right time to invest in strong foundational processes.

Are we eating enough leafy greens as a team? Let's start with "are we eating tonight?" and work from there.

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 ORCS Web

Get involved in Open Source today - How to contribute a patch to a GitHub hosted Open Source project like Code 52

January 25, '12 Comments [21] Posted in Open Source
Sponsored By

It's been over 5  years since my post how to contribute a patch to an Open Source Project. That post is focused primarily on Subversion as the source control system. If you are using CodePlex and Subversion for example, those instructions work great. Here's the same idea for GitHub projects.

Folks email me all the time asking questions like "how can I be a better programmer?" "how do I get more experience?" or even the very specific "how can I make my resume more attractive?" My answer is almost always get involved in open source.

Work with an open source project. Fix a bug, do their website, write some documentation. You don't necessarily even have to write code. A lot of open source projects need help and that help can mean doing forums work, support calls, whatever. The thing that folks forget about open source is that it's most volunteers who are doing it for the love of it. They show up.

"80% of success is just showing up." - Woody Allen

Sometimes open source projects fail simply because only one or two people actually show up. Day after day. Using open source is easy, but making open source is hard.

NOTE: This example uses Git and GitHub. It is not meant to be comprehensive nor ideal. It is workable and works, but if you are considering working in Open Source or with Git for multiple projects and features you will want to explore more complete (and complex) workflows. There's an excellent "Git Workflow for Agile Teams" article, as well as a suggested Git Workflow from the NuGet team, and a fantastic screencast from Ryan Bates on contributing with Git as well as a fine screencasted introduction from Bobby Johnson.

Code 52

It can be an overwhelming thing, though, to jump into a large open source project that is already established. It can also be hard to decide which small project to start, because no one wants to waste their time. How do you choose?

Some lovely gents (Andrew Tobin, Brendan Forster and Paul Jenkins) over at Code 52 have started a great idea. A new coding project every week.

What a great idea! Nothing too hard that it can't be jumpstarted in a week. This totally lowers the barrier to entry and also encourages that things stay fresh. It also creates a bunch of great codebases for us (the community) to fork and spin off into larger projects that live longer than a week.

The guys says they figured a week because:

  • shorter timelines encourage achievable goals.
  • shorter timelines reduce the incentive to procrastinate.
  • more variety of projects to work on over a period of time.

Contributing a patch to a small Open Source project on GitHub

The Code52 projects are hosted on GitHub. I host some of my own projects on BitBucket and others on CodePlex. It doesn't really matter where a project is as long as it makes you happy.

Let's say I want to contribute a fix to the DownmarkerWPF project they worked on a few weeks back. There's a few things I can do.

Raise an issue

Filing a bug is literally the least you can do to help a project. Even better if it isn't a ragebug (where you just tell them how they suck) but includes everything you know about the issue, perhaps a stacktrace or a screenshot. Bonus points if you're kind in tone.

Suggest a Feature

Be helpful and suggest an interesting or innovative feature for their product. Bonus points if you include mockups, suggest a design or even better, start implementing it!

Fork the Code, change it, then do a "pull request"

With some SCC (Source Control Systems) you'll change the code locally package it up as a "patch/diff" file and send that file onto the project team for integration at a later time. You'll want to just use the website for spelling changes and easy stuff.

With some newer systems like Mercurial and Git you'll push your code to a central place and send a "pull request" that says "hey, the code is over here, pull it in, m'kay?"

GitHub will allow you to make changes in the browser, but that's not realistic for actual code changes. Let's get the DownmarkerWPF code, change it, and submit a pull request.

It's a lovely Markdown Editor for Windows. If you don't want the source and just want a decent zipped up version you can run, you can download it.

Markdown Editor for Windows

Since I am going to fix what I think is an "issue" I'll first make an issue on the site and claim it. It's issue 82, so I will remember that number.

My GitHub Issue

I'll fork the code from the website and then clone my copy to my local machine. Note the URL I'm using is my fork of the code.

C:\Code52>git clone https://shanselman@github.com/shanselman/DownmarkerWPF.
git
Cloning into DownmarkerWPF...
remote: Counting objects: 1870, done.
remote: Compressing objects: 100% (634/634), done.
remote: Total 1870 (delta 1347), reused 1728 (delta 1210)
Receiving objects: 100% (1870/1870), 11.40 MiB | 2.39 MiB/s, done.
Resolving deltas: 100% (1347/1347), done.

I could make a branch for myself to describe what I'm doing but I'm not going to because it's unnecessarily confusing for this example.

So, I love the idea of a Markdown editor for Windows as I'm writing a book with my wife using Markdown. However, my wife and I (and Leanpub.com) are using *.mkd as our extension, while the Code52 project uses *.md, *.markdown, and *.mdown. Here's an small but impactful change that I can make.

I'll find the code, and change it. Don't get overwhelmed now by the awesomeness and impact of this fix.

public static class Constants
{
public static readonly string[] DefaultExtensions = new[] { ".md", ".markdown", ".mdown", ".mkd"};
...
}

Now I'll compile and test the change. It works!

Behold the greatest bug fixed in the history of software

Now I'll commit my change locally, then push it to the server. Add, Commit, Push.

C:\Code52\DownmarkerWPF>git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: src/MarkPad/Constants.cs
#
no changes added to commit (use "git add" and/or "git commit -a")

C:\Code52\DownmarkerWPF>git add .

C:\Code52\DownmarkerWPF>git commit -m "#82 - Added .mkd extension support"
[master 17c5704] #82 - Added .mkd extension support
1 files changed, 1 insertions(+), 1 deletions(-)

C:\Code52\DownmarkerWPF>git push
Password:
Counting objects: 9, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 453 bytes, done.
Total 5 (delta 4), reused 0 (delta 0)
To https://shanselman@github.com/shanselman/DownmarkerWPF.git
792d099..17c5704 master -> master

Cool, so now I can see on the website that my issue #82 has been associated with my change because I used the number in the commit message.

Look it's issues attached to commits!

Now I'll let the Project Administrators know where they can get it by pressing Pull Request on the website.

I'm issuing a pull request

Now I wait some number of minutes, hours or days for the owner of the project to accept my request. It's totally up to them what they accept and what acceptance criteria they have.

Here's my fix, now accepted, merged and closed by the Project Administrator. They will then close the issue.

My accepted pull request

Open Source isn't as scary as it seems. Go out there now and offer your help, time and assistance to your favorite project. Promote them, use them, fix their spelling and bugs. You can play with the Code 52 guys in their chat room on Jabbr or learn all about the project at the Code 52 website.

Related Links

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 ORCS Web

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