Author Archives: markn

About markn

Mark is the owner and founder of Timesheets MTS Software, an mISV that develops and markets employee timesheet and time clock software. He's also a mechanical engineer, father of four, and a lifelong lover of gadgets.

    Find more about me on:
  • googleplus
  • linkedin

Excel 2010 Date Bug

p>If you’re working with DateTmePickers on a VBA form in Excel 2010 be aware that there’s a fairly serious bug with assigning date values affecting the actual system time. For example the following code will change the system time of your PC to 1/1/1899!

  Date = DateSerial(1899,1,1)

This is a big security hole in Office 2010, at least on Windows7 x64 Professional (which is the only place I tested it on). Being able to change the system time so easily is ridiculous. Up until now I’ve had to set the system time from VBA (or VB6 for that matter) by making use of the SetSystemTime API function doing someting like this:

 Public Declare Function SetSystemTime Lib "kernel32" _
   (lpSystemTime As SYSTEMTIME) As Long
   
Public Type SYSTEMTIME
  wYear As Integer
  wMonth As Integer
  wDayOfWeek As Integer
  wDay As Integer
  wHour As Integer
  wMinute As Integer
  wSecond As Integer
  wMilliseconds As Integer
End Type

Public Type TIME_ZONE_INFORMATION
    Bias As Long
    StandardName(31) As Integer
    StandardDate As SYSTEMTIME
    StandardBias As Long
    DaylightName(31) As Integer
    DaylightDate As SYSTEMTIME
    DaylightBias As Long
End Type

Public Declare Function getTimeZoneInformation Lib "kernel32" _
    Alias "GetTimeZoneInformation" (lpTimeZoneInformation As TIME_ZONE_INFORMATION) As Long

Private Declare Function GetTimeZoneInformationAny Lib "kernel32" Alias _
    "GetTimeZoneInformation" (buffer As Any) As Long

Public Function GetTimeDifference() As Long
   Const TIME_ZONE_ID_INVALID& = &HFFFFFFFF
   Const TIME_ZONE_ID_STANDARD& = 1
   Const TIME_ZONE_ID_UNKNOWN& = 0
  
   Const TIME_ZONE_ID_DAYLIGHT& = 2
    'Returns  the time difference between
    'local & GMT time in seconds.
    'If the  result is negative, your time zone
    'lags behind GMT zone.
    'If the  result is positive, your time zone is ahead.
    
    Dim tz As TIME_ZONE_INFORMATION
    Dim retcode As Long

    Dim Difference As Long
    
    'retrieve the time zone information
    retcode = getTimeZoneInformation(tz)
    
    'convert to seconds

    Difference = -tz.Bias * 60
    'cache the result

    GetTimeDifference = Difference
    
    'if we are in daylight  saving time, apply the bias.
    If retcode = TIME_ZONE_ID_DAYLIGHT& Then

        If tz.DaylightDate.wMonth <> 0 Then
            'if tz.DaylightDate.wMonth = 0 then the daylight
            'saving time change doesn't occur
            GetTimeDifference = Difference - tz.DaylightBias * 60
        End If

    End If
    
End Function

Public Function LocalToUtc(ByVal vdtLocal As Date) As Date   
    Dim Differerence As Long
    Differerence = GetTimeDifference()
    LocalToUtc = DateAdd("s", -1 * Differerence, vdtLocal)
End Function

Public Function setSystemClock(datSet As Date) As Boolean
  Dim ST As modGlobals.SYSTEMTIME
  Dim datUTC As Date
  
  datUTC = modGlobals.LocalToUtc(datSet)
  
  With ST
     .wYear = Year(datUTC)
     .wMonth = Month(datUTC)
     .wDay = Day(datUTC)
     .wHour = Hour(datUTC)
     .wMinute = Minute(datUTC)
     .wSecond = Second(datUTC)
  End With
  If SetSystemTime(ST) Then
    setSystemClock = True
  Else
    setSystemClock = False
  End If
End Function

Digital Code Signing Certificates

Several years ago I decided to make use of digital code signing certificates to sign the executable files of all my software products and also to sign the installers. As I’ve just had to renew my certificate I thought I’d write about it quickly here. Basically a digital code signing certificate allows you to fingerprint an executable file to assure you that a given file is from a given software publisher. Furthermore, it also checksums a file to prevent the executable file from being modified after it was signed.

Both of these are desirable from a user level because it helps to assure you that a file that is being downloaded is actually from who you expect it to be AND it hasn’t been modified to include something nefarious (such as virii or spyware). As a software publisher both of these things are useful because potential customers are more likely to actually install your software after they’ve downloaded it once it’s been signed correctly. It’s easy to tell if an executable file is digitally signed by the publisher. When you try to run the file after you’ve downloaded it from the internet Microsoft Windows will generally show you a message like this:

