Here's an interesting exercise for the day.

 

In Visual Studio 2005/2008,

1. Create a new Console Application.

2. Put in the following code in Main:

double x = 5.15;
double y = x / 100;
Console.WriteLine("y = " + y);

3. Put a breakpoint at the Console.Writeline(..).

4. Press F5 to debug the application.

5. Watch the value of y. What is its value in the watch window?

6. Press F10 to continue with the console write. What is the value of y as displayed?

 

Do the same for x=4.15, x=6.15,x=7.15,x=8.15.... What are the values displayed?

Try also to divide by 10 or 1000 using the same set of values for x. (E.g. 4.15/10, 6.15/1000). What is the resulting value for y?

 

Using pen and paper, what are the supposed results? :)

 

Hint: It appears that there are extra values for the results using x=5.15, x=6.15, and x=7.15. Weird eh?

 

I've stumbled upon a free .Net obfuscator--Eazfuscator.NET. So far, it works well for my purposes. Most obfuscators are costly--ranging from $200 to $2000! But this one is freeware and it works better than the free one bundled with Visual Studio 2005.

It is free and easy to use!
Okay, after almost a year and an offshore assignment, I finally had a chance to update this blog.

I was developing a .Net 2.0 C# windows application wherein I basically have to print PDF files from a Windows application. I tried to use the Adobe Acrobat Reader ActiveX object embedded in my form to preview and print PDF documents. It worked fine; I just have to import the COM component and Visual Studio will do most of the Interop work for me. I then have to locate the file and load it to the AxAcroPDF control:

axAcroPDF1.LoadFile(pdfFileName);

I'd then delete the PDF file immediately afterwards to somehow obscure it from the user. The ActiveX object seems to save it in memory such that I can make a call like:

axAcroPDF1.Print();


...and all went smoothly. But when I ran it on another machine with the most recent version of Acrobat (8.1.2), I got an E_NOINTERFACE exception. After much research, I then decided to use a WebBrowser .Net 2.0 control instead. Thus, my codes looked like so:

webBrowser1.Navigate(pdfFileName);


...assuming of course that the user has a PDF reader installed and integrated into his web browser. This is a much easier alternative than to using unmanaged code. However, it does not go away without problems. When I try to call:

webBrowser1.Print();


I get nothing. I can't seem to force the browser to print its PDF contents. To keep the long story short, I had to tinker with the underlying ActiveX object of the WebBrowser control. First, I needed a reference to shdocvw.dll (windows system32 directory). Then, I did something like:

object n = null;
SHDocVw.WebBrowser wb = (SHDocVw.WebBrowser)webBrowser1.ActiveXInstance;
wb.ExecWB(OLECMDID.OLECMDID_PRINT
, OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER
, ref n
, ref n);

It worked! (MSDN says that the two pointers are optional so I just put null in there.)

WCF

This week I had a Windows Communications Foundation training from Developmentor, sponsored by our company. I learned a lot about the new framework (dotnet 3.0) and communications. What interested me the most was the Day 4 topic which was Peer-to-peer applications. Although I might not be able to use it for regular business applications, I would be using it just for fun.

Here is our instructor's (Scott Reed) del.icio.us link:
http://del.icio.us/mscottreed
Posted by Alexis' Blog
There is a slight modification for my previous post. The conditions for the if statement there is inadequate. The bug occurs when refreshing the browser when the mouse is beyond the leftmost side of the window, a valid yet unanticipated negative value for the X. This is evident especially for dual monitors--like what I am using. Thus the new conditions are as follow:

if (window.event.clientX 0
&& window.event.clientY 0
&& (window.event.clientX -1000 || window.event.clientY -1000)) {

//do closing routine...
}


The 1000 value is a safe value for anticipating the event that we really expect--i.e. closing the window. Apparently, values lower than that seem to cause erroneous triggering.
This is in response to my previous post re JavaScript Hashtable Implementation. I modified my code to be able to remove elements, as well as get an enumeration of the elements in cases wherein the keys are strings rather than integers.

Here are the new members of the Hashtable object:

Methods:
remove(string keyName) - Remove an element by key name
getAt(int index) - Get the value at the specified index
getEnum[int index] - Get the key name at the specified index

Properties:
count - Get the number of elements of the Hashtable object
location - (deprecated)

So, here's the new code:

