Jane Dallaway

Jane Dallaway

Jane Dallaway  //  Service Delivery manager, photographer, dog owner, gardener, reader, learner, software developer and occasional snowboarder

This blog contains all sorts of bits and bobs, from development related stuff, through process and productivity stuff, to photography stuff, and general inspiration things. It's a bit all over the place with no real theme, but then so am I

Email: jane @ dallaway.com
Also at:    

Reviewing a document via the kindle

Another one for the "note to self" file.

Richard asked me to proof-read a review of a book he'd written.  He sent it to me as a RTF document directly to my kindle via the free.kindle.com email address.  

I found a few spelling mistakes, some grammar issues and some bits which didn't scan/parse as well as they could.  I initially started making notes against them, but realised that without context these were useless, so started highlighting the relevant text too.  Highlights and Notes are stored in date order, with the most recent at the end of a file, which means that to get this right, the order needs to be:

  • Highlight the text to give the comment context
  • Make a note about the thing that is spelt wrong or whatever

As I hadn't done this, I needed to edit the clippings afterwards in a text file which was time-consuming and painful, and the main reason why I've written this as a blog post.

The clippings for all books can be found on the My Clippings.txt in the documents folder on the Kindle (or at least they can when mounted on a mac).  This is a text file which contains information like:

==========
<File Name> (<author name>)
- Highlight Loc. 14 | Added on Friday, December 31, 2010, 04:23 PM


<highlighted text>
==========
<File Name> (<author name>)
 - Note Loc. 14 | Added on Friday, December 31, 2010, 04:24 PM

<contents of note>

I needed to go through this file after I'd read the review and match up the Highlight with the Note and re-order.  Definitely something to avoid next time, or to find/write a macro/script to help with

Filed under  //  nts   reading   tool  

Comments (1)

Getting highlights and notes from kindle to text file

I've just finished reading ReWork: Change the Way You Work Forever (which is very good by the way) by Jason Fried, David Heinemeier Hansson and used the kindle app on my iPhone to do so.  As I read I highlighted some bits, and added notes to others.  This was great functionality, and at least I could see those notes using the kindle website.  

Highlights
Prior to using this app, when reading a book and making notes, I've been using toodledo to store them in.  That way I can read them using the appigo notes app or the toodledo app.  Ideally I wanted to get my notes/highlights from this book into toodledo to join them.  A quick google led me to the NoteScraper applescript script which exports highlights into evernote.  I don't use evernote much anymore, but still have it installed, so fired it up, went to the kindle site, navigated to the page containing my highlights and notes for ReWork and ran the script.  

Choosehowtostore
Because I want to get one text document for all my highlights and notes, I choose "All notes in one" at the first dialog box.  I enter "kindle" as the name of my notebook, and chose default tags from the next two dialogs.  When the script is completed, I'm left with all the notes and highlights for a book in an evernote note, which is easily copy and pasteable into a text file, or into toodledo notes.

Update: Whilst this worked, it wasn't ideal, so I rolled my own (Mac OS based - uses applescript)

Filed under  //  nts   reading  

Comments (0)

TSQL: Escaping % in a SQL Like clause

Today I had cause to search a text field in a SQL Server 2005 database for the phrase %3 (I had some data being url encoded incorrectly) and this wasn't something I'd tried to do before so I had to find out how to escape the % sign.  A quick google and a re-read of the LIKE syntax, and I discovered that to escape the % I had to do something like

WHERE [Value] LIKE '%!%3%' ESCAPE '!'

After talking this through with a colleague, he asked me to try some other escape characters, and here's what we found out:

Attempting to use a string as an escape phrase, i.e.

WHERE [Value] like '%WORD%1%' ESCAPE 'WORD'

doesn't work, and fails with an error of

 

Msg 506, Level 16, State 1, Line 1

The invalid escape character "WORD" was specified in a LIKE predicate.

 

Attempting to use % as the escape character, gets it quite confused 

WHERE [Value] like '%%%1%' ESCAPE '%'

returns 0 rows, but no errors

 

Attempting to use ' as an escape character, which needs to be escaped itself 

 

