27 Nov 2014

Lenovo ThinkPad T410 Fingerprint Reader stopped working after update

Did a long-put-off update on my Thinkpad with all its recommended Lenovo drivers from the ThinkVantage tool. All dandy, apart from the fingerprint reader stopped working. It used to have a little green light on to show it was ready, now it was off in sleep mode.

Simple solution: Go to Device Manager > Biometric Devices > TouchChip Fingerprint Coprocessor > Properties > Power Management and untick the "Allow the computer to turn off this device" option.

18 Nov 2014

Remote Desktop connection failed

Couldn't connect via RDC via an RD Gateway. Tried all sorts but in the end tried going into Device Manager, showing all hidden devices, and removed all the ISATAP virtual tunneling adapters that various Virtual Machines had added. It worked!

22 Oct 2014

Installation Ended Prematurely - MVC Hotfix MS14-059

Just had a scary moment when a production MVC application went down due to MS Updates removing the MVC 3.0.0.0 dll and replacing it with MVC 3.0.0.1.

Although we located the MS Hotfix (MS14-059), the installer gave us a worrying "Installer Ended Prematurely" error.

The solution was simple - the server needed a reboot to allow it to install some pending updates before the Hotfix could be run.

21 Oct 2014

VBScript / Classic ASP value equivalency crib sheet


DBNULL VALUE

Equivalent to: NULL

ZERO VALUE 

Equivalent to: FALSE

STRING NUMBER VALUE (e.g "0")

Equivalent to: NUMBER VALUE (but STRING ZERO is not FALSE!)

EMPTY VALUE / UNDEFINED VALUE / UNPROVIDED REQUEST VALUE

Equivalent to: FALSE (but not NULL!)

EMPTY STRING ("")

Not equivalent to FALSE, EMPTY, ZERO or NULL!


NOTE: If you compare NULL with anything, it just returns NULL, not TRUE/FALSE

NOTE: While 0 is equivalent to FALSE, 1 is NOT equivalent to TRUE


19 Sep 2014

A simple script for scheduled Access DB backups

Here's a simple wee backup script to save as a VBS file (e.g. backup.vbs) and then run from Windows Task Scheduler.

Saves a copy with a datestamp in the filename e.g. Data_2014-09-07.mdb

Dim oldfilePath
Dim newfilePath

oldfilePath = "C:\LivePath\Data.mdb"
newfilePath = "D:\Data_Backups\Data_"

newfilePath = newfilePath & datepart("yyyy", date()) & "-"
newfilePath = newfilePath & Right("0" & DatePart("m",Date), 2) & "-"
newfilePath = newfilePath & Right("0" & DatePart("d",Date), 2) & ".mdb"

Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")

fso.CopyFile oldfilePath, newfilePath, true

Set fso = Nothing
 

25 Aug 2014

Adding a Clear Filter / Clear Search Button to DataTables

I wanted a generic way to add a "clear filter" button to the text filter on all the DataTables on a site.

One way would be to change the input type of the filter to "search" - then HTML5 browsers will automatically show a clear widget. However, you'd have to press return after clicking it, so I wanted a one-click solution.

Here's what I came up with. It works with DataTables 1.9.


// Setup DataTable Defaults
$.extend( $.fn.dataTable.defaults, {
 fnInitComplete: function(oSettings, json) {

  // Add "Clear Filter" button to Filter
  var btnClear = $('<button class="btnClearDataTableFilter">CLEAR</button>');
  btnClear.appendTo($('#' + oSettings.sTableId).parents('.dataTables_wrapper').find('.dataTables_filter'));
  $('#' + oSettings.sTableId + '_wrapper .btnClearDataTableFilter').click(function () {
   $('#' + oSettings.sTableId).dataTable().fnFilter('');
  });
 }
});

16 May 2014

A ValueInjecter Injection that ignores null values

Want to use ValueInjecter but don't want to copy null values into your model?

public class NoNullsInjection : ConventionInjection
{
    protected override bool Match(ConventionInfo c)
    {
        return c.SourceProp.Name == c.TargetProp.Name
                && c.SourceProp.Value != null;
    }
}

Usage:

