Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Log Application Versions

3.00/5 (5 votes)
23 Aug 20056 min read 1   297  
Logging remote application version numbers using web services

Sample Image

Introduction

This article is about using a web service to gather remote program version numbers. The problem was that many customers were running multiple versions of our product. We had no idea of what version they had and sometimes neither did they when they called for support. Since the customers were allowed to run a production version, a test version, and a development version of our products, we needed to know what version they were running in what circumstance. To retrieve the information that we needed, we used web services since the resulting data stream is nothing more than XML, which is plain text, and it can be transferred essentially without restriction over networks that have security measures in place to block other kinds of data. This code snippet shows the basic algorithms used in the process. Before installing, please read the Readme.txt file.

Background

There are many good books available to learn web services. You can also learn by reading and trying the articles at CodeProject or other sites. If you are unfamiliar with webservices, any place is a good place to start.

Using the Code

There are two pieces of code that will be shown. First, the web service since it will be called by the client. The pieces of information that we needed to gather are, Customer, Computer Name, Place, Product, Version, and Date. The information was gathered during the install and saved to a config file. With this information, we could determine what each customer had for each product installed. To store the information, I used Access, but you could just as easily use any other database. When the request came in, I wanted to see if the same pieces of information had already come in. If so, then all that was needed was to update the date. This way, we could run a report for each customer to see what versions of the products they were running when they called. Old dates for customers showed that the server is no longer being used. This could happen when a server dies.

To start, I created a web service project which just had the hello world WebMethod. I kept this method for testing down the road. I added a new method called SetCVersion.

VB
'
' Web service to track what servers are live
' with what versions of the software.
'
Public Function SetCVersion(ByVal Cusname As String, _
    ByVal ComputerName As String, ByVal PlaceName As String,
    ByVal ProductName As String, _
    ByVal VersionNumber As String) As Boolean
        Dim flg As Boolean
        Dim cdb As CVersionDB
        '
        ' Create the class to store the information
        '
        cdb = New CVersionDB()
        '
        ' Initialzise the class. get the connection
        ' string and any other information that is needed. 
        '
        cdb.Initialize()
        '
        ' Update the database to hold the passed information
        '
        flg = cdb.UpdateDB(Cusname, ComputerName, _
                  PlaceName, ProductName, VersionNumber)
        '
        ' Return the status. 
        '
        SetCVersion = flg
End Function

As discussed, we wanted to track all of the information but only add or update based on the last time it was sent. I created a class to do the database updates; this separates the web service from the actual code that does the business logic. You should always do that since the code may be called from another component later. In fact, you should really create an assembly that does the work but for showing the concept, I did not do that.

The Initialize method just gets the connection string from the config file. The UpdateDB method does all of the work. Based on the passed information, we retrieve the records for the company, computer, and all of the other information. If we find a record, we update the date to show that it was used at that location. If we do not find a record, we add one. All we are trying to do is keep track of the products and their versions on each computer to help the customer out when they call. For clarity, I removed the error logic for demonstration purposes, but it is in the downloadable code.