WHERE [Value] like '%''%1%' ESCAPE ''''

returns the correct rows

Filed under  //  SQLServer   nts  

Comments (0)

SQL Server Execution Plans - what should I look for in SQL Server 2005?

I've spent some time today reviewing the query plans for my current project, and as ever I keep forgetting what I'm trying to get to.  I found this useful page which reminded me of the orders - from best to worst:

  1. CLUSTERED INDEX SEEK - Very fast and efficient - the table is physically ordered according to specified column(s) and SQL can go find it AND since all of the data is phsically ordered right, can pull the data sequentially
  2. INDEX SEEK - which is very fast and efficient.  The SQL server knows pretty much where the data is and can go directly to it and seek out the rows it needs.  The data isn't ordered in the DB by the fields in the index so it's likely not pulling the data sequentially like it is in the CLUSTERED INDEX SEEK, but it can still translate to a massive improvement in query execution cost/speed.
  3. INDEX SCAN - which as you can see still implies using the index, but it doesn't know exactly where the data is, so it may scan the whole index or a partial range of the index to find it's data. Can be very slow and costly, but still scans through the index as opposed to scanning the physical table. 
  4. CLUSTERED INDEX SCAN - a clustered index is really not much more than a table with the data physically ordered by specified columns.  So if you see a CLUSTERED INDEX SCAN, it's pretty much the same as a TABLE SCAN for performance because SQL has to physically search through every single row in the clustered index (which really IS the table).  
  5. TABLE SCAN - slow, inefficient.  SQL has to physically look at every single row in the table. Shouldn't see this often, if you do, you may need to rewrite something or add indexes.

I've managed to remove all the scans, and everything is now at least using a seek.

Filed under  //  SQLServer   nts  

Comments (0)

Generating the SQL equivalent of Guid.Empty

I've been refactoring one of our projects today, and one of the areas I've been working on has been reducing 5 or 6 similar stored procedures into 1 more generic version.  In doing this, I've had to add a couple of nullable parameters, one of which is a GUID.  

If it is specified, then I need to set an AssignedToUser column to be the GUID, and I also need to record the date of the assignment.  I can do this all within the UPDATE statement, but I needed to only affect the assignment date when the GUID is specified.  Enter the ISNULL function, but what do I set my default value to when it is null? I really wanted to create a known GUID without hardcoding a fixed GUID - a SQL equivalent of Guid.Empty.  A quick bit of googling and I came up with

SELECT CAST(CAST(0 as BINARY) AS UNIQUEIDENTIFIER)

which evaluates to 

00000000-0000-0000-0000-000000000000

Job done, and recorded here so I can find it next time I need it

Filed under  //  SQLServer   nts  

Comments (1)

Outlook macro to forward an email to Toodledo and then file it

I've recently been having problems with a sore left wrist (not my mouse hand, my Ctrl+C,Ctrl+V hand) and have been assessing what some of my recurrent activities are.

Madgex have bought an ergonmic keyboard for me to use, and have had the lovely people from Posture People in to assess my workstation/posture (my monitors were too far away, my mouse wasn't in the right place, my seat wasn't supporting me properly and I wasn't sitting correctly (think of a seated tadasana)). My new keyboard comes with the concept of Favourites, i.e. quick launch buttons to start frequently used applications. This is a good idea, and got me thinking about other recurrent activities that I could program either a button, or a macro to do.

One of my regular activities, as I've mentioned before, is forwarding emails to toodledo for adding to my task list for tomorrow. I do this by sending the email to a unique address, and editing the subject line to include:
@@work - i.e. give the task the context of @work
#tomorrow - i.e. give the task a due date of tomorrow
*Actioned - i.e. put the task in the folder named Actioned
I then move the email to a subfolder of my Inbox named Actions

I figured that I could write a macro to do this, so with a bit of help from here and there, I got the following macro working. I've named the project "SendTo", so the macro is called as "SendTo.Toodledo" and I've added a shortcut to my menu bar to this macro. It works on a single email at a time, which suits my process - I try and read the email before deciding whether it needs to be actioned or just filing straight away.

Sub Toodledo()
'Forward the selected email to Toodledo, updating the subject with the appropriate shortcuts and move to appropriate folder
On Error Resume Next

  Dim objMail As Outlook.MailItem
  Dim objItem As Outlook.MailItem

        Set objItem = GetCurrentItem()
  Set objMail = objItem.Forward

    objMail.To = "<toodledo email address goes here>" 'my toodledo email address
  objMail.Subject = "Respond to " + objMail.Subject + " @@work #tomorrow *Actioned" 'Prefix with Respond to, and append context of @work, date of tomorrow, and folder of Actioned
  objMail.Send

    Call MoveMessageToFolder(objItem, "Actions") 'move it to my Actions folder

    'clean up
  Set objMail = Nothing
  Set objItem = Nothing

End Sub

Private Function GetCurrentItem() As Outlook.MailItem
'Taken from code sample provided at http://www.pcreview.co.uk/forums/thread-2798274.php
On Error Resume Next

    Dim objApp As Outlook.Application
  Set objApp = Application

    On Error Resume Next

    Select Case TypeName(objApp.ActiveWindow)
    Case "Explorer"
      Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
    Case "Inspector"
      Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
    Case Else
  End Select

    'clean up
  Set objApp = Nothing
End Function

Private Sub MoveMessageToFolder(objItem As Outlook.MailItem, ByVal sFolder As String)
'Loosely based on code found at http://verychewy.com/archive/2006/04/12/outlook-macro-to-move-an-email-to-fol...
On Error Resume Next

  Dim objFolder As Outlook.MAPIFolder
  Dim objInbox As Outlook.MAPIFolder
  Dim objNS As Outlook.NameSpace

  Set objNS = Application.GetNamespace("MAPI")
  Set objInbox = objNS.GetDefaultFolder(olFolderInbox)
  Set objFolder = objInbox.Folders(sFolder)

  If objFolder Is Nothing Then
    MsgBox "This folder doesn't exist!", vbOKOnly + vbExclamation, "INVALID FOLDER"
  End If

       objItem.Move objFolder

     'Clean up
  Set objFolder = Nothing
  Set objInbox = Nothing
  Set objNS = Nothing
End Sub

There isn't anything very clever going on here, but having written it, it may just help someone else.

Note: I then had to sign my macro to ensure that this started successfully without warnings on subsequent starts of outlook

Filed under  //  code   nts   productivity  

Comments (0)

NTS: App_Offline.htm and working around the "IE Friendly Errors" feature

Yet another in the note to self category.

When using App_offline.htm files to take down a site in IIS, if the file size isn't 512 bytes of content or greater then IE may choose to default to the "Show Friendly Http Errors". Comments count towards the byte size so client side comments will work too.

There is more about this at ScottGu's blog

Filed under  //  .NET   howto   nts  

Comments (0)

NTS: The HTTP verb POST used to access path '' is not allowed

Another for the Note To Self list

A lot of our sites use a url mapper, so when setting up the sites within IIS we map extension .* to the appropriate aspnet_isapi.dll.

I'd got carried away when setting up the webservice and did the same thing, resulting in a The HTTP verb POST used to access path '/WebService/WebService.asmx/DoSomething' is not allowed. error. Removing the .* mapping fixes this.

Filed under  //  .NET   nts  

Comments (0)

NTS: InstallUtil and parameters

Definitely under the note to self category this one...

I've been working with installing a service and took the base code from our platform. Part of the command line specifies a parameter to be used within the installer, but no matter what I did I could not get the parameter to be picked up.

An example of the installation command line is
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installUtil.exe" "C:\Services\MyService.exe" /SERVICENAME="My Special Service"
which, at least in theory, allows the service to be created so that in the Services dialog it is listed under the name "My Special Service"

A quick google with the right keywords and I stumbled across The curious case of InstallUtil and service parameters which both explains the situation and provides a lovely working solution.

In my case, the code was even simpler than the example as I was specifically looking for only one parameter, the service name, and so my OnBeforeInstall and OnBeforeUninstall become

protected override void OnBeforeInstall(System.Collections.IDictionary savedState)
{
   base.OnBeforeInstall(savedState);
   SetServiceNameFromCommandLineParameter();
}

protected override void OnBeforeUninstall(System.Collections.IDictionary savedState)
{
   base.OnBeforeUninstall(savedState);
   SetServiceNameFromCommandLineParameter();
}

where SetServiceNameFromCommandLineParameter is :

void SetServiceNameFromCommandLineParameter()
{
   const string SERVICE_NAME = "SERVICENAME";

   String[] args = System.Environment.GetCommandLineArgs();
   String no_log_file = null;
   InstallContext tmp_ctx = new InstallContext(no_log_file, args);

   string serviceName = tmp_ctx.Parameters[SERVICE_NAME];

   if (serviceName == null)
   {
      throw new ApplicationException(string.Format("{0} undefined", SERVICE_NAME));
   }

//Set service name
   this.serviceInstaller1.DisplayName = serviceName ;
   this.serviceInstaller1.ServiceName = serviceName;
}

where serviceInstaller1 is defined as private ServiceInstaller serviceInstaller1;

As to why this works in the base code, but doesn't for mine I have no idea, but I have at least got it working now

Filed under  //  NET   nts  

Comments (0)

SQL Server 2005 restore error message

This is definitely a note to self, as I'm sure to have this happen again. I received the following error message this morning when attempting to restore a database

Msg 3219, Level 16, State 3, Line 2
The file or filegroup "MyDB_log" cannot be selected for this operation.

using script similar to the following

RESTORE database [MyDB]
FILE = N'MyDB' ,
FILE = N'MyDB_log' ,
FROM disk = N'C:\MyDB_backup.bak'
WITH FILE = 1,
MOVE N'MyDB' TO N'c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\MyDB.mdf',
MOVE N'MyDB_log' TO N'c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\MyDB.ldf',
NOUNLOAD, REPLACE, STATS = 10
GO

To fix this, I simply removed the lines starting with FILE and ran it again. Success! So the final, working script was

RESTORE database [MyDB]
FILE = N'MyDB' ,
FILE = N'MyDB_log' ,
FROM disk = N'C:\MyDB_backup.bak'
WITH FILE = 1,
MOVE N'MyDB' TO N'c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\MyDB.mdf',
MOVE N'MyDB_log' TO N'c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\MyDB.ldf',
NOUNLOAD, REPLACE, STATS = 10
GO

Filed under  //  SQLServer   code   nts  

Comments (0)