Sunday, December 6, 2009
Wordpress
After a little bit or research I decided to move my blog over to wordpress.
http://vbguru.wordpress.com
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
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!
Your other team members will love you if you now use a 'wrapper' to manage the gateway, check this code out:
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.
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.
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
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.
#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#.
Subscribe to:
Posts (Atom)