Sunday, December 6, 2009

Wordpress

After a little bit or research I decided to move my blog over to wordpress.

http://vbguru.wordpress.com

Friday, December 4, 2009

Inheritance, and why it rocks!

Inheritance is something that is very foreign to a VB6 developer, however it is very, very cool. Think about this scenario lets say your are on a team of developers. You are working on a product intended to sell to a retailer who wants to process credit cards. But each retailer will use a different credit card processor so you need to support Costco, paypal, and Autorize.Net. Your job is to write the code that connects to the gateway, but there are other devlopers on your team that need to be able to use your code. How do you give them one interface to your code, but you want to execute the right routine based on the credit card processor? Well inheritance offers the perfect solution.

Here we create our 'base' class. We declare it as MustInhert so that we can use the MustOverride property on the ProcessCard Function

Public MustInherit Class CreditCard

  Public MustOverride Function ProcessCard(ByVal CardNumber As String) As Boolean

End Class


You'll notice that we created a function signature, but it has no code attached. We add the code later when we create the gateway's class.

When your create your class that inherits your base class you'll notice when you add the line 'Inherits CreditCard' that it will autofill the MustOverride Function.  Visual Studio makes it easy for you!

Public Class Costco
  Inherits CreditCard

  Public Overrides Function ProcessCard(ByVal CardNumber As String) As Boolean
    'code to process a costco card
  End Function

End Class

Public Class AutorizeNet
  Inherits CreditCard

  Public Overrides Function ProcessCard(ByVal CardNumber As String) As Boolean
    'code to process a Autorize.Net card
  End Function

End Class

Public Class PayPal
  Inherits CreditCard

  Public Overrides Function ProcessCard(ByVal CardNumber As String) As Boolean
    'code to process a PayPal.Net card
  End Function

End Class

Your other team members will love you if you now use a 'wrapper' to manage the gateway, check this code out:

Public Class MyCreditCard
  Private mGateWay As CreditCard

  Sub New()
    'ASK THE DATABASE OR INI OR SOMETHING
    'WHAT PROCESSOR TO USE and put it in i
    Dim i As Integer

    Select Case i
      Case 0
        mGateWay = New Costco
      Case 1
        mGateWay = New AutorizeNet
      Case 2
        mGateWay = New PayPal
    End Select

  End Sub

  Public Function ProcessCard(ByVal CardNumber As String) As Boolean
    mGateWay.ProcessCard(CardNumber)
  End Function
End Class

Now your UI guy just has to write something like this and he never has to worry about which credit card processing gateway you are using.

  Public Sub ProcessCC()

    Dim cc As MyCreditCard = New MyCreditCard

    cc.ProcessCard("12456789012345")

  End Sub

Thursday, December 3, 2009

Using a One-Way Hash on Passwords

The best thing to do with a password is convert it into a one way Hash. This way no one knows what your user's passwords are, not even a hacker who got into your database. Here is a small class I wrote to Convert a password into a hash.

Public Class Hash

 

  Private Function ComputeHashValue(ByVal data() As Byte) As Byte()

    Dim hashAlg As System.Security.Cryptography.SHA1 = System.Security.Cryptography.SHA1.Create()

    Dim hashvalue() As Byte = hashAlg.ComputeHash(data)

    Return hashvalue

  End Function

 

  Public Function HashPassword(ByVal password As String) As String

    Dim encoder As System.Text.UTF8Encoding

    Dim b() As Byte

 

    encoder = New System.Text.UTF8Encoding

    b = encoder.GetBytes(password)

    b = ComputeHashValue(b)

 

    Return Convert.ToBase64String(b)

 

 

  End Function

 

End Class

Wednesday, December 2, 2009

Being Good With SQL, Using SQL Cursors

If you want to make any money programming in VB.NET then you need to be in the business of writing good SQL server code. VB, business programming and Databases all come together in the same package.  And so from time to time I will be giving out some tips about advanced SQL Server concepts.  I don't think of myself as a SQL Guru, but I do know a lot about it.  MS SQL is not the only database language you may need to learn, but the good news is that nearly all databases use the same T-SQL Language and so if you get good at one of them, it's generally pretty easy to use the others. Being good at designing table structure translates into EVERY database engine the same as well.


Today I wanted to talk for a moment about using SQL cursors, because they are very cool.  Have you ever wanted to do a loop inside a Stored procedure?  Well check out this code, you this will loop through all users that do not have a locker assigned (using a cool "NOT IN" SQL statement) and assign each of them the next available locker.



