Thursday, December 20, 2012

A colleague of mine at Magenic recently posted on how to deploy and debug a WinRT app on a Surface RT.

Another alternative is to install the app onto the Surface device via PowerShell. This won’t attach the debugger, but is often an appropriate solution for people who are just testing the app (QA testers, colleagues willing to provide feedback, etc.).

This is a multi-step process. At a high level it goes like this:

  1. Developer packages the WinRT app to a folder on their hard drive, then puts the package on a network share or USB key, etc.
  2. Tester unlocks PowerShell on their device (this is a one-time thing)
  3. Tester gets the WinRT app package and runs a PowerShell script to install the app on their device

Creating the Package

The developer needs to create a distributable package for the app. This is done by right-clicking on the WinRT project in the Visual Studio solution explorer, and choosing Store –> Create App Packages.

image

This brings up the Create App Package wizard. The first question is whether you want to deploy the the store, and the answer in this case is No.

Next, you’ll be asked where to create the package, how to create the package version number (different from the app version number) and what platforms to target.

image

The Neutral architecture in Release (Any CPU) allows testing on Intel and ARM devices.

When the Create button is clicked, the project is built and packaged, with the results placed in the specified folder.

image

The top level folder contains an appxupload file that you can safely ignore (it is used for uploads to the store). It also contains a sub-folder with the actual app package.

image

These are the files you must make available to the tester. You can put these files on a network share, a USB key, a SkyDrive folder, or any other location where the tester can gain access. The Add-AppDevPackage.ps1 file is the PowerShell script the tester will run to install the app.

Unlocking PowerShell

The tester’s device must be able to execute PowerShell scripts before they can install the app. By default PowerShell has security settings that prevent scripts from executing. This TechNet article discusses running PowerShell scripts. In summary, you need to open PowerShell as Admin and run this command:

Set-ExecutionPolicy unrestricted

Be aware that this allows execution of any script, so you do assume some risk by enabling this policy.

Once this has been done your test device is now able to install WinRT apps by executing the PowerShell script generated by Visual Studio.

Installing the App

On the test device you must have access to the contents of the package folder created by the developer in Visual Studio. You might get those files from a network share, a USB key, or other location.

Simply execute the Add-AppDevPackage.ps1 file in PowerShell to install the app.

The script will ask permission to run.

image

If this device does not have a side-loading unlock key (MAK or developer key), you will be asked if you want to get a developer key. You should answer yes and walk through the wizard to get a developer key for this device. This step will require you to enter your Microsoft Account email address and password. The resulting key will expire after a short period of time (currently three months).

The PowerShell script will then ask for permission to install the certificate for the app. If you’ve already installed the certificate (perhaps you are installing a newer version of the same app) the script will skip this step.

image

image

Once the certificate is installed, the script will install the WinRT app itself.

image

At this point the WinRT app is installed and its tile should appear on the start screen along with all other apps installed on this device.

The user may now run the app like any other app.

Once the developer key for this device expires the app will stop working. Obviously the intent of this installation approach isn’t for the user to run the app forever, but rather so they can test it and provide feedback during the development process.

Thursday, December 20, 2012 12:06:59 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, December 19, 2012

This is something I use from time to time, and I thought I’d post it here so I can more easily find it next time I need the code.

This is an IDataReader implementation that reads in comma-separated value files. Probably incomplete, but it works well in the scenarios where I’ve needed it.

using System;
using System.Data;
using System.IO;

namespace Csla.Data
{
  public class CsvDataReader : IDataReader, IDisposable
  {
    private StreamReader _file;
    private string[] _headers;
    private string[] _line;

    public CsvDataReader(string filePath)
    {
      _file = File.OpenText(filePath);
      Read();
      _headers = _line;
    }

    public void Close()
    {
      _file.Close();
      _file.Dispose();
      _file = null;
    }

    public int Depth
    {
      get { throw new NotImplementedException(); }
    }

    public DataTable GetSchemaTable()
    {
      throw new NotImplementedException();
    }

    public bool IsClosed
    {
      get { return _file == null; }
    }

    public bool NextResult()
    {
      return false;
    }

    public bool Read()
    {
      var result = !_file.EndOfStream;
      if (result)
        _line = _file.ReadLine().Split(',');
      return result;
    }

    public int RecordsAffected
    {
      get { throw new NotImplementedException(); }
    }

    public void Dispose()
    {
      if (_file != null)
      {
        _file.Dispose();
        _file = null;
      }
    }

    public int FieldCount
    {
      get { return _headers.Length; }
    }

    public bool GetBoolean(int i)
    {
      return Boolean.Parse(_line[i]);
    }

    public byte GetByte(int i)
    {
      return Byte.Parse(_line[i]);
    }

    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
      throw new NotImplementedException();
    }

    public char GetChar(int i)
    {
      return Char.Parse(_line[i]);
    }

