Monday, September 17, 2012

Easy way to debug a Windows Service at startup

The typical way of debugging a Windows Service, is to attach a debugger to it after it has started. This does not work very well if one needs to debug code that only executes during the startup of the Windows Service. A useful technique I have used to debug Windows Services is to launch the debugger from the Windows Service itself if a DEBUG parameter is specified. For example:

Windows Service Properties


protected override void OnStart(string[] args)
{
    // Only use this code in Debug mode.
    #if DEBUG
 
    List<string> arguments = new List<string>(args);
    if (arguments.Exists((arg) => arg.Equals("DEBUG",
        StringComparison.InvariantCultureIgnoreCase)))
    {
        // Launch Debugger if DEBUG argument is provided.
        System.Diagnostics.Debugger.Launch();
    }
 
    #endif
}

Wednesday, September 12, 2012

VB6 Binary Compatibility Issue on public COM fields

I discovered a very interesting VB6 ActiveX DLL issue the other day when I was trying to recompile some legacy code. Every time I would recompile a particular ActiveX DLL project, the “Break compatibility” dialog would be displayed even though the public field in question did not change.

Binary Compatibility Issue

The class that was causing this issue contained a public field that referenced an OCX control. I would never recommend doing that, but doing so should not cause Binary Compatibility to break every time it is rebuilt.

Using Microsoft’s OLE/COM Object Viewer, I discovered VB6 had declared this field (i.e. its associated methods) as IDispatch rather than IPicClip. This causes consumers of the library (including the VB6 compiler) to view the field as an Object rather than a PicClip.PictureClip.

OLEView IDispatch

After some trial an error, my colleague and I determined that if an OCX control is going to be available to consumers of the ActiveX DLL, the OCX library must FIRST be referenced using the References dialog before adding it to the Toolbar using the Components dialog.

References Dialog

Components Dialog

After adding the OCX library using the Reference dialog first, the “Binary Compatibility” dialog does not appear when rebuilding the ActiveX DLL and the class looks as expected in Microsoft’s OLE/COM Object Viewer.

OLEView IPicClip

NOTE: In some situations you may not be able to reference the OCX using both the References and the Components dialogs, and I would not recommend making OCX controls available using public class fields anyway.

Sunday, April 22, 2012

jQuery Mobile: Removing a Page from the DOM

By default jQuery Mobile loads pages via Ajax, allowing it to animate the page transitions. This behavior can sometimes cause a problem, especially if JavaScript is being used on the pages.

For example, if a website has two pages that contain elements with the same id attributes and a jQuery selector is used that refers to the elements by their ids, the jQuery may select the wrong element.

Page 1

<!DOCTYPE html>

<html>

       <head>

       <title>Page 1</title>

       <meta name="viewport" content="width=device-width, initial-scale=1">

       <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />

       <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

       <script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>

    <script type="text/javascript" src="UnloadExample.js"></script>

</head>

<body>

 

<div id="Page" data-role="page" data-theme="b">

 

       <div data-role="header" data-theme="b">

              <h1 id="header">Page 1</h1>

        <a href="UnloadPage2.htm" data-icon="arrow-r" data-iconpos="right" class="ui-btn-right">Page 2</a>

       </div><!-- /header -->

 

       <div data-role="content"> 

              <p>This is page 1.</p>

        <a id="ShowButton" data-role="button">Show</a>

       </div><!-- /content -->

 

</div><!-- /page -->

 

</body>

</html>

 

Page 2

<!DOCTYPE html>

<html>

       <head>

       <title>Page 2</title>

       <meta name="viewport" content="width=device-width, initial-scale=1">

       <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />

       <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

       <script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>

    <script type="text/javascript" src="UnloadExample.js"></script>

</head>

<body>

 

<div id="Page" data-role="page" data-theme="b">

 

       <div data-role="header" data-theme="b">

        <a href="UnloadPage1.htm" data-icon="arrow-l" data-iconpos="left">Page 1</a>

              <h1 id="header">Page 2</h1>

       </div><!-- /header -->

 

       <div data-role="content"> 

              <p>This is page 2.</p>

        <a id="ShowButton" data-role="button">Show</a>

       </div><!-- /content -->

 

</div><!-- /page -->

 

</body>

</html>

 

UnloadExample.js

$(document).delegate("#ShowButton", "click", function () {

    alert($("#header").text());

});

If the Show button is clicked on the first page, an alert box is shown with the message "Page 1".

Page 1


Then if the "Page 2" button is clicked, Page 2 is displayed. If the Show button is clicked on the second page, an alert box is shown with the message "Page 1", not "Page 2".

Page 2 Before


Since Page 1 is still in the DOM, jQuery selects the "#header" element on the hidden page (Page 1) instead of the one that is actually visible (the one on Page 2).