target.InjectFrom(new NoNullsInjection(), source);

15 Apr 2014

Access MDB activity causes Visual Studio 2012 "File Modified Outside Environment" warning

I've found a way to stop this when it starts. Close VS2012 and delete your Visual Studio solution's (hidden) SUO file, which you will find with the SLN file.

10 Feb 2014

Classic ASP FPDF creates TMP files in folder

Weird little problem just now - a classic ASP (vbscript) page used FPDF to generate PDF files. All working fine but weirdly, the script seemed to be generating TMP files in its directory - one for each PDF generated.

Took a while to figure out, but turned out that the IIS user account had WRITE permission on the folder but not MODIFY. Once MODIFY was added, the TMP file problem went away. Small victories...

6 Feb 2014

Lottie Dexter (Year of Code) and Jeremy Paxman on BBC Newsnight 5 Feb 2014

Okay, just finished watching this debacle and want to reel off some thoughts. Venty venty.

I guess it must be true for any skilled worker that when journalists cover your area of expertise, your hackles rise and you begin to wonder what basic stuff is being misunderstood and misrepresented by those journalists in all the other articles you've ever read on other subjects. Fair enough, journalists are generalists - they can't be expert in everything. However, the computer industry must be one of the last ones where a journalist can describe your passion and life's work as "baffling ... gobbledegook" and then dismiss it with a "it doesn't mean anything!". Both of those conclusions were drawn by Jeremy Paxman and Zoe Conway on Newsnight tonight regarding what they termed "code", as they were discussing the current "Year of Code" initiative. I'm surprised they can be so clueless and dismissive regarding computer code; would they take a cursory glance at the work of physicists, doctors and mathematicians and dismiss it simply because they don't understand it?

On the other hand, in many ways you'd be right to be dismissive regarding the basic premise being purported by Lottie Dexter, director of the Year of Code initiative. She did a very bad job of explaining either "code" or why and how it should be taught to young people. Most baffling of all is why she continued the lie that computer programming is something you can learn quickly ("in a day"!), while also admitting that she doesn't know how to program at all herself. Facepalm.

Regarding the "why teach code to 5 year olds" question, I'm not surprised that she had a hard time answering questions. My answer would be "don't". People who code tend to be natural problem solvers who enjoy working with abstract concepts (some people think strong mathematics ability is a requirement but that's not necessarily true). I'm of the opinion that *most* people don't fit that profile. But also, the article kept stressing that in the future we will all need to code to be useful in the knowledge economy. You could have made that point twenty years ago, but people today don't need to code on a daily basis. Hell, I wouldn't need to write software if it wasn't my actual job - why does everyone suddenly need to start writing javascript?

We don't teach Mandarin, Chemistry or A-level maths to five year olds because we realise that a) they're hard subjects, and b) not everyone will need those skills. Computer programming is in the same league. We save these skills to be taught later when people start to become aware of their strengths and interests. So I'm all in favour of teaching good coding skills in schools, but only to the students that want to learn. Teaching coding across the board just seems bizarre.

Watching the segment again on iPlayer (link - starts at 17:50), the implications of this "coding" requirement entering the curriculum in primary schools from Sept 2014 began to sink in. Teachers will surely need a lot of support in getting up to speed with this, and kids aren't going to be able to learn "code" without using a computer directly - most primary schools I know only have one computer per class. I agree with Clive in the comments below that we could be teaching broad problem solving concepts without a computer. However this initiative whiffs of sophistry and lip service from the government. I sincerely hope these lessons won't be rote "copy out the code block into the box and press RUN" exercises, but I expect to be disappointed...

27 Jan 2014

PostCode Anywhere, JSONP and IE7 Cross Domain problems

First off, let me say that I like Postcode Anywhere (PCA), they're a great service.

Today I had to fix a bug with a site using PCA's Bank Account Validation. It was working great generally, but failing for IE7.

IE7! The bane of my life! It doesn't use CORS, doesn't even use IE8's crappy XDomainRequest object. It just plain can't make an AJAX call to an endpoint on a different domain.

