A site devoted to discussing techniques that promote quality and ethical practices in software development.

Friday, December 19, 2014

Experience in installing PDFCreator 2.0.x

I have been a long term, though slow to update, user of PDFCreator and recently I have decided to upgrade it to 2.0.0 from 1.7.3.

The installation experience left me with a sense of unease as it triggers the resident shield of my AVG 2015 flagging some files as being a Malware/Trojan/Adware. I will come back to this.

As a result of this alarm, I revisited my trust old friend CutePDF Writer, which has fewer feature than PDFCreator. The installation of CutePDF Writer 3.0 went without tripping my AVG but one has to be on the wit about its attempt to slip in some PUP and toolbars. It is nice to see the installation script offering a feature to skip all the PUP.

Since PDFCreator's installation script trips my AVG, I have decided to investigate this further in a controlled environment. First of all, I went to PDF Forge site to obtain the MD5 of the installation package to make sure I was not using a tainted package.

My investigation used 2.0.1, the latest release to determine what's going on. I use two installation scenarios - with network access and without network access and they have different behavior causing AVG to report different alerts. My experiments with installing PDFCreator do not install Image2PDF and PDFArchitect.

With network access

When the installation package, PDFCreator-2_0_1.exe (MD5:1464dab853dfac75097e6f81fa060c9a), is invoked, the first thing it does is to spawn a process called DownloadUpdateInfo.exe and this runs its twin DownloadUpdateInfo.tmp for a brief moment and then closed down.

After soliciting inputs from the user, it then invokes CBStub.exe which controls the invocation of the process InstallManager.exe. It is at this point that the resident shield of AVG 2015 alerts the user of the presence of a Malware ladden file. It alleges that it is infected with MalSign.Generic.5E6.

This file, together with its companion file, inetc.dll, which appears to be doing the HTML get, put, post, and head operations, are deposited in the %Temp%\. is a randomly generated temporary directory name. They disappear after successful installation and one needs some trickery to capture them.

According to VirusTotal, there are 10 out of 56 Anti-virus tools reporting this file as infected.

What this file does is to offer user a chance to install Ad-Aware Web Companion:
Strange, asking user to install an Ad-Aware component results in being classified as a Malware! What this does is to then invoke the Mntz_Installer.exe, which seems odd as most people on the Internet identifies this as the Opera Network Installer. Whatever this file is, it installs two services, namedly, LavasoftTcpService.exe and Lavasoft.SearchProtect.WinService.exe, which are part of the Web Companion software.


In all fairness, one can safely consider the alert from AVG for InstallManager.exe as a false-positive and can ignore it. If you are running AVG and feel uncomfortable when it raises the alert, it will not harm the operation of PDFCreator if you ask AVG to protect you. In this case, AVG will destroy InstallManager.exe and its subsequent operations.

Without network access

Often, it is advisable to install downloaded software with network disconnected to see if it calls home.

When the PDFCreator installation package is invoked with network disconnected, it does not invoke the DownloadUpdateInfo.exe.

Instead it extracted a bunch of files into a temporary directory %Temp%\ which happens to contain the OCSetupHlp.dll. The presence of this file triggers the AVG 2015's resident shield identifying it as an Adware AdLoad.OpenCandy.

According the VirusTotal, there are 12 out of 56 AV tools identifying it as infected with OpenCandy. Exactly what this being used is unsure but it does not appear to hamper the installation if one asks AVG to remove this offending DLL.

When installing without network access, the installation package will not prompt you about the installing the Ad-Aware Web Companion using the InstallManager.exe and hence it will not trip the AVG's resident shield.

If you examine this DLL's version information and its export functions, it is unambiguously associated with OpenCandy and hence it is fair to say that PDFCreator installation is tainted by OpenCandy but PDFCreator does not seem to have infected with OpenCandy after installation and during its operations.

In view of this, it is fair to say this is also a false-positive even though it is part of OpenCandy system.

The experiments show that while PDFCreator installation package causes AVG to raise alarms during the installation, they are safe and one can safely ask AVG to protect yourself against these files without jeopardising the operations of PDFCreator. PDFCreator runtime does not cause any resident shield alarm.

Thursday, June 5, 2014

Handling Popup Menu (aka Context Menu) in a Gtk# TreeView widget