This issue can be avoided by removing the hidden page from the DOM after Page 2 is shown. The following JavaScript can be added to the UnloadExample.js page to accomplish this.

$('#Page').live('pagehide', function () {

    $(this).remove();

});

Now when the Show button on Page 2 is clicked, the alert box message will be “Page 2”.

Page 2 After


Monday, April 16, 2012

jQuery Mobile: Finding the “Real” Collapse Event

I have found that if you have a group of jQuery Mobile (Version 1.1.0) collapsible blocks collapsible blocks (https://web.archive.org/web/20120501053458/http://jquerymobile.com/demos/1.1.0/docs/content/content-collapsible.html) (e.g. <div data-role="collapsible">) in a collapsible set collapsible set (https://web.archive.org/web/20120501053458/http://jquerymobile.com/demos/1.1.0/docs/content/content-collapsible-set.html) (e.g. <div data-role="collapsible-set">) the collapsible blocks’ “collapse collapse” (https://web.archive.org/web/20120501053458/http://jquerymobile.com/demos/1.1.0/docs/content/content-collapsible-events.html) event seems to fire more often than it should.

For example, if a page contains a collapsible set containing five collapsible blocks that are currently collapsed and one of the blocks is expand, a “collapse” event will be raised for the other four blocks in the set, even though they were already collapsed. I would not have expected to see any “collapse” events in that situation.

Then, if one of the other collapsed blocks is expanded, I would expect to only see a “collapse” event raised for the one block that was expanded, but a “collapse” event is raised for all of the blocks in the collapsible set (except for the one that was just expanded).

For my purposes I, only want to know about the “collapse” events that occur when a collapsible block is truly collapsed (i.e. the collapsible block went from an expanded state to a collapsed state). To accomplish this, I add a new attribute to the collapsible block, called data-previous-state. On the “expand” event for the collapsible block, I set this attribute to “expanded”. On the “collapse” event, I check to see if the data-previous-state attribute is set to “expanded”. If it is, I perform my collapse logic and set the data-previous-state attribute to “collapsed”. If the data-previous-state attribute is set to “collapsed”, I ignore it.

The following is the code for a page that demonstrates this issue. The collapse events highlighted in yellow are the “real” collapse events.

<!DOCTYPE html>

<html>

<head>

    <title>jQuery Mobile Collapsible Content Events</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

    <script type="text/javascript" src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>

    <style>

        #EventOutput

        {

            border-top: 1px dotted Grey;

        }

        #EventOutput div

        {

            border-bottom: 1px dotted Grey;

        }

        .highlight

        {

            background-color: Yellow;

        }

    </style>

</head>

<body>

    <div id="CollapsibleContentEventsPage" data-role="page">

    <div data-role="header" data-position="fixed">

        <h1>

            Collapsible Content Events

        </h1>

    </div>

    <div data-role="content">

      <div data-role="collapsible-set">

        <div class="section" data-section="1" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 1

          </h3>

          <p>

            I'm the collapsible set content for section 1.

          </p>

        </div>

        <div class="section" data-section="2" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 2

          </h3>

          <p>

            I'm the collapsible set content for section 2.

          </p>

        </div>

        <div class="section" data-section="3" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 3

          </h3>

          <p>

            I'm the collapsible set content for section 3.

          </p>

        </div>

        <div class="section" data-section="4" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 4

          </h3>

          <p>

            I'm the collapsible set content for section 4.

          </p>

        </div>

        <div class="section" data-section="5" data-role="collapsible" data-content-theme="d">

          <h3>

            Section 5

          </h3>

          <p>

            I'm the collapsible set content for section 5.

          </p>

        </div>

      </div>

    </div>

    <div data-role="content" data-theme="d">

      <h3>

        Event Details

      </h3>

      <div id="EventOutput">

      </div>

    </div>

    </div>

 

<script type="text/javascript">

 

    $("#CollapsibleContentEventsPage").live("pageinit", function (event) {

 

        $("#EventOutput").prepend("<div>" + (new Date()).getTime() + ": pageinit</div>");

 

        $("div.section").on("expand", function () {

            $(this).data("previous-state", "expanded");

        });

 

        $("div.section").on("collapse", function () {

 

            var eventInfo;

 

            if ($(this).data("previous-state") == "expanded") {

                eventInfo = "<div class='highlight'>"

            }

            else {

                eventInfo = "<div>"

            }

 

            eventInfo += (new Date()).getTime()

                + ": collapse - Section "

                + $(this).data("section")

                + "</div>";

 

            $("#EventOutput").prepend(eventInfo);

 

            $(this).data("previous-state", "collapsed");

        });

    });

</script>

</body>

</html>