CREATE PROCEDURE [dbo].[spDEMO]
AS
BEGIN
    SET NOCOUNT ON;

DECLARE @idUser as int
DECLARE @idLocker as int

DECLARE UserLocker_cursor CURSOR FOR
        --Get all the users that don't have lockers
        SELECT idUser From tblUser where idUser NOT IN
            (

                SELECT idOwner from tblLocker where idOwner is not null
            )

        OPEN UserLocker_cursor

        FETCH NEXT FROM UserLocker_cursor
        INTO @idUser

        WHILE @@FETCH_STATUS = 0
        BEGIN
            SET ROWCOUNT 1 --Return only one record
            SELECT @idLocker=idLocker From tblLocker where idLocker is null
            SET ROWCOUNT 0 --Return all records (important to reset this setting!)

            --Now Assign a locker to each user           
            Update tblLocker set idOwner=@idUser Where idLocker = @idLocker

        FETCH NEXT FROM UserLocker_cursor
        INTO @idUser

        END

    CLOSE UserLocker_cursor
    DEALLOCATE UserLocker_cursor

END

Tuesday, December 1, 2009

Threading

When VB.NET first came out I had many thoughts of going back to VB6. They seemed to have changed everything, and the VB6 to .NET converter always failed to convert my code. But then there was two things that I discovered that sold me on VB.NET.

#1) Threading
#2) Registry Access

Back in my VB6 days my team tried many times to get things to work muti-threaded, there were magazine articles at the time that claimed to be able to do it using windows API hacks, and MDI forms, but we were never able to get it to work. In .NET you just have to call .Start on a thread object is just Amazing.

Registry access in VB6 was crazy. You had to write pages and pages of code using a bunch of Win32 API Calls. In .NET I changed my pages of code into just a few lines. Once I wrote my first .NET Registry access routine I never wanted to write in VB6 again.


Here is some code that I modified that does both Registry Access and threading. I'm not sure who wrote this code originally, but I modified it so it would be thread safe. Your form needs to have the following controls:

A timer named Timer1, set to go off every 5 seconds (5000 ms)
A datagrid control named DataGridView1
Two buttons Button1 and Button2


If your are using this on a VISTA box you will need to set your UAC Settings, see this post for more information. http://vb-daryl.blogspot.com/2009/11/uac-administrator-access.html



Imports System.Threading.Thread
Imports Microsoft.Win32


Public Class Form1

  Dim dtResults As DataTable
  Dim dtFound As DataTable

  Public Shared ProcessThread As System.Threading.Thread
  Dim Path As String = "SYSTEM\\"
  Dim SearchStr As String = "USERNAME"
  Dim WaitRequest As Boolean
  Dim TS As ThreadStatus

  Enum ThreadStatus
    Running
    Wating
  End Enum

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    dtResults = New DataTable
    dtResults.Columns.Add("Name", GetType(String))
    dtResults.Columns.Add("Value", GetType(String))


    dtFound = New DataTable
    dtFound.Columns.Add("Name", GetType(String))
    dtFound.Columns.Add("Value", GetType(String))

    Timer1.Enabled = True

    TS = ThreadStatus.Running
    ProcessThread = New System.Threading.Thread(AddressOf SearchThread)
    ProcessThread.Start()

    '    SearchThread()
  End Sub

  Sub SearchThread()
    Search(Path, SearchStr)
    MsgBox("Search Complete")
  End Sub

  Public Sub Search(ByVal Path As String, ByVal SearchStr As String)

    If WaitRequest = True Then
      WaitRequest = False
      TS = ThreadStatus.Wating

      While TS = ThreadStatus.Wating
        System.Threading.Thread.Sleep(10)
      End While

    End If

    Dim dRow As DataRow

    Dim ParentKey As RegistryKey = Registry.LocalMachine.OpenSubKey(Path, True)
    ' Loop through values in the subkey
    For Each valueName As String In ParentKey.GetValueNames()
      On Error Resume Next
      'Create String to Compare against
      Dim CurStr As String = valueName + " = " + ParentKey.GetValue(valueName)
      Dim CurValue As String = ParentKey.GetValue(valueName)
      dRow = dtResults.NewRow
      dRow("Name") = valueName
      dRow("Value") = ParentKey.GetValue(valueName)
      dtResults.Rows.Add(dRow)

      'ListBox1.Items.Insert(0, valueName + " = " + ParentKey.GetValue(valueName))
      If CurValue = SearchStr Then
        Dim dRowF As DataRow = dtFound.NewRow()
        dRowF("Name") = valueName
        dRowF("Value") = CurValue
        dtFound.Rows.Add(dRowF)
        CurStr = ""
        CurValue = ""
      End If
    Next
    'if there are sub keys loop through and be recursive
    If ParentKey.SubKeyCount > 0 Then
      For Each subKeyName As String In ParentKey.GetSubKeyNames()

        dRow = dtResults.NewRow
        dRow("Name") = Path + subKeyName
        dRow("Value") = ""
        dtResults.Rows.Add(dRow)

        'ListBox1.Items.Insert(0, "")
        'ListBox1.Items.Insert(0, Path + subKeyName) ' Writing the Keyname
        'This is what makes me recursive!
        Dim Thispath As String = Path + subKeyName + "\\"
        Search(Thispath, SearchStr)
      Next

    End If

  End Sub

  Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

    WaitRequest = True

    Timer1.Stop()

    While TS = ThreadStatus.Running
      System.Threading.Thread.Sleep(10)
      Application.DoEvents()
    End While

    Me.Label1.Text = "Checked " & dtResults.Rows.Count & " Rows"
    Dim dtTemp As DataTable = dtResults.Copy
    Dim dtTempF As DataTable = dtFound.Copy

    Me.DataGridView1.DataSource = dtTemp
    Me.DataGridView2.DataSource = dtTempF

    TS = ThreadStatus.Running

    Timer1.Start()
    Dim x As DataView = New DataView(dtTemp)
    x.Sort = "idOrder, Name"

  End Sub

  Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    ProcessThread.Abort()
    ProcessThread = Nothing
  End Sub