Windows Installation Warning Message

Windows Installation Warning Message

If the file is digitally signed then the name of the publisher will appear here. If you want to dig down deeper you can view the file properties of a signed file and you’ll see something like this:

Signed File Properties

Signed File Properties

I use Comodo as the issuing body for the code signing certificates for my software. Rather than purchase directly from them I use one of their re-sellers, K-Software. The ordering process is painless and once you’ve placed an order Comodo will contact you for some identity documents to prove who you are. This is usually business registration documents but being in Australia I had to provide a bit more information and Comodo rang me as a further verification of my business identity. It should be comforting to the consumer that they go through this sort of process, as Comodo really does want to ensure that they only issue certificates to legitimate businesses.

One tip to anyone wanting to get one of these certificates is to not use Google Chrome or Mozilla Firefox when it comes time to actually download and install your code signing certificate. This is simply because the process within IE8 or better is fully automated and painless. Chrome and Firefox require you to jump through a few extra hoops to do the actual certificate installation and based on past experience it’s just not worth the hassle. Another tip is to ensure that you backup your certificate (which can be done via IE internet properties) somewhere safe so that you can move it to a new PC if required.

Actually signing your executable file and installer is pretty simple if you’re using Windows. I use the Microsoft command line tool signtool.exe that can be used to digitally sign files. This tool is part of the .NET SDK so you’ll need to ensure you’ve got that installed. Actually using signtool.exe is easy, there’s a line in all of my software build scripts that signs both the program executable file and software installer. The line looks something like this:

c:\code signing\signtool.exe" sign /a /t http://timestamp.comodoca.com/authenticode "C:\PathTo\Exe File\ProductName.exe

New Panasonic Hi Def HDD Recorder Coming Soon

Kath wants to be able to record HD tv channels. Something that our current Panasonic recorder cannot do. I want to buy the Blu-ray version of Star Wars and then actually be able to watch it. This is also something that our current Panasonic recorder cannot do. So what’s the solution? Well, replace our perfectly good Panasonic DVD 250GB HDD SD recorder with this beast of course.

It appears to be WiFi enabled for some reason that I cannot determine (but anything with WiFi is better) and I’ve got high hopes it will play media off of an external USB HDD too. Just gotta wait for the May invoices to be paid by my lovely customers and I’ll be ordering one. Hopefully I’ll be back here soon to say happy things about it.

Prometheus – Hit or Miss

I went to see Prometheus last night. This is the long awaited “prequel” for the move Alien and the first time that the director of that fine film, Ridley Scott, had returned to the Alien franchise. Now the first two Alien movies were excellent, the third was ok, and the fourth was execrable while the spin off “Alien vs Predator” movies have been deplorable beyond belief. So, aficionado’s of the series (myself included) expected a lot of Prometheus and sadly it largely failed to deliver for me. I found the character development to be somewhat childish and the sound-track just didn’t fit with the subject matter of the movie. The biggest failure of the movie though, was the complete lack of suspense or edge of the seat thrills that Alien and Aliens both had in spades. So I guess that makes Prometheus a miss for me.

All that being said I did like the premise behind the movie being a “parallel” prequel rather than a direct lead up to the events on LV-426 shown in Alien and Aliens. I also liked the idea that the acid-for-blood aliens in the original movies could have many different variations that evolved on different planets in isolation to each other. However, despite these positives I am not naive enough to miss that this parallel prequel strategy leaves the franchise wide open for (and I am going to copyright this phrase), prequel-sequels.

OleDB Jet Error – Query is Too Complex

I spent a few months late last year re-writing one of my products, Timesheets Lite, from the ground up in C# and WinForms. The old version was written in Visual Basic 6 and was working just fine but in the interests of “future-proofing” the product and learning a modern language I decided to re-write it.

The process was fairly smooth apart from a large number of inexplicable (and seemingly pointless) changes to the way that OleDB connections work. This has thrown up a lot of problems that the old VB6 version never experienced and it’s proving to be a frustrating experience getting to the bottom of them. One that was thrown up yesterday was one user who was getting the following error message:

