Friday, December 17, 2010

Developing on the Win phone 7 hardware without a developer account

Microsoft have released a free toolset for developing Windows Phone 7 applications. However you cannot debug or deploy onto actual hardware until you create a developer account @ $99 per year.

In my case, I only have a demo phone for 2 weeks so a developer account seems like a waste of money.

To work around this restriction, you need to do the following:

1 Unlock the phone:
Download and install the Chevron unlocker and certificate from here.

2 Stop the phone from relocking every time you reboot
Edit your hosts file (C:\Windows\System32\drivers\etc\hosts)
Add the line
127.0.0.1 developerservices.windowsphone.com

You can now deploy and debug on your phone.

Note: the phone will still relock itself every couple of weeks, giving the following error

“[application name] has been revoked by Microsoft. Please uninstall it.”

Just rerun Chevron and unlock again.

2nd note: You can deploy your .xap file to others and they can run them on unlocked phones. However the continual relocking may get annoying.

3rd note: You can't use Chevron to pirate applications. It will only allow you to run unsigned applications.

Monday, December 13, 2010

Developing for Windows Phone 7 in a virtual machine

According to Microsoft, installing the windows phone developer tools into a virtual machine is not supported. This is because the phone emulator is itself a virtual machine and, as Inception has shown, running a virtual machine inside a virtual machine gets really slow. The emulator also requires DirectX 10 for XNA develoment, and current virtual machines only offer DirectX9.

However I do all my development in virtual machines. I already have a VM setup with VS2010, version control, database etc. I don't fancy setting that up all over again just for a phone, particularly one that I only have for 2 weeks.

Time to do some testing...

Virtual PC
Running the dev tools in a Windows 7 Virtual PC works (or rather fails to work) as advertised. While I could create and compile a phone project, I couldn't actually run it in the emulator.

VMWare
Using a VMware vm was much better. I could compile and run a silverlight project on the emulator. On my laptop, the emulator performance was dire. On my desktop however, emulator performance was adequate but not stunning.

On either machine, XNA projects wouldn't run on the emulator due to the lack of DirectX 10. They would compile but trying to deploy would fail with "The current display adapter does not meet the emulator requirements to run XNA Framework applications."

However deploying and running on a real phone worked fine. Both Silverlight and XNA deployed and ran without any issues.

Booting from a virtual hard drive (thanks Paul)
Should work but requires Windows 7. See here.

TL;DR
You can develop Silverlight applications in a VMWare virtual machine, testing against the emulator (slow) or actual hardware (fast). You can develop XNA applications in a VMWare vm but you need to deploy to actual hardware.

Useful links
Microsoft's free tools: Create App hub
Charles Petzold giant ebook: Programming Windows Phone 7
Reddit Win Phone 7 section: http://www.reddit.com/r/wp7dev/

Friday, September 10, 2010

Monday, March 22, 2010

Windows Phone 7 - A party pack of sweets for developers

They are playing advertisements for Pascall's Party Pack on TV at the moment. The tag line is "All sweets you love, and one you can't stand." That pretty much sums up Windows Phone 7 for developers. Lots of goodness with a few things that may leave a bad taste in your mouth.

Despite the name, Windows Phone 7 Series is not a successor to Windows Mobile 6.x. Instead the name is a marketing nod towards Windows 7. Although both WP7 and WM6 are based on Windows CE, there is no resemblance at a higher level. From a user point of view, WP7 is closer to the iPhone than to WM6. A more accurate name would be Windows Phone 1.

After far too much time reading, watching and playing, here are my thoughts on WP7 as relates to development:

