Wednesday, 12 November 2014

Lansweeper: Add Uptime To Your Hardware Reports

Quick tip today. If you need to add an "Uptime" column on your Lansweeper reports, feel free to add the following;

Cast(DateDiff(d, 0, DateAdd(second, DateDiff(s, tblAssets.Lastseen, GetDate()) + tblAssets.Uptime, 0)) As VARCHAR(15)) + ' day(s) ' + Convert(VARCHAR(8),DateAdd(second, DateDiff(s, tblAssets.Lastseen, GetDate()) + tblAssets.Uptime, 0),108) As Uptime

It's not going to be the best column format for sorting but it's definitely useful to see how long your servers have been running since last reboot.

Thursday, 24 July 2014

VevoCart Error: Site Cannot Be Empty

When using PayPal Pro, you may experience the error "Site Cannot Be Empty. Click here to re-enter payment information".

This issue is caused by the "SiteName" configuration being empty and the error itself is reported by PayPalPro, so searching for the error message in VevoCart is not helpful. This configuration option is difficult to leave empty on the default language, so this issue typically only occurs when you run your multi-store site with multiple languages. If the configuration value is not set for your current language, you will experience this error.

Solution 1: Select the "Store Config" option in your administration panel. Your "Store Name" will likely be filled in. Select the "Language" from the top right of the store Config panel to change the language. Once changed, you can now fill in the Store Name option for the language.

Solution 2: To update the configuration in the database, you will need to update the ConfigurationValue table where the ConfigID is 1 (the CultureID is obviously different depending on the language you wish to update).

UPDATE dbo.ConfigurationValue
SET ItemValue = 'Site Name'
WHERE dbo.ConfigurationValue.ConfigID = 1
AND dbo.ConfigurationValue.CultureID = 2

Tuesday, 4 March 2014

Prevent AppLauncher.exe starting on WT41N0

You may have noticed the startup folder structure has changed a little since the WT4090 and AppLauncher.exe starts up through different means. If you want to supress this without having to resort to using Platform Builder, you can do so with a registry merge in the \Application folder. Create the following .reg file and put it in your \Application folder:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SVCStart\1\Configurations\Display]
@=""
"Default"=""
"Delay"=dword:00000600

It appears that Motorola have configured this as the first startup option in the registry, so this registry merge simply overwrites the option with a blank entry. Not sure if Windows CE will stop processing startup options if it encounters a blank entry but let me know if you find any problems with this method.

Tuesday, 31 December 2013

ASP.NET 4.0 and IE10 and IE11

Had some problems recently with ASP.NET 4.0 and browser versions IE10 and IE11. Further digging reveals the issue relates to how ASP.NET works out the capabilities of the browser before rendering the pages. Microsoft Hotfix KB2836939 should fix the issue for most users, however, this particular server wasn't playing ball after the hotfix was applied. (Non standard browser config files? Previous Hotfix for same issue? Not sure, would love to hear from anyone else with same problem to diagnose why this happened.)

It's worth noting that I did NOT get the "__postback is undefined" error that most people see - I was simply not getting any JavaScript rendered at all (EG: with the AUTOPOSTBACK property set to true, the control wouldn't render the "onChange" attribute to trigger the postback in the browser).

ASP.NET applications do allow you to overrule the machine level settings for the browsers. I started by creating a web page to show me my browser capabilities.

Browser.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Browser.aspx.cs" Inherits="BrowserTest" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:literal id="litBrowser" runat="server"/>
    </div>
    </form>
</body>
</html>

With a code behind with the following in it;

Browser.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
using Vevo.WebUI;