End Class

This code does have a bug that I didn't take the time to figure out, after it searches 200,000 or so keys it starts crashing. I'm not sure why, my guess is it is trying to access some System Protected Key, but this code works well enough that I am not going to worry about that.

Now that you've seen that I would like to discuss some of the concepts that you need to be aware of in Threading.

Mainly "Thread Safety" and "Thread Management".

"Thread Safety"

Most people new to threading do not think much about this, you spawn some thread and want to post it's results back to the UI.  But you will find when you code tries to access a datagrid, or listbox that is on the UI thread that it will throw an error as a background thread will not be allowed to mess with the UI thread. There are a number of solutions to this, I generally use the Singleton pattern to create a buffer to hold data in.  I'll talk more about Singletons in later posts.  For this example I decided to use the timer control to pause the background thread, and update the UI with it's current results.

"Thread Management"

This concept is important as well. If you do not stop your other threads when your application is shut down they will keep running forever.  You also need to be concerned about how many threads you create. The first time I wrote a threading application I wrote a program which searched all files and folders on a hard drive. The main thread searched for new folders, and it spawned another thread to search the files. As it ran it just kept spawning thread after thread until it hit around 32,000 threads at which time my computer, without giving an error message, turned itself off.  In this example we only create one thread so you need not worry about it crashing you computer.