// create an instance of the hashtable object
function Hashtable(){
this.hash = new Array();
this.keys = new Array();
this.getEnum = new Array();
this.count = 0;
}

Hashtable.prototype.hash = null;
Hashtable.prototype.keys = null;
Hashtable.prototype.count = null;
Hashtable.prototype.getEnum = null;

// get the value at the specified index
Hashtable.prototype.getAt = function (index) {
return this.hash[this.getEnum[index]];
}

// get the corresponding value
Hashtable.prototype.get = function (key) {
return this.hash[key];
}

Hashtable.prototype.remove = function (key) {
for (var i = this.keys.length - 1; i >= 0; i--) {
if (this.keysIdea == key) {
this.keys.splice(i, 1);
this.getEnum.splice(i, 1);
this.hash[key] = null;

this.count = this.keys.length;
}
}
}

// create an entry in the hashtable
Hashtable.prototype.put = function (key, value) {
if (value == null)
return null;
// create a new entry
if (this.hash[key] == null) {
this.keys[this.keys.length] = key;
this.count = this.keys.length;
this.getEnum[this.count - 1]= key;
}

// set the value
this.hash[key] = value;
}
Posted by Alexis' Blog
Filed under: ,
I found this blog that addresses my concern in IIS 5.1 for Windows XP. I recently discovered that it is crippled in such a way that it only allows 10 concurrent connections. Moreover, it is hardcoded to be configured to at most 40. If the maximum concurrent connections have been reached, your website's users will receive the following error:

HTTP 403.9 - Access Forbidden: Too many users are connected
The workaround involves modifying the maximum allowable connections to 40. Still, you're stuck at 40.
Posted by Alexis' Blog
I needed to do some routines when a user has closed the window. I do not want those routines to trigger when refreshing the page or unloading the document; I just need them to happen when the browser window is closed.

This is the usual proposed solution: assign a function on the onbeforeunload event of the body or window. The problem with this is it also triggers when refreshing or moving away from the page (i.e. back or forward). I stumbled upon a solution that proposes tapping the onunload event instead. Thus, I have a function like this:

function body_unload() {
if (window.event.clientX 0) {
alert("The user is closing the window.");
} else {
alert("The user is refreshing or navigating away.");
}
}

I then assign this to the onunload event of the body. From there I could perform my JavaScript and/or AJAX routines.

Although this works for my purposes, the main downside of this is that I cannot issue a confirm dialog. The page has been unloaded at this point.
In Internet Explorer, when you use window.close() in JavaScript to close the current browser window, you will be asked something like "A script is attempting to close this window. Do you want to continue?" As a programmer, this can be annoying if you are un-maliciously closing the window. A workaround to this would be setting the window.opener property to something else.

Example:

In your JavaScript, have something like:
function logoff() {
if (confirm("Do you want to log off?")) {
window.opener = "x";
window.close();
}
}


Then in your HTML, have a button or link that calls this JavaScript function onclick.
Ever had Windows XP crash? And worse comes to worse you had to reformat your PC and you need to back up your data? The BIG problem is: you can't access your folders! Well, here's a workaround I've gathered around the net (that is yet to be personally tested). It is however assumed that you haven't encrypted (i.e. files with green filenames) your files. That is "irreversible" and thus cannot be recovered.

1. Use your drive as a slave drive in another computer. The master should have a Windows XP installed and the user logged on must have administrator rights. Let's say your data drive is D: while your system drive is C:.
2. Open your trusty command prompt and type the following:
cacls [FOLDER or FILENAME] /E /P [USERNAME]:F
where: FOLDER or FILENAME = the name of folder or filename to gain access to
USERNAME = the currently logged-in user's Windows XP account name

CALCS is the command to display or modify access control lists (ACLs) of files.
/E Edit ACL instead of replacing it.
/P user:perm Replace specified user's access rights.
Perm can be: N None
R Read
W Write
C Change (write)
F Full control


3. To restore the ACL for that folder/file:
cacls [FOLDER or FILENAME] /E /R [USERNAME]
Posted by Alexis' Blog
Filed under: ,
The problem: I have a two-dimensional object array. Each first level element of the array contains five object elements--except for the last one, which only has three. However, I have a procedure that needs to concatenate another array at the end of the original one. Since I need to put the unique three-element object array at the end of the list, I had to find a solution to sort it via the elements' length.

