Category : Development

Remote Control via Twitter

twitter_logo Twitter is one of those applications / services that I’ve had trouble getting to grips with. For me it seems it’s like shouting about what you are doing right now to a huge audience that is not listening. Who really cares that @kjhughes is heading to the shops to get some Mint sauce ?? Maybe I’m just not that kind of social animal, maybe I don’t have enough friends using it, maybe I should ‘but in’ to other peoples conversations more, maybe I’m just plain boring…

I do see a use for it though (for me). It’s a pretty neat way to do some remote control stuff – like set up a Media Center recording, reboot my PC, and also it’s a neat way of getting updates, like new blog comment received, TV recording completed and the like….

So, right now I need to get my Outlook addin project completed, but right afterwards I’m planning an app that interfaces to twitter and accepts direct tweets as remote control instructions, and also can update me on specific events. I am also thinking about adding twitter alerts to dasBlog (on comments, posts, errors, daily reports etc)

I can see myself getting immersed in this twitter thing…

GEO 51.4043197631836:-1.28760504722595

Subclassing Windows in C#

image I’ve been toying around with creating an Outlook addin recently that adds a new panel to the main Outlook inspector window. Actually it is going to be a ‘folding’ or ‘collapsing’ windows similar to the docked ToolWindows in Visual Studio.image

Anyway, the stuff around getting the correct window handle for the Outlook inspector window and resizing it to allow some space to insert my new panel was fairly simple, but I also had to hook into the message look of the window so that I could capture any move or resize messages and so resize things again to accommodate my panel.