VB
    Public Function UpdateDB(ByVal Cusname As String, _
        ByVal ComputerName As String, ByVal PlaceName As String, _
        ByVal ProductName As String, _
        ByVal VersionNumber As String) As Boolean
    Dim cnn As OleDbConnection = New OleDbConnection(connstr)
    Dim cmdVersion As New OleDbCommand
    Dim cversionDA As New OleDbDataAdapter
    Dim cversionDS As New DataSet
    Dim selstr As String
    Dim tblName As String = "CVersions"
    Dim recordCnt As Integer
    Dim recordPos As Integer
    Dim retflag As Boolean
    Dim AddType As Boolean
    Dim NowTime As Date = Now
    '
    ' Set the initial strings so we can use them as we go. 
    '
    retflag = False
    selstr = "SELECT * FROM CVersions Where CVCustomer = '" & _
              Cusname & "' AND CVComputerName = '" & _
              ComputerName & "' AND CVProduct = '" & _
              ProductName & "' AND CVVersion = '" & _
              VersionNumber & "' AND CVPlace = '" & PlaceName & "'"
    Try
        cmdVersion = cnn.CreateCommand
        cmdVersion.CommandText = selstr
        cversionDA.SelectCommand = cmdVersion
        ' Automatically generate the Update, Insert, 
        ' and Delete commands
        Dim cb As OleDbCommandBuilder = _
               New OleDbCommandBuilder(cversionDA)
        recordCnt = cversionDA.Fill(cversionDS, tblName)
        recordPos = 0   ' set the initial record position
        AddType = False
        If recordCnt = 0 Then
            Dim myRow As DataRow
            Try
                ' if not found then create a row
                AddType = True
                myRow = cversionDS.Tables(tblName).NewRow()
                cversionDS.Tables(tblName).Rows.Add(myRow)
                ' find the count so we can update
                ' the data, or in this case create it. 
                recordCnt = cversionDS.Tables(tblName).Rows.Count
                recordPos = recordCnt - 1   ' zero based

            Catch ex As Exception
                '
                ' Catch any exceptions that may occur
                '
                ' Create the LogFile class
                '
            End Try
        End If

        cversionDS.Tables(tblName).Rows(recordPos)("CVCustomer") = Cusname
        cversionDS.Tables(tblName).Rows(recordPos)("CVComputerName") = ComputerName
        cversionDS.Tables(tblName).Rows(recordPos)("CVPlace") = PlaceName
        cversionDS.Tables(tblName).Rows(recordPos)("CVProduct") = ProductName
        cversionDS.Tables(tblName).Rows(recordPos)("CVVersion") = VersionNumber
        cversionDS.Tables(tblName).Rows(recordPos)("CVDate") = NowTime

        cversionDA.Update(cversionDS.Tables(tblName))
        retflag = True
        '
        ' Create the LogFile class
        '
        Dim lff As New LogFile
        '
        ' Initialzise the class. get the LogLocation string
        ' and any other information that is needed. 
        '
        lff.Initialize()
        '
        ' Depending on if this was an update
        ' or an add show the result in the log file. 
        '
        If AddType Then
            lff.write("Added record for cus = " & Cusname _
                      & " Computer = " & ComputerName & _
                      " Product = " & ProductName & _
                      " Version = " & VersionNumber & _
                      " Place = " & PlaceName)
        Else
            lff.write("Updated record for cus = " & _
                      Cusname & " Computer = " & ComputerName & _
                      " Product = " & ProductName & _
                      " Version = " & VersionNumber & _
                      " Place = " & PlaceName)
        End If
    Catch ex As Exception
        '
        ' Catch any exceptions that may occur
        '
    End Try
    '
    ' Cleanup after you
    '
    cversionDS.Dispose()
    cversionDA.Dispose()
    '
    ' Show our return status
    '
    UpdateDB = retflag
End Function

Now to test this without a client, just start the project. The initial page in the article should show up, that is the default page. Enter in the sample data and press the Invoke button. This will send in the data as if it came from a client. You can debug the entire web service this way. Before we put this in the public domain, we must set the namespace. By not having set one, the default of tempuri.org is used. Now this is fine for development purposes but it must be changed before you put this to use. Based on what your webservice will be doing, you should also check the different attributes that are available. Some will increase performance based on what you are doing. In a future article, we will explore the performance of this webservice. Some of the attributes that are available are:

Property Description
BufferResponse true/false - get or set if this webmethod should buffer the response it sends back
CacheDuration Allows you to get or set how long the buffered response is held for
Description Set a descriptive message about this webmethod
EnableSession true/false - get or set whether this webmethod supports sessions
MessageName Set the name of the method that users will use in their URL when calling it
TransactionOption Allows you to get or set whether this method will support transactions and in what capacity
TypeID Set a unique value if you subclass the ATTRIBUTE class

The client is a VB form application that calls the web service. For testing purposes, I created two ways to call the web service. One interactive, and the other in a batch mode. I prompt for the URL so I can test from a remote machine and the local machine that the web service is running on. When you run the client program on a remote computer, just change localhost to the machine name that the web service is running on.

Sample Image

Using the program in an interactive mode, we can now test a new company, computer and an update of a company, computer. If you enter information in for the first time, it should be an add. If you press the Send button again, it should be an update. An example of setting the URL in code is shown below for the batch mode. If the TargetURL string is empty, I use the string from the config file. If the user has entered in another URL, I will use that one.

VB
Private Sub Sendbatch()
    Dim mycver As New localhost.CVersion()
    Dim flg As Boolean
    Dim ss As String
    '
    ' This is what would be used to change the url of the web service.
    '
    ss = txtURL.Text
    If (ss = String.Empty) Then
        mycver.Url() = ConfigurationSettings.AppSettings("URLStr")
    Else
        mycver.Url() = ss
    End If
    '
    ' Call the webs service in a batch mode.
    ' Meaning a few times without operator input
    '
    flg = mycver.SetCVersion("Customer1", "computer1", _
                      "place1-prod", "product1", "v1.1")
    flg = mycver.SetCVersion("Customer1", "computer2", _
                      "place2-test", "product2", "v6.9")
    flg = mycver.SetCVersion("Customer2", "computer1", _
                      "place1-prod", "product1", "v1.2")
    flg = mycver.SetCVersion("Customer2", "computer2", _
                      "place2-test", "product2", "v7.0")
End Sub

These programs show the basic web service in use. From this, you should be able to create your own web service to do the tasks that you need to do.

Points of Interest

Some of the next things I plan to write about are using this web service to do performance testing. That is the main reason I left the helloworld and byebye world web methods in the service. One item you might have noticed is that anyone can send in the information since there is no security around the service. With the release of WS-Security or .NET 2.0, you will be able to include account information in the header of the message.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.