This was why the PCA ajax call was failing. I figured the only solution was to use JSONP. However the PCA JSONP docs seemed scant. I couldn't get a JSONP call to work until I got DevTools out and looked at what was being returned from PCA on the JSONP call - it was returning a nice javascript array OK but not wrapping it in a call to a callback function!

OK, here's the meat. To make a JSONP call on PCA, you need to provide an extra parameter to the call. I found this mentioned randomly on this page of the PCA site.

You can either supply CallBackVariable or CallBackFunction in the call querystring, and bob's yer uncle.

Here's my code to show you how I did it.



// Javascript for PCA Bank Lookup Demo
//
// Requires input fields on your page with the following IDs:
//   Bank_AccountNo, Bank_SortCode, Bank_Name, Bank_PayMethod
// For further details of the returned data from PCA, check the contents of the returned array
//  or RTFM here: http://www.postcodeanywhere.co.uk/support/webservices/BankAccountValidation/Interactive/Validate/v2/default.aspx

function LookupBankDetails() {

 var pcaLicenceKey = 'YOUR-KEY-HERE';

 // Note we don't specify HTTP or HTTPS, so it will use the protocol cuurently in play
 var serviceUrl = '//services.postcodeanywhere.co.uk/BankAccountValidation/Interactive/Validate/v2.00/json2.ws?Key=' + pcaLicenceKey;

 // Build the query string
 serviceUrl += '&CallBackFunction=LookupBankDetails_Callback';
 serviceUrl += '&AccountNumber=' + encodeURIComponent($('#Bank_AccountNo').val());
 serviceUrl += '&SortCode=' + encodeURIComponent($('#Bank_SortCode').val());

 $.ajax({
  url: serviceUrl,
  dataType: 'jsonp',
  type: 'GET',
  jsonpCallback: 'LookupBankDetails_Callback',
  error: function (error, data, type) {
   alert(data + ": " + type + "."); 
  }
 });
}

function LookupBankDetails_Callback(response) {

 if (response.length == 1 && typeof (response[0].Error) != "undefined") {
  // Show the error message
  alert(response[0].Description);
 }
 else {
  // Check if there were any items found
  if (response.length == 0)
   alert('Sorry, your bank\'s details could not be located');
  else {

   var jsonResult = response[0];

   if (!jsonResult.IsCorrect) {
    alert('Sorry, your bank\'s details could not be located');
   }
   else {
    $('#Bank_Name').val(jsonResult.Bank);
    $('#Bank_PayMethod').val(jsonResult.FasterPaymentsSupported ? 'Fast' : 'BACS');
   }
  }
 }
}

JQuery Conditional Validation (Yes, the official documentation sucks)

Venting! jQuery Validation is a great plugin but its documentation is crap! So much cool stuff is hidden away for want of decent docs. If enough of you agree with me, I might have to write some! Watch this space. 

Anyway, I just wanted to implement some conditional validation

i.e. MAKE INPUT 'A' REQUIRED ONLY IF INPUT 'B' HAS A VALUE

And so, given two inputs with IDs InputA and InputB, the code is:

    
$(function() {
 $('#YourForm').validate({
  rules: {
   InputA : { 
    required : '#InputB:filled'
   }
  }
 });
});

You can also do this inline in your form by using declarative syntax, which I have found bugger-all documenation on!
 
<input name="InputA" type="text" data-rule-required="#InputB:filled" />
<input name="InputB" id="InputB" type="text" />

Finally, when required status is dependent on something more complicated, you can throw in a function e.g.
 
$('#myForm').validate({
 rules: {
  InputA : {
        required: function (elem) {
              // InputA is required if InputB contains 'AmazingThingy'
              return $('#InputB').val() == 'AmazingThingy';
   }
  }
 }
});

8 Jan 2014

ADODB.Command error '800a0cc1' Item cannot be found in the collection corresponding to the requested name or ordinal.

If you get this error when you're doing classic ASP with an MS Access backend:

ADODB.Command error '800a0cc1' 
Item cannot be found in the collection corresponding to the requested name or ordinal.

And it doesn't make sense.... check that you haven't got that table open in Access. Doh! Stupid error message!
If I helped you out today, you can buy me a beer below. Cheers!