public partial class BrowserTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        HttpBrowserCapabilities bc = Request.Browser;
        litBrowser.Text += "<p>Browser Capabilities:</p>";
        litBrowser.Text +="Type = " + bc.Type + "<br>";
        litBrowser.Text +="Name = " + bc.Browser + "<br>";
        litBrowser.Text +="Version = " + bc.Version + "<br>";
        litBrowser.Text +="Major Version = " + bc.MajorVersion + "<br>";
        litBrowser.Text +="Minor Version = " + bc.MinorVersion + "<br>";
        litBrowser.Text +="Platform = " + bc.Platform + "<br>";
        litBrowser.Text +="Is Beta = " + bc.Beta + "<br>";
        litBrowser.Text +="Is Crawler = " + bc.Crawler + "<br>";
        litBrowser.Text +="Is AOL = " + bc.AOL + "<br>";
        litBrowser.Text +="Is Win16 = " + bc.Win16 + "<br>";
        litBrowser.Text +="Is Win32 = " + bc.Win32 + "<br>";
        litBrowser.Text +="Supports Frames = " + bc.Frames + "<br>";
        litBrowser.Text +="Supports Tables = " + bc.Tables + "<br>";
        litBrowser.Text +="Supports Cookies = " + bc.Cookies + "<br>";
        litBrowser.Text +="Supports VB Script = " + bc.VBScript + "<br>";
        litBrowser.Text +="Supports JavaScript = " + bc.JavaScript + "<br>";
        litBrowser.Text +="Supports Java Applets = " + bc.JavaApplets + "<br>";
        litBrowser.Text +="Supports ActiveX Controls = " + bc.ActiveXControls + "<br>";
        litBrowser.Text +="CDF = " + bc.CDF + "<br><br>";
        litBrowser.Text +="User-Agent = " + Request.UserAgent + "<br>";
    }

}

Before I fixed the problem, I was getting the following results:

Browser Capabilities:

Type = Mozilla
Name = Mozilla
Version = 0.0
Major Version = 0
Minor Version = 0
Platform = WinNT
Is Beta = False
Is Crawler = False
Is AOL = False
Is Win16 = False
Is Win32 = True
Supports Frames = False
Supports Tables = False
Supports Cookies = False
Supports VB Script = False
Supports JavaScript = False
Supports Java Applets = False
Supports ActiveX Controls = False
CDF = False

User-Agent = Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko

First, I figured I'd need to update the ie.browser file and drop it into the "App_Browsers" folder in the application. Below is what I modified it to.