Tasty:
  • Development is done in c# and Silverlight/XNA. While native code would be nice, C# is easier to get into than Objective C. I haven't used either Silverlight or XNA previously but they look a lot more promising than the XP era Windows Forms used by Windows Mobile.
  • The tools are much better than those for the iPhone, and free
  • Push notifications look at lot easier to do than on the iPhone
  • Apparently xbox live integration is really good (I wouldn't know)
  • There are metric shitloads of tutorials, walk throughs and documentation (Twitter apps are the new hello world)
  • Games programming looks really, really nice

Meh:
  • The tools don't work well in virtual machines. You can make it work in a Win 7 32bit VM but it will run like a dog. The tools don't work at all in Win 7 x64. If you don't want to install onto your main system, you can try booting from a virtual hard drive.

Yuck:
  • No database support (apparently it's not necessary coz you have xml and the cloud). SQL Server CE is built into the rom, but no access is provided.
  • No multitasking (push notifications only)
  • No access to the file system. Application files all go into Isolated Storage in the app folder.
  • No "sideloading" of applications. Apps can only be installed from the Marketplace, or by Visual Studio
  • No built in file synchronisation (it's this cloud thing again).
  • No Silverlight support in Windows Mobile 6.x (but there is Silverlight for Symbian wtf) and no Win forms support in WP7. I.e. even if your win mobile app was written in c# it needs to be rewritten for WP7.
  • Limited APIs (no access to contacts, no sockets, ...)
  • No native code - no c, c++, pascal etc (and thus no firefox :()

I haven't felt this conflicted since the vfr 1200. Some nice things balanced by some not so nice.

As mentioned, so this is essentially version 1. Some of the issues are planned to be fixed after the initial release (copy/paste, database access).

Links

Microsoft
Windows Phone 7 tools
Code samples
Developer network
Mix10 videos (check out the keynote)
UI Guide

Silverlight
Get started in Silverlight
Get started with Silverlight in WM7

Example apps
Twitter client
Another twitter client (Scott Gu)
Labyrinth
Sqlite database

Blogs
Artificial Ignorance
10rem
Mobile development

Saturday, February 13, 2010

Solving a mid-life crisis with a Solid State Drive

My development laptop is now 18 months old, which makes it older than me in computer years. As part of a mid-life refresh, I replaced the boot drive, (250gb 7200rpm) with an Intel X25M 160gb ssd.

The result of this is that things are much snappier. How much snappier? I timed a few things of importance to me, booting my laptop and virtual machines, starting delphi and rebuilding a medium sized project (600,000 loc).

Overall, using an ssd cut the times by an average of 39%. Not too bad an improvement. To put it another way, my "getting started" time (boot laptop, boot vm, start delphi) went from 6:05 to 3:37.




Edit:
The Delphi 2007 install is screwed up somewhere. It certainly never used to take 3 minutes to start up:( but sometime last year it started getting really slow. I don't use that install or vm much so I haven't bothered trying to sort it out.

Thursday, January 14, 2010

[.net] Using sql server full text searching with Mindscape's LightSpeed

Advance warning: This post is only of use to people using Lightspeed or suffering from insomnia.

The problem
For my current c# project, I am using Mindscape's Lightspeed O/R framework. Lightspeed is a mighty fine product that makes object persistence a breeze. I would kill to have this in delphi.

However the only full text searching that LightSpeed supports out of the box is Lucene.net. Sql Server full text searching is not provided and no-one else seems to have created it.

The good news is that Lightspeed has a pluggable search engine framework so it is possible to add a new search engine. The bad news is that it's not overly well documented and there aren't many examples. The good news is that their online support is pretty good.

The resolution
Mindscape have a blog post outlining the process of adding a new search engine. However there are a number of traps for young players that aren't covered there, or indeed anywhere. The following should shed some light on the process.

Creating a new search engine requires implimenting ISearchEngine
  public interface ISearchEngine
{
IList<SearchResult> Search(string query, params string[] scopes);
void Add(IndexKey indexKey, string data);
void Update(IndexKey indexKey, string data);
void Remove(IndexKey indexKey);
void Optimize();
void Clear();
LightSpeedContext Context { get; set; }
void BeginBulkAdd();
void EndBulkAdd();
}
For sql server, and for most databases with inbuilt FTS, most of these methods can just be left as empty method bodies. All that needs to be implemented is Context (stores lightspeed configuration info such as the database connection string) and Search.

All that is needed to implement Context is:
    public LightSpeedContext Context { get; set; }

The fun comes in implementing Search:).

Example class
LightSpeed takes a class and maps it to a database table. In my case, the class is CmsModels.Entities.AccClaim. It is stored in the table AccData and has an integer primary key called ClaimId.

To perform a search, say finding all of my claims, I need to run the following query:
    select *
from FreeTextTable(AccData, *, 'Sean Cross Prevshort')
order by RANK desc
returning something like
    KEY       RANK
175671 27
175673 23
175646 15
175657 7
Key is the pk field (ClaimId) and Rank is how well the record matched the query.

Implimenting search
The Search method takes a query ("Sean Cross Hastings") and an array of type names (["CmsModels.Entities.AccClaim", ...]). It returns a list of SearchResult objects. SearchResult has the following constructor:

    public SearchResult(
string key,
string scope,
string entityId,
float score
)

In short, we take the query and the class name, construct a query, run it and use the results to create a list of SearchResult objects. Easy, in theory.

The devilish details
A Getting the table name
Given an object name, Lightspeed has a number of ways of determining the table name. Which option is chosen depends on the model and class settings.
The possibilities are
  1. Table name = class name (eg AccClaim)
  2. Table name = pluralised class name (eg AccClaims)
  3. Table name is explicitly set in class attributes (eg [Table("AccData", IdColumnName="ClaimID")])
  4. Table name is set programmaticly using a user defined naming strategy object (eg TBL_ACCCLAIM)
AFAIAA It is not possible to cover all these cases without access to LightSpeed internals. I have suggested that they provide a GetMyBloodyTableName method but that hasn't happened yet.

I have opted to only support cases 1 and 3 as this covers most of my classes, and it's easy. Any table name that falls into a different case can still be searched by specifying the table name explicitly.

To get the table name, I look for a TableAttribute and use it. If I can't find one, I use the type name.
    string tableName = "";
Type t = Type.GetType(scope);
object[] tableAttrib = t.GetCustomAttributes(typeof(TableAttribute), false);
if (tableAttrib.Length > 0)
{
tableName = ((TableAttribute)tableAttrib[0]).Name;
}
else
{
tableName = t.Name.ToUpper();
}
B Running the query
LightSpeed doesn't support running random sql so it's back to ado.net. The Context object can be used to create a SqlCommand object so it's pretty straightforward:

    IDbCommand command = Context.DataProviderObjectFactory.CreateCommand();           
Context.CreateUnitOfWork().PrepareCommand(command)
command.CommandText = string.Format("select * from FreeTextTable([{0}], *, @query) order by RANK desc", tableName);
((SqlCommand)command).Parameters.AddWithValue("@query", query);
IDataReader reader = command.ExecuteReader();

while (reader.Read())
{
...
}
C Creating the SearchResult objects
The SearchResult constructor is as follows:
    public SearchResult(
string key,
string scope,
string entityId,
float score
)
scope is the full class name passed into the Search method (eg "CmsModels.Entities.AccClaim")
entityId is the pk returned from the query in the Key field (eg 175671)
score is the rank returned from the query in the Rank field (eg 27)

key is the problem child. It is not properly explained anywhere in the documentation. I only found out how it is created by creating a dummy Add method, putting a breakpoint in there and examining the values passed in. It is a string in the format "{type name}]{entityId}" (eg "[AccClaim]175671").

So creating the results is
    while (reader.Read())
{
string entityId = reader[0].ToString();
int rank = reader.GetInt32(1);
string srKey = string.Format("[{0}]{1}", t.Name, entityId);
var sr = new SearchResult(srKey, scope, entityId, rank);
result.Add(sr);
}
Use the source Luke
The full source code is here. This is "works on my machine" quality code, so use with care. In particular:
  1. It doesn't handle pluralisation or naming strategies
  2. I cast directly to SqlCommand without testing it. Works for me but..
  3. It's not solidly tested. I only use it for one table so it may do funny things with other table structures.
  4. While running the code for the first time, the office power failed and the entire building went dark. I'm not saying it's related, but if it happens to you, you are on your own.
Things for MindScape to do
Provide a GetMyBloodyTableName and GetMyBloodyKey helper methods. Pretty please.