Enable Debugging In DLL Development

When developing a standard application it’s easy to just debug it step-by-step. But, when developing a library (DLL file), we need to do additional steps.

In this case I’m using Visual Studio 2005 and developing a library that will be used by IIS 7 in Windows Server 2008 environment.

Step 1:

Run remote debugger wizard from “Start -> All Programs -> Microsoft Visual Studio 2005 -> Visual Studio Tools -> Visual Studio 2005 Remote Debugger Configuration Wizard”

The purpose of this step is to open ports in Windows Firewall for Visual Studio to do debugging.

msvs2005rdcwizard_01

msvs2005rdcwizard_02

msvs2005rdcwizard_03

msvs2005rdcwizard_04

Step 2:

Run the remote debugger based on the processor the library is built. In this example the library is built using x86 processor. Run the program from “Start -> All Programs -> Microsoft Visual Studio 2005 -> Visual Studio Tools -> Visual Studio 2005 Remote Debugger”.

Up to this step the remote debugger is already up.

msvsrdmonitor_01

msvsrdmonitor_02

Step 3:

Make sure the output of the library is the location where the library will be called by the IIS.

SolutionPropertiesBuild

Step 4:

Attach the process to IIS process in “Tools -> Attach to Process …”, select to show “Managed code” only, and then choose IIS process (w3wp.exe) from the list.

msvstools_01

msvsattachtoprocess

After the process is attached the solution will run in debug-mode by itself. Create a break-point in the library code, and then run the program that trigger this library, you will see process will stop at the designated break-point.

Reference:

http://cedricboudoya.wordpress.com/2008/11/04/how-to-debug-a-wcf-service/

Read XML File Using Visual Basic 6

There are many ways to store a data in a file, one of them is using XML format. Recently I had a project that I put settings into a XML file.

<SETTINGS>
    <DISCOUNTOPTFIELD>DISCOUNT</DISCOUNTOPTFIELD>
    <DISCOUNTITEM>DISCOUNT</DISCOUNTITEM>
</SETTINGS>

I’m using Visual Basic Application to access the XML file. In order to do that I used Microsoft XML v.6.0 (msxml6.dll).

msxml6

The implementation of msxml6 is as shown below:

Public Function readSetting(sSettingName As String) As String
On Error Resume Next

    Dim doc As New MSXML2.DOMDocument60
    Dim success As Boolean
    Dim sResult As String

    success = doc.Load("settings.xml")
    If success = False Then
        MsgBox doc.parseError.reason
    Else
        sResult = doc.selectSingleNode("/SETTINGS/" & UCase(sSettingName)).Text
    End If

   readSetting = sResult
End Function

The value of variable sSettingName is either “DISCOUNTFIELD” or “DISCOUNTITEM”.

Reference:

http://stackoverflow.com/questions/3870485/reading-xml-files-in-vb6

Preventing Multiple Instances of An Application

Have you experienced a user that run an EDI application two times in one computer, which cause the data that being transferred became haywire? I have.

One way to solve this problem is by preventing the second instance of the application to run.

In Visual Basic 6 we can use the code below:

    Dim rc As Long

    If App.PrevInstance Then
        rc = MsgBox("Application is already running", vbCritical, App.Title)
        Exit Sub
    Else
        frmMain.Show
    End If

In Visual Basic .NET (2005) we can use the code below:

    Dim oMutex As System.Threading.Mutex
    oMutex = New System.Threading.Mutex(False, "ca91daff-26a3-49cd-97e0-4d57b50c9d3b")
    If (oMutex.WaitOne(0, False) = False) Then
        MessageBox.Show("The Accpac Interface is already running")
        Exit Sub
    End If

The “ca91daff-26a3-49cd-97e0-4d57b50c9d3b” is the application GUID. You can find it in the Project Properties -> Assembly Information

ProjectProperties

AssemblyInformation

Another way of doing it is by using “Make single instance application” option in the Project Properties, I have never used this method though.

MakeSingleInstanceApplication