ie.browser
<browsers>
    <browser id="IE" parentID="Mozilla">
        <identification>
            <userAgent match="MSIE (?'version'(?'major'\d+)(\.(?'minor'\d+)?)(?'letters'\w*))(?'extra'[^)]*)" />
            <userAgent nonMatch="IEMobile" />
        </identification>

        <capture>
            <userAgent match="Trident/(?'layoutVersion'\d+)" />
        </capture>

        <capabilities>
            <capability name="browser"              value="IE" />
            <capability name="layoutEngine"         value="Trident" />
            <capability name="layoutEngineVersion"  value="${layoutVersion}" />
            <capability name="extra"                value="${extra}" />
            <capability name="isColor"              value="true" />
            <capability name="letters"              value="${letters}" />
            <capability name="majorversion"         value="${major}" />
            <capability name="minorversion"         value="${minor}" />
            <capability name="screenBitDepth"       value="8" />
            <capability name="type"                 value="IE${major}" />
            <capability name="version"              value="${version}" />
        </capabilities>
    </browser>

      <browser id="IE10Plus" parentID="Mozilla">
        <identification>
            <userAgent match="Trident\/7.0; rv:(?'version'(?'major'\d+)(\.(?'minor'\d+)?)(?'letters'\w*))(?'extra'[^)]*)" />
            <userAgent nonMatch="IEMobile" />
        </identification>

        <capture>
            <userAgent match="Trident/(?'layoutVersion'\d+)" />
        </capture>

        <capabilities>
            <capability name="browser"              value="IE" />
            <capability name="layoutEngine"         value="Trident" />
            <capability name="layoutEngineVersion"  value="${layoutVersion}" />
            <capability name="extra"                value="${extra}" />
            <capability name="isColor"              value="true" />
            <capability name="letters"              value="${letters}" />
            <capability name="majorversion"         value="${major}" />
            <capability name="minorversion"         value="${minor}" />
            <capability name="screenBitDepth"       value="8" />
            <capability name="type"                 value="IE${major}" />
            <capability name="version"              value="${version}" />

            <capability name="ecmascriptversion"    value="3.0" />
            <capability name="jscriptversion"       value="5.6" />
            <capability name="javascript"           value="true" />
            <capability name="javascriptversion"    value="1.5" />
            <capability name="msdomversion"         value="${majorversion}.${minorversion}" />
            <capability name="w3cdomversion"        value="1.0" />
            <capability name="ExchangeOmaSupported" value="true" />
            <capability name="activexcontrols"      value="true" />
            <capability name="backgroundsounds"     value="true" />
            <capability name="cookies"              value="true" />
            <capability name="frames"               value="true" />
            <capability name="javaapplets"          value="true" />
            <capability name="supportsCallback"     value="true" />
            <capability name="supportsFileUpload"   value="true" />
            <capability name="supportsMultilineTextBoxDisplay" value="true" />
            <capability name="supportsMaintainScrollPositionOnPostback" value="true" />
            <capability name="supportsVCard"        value="true" />
            <capability name="supportsXmlHttp"      value="true" />
            <capability name="tables"               value="true" />
            <capability name="supportsAccessKeyAttribute"    value="true" />
            <capability name="tagwriter"            value="System.Web.UI.HtmlTextWriter" />
            <capability name="vbscript"             value="true" />
        </capabilities>
    </browser>

    <!-- Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4325) -->
    <browser id="IE6to9" parentID="IE">
        <identification>
            <capability name="majorversion" match="[6-9]" />
        </identification>

        <capabilities>
            <capability name="ecmascriptversion"    value="3.0" />
            <capability name="jscriptversion"       value="5.6" />
            <capability name="javascript"           value="true" />
            <capability name="javascriptversion"    value="1.5" />
            <capability name="msdomversion"         value="${majorversion}.${minorversion}" />
            <capability name="w3cdomversion"        value="1.0" />
            <capability name="ExchangeOmaSupported" value="true" />
            <capability name="activexcontrols"      value="true" />
            <capability name="backgroundsounds"     value="true" />
            <capability name="cookies"              value="true" />
            <capability name="frames"               value="true" />
            <capability name="javaapplets"          value="true" />
            <capability name="supportsCallback"     value="true" />
            <capability name="supportsFileUpload"   value="true" />
            <capability name="supportsMultilineTextBoxDisplay" value="true" />
            <capability name="supportsMaintainScrollPositionOnPostback" value="true" />
            <capability name="supportsVCard"        value="true" />
            <capability name="supportsXmlHttp"      value="true" />
            <capability name="tables"               value="true" />
            <capability name="supportsAccessKeyAttribute"    value="true" />
            <capability name="tagwriter"            value="System.Web.UI.HtmlTextWriter" />
            <capability name="vbscript"             value="true" />
        </capabilities>
    </browser>

    <!-- Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0;) -->
    <browser id="IE7" parentID="IE6to9">
        <identification>
            <capability name="majorversion" match="7" />
        </identification>
        <capabilities>
            <capability name="jscriptversion" value="5.7" />
        </capabilities>
    </browser>

    <!-- Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729) -->
    <browser id="IE8" parentID="IE6to9">
        <identification>
            <capability name="majorversion" match="8" />
        </identification>
        <capabilities>
            <capability name="jscriptversion" value="6.0" />
        </capabilities>
    </browser>


    <gateway id="IEbeta" parentID="IE">
        <identification>
            <capability name="letters" match="^([bB]|ab)" />
        </identification>

        <capture>
        </capture>

        <capabilities>
            <capability name="beta"    value="true" />
        </capabilities>
    </gateway>
</browsers>

My results from the browser page were unaffected, however - the browser was still being detected as "Mozilla". I decided to hack out the Mozilla detection from the generic.browser file (trying the "NonMatch" element didn't work for me - if someone can explain how to prevent IE11 detecting as Mozilla, I'd love to hear from you).

generic.browser
<browsers>
    <browser id="GenericDownlevel" parentID="Default">
        <identification>
            <userAgent match="^Generic Downlevel$" />
        </identification>

        <capture>
        </capture>

        <capabilities>
            <capability name="cookies"                     value="false" />
            <capability name="ecmascriptversion"           value="1.0" />
            <capability name="tables"                      value="true" />
        <capability name="type"                        value="Downlevel" />
        </capabilities>
        <controlAdapters>
        <adapter controlType="System.Web.UI.WebControls.Menu"
                     adapterType="System.Web.UI.WebControls.Adapters.MenuAdapter" />
        </controlAdapters>
    </browser>

</browsers>

After uploading the new browser files to the App_Browsers folder on the server I get the following and the website is working again! (Note: you may need to restart the application for this to take effect. If, like me, you don't have access to the server to do this, write a new file in the "bin" folder - any file changes in this folder cause an application to restart.)

Browser Capabilities:
Type = IE11
Name = IE
Version = 11.0
Major Version = 11
Minor Version = 0
Platform = WinNT
Is Beta = False
Is Crawler = False
Is AOL = False
Is Win16 = False
Is Win32 = True
Supports Frames = True
Supports Tables = True
Supports Cookies = True
Supports VB Script = True
Supports JavaScript = True
Supports Java Applets = True
Supports ActiveX Controls = True
CDF = False

User-Agent = Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko

Friday, 14 June 2013

Error: The bootstrap could not be loaded

When working with Motorola's new WT41N0 with Windows Embedded CE 7 (or Embedded 2010 depending on what screen you're looking at!), you may receive a "The bootstrap could not be loaded" error from the Device Connectivity Component when trying to deploy or debug a Visual Studio 2008 VB or C# .NET project.