There are two ways to invoke the context menu, namely the familiar right mouse click and pressing Shift-F10.

To handle these two triggers requires some special treatments and this post is to illustrate how to accomplish them. The Internet and in fact the Mono forums contain materials showing how to handle the right mouse click and it is repeated here for completeness but seem to fail to discuss how to deal with Shift-F10.

To intercept the right mouse click

To intercept the right mouse click you need to provide a ButtonPress event handler to the TreeView's ButtonPress event and most importantly you need to tell the runtime to slot your handler before the default ButtonPress handler, or else you won't see the right mouse click.

Here is the code fragment to add a ButtonPress event handler, which you can also specify using the properties pad in MonoDevelopment IDE.

this.treeview1.PopupMenu += new global::Gtk.PopupMenuHandler (this.OnTreeview1PopupMenu)

When defining the handler, make sure you adore the handler with the Glib.ConnectBefore attribute as follows:

[ GLib.ConnectBefore ] // need this to allow program to intercept the key first.
protected void OnTreeview1ButtonPressEvent (object o, ButtonPressEventArgs args)
{
    if( args.Event.Button == 3 )    // Right button click
    {
        Debug.WriteLine( "Right mouse click detected" );
        ShowContextMenu("Right Click - ");
    }
}

To handle Shift-F10

It seems the treatment to invoke the context menu via the keystroke is not as popular as using the right mouse click and hence the forums have scant discussion on this. This may be due to poor documentation, in particular to the use of PopupMenuArgs, the event argument for the PopupMenuHandler delegate. In the absence of a recommended way from the Mono team to invoke the pop up, below offers a possible way to accomplish this.

When Shift-F10 is pressed on a TreeView, the runtime will invoke the TreeView.PopupMenu event handler if defined. This is different from other widget's way of handling context menu; Others have a PopulatePopupMenu event allowing the control's provider to construct the menu and the runtime will then render the menu.

Hooking the TreeView.PopupMenu event is easy but the same treatment used in invoking the user constructed pop up menu for right mouse click does not seem to work; in fact nothing is displayed. Hence it needs a slight departure from simply calling directly the Menu.Popup in the TreeView.PopupMenu event handler. You need to basically post yourself a message, using a Windows' parlance, and then you can invoke the popup. This can be accomplished by using the Application.Invoke method or its overloads.

Here is the code fragment to install an event handler for PopupMenu:

this.treeview1.ButtonPressEvent += new global::Gtk.ButtonPressEventHandler (this.OnTreeview1ButtonPressEvent);

Once again if you prefer, you can use the properties pad for the TreeView object in the MonoDevelop to specify this.

Below is the code fragment showing the way to use Application.Invoke() to show the context menu:

protected void OnTreeview1PopupMenu (object o, PopupMenuArgs args)
{
    Debug.WriteLine( "TreeView Popup Menu click" );
    // Post yourself a message to invoke the context menu.
    // Calling ShowContextMenu() directly from here does not
    // work.
    Application.Invoke( delegate 
        {
            Debug.WriteLine( "Delegate invoked" );
            ShowContextMenu("Shift-F10 - ");
        } );
}

For completeness, here is the implementation of very simple ShowContextMenu():

void ShowContextMenu (String prefix = "")
{
    Menu m = new Menu();
    MenuItem mi = new MenuItem( prefix + "Item 1" );
    mi.Activated += (object sender, EventArgs e) => 
    {
        String s = prefix + "Item 1 Clicked";
        Debug.WriteLine( s );
        ShowMsgBox( this, s ); 
    };
    m.Append(mi);
    
    mi = new MenuItem( prefix + "Item 2" );
    mi.Activated += (object sender, EventArgs e) => 
    {
        String s = prefix + "Item 2 Clicked";
        Debug.WriteLine( s );
        ShowMsgBox( this, s );
    };
    m.Append( mi ); 
 
    m.ShowAll();
    m.Popup();
}

Tuesday, May 13, 2014

CLR and Mono Runtime difference - System.Diagnostics.DefaultTraceListener.AssertUiEnabled

This one to some is a very contentious issue and is present in the Mono runtime 2.10.8.1 running in Mint-15.

While this property is not well known to many as rarely one would need to touch this in CLR, it is intimately related to the well-known method System.Diagnostics.Debug.Assert().