One more way to prevent multiple instance is by checking all of active processes, see the code below:

    Dim instanceCount As Integer = Process.GetProcessesByName("explorer").Count()
    Console.WriteLine(String.Format("{0} Instances Running", instanceCount.ToString()))
    Console.ReadLine()

References:

DEP Problem with Customized .NET Program

Last month there was a customer that wanted to migrate their server to a new server. Last time the server’s operating system was Windows Server 2003 64-bit. Now their server’s operating system is Windows Server 2008 R2. In this new server they need to run a customized program, that was created using Visual Basic .NET. But, after installed the Accpac Finder of the program caused the program to crash for every time it was executed.

screenshot

According to my colleague’s experience, this problem is caused by DEP setting in the windows that isn’t allowing the Accpac Finder to run. In order to by pass the checking by DEP, we needed to run a command that will amend the program. One thing to be noted is this command must be run in Visual Studio 2005 Command Prompt.

editbin.exe /NXCOMPAT:NO C:\Project Folder\bin\Program.exe

After the command was executed, the program could execute Accpac Finder.

Tribute to my colleague, Edy Simon.

Seek Function for MS Access

“Seek” function is very useful when we need to find a record from a long list of records. This function is finding a given value in an indexed field. Unfortunately it is not so straight forward when working with Microsoft Access database. By default it is not possible to use “Seek” function of ADODB to find records in Microsoft Access database.

In order to do that we need to set “CursorLocation” as “adUseServer” and “Options” as “adCmdTableDirect” when we open the recordset. Below is the sample of using “Seek” function.

Sub LinkTableSeek()
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset

    Set cn = New ADODB.Connection
    With cn
        .Provider = "Microsoft.Jet.OLEDB.4.0"
        .ConnectionString = "C:\Program Files\Microsoft " _
        & "Office\Office10\Samples\Northwind.mdb"
        .Open
    End With
    Set rs = New ADODB.Recordset
    With rs
        .ActiveConnection = cn
        .Source = "Customers"
        .CursorLocation = adUseServer

        .CursorType = adOpenKeyset
        .Open Options:=adCmdTableDirect
        .Index = "PrimaryKey"
        .Seek "WOLZA"
        If (Not .EOF And Not .BOF) Then
            MsgBox rs.Fields("CompanyName").Value
        Else
            MsgBox "Record not found"
        End If
        .Close
    End With
    Set rs = Nothing
    Set cn = Nothing
End Sub

Check this link from Microsoft support website.

Instance Cloning

Sometimes I got confused myself how to copy an instance to another identical instance.  I found an interface called “ICloneable Interface”. When in use this interface will create a new method called “Clone”. In this method I need to write code to create a new instance and then copy the content of every property into the new instance. The process of cloning gave me another question mark, why should I use “ICloneable Interface” while I could copy the instance without using the interface. Could I remove the “ICloneable Interface”?

Luckily I found this thread in one of StackOverflow’s forum. Matt Hamilton, that referred Brad Adam’s article, suggested that we should not use “ICloneable Interface” anymore, because it only done a shallow-copy.  He recommended that we should create our own “Clone” method to do the cloning.

References:

Enum Item Naming Problem in Visual Basic 6

In Visual Basic 6 and previous versions, if you type an Enum value with the wrong case the system changes the case to match what you typed. For example, suppose you define an Enum like this:

    Private Enum People
        perManager
        perEmployee
        perCustomer
    End Enum

Now suppose you are writing code and you type:

    the_customer.PersonType = percustomer

Visual Basic updates the definition of the Enum so this value is spelled percustomer rather than perCustomer. Not fatal but annoying!

You can prevent this by declaring variables with the same names and the proper case. The coolest part is that the declarations don’t need to be incorporated into the compiled code so you can hide them using compiler directives.

    #If False Then
        Dim perManager
        Dim perEmployee
        Dim perCustomer
    #End If

    Private Enum People
        perManager
        perEmployee
        perCustomer
    End Enum

Now if you type the Enum value in the wrong case, Visual Basic corrects it so it matches the hidden variable declarations.