I generally create my own threading class which spawns a set number of threads (usually in it's constructor) and manages them.  It keeps a Queue of new things to spawn threads for, and then checks the status of each thread, once the thread is done with it's task the threading class records the results, disposes the thread and creates a new thread with the next task in it's Queue.  I believe this is called "Thread Polling" but I don't know I created this method on my own without reading about it.

i += 1

Here is just a little trick that if you are an old VB6 programmer you might not realize is available in VB.NET. Do you still use i = i + 1 when you need to increment your i counter? well there is a shorter way, just do i += 1 this will increase i by 1. I don't know why they don't let us use i++ it seems this would be pretty easy for the .net framework, but maybe they are trying to not make VB look too much like C#.

Monday, November 30, 2009

Create a variable without Dim

So this is a cool feature of .NET, I might be wrong but I think this is a feature that didn't come out until after the 2005 edition.

Do you ever Dim i as Int and use it over and over again, just to realize that you forgot to set i = 0 before one of your loops? Well fear no more, you can create a variable named i without diming it and it only lives inside a narrow scope. Check this out:

    For i As Integer = 0 To 10

 

    Next



You can even Dim a variable inside a IF Block (or any other block) and it is only available in the scope of that block.

    If True = True Then

      Dim i As Integer = 0

      i = i + 1

    End If

 

    If True = True Then

      Dim i As Integer = 0

      i = i + 1

    End If

Best tool to post Source Code

I have been evaluating different tools to use for posting source code, I have found a few that work ok but most of them do not support the full color of Visual Studio Code.  Well I found this must-have add on to Visual Studio that is perfect for blogging.  As you can see I already updated a number of my posts using it.

http://copysourceashtml.codeplex.com/

After you install it in the edit menu and the right-click context menu inside Visual Studio you get a new option that says "Copy As HTML.."

Here is a line with a bunch of colors:

    dt.Columns.Add(New System.Data.DataColumn("Field", GetType(String)))

Thursday, November 26, 2009

UAC Administrator Access

Ever need to run your app to request Administrator access?
Well in Visual Studio 2008 it is very easy:

Right click on your project and press the button for "View UAC Settings"

Change the Level to:

level="requireAdministrator"


SQL CE Takes too much Memory

This is a bast form the past, I was thinking about how to promote my new blog so I signed into http://www.vbforums.com to answer a few questions, and I found this posting, something I figured out and posted about 5 years ago.  This was two posts, the first one describing my problem and the second one gives the solution.

----- (POST #1)

I have an MC 1000. At first I thought it was perfect, ultra low cost, and no extra features that were never used. At first they run perfectly, but after you insert a few hundred records into its CE Database it starts running slower and slower until it is almost unusable. I have the users reboot the device and it runs fine again for a while but does the same thing again. All my code is doing is adding records to the SQL CE DB.

Anyone have similar problems? I am thinking of switching over to a XML file instead of SQL CE.

I have converted as much storage memory into program memory and it has helped, but only for a while.

----- (POST #2)

I came across the following MS Article while researching this problem:

http://support.microsoft.com/?kbid=842191


It mentions:

Q17: Does setting my ADO Recordset to 'nothing' reclaim any memory?

A17: Generally, the answer is "yes." However, Microsoft recommds that all your applications use set rs=nothing and set cn=nothing when you are finished using them. Database engines can take a fair amount of memory, and it is best not to leak memory.

Usually, Microsoft Visual Basic eventually releases the memory. However, there have been some cases where the memory is not released quickly enough and you can run out of memory on the device, especially if you have a particularly bad memory leak.

Made me think: am I setting all my objects to nothing? I went through my code and found that although I was setting all my Connections = Nothing I wasn't setting the SqlCeCommand Objects to nothing when I was done with them. I added a few cmd = Nothing lines and now my App runs Faster then ever and doesn't seem to be stopping for anything.

Whoo!




Wednesday, November 25, 2009

Visual Studio 2008 Locks or Freezes in ASPX

I have been having this issue for a while now, it seems to happen at random, but it's pretty consistent. What happens is suddenly when you are working with a project in Visual Studio 2008 with an ASPX page your visual studio will lock up and become unresponsive forever. You have to crash it, and pray that you saved recently. Here are some links that I found to help me fix it.

http://abdullin.com/journal/2009/5/12/visual-studio-2008-locks-or-freezes-in-aspx.html

http://geekswithblogs.net/hinshelm/archive/2009/07/19/office-2010-gotcha-2-visual-studio-2008-locks.aspx

What worked for me was finding:

C:\Program Files (x86)\Common Files\microsoft shared\
OFFICE12\Office Setup Controller\Setup.exe

I ran it as an administrator and told it to do a repair. Once this was done not only did Visual Studio stop locking up, but loading the ASPX pages is faster as well.

Tuesday, November 24, 2009

Dim x as New

Let me say in my not so humble opinion that 'AS NEW' is dead in my eyes. I always hated back in my VB6 days that some variables had to be declared "AS NEW" while others had to just "AS". As soon as I discovered in .NET that you never have to use "AS NEW" but instead you can use "Dim X AS MyObj = New MyObj" I was sold.

Sometimes when I am lazy I still use "AS NEW" but I think it's a bad habit, and should never appear in 'good' code.

A small rant

Ok so there is one thing about .NET that bugs me, and it's not the design. Let me know If I ever do this, but it seems like every example in the help documentation never tells you what namespaces are imported. I hate it when I see some System.Net.Whatever.lala.AwsomeFunciton in a code example but all they have is AwesomeFunciton. Then I have to spend a few mins google'n AwesomeFunction Namespace or looking it up in the MSDN Library. If you are using an import or a reference in your example code, you should include it.

Like I said If I am guilty of doing this let me know, but I always try to keep it in mind when posting code.

Generate a Unique ID

Here is some code I wrote to generate always unique ID's (Only Unique to One application, two applications could generate the same ID, however it is very unlikely)

Note that I used the keyword "Shared" by doing this your code can get an ID without creating a new object.

The SyncLock Command makes sure only one thread can access it at a time.

The Sleep one millisecond command makes sure if two threads requested data at the same time, they both get different ID's.



Public Class UniqueID

Public Shared ReadOnly Property Generate() As String
Get
Dim UniqueID As String

SyncLock "GENID"

System.Threading.Thread.Sleep(1)

Dim d As String = Now.DayOfYear
Dim y As String = Now.Year
Dim h As String = Now.Hour
Dim m As String = Now.Minute
Dim s As String = Now.Second
Dim ms As String = Now.Millisecond
If d.Length = 1 Then d = "00" & d
If d.Length = 2 Then d = "0" & d
If h.Length = 1 Then h = "0" & h
If m.Length = 1 Then m = "0" & m
If s.Length = 1 Then s = "0" & s
If ms.Length = 1 Then ms = "00" & ms
If ms.Length = 2 Then ms = "0" & ms

UniqueID = y & d & h & m & s & ms

End SyncLock

Return UniqueID

End Get
End Property
End Class

Monday, November 23, 2009

Using Ajax To Avoid Timeouts

So I thought since I mentioned AJAX in my last post that I would include how to use it. Not that I am an expert as I just decided to use AJAX for the first time today, and so I'm very new to it, but it was way easy to use.

First thing you do is you have to add a ScriptManager to your page. This is easy to do, it's found in the VS UI tool menu under AJAX Extensions. You don't have to do anything with it other then drop it on your page. You Can edit the AysncPostBackTimeout property if you know your tasks are going to take a while.

Then drop in a AJAX UpdatePanel. This is where the magic happens, anything you put inside this box, say like a command button, when pressed will not cause your entire page to do a post back. You can drop in a Label and update it's text without having to reload the whole page.

Add a AJAX UpdageProgress control and you can put some text in it like "Please wait while your request is processed.." and bam, you have a user message that will be displayed while the AJAX process is running.

One little trick about if you use a Button, I added this code so that the user can't press the button twice:

Button1.OnClientClick = "this.disabled = true;__doPostBack(this.name,'')"


It's really that easy. Here is some code:



<asp:UpdateProgress ID="UpdateProgress1" runat="server"
AssociatedUpdatePanelID="UpdatePanel1">
<ProgressTemplate>
Processing.. Please Wait
</ProgressTemplate>
</asp:UpdateProgress>

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Button ID="cmdProcess" runat="server" Text="Process"
onclick="cmdProcess_Click">
</ContentTemplate>
</asp:UpdatePanel>

Soap Client Timeout WebServices

Ok so I created this blog post so that when someone else searches the internet for this problem they can find my simple solution. I hate it when I search on google for over 20 mins trying to find some simple solution. I Hope this helps someone.

I have a web service which is taking in a tab delimited data file and put it into a SQL database. But I had problems, my web browser kept timing out before the processing was done. Oddly enough the web service finishes the task anyway, but I have a user issue with them getting an error message.

So the fist thing I did was I used AJAX to place a message on the screen that the file was being processed and I set the AysncPostbackTimeout in the Script Manger to 0 so it would never time out. But this only solved one problem, the bowser stopped displaying an error message, but the underlining call was still dieing, and so I could not update the web site once it was done.

To fix that I updated the InnerChannel.OperationTimeout to an hour by doing so:
(Web Service Soap Client).InnerChannel.OperationTimeout = New System.TimeSpan(1, 0, 0)

This makes it wait an hour before it gives a timeout error (more then enough time)

I should change all the values to 5 mins as that now if there really is an error It will make the user wait an hour.

My VB Blog

So I deicded to start a blog to give whomever cares insight on all the little tricks I do In VB.NET. I have been programming in Basic my entire life, I was 8 years old when I wrote my first computer program on a VIC 20 in good old Basic. I have been professionally programming in VB for over 10 years. I started in VB 6, and moved onto VB.NET the same day Microsoft released it. At first I hated it, but I quickly learned to love it.

I don't know why you would want to program in any other language. It's fast and easy, and with Visual Studio's amazing intellisense I'd never switch to a different platform.