The runtime behaviour of Debug.Assert() depends on the behaviour of the trace listener(s) that have been loaded at that time. When the expression becomes false, Debug.Assert() calls the System.Diagnostics.TraceListener.Fail().

At start up time, CLR & Mono would load a number of System.Diagnostics.TraceListener-derived class(es). If there is no overriding specification in the application's config file, the runtime loads the System.Diagnostics.DefaultTraceListener and is identified in the collection of TraceListeners by the name "Default".
 
In CLR for most runtime environment, such as Console, WinForm, WPF, WCF, Debug.Assert() by default will alert the user with a user-interface that allows the user to abort or ignore. This behaviour has not changed since the first release of the .Net framework and runtime. Of course this behaviour is entirely configurable.

If System.Diagnostics.DefaultTraceListener is the default TraceListener, the default behavour of alerting the developer is by means of a user-interface to inform of the unmet condition. This is the desired behaviour for most situations during development. This is because the System.Diagnostics.DefaultTraceListener.AssertUiEnabled is default to true.

However, in Mono, the System.Diagnostics.DefaultTraceListener.AssertUiEnabled is by default initialized (or lack of explicit initialization in DefaultTraceListener class) to false.

This discrepancy in the default value often leads to developer's gripe and  incorrectly accusing the Mono's System.Diagnostics.Debug.Assert() failure to catch the unmet condition; by defaut Mono just does not alert the user loudly. The Internet has plenty of Linux/Unix ways of 'fixing' this problem. But I will present here the .Net ways of fixing this discrepancy in the spirit of maintaining cross-platform runtime consistency.

It is nothing more annoying when one writes defensive code using Debug.Assert() liberally only to be silently scuttled by a difference in default value in another class. I have lost count of the number of hours trying to find some problems that should have been caught by Debug.Assert() but flew past me silently!

How to fix this?

To convince yourself you can report out the default value for DefaultTraceListener.AssertUiEnabled by writing a simple console application like this that can run successfully in both Mono and CLR:

class MainClass
{
  public static void Main (string[] args)
  {
    Console.WriteLine ("Default value of AssertUiEnabled = {0}",
      (Debug.Listeners ["Default"] as DefaultTraceListener).AssertUiEnabled);
  }
}

You should get true when run in CLR and false when in Mono.

The reason for assuming false in Mono could be historical where Mono initially did not have any GUI support; this has changed and the code for DefaultTraceListener.Fail() contains code to invoke user-interface.

However, even in the absence of rich user-interface it should adopt the approach used by other languages, such as Java's assert keyword, assert() in C/C++ language, where it aborts the execution reporting the point of failure. Not reporting to a developer loudly by default is dangerous, considering the usage promoted by Debug.Assert(). If a crude way of alerting the user is unsuitable, the .Net has ways to allow user to alter the behaviour and that is a user-initiated process and that the user then know where to look for violations. This also makes the runtime behaviour consistent with CLR. Not telling misleads the developers of fault. The current situation is like asking Java developers to make the JRE's behaviour of java -ea different in Windows and in Linux!

Without recompilation - use Application Configuration File

This is by far the most convenient way to fix this problem and that it works for both CLR and Mono.

You simply include the following fragment in your application configuration (if none, create one) to add an assert element to force the assertuienabled to true:

  <system.diagnostics>
       <!-- This changes the DefaultTraceListener.AssertUiEnabled from false to true -->
       <assert assertuienabled="true" />
  </system.diagnostics>

With code

This approach will require you to compile new code. However, if you are testing ready-made assembly and do not want to rebuild them, this approach can be adopted by including the following piece of code in the start up code:
 
(Debug.Listeners ["Default"] as DefaultTraceListener).AssertUiEnabled = true;

I hope this post will make the experience of developers looking for Mono as their cross-platform environment more pleasing.

CLR and Mono Runtime difference - XmlSerializer for read-only auto-property

This is one of a number of posts to highlight runtime difference between Mono and CLR/.Net. It is not a criticism of the good works of the Mono team but to highlight the differences so that developer interested in using Mono as a cross platform development platform, like me, is aware of them and to take necessary avoidance strategy.

Of course, in a perfect world, there shouldn't be any runtime difference and let's hope these posts are of transient nature.