Product: Timesheets Lite NET
Version: 3.3.4.0
Error:Query is too complex.
Source:Microsoft JET Database Engine
Raised by:Void ExecuteCommandTextErrorHandling(System.Data.OleDb.OleDbHResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteScalar()
at timesheetslite.appClass.iExecuteScalarQuery(String sSQL, DateTime[] datParameterValues)

The error was being thrown in a method that checked for employee timesheet activity across a time period and for a (potentially large) number of projects. The large number of projects was the problem as It turns out that there’s an upper limit on the number of AND’s and OR’s that can be used as criteria in an OleDb select statement. Supposedly it’s something around 40. So, I’ve had to re-write the routine to break up the select statements into blocks of 20 projects. It works fine now but you have no idea how annoying it is to see new error messages from a modern programming language when an archaic language like VB6 had no problems with the same thing. Anyway, for those who are interested here’s the code.

            string sSql = string.Empty;
            string sProjectCriteria = string.Empty;
            Int32 iProjectCount = 0;
            DateTime[] parameters = new DateTime[2];
            Int32 iRecords = 0;
            Int32 iCriteriaCount = 0;
            Int32 iCriteriaLimit = 20;

            parameters[0] = this.getStartOfDay(pStart);
            parameters[1] = this.getEndOfDay(pEnd);

            if (projects.Count > 0)
            {
                foreach (Project project in projects)
                {
                    if (iCriteriaCount == 0)
                    {
                        sProjectCriteria = " AND (";
                    }

                    sProjectCriteria += "lngProjectID=" + project.ID.ToString();

                    iProjectCount++;
                    iCriteriaCount++;

                    if (iProjectCount != projects.Count && iCriteriaCount<iCriteriaLimit)
                        sProjectCriteria += " OR ";

                    if (iCriteriaCount == iCriteriaLimit) //break up query into blocks to stop the query too complex error
                    {
                        iCriteriaCount = 0;
                        sProjectCriteria += ") ";
                        sSql = "SELECT count(lngID) as time_records from tblTimes where datDate>=@Parm0 and datDate<=@Parm1 and lngEmployeeID=" + this.ID.ToString() + sProjectCriteria;

                        iRecords = app.iExecuteScalarQuery(sSql, parameters);

                        if (iRecords > 0)
                            return true;

                    }
                }

                sProjectCriteria += ") ";
            }

            return false;

Excel VBA Multipage and ListView Bug

I’m going back to my roots on a small consulting job and hacking together a tracking system in Excel with some VBA forms thrown in for giggles. I’ve come across a redraw bug when you put a ListView control on a MultiPage control. For whatever reason the first redraw of the form displays the ListView at position 0,0 of the MultiPage regardless of where you positioned it in the designer. This ListView moves to the correct location when you either change the current page of the MultiPage or drag the form but clearly this isn’t a great solution. I came up with another solution that seems to have worked pretty well. Just force a re-draw of the ListView whenever the MultiPage is clicked.

Private Sub MultiPage1_Click(ByVal Index As Long)
  '
  'workaround for redraw problem with listview in multipage
  '
  Me.lvwResearchers.Visible = False
  Me.lvwResearchers.Visible = True
End Sub

Builders are Paying a Visit 2

The Wall to be Removed

The Wall to be Removed

The builders are still here and the banging has started. They’ve been wandering around with a gas gun and a big DeWalt power saw which is always an exciting thing. Above you can see what part of the wall they are removing, immediately behind this wall is the large room that we are splitting in two. Below you can see a view from the room that is being partitioned. The red shaded area on the right is the wall that you can see above. The blue shaded area is where the new wall is going to be constructed.

New Wall to be Added

New Wall to be Added

Builders are Paying a Visit

It’s not anything technical but I guess the builders paying us a visit today (and tomorrow) is worth a mention. We are having a new wall put into the middle of a large room (3.5mx6m) to form a bedroom. The other half of the large room is being opened up to our living area by having the 3m segment of wall between the two removed. There’s some other things happening too but these are just some power points being installed and a TV antenna outlet being moved.

Up until now the only work we’ve had to do in preparation for this work is to move furniture. This will change once the builders are finished though. The new bedroom will need painting and carpeting and the newly created extension to our living area will also need painting and some sort of flooring put in.

Rooftop PV System Installation – Images of the Completed Install

I finally clambered up onto the roof yesterday to take some pictures of the panels mounted on the roof. I have to say that the install was very neat and tidy, everything was square and straight and there was no rubbish, screws, cut wire or any other junk left up there. You can see the images below.

DC Isolator and 11 Panel String

DC Isolator and 11 Panel String

Two Panel Detail

Two Panel Detail

All 22 Panels

All 22 Panels

Telstra WTF!

So I have a new phone, it’s a HTC Wildfire S, a lower tier “smartphone”. It’s a pre-paid unit locked to the Telstra network that came with a SIM with $10 of credit. I used the phone to ring Telstra to activate the SIM. And it cost the $10 that was on the SIM. WTF!!!!! Nice service Telstra, charging people to activate their SIM. Just deplorable.

More on the phone and why I bought it at a later date. Oh, Telstra, you suck!