The immediate solution was to use ArrayList.Sort(IComparer). Okay I created a class that looked similar to this:

class MyComparer : IComparable
{
private object _data;
public object Data
{
get { return _data; }
}
public MyComparer(object data)
{
_data = data;
}

int IComparable.CompareTo(object obj)
{
MyComparer mc = (MyComparer)obj;
object[] myData = this._data as object[];
object[] thatData = mc.Data as object[];
return (myData.Length
}


To use it in one of my methods:

private static object[] _sortChartData(object[] oData)
{
ArrayList arrData = new ArrayList();
for (int i = 0; i < oData.Length; i++) {
arrData.Add(new MyComparer(oDataIdea));
}
arrData.Sort();
for (int j = 0; j < arrData.Count; j++) {
arrData[j] = (arrData[j] as MyComparer).Data;
}
return arrData.ToArray();
}


With this I can sort the contents of the original object[] to the one desired.
Posted by Alexis' Blog
Filed under: ,
I've come across Predicates in dotNet 2.0. I felt so disgusted with too many foreach loops when looping through list collections. So, here was my problem: I have three string Lists, say, A, B and C. List string A is the reference list; while B and C contain elements found in A. By brute force method (and practically the only way we can do it in dotNet 1.x), we do something like:
foreach (string strA in A)
{
foreach (string strB in B)
{
if (strB.Contains(strB)) { /* do something... */ }
}
foreach (string strC in C)
{
if (strC.StartsWith(strC)) { /* do something... */ }
}
}

In dotNet 2.0, Predicates are provided for the generic features such as the System.Array and System.Collections.Generic.List classes. These classes provide methods like Find, FindAll, FindLast, etc. that use predicates to help developers search for certain elements in collections via delegates rather than looping at each element. Developers get the ability to "walk" an entire data structure, determining whether each item meets a set of criteria, without having to write the boilerplate code to loop through each row manually. In addition, it is more efficient to go.

Okay, back to our example. By employing predicates, I created a new class called StringFilter:
public class StringFilter
{
private string _strReference;
public bool ContainsString(string s)
{
return s.Contains(_strReference);
}
public bool StartsWithString(string s)
{
return s.StartsWith(_strReference, StringComparison.InvariantCultureIgnoreCase);
}
public StringFilter(string strReference)
{
_strReference = strReference;
}
}

Now, rewriting our example using this new class as predicate:

foreach (string strA in A)
{
StringFilter sf = new StringFilter(strA);
if (B.Exists(sf.ContainsString)) { /* do something... */ }
if (C.Exists(sf.StartsWithString)) { /* do something... */ }
}
The new class provides flexibility in searching elements of the collection.
Posted by Alexis' Blog
This code returns the volume serial for a hard drive (VB6).

Code

Public Declare Function GetVolumeSerialNumber Lib "kernel32" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As Long, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber As Long, ByVal lpMaximumComponentLength As Long, ByVal lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As Long, ByVal nFileSystemNameSize As Long) As Long

Public Function VolumeSerial(DriveLetter) As Long
Dim Serial As Long
Call GetVolumeSerialNumber(UCase(DriveLetter) & ":\", 0&, 0&, Serial, 0&amp;amp;, 0&, 0&, 0&)
VolumeSerial = Serial
End Function


Example Usage
MsgBox VolumeSerial("C")
Posted by Alexis' Blog
Filed under: ,
It is officially released.

The Microsoft .NET Framework 3.0 is the new managed code programming model for Windows®. It combines the power of the .NET Framework version 2.0 with new technologies for building applications that have visually compelling user experiences, seamless communication across technology boundaries, and the ability to support a wide range of business processes. These new technologies are Windows Presentation Foundation, Windows Communication Foundation, Windows Workflow Foundation, and Windows CardSpace. The .NET Framework 3.0 is included as part of the Windows Vista™ operating system; you can install it or uninstall it using Windows Features Control Panel. This redistributable package is for Windows XP and Windows Server 2003.
Downloads:
Posted by Alexis' Blog
The recent Office 2007 RTM presents a bug when opening buildingblocks.dotx. The solution for this is to delete the file and let Office recreate it. It can be located in:

%drive%:\Documents and Settings\%username%\Application Data\Microsoft\Document Building Blocks\1033
Posted by Alexis' Blog
Filed under: ,
More Posts Next page »