This post draws reader's attention to the difference of the runtime behaviour of  System.Xml.Serialization.XmlSerializer in Mono and in CLR. 

In CLR, if the serializer is presented with a class that has read-only auto-property, the runtime will throw an exception, System.InvalidOperationException, whose origin can be traced to the sgen.exe. However, when the same piece of IL code is executed in Mono (without compilation), there is no exception and in fact Mono would blissfully serialize/deserialize those read-only auto-properties, which is clearly wrong.

This runtime discrepancy only arises only if you use read-only auto-property like this:

[Serializable]
public class Sample
{
   public String Name { get; private set; }
   // ....
}


Mono can handle any other forms of read-only property constructs.

Monday, March 3, 2014

When technology is abused or misused, government has a right to step in.

It is good to see a government in Shanghai stepped in to ban the taxi driver from receiving bookings from smartphone apps during certain peak hours to avoid creating a situation that severely disadvantage those that have been left behind by technology.

The following story illustrates the dire situation that requires intervention:
The following story was widely circulated in Shanghai recently, and illustrates the point. It is about an old woman who stood on the street, in front of a hospital gate after she had just visited the doctor for some medical checks.

She waited on the street for about an hour trying to hail a taxi without success.

Many taxis stopped but the first question the drivers asked her was if she had this or that taxi-booking app in her smartphone in the hope they could get the bonus on top of the normal fare. She didn't have one of the apps so those taxi drivers said sorry and left her on the side of the road.
Companies & individuals should never be allowed to have a one-sided view exploiting technology to benefit a few and leaving those less capable and sadly the most vulnerable behind. Technology can both benefit a society but can also destroy it depending on whether one can strike a balance.

The government of Shanghai should be congratulated for recognising
new technology should improve the quality of life for the general public, not just allow some people, like taxi drivers, to make quick money or help app developers quickly gather enough users so they can get listed on Nasdaq and make their own fortune.
 Can we direct his energy to humanize the bank?

Monday, February 3, 2014

Software is not created to serve human. A banking example.

This is a rather provocative title for a purpose. Recently I read a very good article from ACM Communication titled "Center Wheel for Success" by Poul-Henning Kamp, Communications of the ACM, Vol. 57 No. 2, Pages 52-54 in which the author questions the high costs of some of the large scale software developments and the finding so many for failing to meet the objectives while many died prematurely. He was citing the a system designed to meet US government's Obamacare as the example.

He attribute this largely to "Blindly deciding that IT be substituted for humans is unenlightened. IT is not a magic potion that makes unpleasant or inconvenient things disappear."

It is nice to find someone that shares my feeling on this topic and that they do not really serve human. At best they should be a tool to help human to deal with mundane and repetitive tasks, which computer and IT programs are apt to do. Human is a master of creating changes and master in complexity and adaptability to deal with ad hoc matters.

Let's consider a real life example.

Today, I was in a bank - it does not matter Which Bank - as I am sure this happenstance is found in any bank any time of the day.

A relatively matured lady was waiting in line patiently for being served and a bank staff approached her to ask how she could help her. She told the staff all she wanted was to get a list of recent transactions of her account that was accessible from the card in her hand. How hard could that be and I am sure that is probably the most required action from any customer.

Without a second to digest the full requirement, the staff (could she be a developer in her previous job?) shepherded her to an ATM machine protruding from the wall and attempted to show her how to get the list. After some moments of fiddling with the ATM without satisfying the customer, the staff realised how stupid she was that did not even listen carefully.

Eventually she took the lady to stand beside a bank teller using her terminal to view the list of transactions. She did not receive a print out despite her money funding the running of the bank.

Is this service? Does the banking system actually serve the customer's needs? Her needs is nothing complex and must be known to anyone in the banking industry without even involving a neuron and yet she still could not get what she wants other than 'being a bank teller' literally.

I contend that the banking system has missed the mark by a long shot. Consider not long ago, she would not have to walk to the bank, waste her time standing in queue and explaining the simple thing that she took for granted for so long  when she was clinging to an information rich bank book; she could simply look at her bankbook. Now she has been given a piece of plastic devoid of any useful information. I have a feeling that she did not enjoy such an experience that the system has successfully made her feeling useless.