    public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
      throw new NotImplementedException();
    }

    public IDataReader GetData(int i)
    {
      throw new NotImplementedException();
    }

    public string GetDataTypeName(int i)
    {
      throw new NotImplementedException();
    }

    public DateTime GetDateTime(int i)
    {
      return DateTime.Parse(_line[i]);
    }

    public decimal GetDecimal(int i)
    {
      return Decimal.Parse(_line[i]);
    }

    public double GetDouble(int i)
    {
      return Double.Parse(_line[i]);
    }

    public Type GetFieldType(int i)
    {
      throw new NotImplementedException();
    }

    public float GetFloat(int i)
    {
      return float.Parse(_line[i]);
    }

    public Guid GetGuid(int i)
    {
      return Guid.Parse(_line[i]);
    }

    public short GetInt16(int i)
    {
      return Int16.Parse(_line[i]);
    }

    public int GetInt32(int i)
    {
      return Int32.Parse(_line[i]);
    }

    public long GetInt64(int i)
    {
      return Int64.Parse(_line[i]);
    }

    public string GetName(int i)
    {
      return _headers[i];
    }

    public int GetOrdinal(string name)
    {
      int result = -1;
      for (int i = 0; i < _headers.Length; i++)
        if (_headers[i] == name)
        {
          result = i;
          break;
        }
      return result;
    }

    public string GetString(int i)
    {
      return _line[i];
    }

    public object GetValue(int i)
    {
      return _line[i];
    }

    public int GetValues(object[] values)
    {
      throw new NotImplementedException();
    }

    public bool IsDBNull(int i)
    {
      return string.IsNullOrWhiteSpace(_line[i]);
    }

    public object this[string name]
    {
      get { return _line[GetOrdinal(name)]; }
    }

    public object this[int i]
    {
      get { return GetValue(i); }
    }
  }
}
Wednesday, December 19, 2012 10:00:22 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, December 07, 2012

The Silverlight.net web site is apparently now gone, merged into the broader msdn.com ecosystem (where it belonged in the first place imo):

http://www.zdnet.com/microsoft-pulls-the-plug-on-its-silverlight-net-site-7000008494/

As we’ve known now for a long time, Silverlight is “dead”. It is in support mode and will be for a decade.

Just like Windows Forms has been since 2005, and WPF is now as well (do you really think Microsoft is going to divert money from WinRT to do anything with WPF at this point??? If so I’ve got this beachfront property for sale…).

As an aside, ASP.NET Web Forms also “died” in 2005, but recently got a major infusion of money in .NET 4.5 – showing that even a “dead” technology can receive a big cash investment sometimes – though it still isn’t clear that this will be enough to breath any new life into Web Forms for most organizations. I suspect it is more likely that this recent investment will just allow organizations with massive Web Forms sites to keep them limping along for another 5-10 years.

If a technology is defined as “dead” when its vendor stops enhancing it and starts maintaining it while they put most of their money into the future, then I must say that I’ve spent pretty much my entire ~25 year career working on dead technologies. And it has been fun! Smile

Although some of us tech geeks like to jump to the next potential upcoming thing, the people who actually fund software projects rarely want to accept that kind of risk. They generally prefer to build applications on stable technology. Most stable technology is “dead” or “dying” based on this idea of “live” technology being rapidly changing and evolving.

Obviously there’s a fine line here.

Target stable technology that is too old and you really are in trouble. Windows Forms is an example of this, because its underlying technology has no migration path to a WinRT future. Although a lot of organizations have massive investments in Windows Forms, I would hope that they’d shy away from starting new development on this extremely stable, but now too old, technology.

Target stable technology that is new, but old enough to be stable and life is generally pretty good. WPF and Silverlight (for smart clients, not for cross-platform RIA) are examples of this. The reason is that these technologies (especially Silverlight) have a good migration story to a WinRT future. A lot of organizations are investing in WPF, and that’s good. But I’d be shocked if Microsoft invests anything in WPF going forward – its future is the one Windows Forms has enjoyed since 2005 – stable maintenance of the technology. Perfect for building critical business apps. Organizations also have large investments in Silverlight, and as long as the intent was smart client development (not cross-platform RIA) it seems to me that they are in the exact same place as everyone using WPF. Arguably better, because Silverlight is much closer to WinRT than WPF.

http://magenic.com/Portfolio/WhitePaperWindows8DevelopmentPlatform.aspx

If you are using Silverlight for cross-platform rich web development, then I do agree that the news is not good. The current alternative appears to be HTML 5, though it is also clear that this is an expensive alternative with an unsure future. Just like every other silver bullet to write once and run anywhere, I think you have to go into such a venture expecting a lot of cost and pain. There’s no widely successful example in the history of computing that indicates otherwise…

The final option is to target “live” technologies. You know, the ones where vendors are dumping huge amounts of money, and where the technology and platform are changing rapidly. Things like HTML 5 and WinRT are examples of this. As a tech geek I love it when organizations want to do this sort of thing, because the challenge is high and we all get to learn a lot of new stuff. Of course the development costs are also quite high because we’re getting paid to learn this new stuff. And the overall costs for the software are high because the technology/platform isn’t stable and the app probably needs to be rewritten (in whole or part) every few months to deal with platform changes.

Some organizations are willing to accept the costs and inconvenience associated with using “live” technologies. But most organizations don’t have the time or money or risk tolerance, and are far better off targeting “dead” technologies like WPF and Silverlight. They just need to be careful to have strategic migration plans so they can get off those technologies before they reach the point of where Windows Forms is today.

Friday, December 07, 2012 11:23:33 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [6]  |