I had started developing it as an Outlook add-in but to speed things up (and prevent me having to register / unregister the addin between tests etc I decided to develop it as a separate app- I could still hook into Outlook and move things around.

The problem came when I was trying to hook the inspector window message loop – it didn’t seem to work. I fired up Spy++ and check that the inspector window was getting the messages – which it was – but they were never getting delivered to my hook code.

I was using System.Windows.Form.NativeWindow and overriding the WndProc function (see my NativeWindowListener class below). To get the hook in place I was creating a new NativeWindowListener class with the inspector window handle as the parameter. Checking the handles and the delegates etc it all seemed to be correct, I just couldn’t fathom why it wasn’t getting any of the messages.

Then the penny dropped. Outlook is in a separate process… (NativeWindow only works across the current process and window handles that are contained in it). What would be needed in this case is a system wide hook, that requires use of the Win32API and interop. I reckon this is overkill just to save a bit of development pain, so will probably move to something where the Outlook addin dynamically loads the panel in and make something available to have the add-in reload the panel – this should allow me to develop the panel code (the majority of the app) without worrying to much about the Outlook addin side of things.

using System;
using System.Windows.Forms;
using System.Text;

namespace Outlook_Subclasser
{
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
internal class NativeWindowListener : NativeWindow
{

    // Constant value was found in the "windows.h" header file.
    private const int WM_SIZE = 0x0005;

    public NativeWindowListener(IntPtr handle)
    {
        AssignHandle(handle);
    }

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
    protected override void WndProc(ref Message msg)
    {
        switch (msg.Msg)
        {
            case WM_SIZE:
                // do your processing in here
                break;

            default:
                break;
        }
        base.WndProc(ref msg);
    }
}
}

and then to use the class you would find the handle of the window you want to subclass and create a new NativeWindowsListener passing in that handle to the constructor. Note – this does not cover a number of aspects around releasing handles etc – you will want to make sure these are covered off…

MyForm myForm = new MyForm();
NativeWindowListener nwl = new NativeWindowListener(myForm.Handle);

 

GEO 51.4043197631836:-1.28760504722595

SMS Gateway follow up

I’ve had a lot of interest in my SMS Gateway app since this post. SMS gateway consist of two components :

SMS Gateway Addinimage
This is an Outlook addin that adds a new toolbar to your Outlook instance. The toolbar allow the user to choose a mobile / cellphone number (from their contacts) and enter a message. When they hit the enter key after the message (or click ‘Send’) a new Task is created when has a subject of ‘SECRETCODE’ and the mobile / cellphone number and the details being the text of the message.

At some stage this Outlook Task is synchronized (over ActiveSync / Direct Push) to a Windows mobile device…

SMSGateway
This is a small app running on a Windows Mobile device that every 15 seconds checks through the tasks. If it finds any tasks that have a subject beginning with SECRETCODE then it parses out the mobile / cellphone number and sends the message text (from the Task details) to that mobile / cellphone number via SMS. Note: the SECRETCODE word is configurable.

imageWhy develop this ?
The purpose of this app was really to allow me to send SMS messages easily from Outlook without having to sign up for (and pay for) a web to SMS service (I already get 100’s of free SMS messages with my mobile / cellphone package).

The application is free for anyone to use (drop me a line – in the comments – if you do use it…)

Windows Mobile CAB file (copy the file to your Windows Mobile device and click on it) : SMSGatewayMobile.CAB
Setup file for the Outlook 2003 Add-in (Outlook 2007 coming soon) : SMSGatewayAddin2003.msi
Source for both the applications : SMSGateway.zip (includes test Outlook 2007 addin code)

I’d be really interested to hear from anyone using this…. post in the comments…

GEO 51.4043197631836:-1.28760504722595

SMS Gateway using WM6 and ActiveSync

image

Recently I have wanted to be able to send SMS messages to my contacts without having to pick up my phone and mess around with the mini keyboard (I wanted to do it directly from PC, but have the message still send by the phone…

There are solutions around that allow you to send a SMS from a form on a web page, but these are generally paid for services or limited to XX messages per day – I have a mobile contract with unlimited texting, so why would I want to pay for another service, and I didn’t want to be limited in the volume of texts I can send per day. there are also solutions around that require the device to be docked / plugged into the PC, I didn’t like this either as it’s just too much hassle (and therefore I never do it)…

So I came up with a simple but effective solution that makes use of ActiveSync / push email technology that is built into Windows Mobile devices.

Basically I wrote an Outlook Addin that allows me to choose a contact from a drop down list, type in the message and “send” it – when I say “send” it, what I mean is the request is transferred to the WM6 device which then sends the actual SMS message.

image

So it goes like this :-image

  • User chooses the contact from a  drop down list of all contacts with mobile numbers.
  • User enters the text of the message
  • User clicks send
  • Outlook Addin creates a new task with a secret keyword followed by the mobile number as the subject and the message in the body of the task.
  • (after a few seconds) the new task is synchronized to the WM6 device via push email / ActiveSync
  • WM6 device regularly checks the tasks list for a task with a subject that starts with the secret keyword
  • The subject line is parsed to get the mobile number the text is to be sent to
  • The body is parsed to get the text of the message
  • A SMS message is send from the WM6 device.
  • The new task is deleted (or marked as complete)
  • The change to the task (delete or marked as complete) is synchronized back to the PC via ActiveSync / push email.

I’ll have more details, the installers and all the source code available next week…

 

UPDATE: See the follow up to this article here which includes binary files and full source code.

 

GEO 51.4043197631836:-1.28760504722595

 

Is agile an excuse for sloppy project management

I was listening to one of Scott Hanselman’s podcasts this morning and Scott made a comment about people thinking that agile methodologies were and excuse for sloppy project management (NOTE: Scott wasn’t of this opinion, he just stated that some other people thought this).

I am fully bought into SCRUM, and whilst we don’t implement if fully at work (we have our own handcrafted way of doing it that really works well for us) I think it brings great benefits.
One of the real stumbling blocks with people adopting SCRUM / Agile is getting over the mind set that they can determine the delivery dates and that they can force the development team into delivering everything they want by that date. I truly do not believe that it is possible to fix both scope (requirements) and timescale (delivery dates) in a software project, even having done lots of design up front. I have written before on the perils of this approach…

Giving up all control of dates is something that takes quite a psychological leap of getting used to, but when you are there, you see all the benefits. Let me give you an example…

abbeyroad Think of The Beatles.
Their ‘products’ were (obviously) their songs, they were all passionate about what they were doing (providing great music to the masses) and they did it really well – everyone loved their product.
When Lennon and McCartney (and Harrison) sat down to write a song, if they’d had a limited time then the quality would have suffered. They were not limited in time and they produced great things.

That is one of the things you have to accept in agile – crafting great software products is an skill and an art, for the developers sometimes their creative juices flow in abundance, sometimes they don’t.
To meet strict timescales, something has to give, and that something is scope (or quality, but you don’t really want that do you ??…)

GEO 51.4043197631836:-1.28760504722595

Redirector HttpModule

imageOriginally I had my website set up to default to my blog (so dasBlog was installed at the website root level instead of in a /blog subfolder).

Recently I have been writing some Web Applications and wanted to restructure my website so that there is a subfolder for each app / main area (blog, projects, etc).

The problem being that all the links out there point to http://kapie.com/2007/12/19/RedirectorHttpModule.aspx and these would all be dead link when moved to http://kapie.com/2007/12/19/RedirectorHttpModule.aspx, so I needed to respond with a HTTP 302 to the original links and tell the client that it should temporarily redirect to the new location (changing to a HTTP 301 when I am happy that it is all working).

This called for a HttpModule…

namespace KSL
{
     public class BlogRedirector : IHttpModule
     {
VisualStudioLogo         private EventHandler onBeginRequest;

public BlogRedirector()
{
onBeginRequest = new EventHandler(this.HandleBeginRequest);
}

void IHttpModule.Dispose()
{
}

void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += onBeginRequest;
}

private void HandleBeginRequest( object sender, EventArgs evargs )
{
HttpApplication app = sender as HttpApplication;

if ( app != null )
{
HttpContext context = app.Context;
string host = app.Request.Url.Host;
string requestUrl = app.Request.Url.PathAndQuery;

if (requestUrl.Contains(@”/blog/”)
|| requestUrl.Contains(@”/foo1/”)
|| requestUrl.Contains(@”/foo2/”)
|| requestUrl.Contains(@”/foo3/”)
|| requestUrl.Contains(@”/foo4/”)
|| (requestUrl.ToLower() == app.Request.Url.Scheme + @”://” + host + @”/default.aspx”))
{
return;
}
else
{
Uri newURL = new Uri(app.Request.Url.Scheme + @”://” + host + @”/blog” + requestUrl);
context.Response.RedirectLocation = newURL.ToString();
context.Response.StatusCode = 302;
context.Response.End();
return;
}
}
}
}
}

 

This basically allows me to redirect any url that does not contain /blog/ or /foo*/ or is not /default.aspx by sending a 302 status code and adding /blog/ to the url to generate the redirect url. The compiled DLLs were stored in the bin folder off the root and the web.config in the root needed the following adding…

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpModules>
      <add type="KSL.BlogRedirector,BlogRedirector" name="BlogRedirector" />
    </httpModules>
  </system.web>
</configuration>

 

This seemed to work fine some of the time, but was a bit hit and miss…. Further investigation pointed me at the web.config files in the subfolders and that they would inherit the sections from the root web.config. So all the subfolder web.config files got the following added.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpModules>
      <remove name="BlogRedirector" />
    </httpModules>
  </system.web>
</configuration>

 

GEO 51.4043197631836:-1.28760504722595

Too many hex calculators around

Just recently we have been interviewing for a new developer.

I have found it incredulous, the amount of people with considerable experience that cannot do hex / dec conversions. One of the things we do during an interview is to have people write code – this is normally a short 10 minute test where we give them an app with one function that converts a hex string to decimal, we ask them to refactor the function so that it no longer using the API call to do the conversion (they have to do it themselves in code).

We go to great lengths to make sure we have explained the task correctly, sometimes we prompt them earlier in the interview with a questions about converting – ‘What is 16 represented in Hex, what is 30 hex in decimal etc). We even provide a working application and allow them to play with it for a few minutes to familiarize themselves with it’s intent and operation.

The task is designed to show us the coding style of the candidate, but we’ve found that instead of looking at their code we’re looking at blank pages – there seems to be a glut of people (at least, that I am interviewing) that don’t even know how to start. We’ve had people simply stare at us blankly, people just sit and twiddle a pencil, people get flustered and simply say ‘I cannot do it, sorry’

Are we just getting below average or unsuitable candidates or have people forgotten this skill (working in number systems other than base 10). Have today’s development tools abstracted all this low level stuff away so much that people just don’t need it anymore (and therefore have teaching institutes stopped covering it) ??

GEO 42.2814047728377:-71.5726983547211

GeoRss for dasBlog

I have completed stage one of GeoRss enabling dasBlog.

In the config page I added some options for enabling GeoRss, specifying a default lat/long and enabling ‘integration’ with Google maps. There is also an option to use the default lat/long for any non geocoded posts.

  clip_image0022_thumb1

If GeoRss is enabled then the edit entry screen provides textboxes to allow specifying lat/long (populated with defaults from config page).

clip_image00421_thumb2

If the google maps integration is enabled then you’ll get the ‘Show Map’ button and clicking it will display a map which you can move around until you find the location and then click on the location to get the lat/long texboxes populated.

clip_image00681_thumb1

If you have existing non geocoded posts then you can have the default lat/long added to those if you wish.

I puzzled around for ages when trying to display the georss in google (http://maps.google.com/maps?q=yourfeedaddress) – it kept telling me that the feed was invalid. I eventually found that feedburner was adding <atom10:link blah blah /> to the xml which for some reason google maps thinks is invalid. The only way I could find to prevent feedburner adding the atom link was to turn OFF the ‘Browser Friendly’ feature in feedburner.

So – stage 2…

The work I still want to do with this is basically to add macros to get lat/long  – fairly easy I guess, and then some way to specify lat/long from Windows Live Writer (and other offline blog clients) – a little more complex. Scott mentioned a geo microformat and from my initial looks seems to be a good route to take – watch this space…  

Now it is simply a case of retrofitting the geo info into all my old posts…

 

Mix UK using social networking tool

Mixuk I registered for Mix:UK a few weeks ago and today got an email from the Mix team about a social networking tool they are using to help people make the most of the conference.

backnetworkThey are using backnetwork, which allows creation of profiles, blogging, photos, adding friends / colleagues etc (all the usual social networking stuff). It also allows you to add any colleagues / friends automagically from any previous backnetwork events you have been to.

 This is certainly a step in the right direction, but it’s missing an ‘auto-suggest relationship’ feature that could analyze your profile (or tags) and suggest other people who have similar interests.

So… my profile is here, anyone interested in any of my tags feel free to contact me and set up a meeting/chat/lunch/coffee/whatever…

MSCRM Importing Does Not Honor Create Dates

Some of the code I have for importing data (from ACT! 2000) to MS CRM creates new ‘PhoneCall’ activities / objects. The problem is, that it seems MSCRM does not allow you to programmatically modify the ‘create date’.

Here is the code I use…

phonecall pc

            CrmDateTime start = new CrmDateTime();

            start.Value = DateTime.Parse(“10/08/2005 12:30”);

            pc.actualstart = start;

            pc.scheduledstart = start;

            CrmDateTime end = new CrmDateTime();

            end.Value = DateTime.Parse(“10/08/2005 14:30”);

            pc.actualend = end;

            pc.scheduledend = end;

            pc.subject = “Phone call regarding sales of Widgets Q2/2005”);
***

            string desc =  “Start    : “ + pc.actualstart.Value + “n”;

            desc += “End       : “ + pc.actualstart.Value + “nn”;
***

            desc += “The details of the phone call go in here”);

            pc.description = desc;

            pc.regardingobjectid = new Lookup();

            pc.regardingobjectid.type = EntityName.contact.ToString();

            Guid contactGuid = new Guid(guidOfContactWeTelephoned);

            pc.regardingobjectid.Value = contactGuid;

The actualstart and scheduledstart (and ends) get populated with the current datetime (this seems to happen if the time they are set to is in the past).

Note the two lines between the ***’s – this is my solution / workaround and simply include the start/end times as text in the body/description of the phone call object.