Sure time has changed but human's needs and modus operandi have not. What good is a system if it cannot meet the human's basic needs other than to satisfy the fancy of the developers.

In this case, why can't the ATM has an option that allows the user to list and print the transactions one is interested in. This is a simple operation and it is definitely a good way to ease those bankbook dependent customers over to a new system. At best the current crop of ATM could only show the current balance.

In HK MTR, they have a balance checking device next to the ticket dispensing machine that allows the Octopus Card holder to list the 10 most recent trips, their costs and the balance remaining. That's a good service.

Surely any bank system analyst would have sat in a bank branch observing how customers interact with the bank over days, recording and understanding their needs and expectations before attempt to develop a system to 'serve' the customers?

It is not hard to replicate a simple bankbook and doing so will make many happier and imposing less burden on them. It is worth remember this simple phrase "You (the developers) are not the users".

If the system requires the user to buy a modem, have an internet connection, learn how to deal with a computer system and to fire up a web browser (web what? to many) to do the job of a bank teller, how can one calls that system serving the customer. It is basically a DIY operation and not serving the customers at all. The bank is passing the buck to the customers making them the pseudo-bank employee with no pay.

Sunday, February 2, 2014

Buggy CBA NetBank Term Deposit Management facility

In the CBA Internet Banking Service, one could supposedly manage one's term deposit investment online. However, the following two examples show the bugs in this program making such a simple task impossible and downright frustrating. Not only that, the design of it is so confusing.

One would expect the largest bank in Australia would not commit this kind simple programmatic mistakes. Before making accusation, the NetBank optimisation check facility was used to ascertain that my operating environment meeting the specification and here is the result:

Please note the facility is not sensitive to operating system and all versions of the operating system contains the latest updates.


1) Select a New Term Deposit option.
The facility displays a list of term deposit option as shown here:

Looks good but on the above mentioned environment it does not allow the user to click on any radio button to select the prefer option unless I am using IE8 & 10. This part also fails in IE11 like Firefox. To ensure no Firefox add-in was causing the problem, the Firefox was re-run in safe mode and it produced the same result. I have also test them using Firefox in Win7 and producing the same result.

Hence this part of the web page appears to be very sensitive to the browser version and type or one could not trust the verification service of NetBank.

2) This is the best one I have seen that even a primary school kid knowing real number comparison could see the folly.

In a section available for entering maturity instructions - which do not appear to apply for the imminent renewal but from all the descriptions, this section appears to be apply at the maturity of the imminent renewal. That confusing part (prime candidate for "Why Software Sucks") is not relevant to the current issue.

In that section there is a field where you can specify "Additional investment amount" and next to the field is a maximum figure of $1,897,643.83, which I can guarantee anyone that I do not have. Please note this figure.

When you enter a value of 0.5, representing 50 cents, the entry validation control raises an error like this:

The error message is:

Since when is 0.5 NOT "less than or equal to the maximum amount ($1,897,643.83) shown"?

I believe what happens under the hood is the application of "Everything is a Nail" anti-pattern looking like this:

    if ( !ValidateInput(amount) )
         ErrMsg = "Please enter an amount less than or equal to the maximum amount shown";
 
As long as ValidateInput() returning false, the same error message is used, irrespective if it is appropriate. In the ValidateInput() $0.5 is probably not a valid entry - being below the minimum of $1.00, I guess. The developer probably expects the user to possess psychic power that can see the rule table residing on the CBA Server.

If you have previously defined an additional investment amount and wanting to remove it. In IE10, you can delete it but it then raises another error like this:

In Firefox, when one tries to delete the entry, the program raises the above mentioned error message. In IE10, you could ignore that protestation and the submit button allows the user to commit the changes even when it says the field is required but with no data. Is it a required field or is it not?

Now you see this buggy program creates more frustration and raise the blood pressure higher.

Thursday, January 30, 2014

Worthy Pdf readers in Linix Mint/Ubuntu

There are plenty of questions on the Internet asking whether there are any PDF Readers (free of course) for Linux that have more capability than the one that is packaged with Ubuntu/Mint, the Evince, that allow the users to annotate and highlight the materials.

Adobe Reader 9 can do this provided that the document contains a policy allowing the users to comment and annotate. In the absence of such a policy, this reader defaults to denying such capability.