To resolve this problem, you need to install the drivers to cope with it which are held in the PSDK. You can get these from the Motorola Support website, select "Mobile Computers", select the model number "WT41N0" and select "Software Downloads" as document type. You need the 41x0cBenPS010010.exe file to install (recommend you close Visual Studio first). Once installed, your deploy dialog box will include the option to deploy to WT41N0c70PSDK ARMV7 Device.

I have also heard that installing the latest CE package builder from Microsoft also fixes the problem.

Tuesday, 27 November 2012

Host files in Windows CE

Windows has the ability to link hosts to specific IP addresses. Think of it as a DNS bypass system. In our warehouse setup, the wireless infrastructure is completely self contained - it does not have any access to our domain infrastructure except for TCP port 80 access to one web server. This means that our wireless infrastructure does not have access to DNS.

We get around this by configuring our devices to convert a host name to an IP address in the HOSTS entries that Windows supports. It's probably not the most practical way to do things but I'm sure other developers will find a better use for the information enclosed in this blog post.

The Windows CE 5 & 6 host entries are entered into the registry in the following location, and the IP octets are entered in HEX. To persist this on your device, create a registry file (EG: hosts.reg) in the "\Application" folder and place 1 entry in the reg file per host name you wish to redirect.

REGEDIT4

[HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\SERVERNAME]
"ipaddr"=hex:0a,14,1e,01

After a cold boot, your registry file will be automatically merged into the registry.

Update: If you are looking to use IPv6, you will need to use the attribute "ipaddr6" rather than "ipaddr". The value will obviously need to be 20 bytes, rather than the 4 bytes used by IPv4.

Friday, 19 October 2012

Google Maps for Business

Google recently invited us to attend the recent Pinpoint event in London. The idea was for us to evaluate the products and services Google can offer in the geo-location and mapping arena.

We're familiar with the web based Google Maps API. It's amazingly simple to use, offers a very rich UI and most importantly, we have shown this to our end users who instantly recognise and know how to use the user interface.

In Google's favour, the mapping views, overlays and ability to create heat maps are second to none. Coupled with the StreetView feature, Google have built an amazingly powerful product that we were excited to start implementing into our software.

However, the message from the event was very much "We're ready for business". I believe Google Maps solutions are far from ready for this task and here are my main reasons;

Routing (Navigation) is incredibly basic. Although Google do have the "beta" moniker on the turn by turn navigation, it is definitely flogging the maps routing as a genuine business product. I beg to differ. There is no ability to avoid certain map location points; imagine you receive data that warns you of a closed road - your planning agents cannot mark this on the map for the routing software to react to this. There is no ability to route for large vehicles, avoiding low bridges or weight restrictions. For taxi drivers, there is no way to include bus lanes in your directions. As a business user this is quite frustrating when you know that nobody can collect, handle and interrogate data quite like Google but they seem to be avoiding some pretty basic projects here.

If you thought it easy to get your directions from elsewhere and overlay them into Google Maps, think again. Mapping software products generally do not play well with each other and you will invariably end up with situations where the directions overlay is placed over an area without a road on the other map.

During the event we were introduced to Google Coordinate. For those unfamiliar, the product allows you to create work flows, assigning jobs to remote workers who can pick them up on their mobile devices, see job info, navigate to the job and will be forced to complete certain mandatory fields before the job is marked as complete. The product shows a lot of promise and I can certainly see the use for companies without their own information systems departments. However, this product again seems to follow the recent trend of Google releasing products that simply aren't ready. When configuring your work flow, you can add mandatory fields that you require the remote worker to complete before the job is closed. These fields are free text so you cannot add, for example, a drop down list of options for the remote worker to choose from. I cannot understand the rationale behind this - it is woefully too simple to be useful in many business scenarios.

So we arrived at Google Pinpoint 2012 fairly confident we needed to buy the Google Maps API for our business and left feeling fairly confident that Google Maps couldn't do what we needed.