There does not appear to be any native Linux PDF readers that can do this. Some such as Okular can do highlighting etc but they are stored in their private format that only the viewer that created it could display them. Hence their annotations are not shown in say Adobe Reader. Therefore this class of viewers are considered not supporting the annotation and highlighting requirements.

As a last resort, I am using 2 Windows PDF viewers running in WINE in Mint/Ubuntu. They are PDF XChange Viewer and FoxIt Reader.

At the time of writing, I have uninstalled "PDF XChange Viewer" because in Mint-64 bit, it consistently crashed the reader when I was switching documents in the tabbed view of the reader. My experience is also supported by reported behaviour in the WineHQ. It is ashamed that it misbehaves in this manner. The other problem with this is with the display when scrolling the document. However, one can alter the display settings to prevent this.

While FoxIt Reader also has a native Linux version, it is a very basic reader similar to Evince that does not do annotation and highlighting. Consequently, this is not used. Instead FoxIt Reader version 6.1.2.1224 is installed with the support of WINE.

So far, it behaves well with the only exception that it fails to account for the height of the task bar in Mint when one maximizes the FoxIt window. As result, the navigation bar is partially covered.

The other issue which may unsettle some is the automatic installation and activation of the FoxIt cloud plug-in and the Reader does not have an easy way to uninstall this plug-in.

To disable this plug-in, close the FoxIt Reader and use the following steps in Mint/Ubuntu:
1) Bring up the File explorer, Nemo or Nautilus
2) Press Ctrl-H to view hidden file
3) Locate the Windows system tools in WINE installed directory which is by default located here:
~/.wine/drive_c/windows/system32
4) Then use the "Wine Windows program loader" to load Control.exe, the Windows control panel program and you should see a window like this:
5) Double click on "Add/Remove Programs" to start the program.
6) Locate the item called "Foxit Cloud" and uninstall that program item.

Next time you start FoxIt Reader, you will not see the "FoxIt Cloud" menu item. I only wish FoxIt would offer a more user-friendly way to disable it and also seek user's consent before activating the plug-in and FoxIt cloud.


Monday, January 27, 2014

Common reasons in software system failure

A post by Charette in IEEE Spectrum on the failure of various government systems sums up pretty much the general reasons why they fail:

put all the blame for the fiasco on Deloitte, which Deloitte heatedly contests. News reports state that at least one Florida lawmaker is suggesting that Deloitte be barred from future Florida contracts, something that Australia’s Queensland government has done to IBM as a result of Big Blue's role in the Queensland Health payroll debacle.
[...]
The bottom line was that no one was in charge, vendors and the state did not get along, the vendors themselves did not get along, no one wanted to hear about the myriad significant technical risks, and political motivations dominated decision making. In other words, all the makings of an all-too-typical government IT project.
Could it be that we are trying to develop software to do far more complex stuff, instead of being a tool to help human, they are being developed to replace human? In many of these systems, the common theme in all these failures - hire more human to remedy the failure!

In most of these large systems development, by the time the system is ready, the world has changed; the political scene has changed causing requirements to change; rules are changing all the time before the ink is dried.


Monday, January 6, 2014

Do not accept answers that you do not understand.

Not only it is the duty of the purse string holders needing to know precisely, without being clouded by technical jargon, what a software solution can do for the enterprise, every users need to know. This ensure that the buyers and users know precisely what they are getting and what they are paying for.

It is refreshing to come across this article in Financial Times relaying the experience of a very wise and persistent director of an enterprise that "demanded the computing experts translate their plans into plain English."

Far too often, as I have observed, that the recipients of software products choose to keep quiet for fear of showing up their ignorance or failure to comprehend of the materials from the so-called "technical experts". They all should emulate this "Dennis".

In fact, it is the communication fault of the "technical experts" that fail to explain the materials, particularly the functional part, in the terms that the users can understand. I don't expect them to explain how data base schemas are designed, XML messages being passed around or how to pool connections but at least they should be able to answer user-centric questions like what is the response time of say 20,000 users accessing the system, the stability of the system in terms of how often one expects a failure.

In a theme similar to the "Why Software Sucks" but at a different level, the  messages from the FT article are worth remembering. Admitting one does not understand the gobbledegook, often silently, and then not demanding answers to one's satisfaction is an abdication of one's duty.



Blog Archive