Posts filed under 'Tip Sheets'

3 More Useful VB.NET String Functions

3 string functions: String To Stream, Compare and Word CountA few weeks ago I wrote an article called 3 Handy VB.NET String Functions You Can Use and it’s been one of the more popular articles on this site. So, I thought I’d follow it up with another article on string functions. Hopefully, you will find this one helpful as well.

Converting a String To a Stream

There are a number of objects in .NET that require a Stream as a parameter and many of these won’t accept a string as a parameter. Many new-to-VB.NET programmers have run into this situation and been frustrated. The trick here is to place the string into a MemoryStream. This is simply a stream object that uses memory as a storage device rather than a disk.

However, you will also need to specify the type of encoding for your string. In most cases, an ordinary string will use ASCII encoding but you may also run into Unicode strings. Therefore it’s important for you to know the type of encoding you should use in your application. The encoding methods are in the System.Text namespace.

Once you know the encoding method, you will want to use the GetBytes function to convert the target string into a byte array.

OK, here’s the example function and it can be reduced down to only one line:

'
'
Dim MemStream As New IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(MyStringData))
'
'

Now that you have the string converted to the stream, perhaps you want to know how to get a string back from the MemoryStream. ToString only returns the name of the object, so what do you do? Remember we converted the string to an array of bytes for the stream so we will need to simply copy this array back to a string, like so:

'
'
MyStringData = System.Text.Encoding.ASCII.GetString(MemStream.ToArray))
'
'

Remember to use the same encoding method for both functions! Also, bear in mind when you’re using streams that you need to properly close and dispose of streams in order to release resources. MemoryStream misuse can result in your application having a memory leak so make sure you do this.

Using String.Compare

It’s common to compare strings using the classic equal (=) or not equal (<>) operators but often the case of the letters being inconsistant has caused programmers to resort to functions like this in VB6:

'
'
If UCase(txtHomeAddress.Text) = UCase(txtShippingAddress.Text) Then
'
'

However, in VB.NET, we can use the String.Compare function to handle this.

'
'
If String.Compare(txtHomeAddress.Text, txtShippingAddress.Text, True) = 0 Then
'
'

This built-in String class function takes two string arguments, either of which can be Nothing, and returns less than zero (-1) is the first string is less than the second, zero (0) if they’re equal, and greater than zero (1) if the first string is greater. Overloads allow you to ignore case, as in the example above. You can also use comparison methods outside of the default one as well using overloads.

Another powerful overload option on this function is the ability to compare parts of a string. In this example, we will see if the beginning 3 characters of our first string match the 3 ending characters of our second string:

'
'
If String.Compare(Puzzle1, 0, Puzzle2, Puzzle2.Length - 3, 3, True) = 0 Then
'
'

For those of you transitioning to VB.NET, remember, strings in VB.NET are zero based, not one based like they were in VB6.

Getting The Word Count

A common way to get the number of words in a string in VB is to use the Split command and then get the count of the resulting array. This is rather inefficient since it requires allocating an array and so forth. It is easier and faster to use a regular expression to do this, as seen in this example function:

'
'
Public Function WordCount(ByVal value As String) As Integer
    Return System.Text.RegularExpressions.Regex.Matches(value, "(((^s*)*S+s+)|(S+))").Count()
End Function
'
'

This regular expression matches any white-space character and the function returns the number that were found. It will consider 2 white-space characters together as one. Regular expressions, while rather obtuse, are very powerful and you should consider them for string parsing or comparison functions not directly provided within the .NET Framework. I do recommend wrappering them in functions for easy correction, modification and reuse.

I hope you’ve found this article helpful. Let me know by leaving a comment with any thoughts or questions you might have.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

2 comments September 7th, 2007

5 Elements of Style For Error Messages

I'm so stupid! I just don't understand this computerIt’s a fact of programming life that errors will happen in our programs once users get ahold of our programs. Some of these may be due to programming bugs, some due to operating system or network access problems, or they may be due to user mistakes. In all these cases our programs should handle these problems gracefully. However we often find ourselves shortcutting error handling and messaging and playing a ‘blame game’ with the user or presenting cryptic error messages.

1. Avoid the Error

The secret of the sword is never to unsheathe the sword. - Taisen Deshimaru

We’ll begin by taking a Zen like approach by saying the best error is no error. This means that we should make every effort to avoid errors we can avoid. For example, before we open a file we should check to see if the file actually exists or if we use String.SubString we should confirm that the length will handle the call. If we pass these errors on to the user interface we’re really allowing two bugs into our program. First, we’re introducing a performance bug by processing an unneeded exception and, secondly, we’re failing to properly validate user input.

2. Do Not Use the Default .NET Exception Text

Have you used something like this in one of your applications?

error message example 1

This kind of error message, while it may be helpful in debugging, is scary to users. You shouldn’t allow this kind of error message become visible to users in a fully released product. If you do include such an error message in a beta release, make sure your test users know that this message is intended for you, not them, and that they know how to copy it to an email for you. You could make it clearer to them by adding text, like so:

error message example 2

Better yet, simply log the full exception message to disk and simply let the user know that the program failed without giving confusing and unnecessary details.

3. Avoid Vague and Generalized Messages

If you’re going to go to the trouble of presenting an error message to the user, make it one that precisely defines the problem, not one that doesn’t say anything meaningful. For example, don’t use something like this:

error message example 3

But, instead, use something like this:

error message example 4

4. Help The User Solve The Problem

Error messages should help the user solve the problem. For example, in the error message just above, it tells the user to contact support since this is the best course of action for them to take.

In VB.NET another way we have to help the user solve the problem is to not use message boxes at all but, instead, use the ErrorProvider component. This component, which I’ll cover in depth in a future article, allows you to check user input and provide immediate feedback through an icon and tooltip rather than a show stopping modal messagebox dialog.

Another way our programs can help a user solve problems is to use auto-suggestion, much like Google does in its searches:

error message example 5

5. Don’t Blame The User

This should almost go without saying but your error messages should not place the blame on the user. Instead they should be polite and non-intimidating. For example, you don’t want to show a user an error message like this:

error message example 6

The rules of presenting a polite error message are simple:

  1. No shouting at the user with ALL CAPS.
  2. Avoid using pejorative terms like fatal, illegal, invalid.
  3. If you must use icons, use matching standard Windows icons and not a skull and crossbones or other intimidating graphics.
  4. Avoid using cutesy error sounds like a ’raspberry’ (I actually heard this on a point-of-sale app in a convenience store!)
  5. The message should not blame the user for the problem but it should help the user seek a solution to it.
  6. The message should be grammatically correct and spell checked (Can you spot this mistake in the example error dialogs in this article?)

I hope this article has been informative and helpful to you. Let me know if you liked it or not by leaving me a comment, using the Contact Me button, or using the rating star system. Or, If you have anything to add, a question, or a funny/sad error message anecdote, please leave a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

8 comments September 3rd, 2007

How To Uninstall a Failed Windows Service Installation

Pulling Out HairI’ve been doing a lot of work with Windows Services in VB.NET recently and, as a result, I’ve ran into a number of little tricks and traps in this area. I’m going to post these short, hopefully helpful, tips as I come across them.

One of these traps can happen when a service gets installed but gets stuck where you can’t completely uninstall it or install a new version. This can be caused by errors in your code, errors on the install itself, copying over an incorrect DLL or EXE manually, or other such things. When this happens it can be quite frustrating.

Here’s what you’ll see if you encounter this problem. When you try to reinstall the service, you’ll get a dialog that says, “The specified service already exists”, even if you’ve gone through the uninstall either from within Visual Studio or from the Add/Remove Programs control panel applet.

The Specified Service Already Exists Dialog

The program’s executables have been deleted from the installation folder but you’ll see your service app in the Computer Management Service console. You can’t seem to get rid of it. If you try to uninstall, you’ll see this message saying you can’t do it.

Only Valid If Currently Installed Dialog

I’ve seen forum posts where people resorted to renaming their service after encountering this error. Some manually edited their registry to get rid of it. Still others wrote a quickie program or script using WMI to kill it. But, there is a much easier way to deal with it.

There is a command line utility in Windows called SC, short for service controller, that allows you to control Windows Services manually. One of the available commands is “delete”. This command deletes references to the specified service in the registry. Here’s the command syntax:

sc delete NameOfYourBadServiceGoesHere

Once you run this from the command window, the failed installation is cleared from the registry and you’re ready to do a clean install of your service program. Of course, you need to be careful about using this command in production environments. Also, you should have gone through the uninstall process first to remove the executables before executing this command.

Let me know if you found this tip helpful or if you have any other ideas or questions about it by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

17 comments August 16th, 2007

How To Convert a WinForms App To A Windows Service

compassIn my previous article, How To Make Debugging .NET Windows Services Easier, I mentioned using a console or WinForms app to scaffold a Windows Service app for debugging and initial development. Unfortunately, there is a little ‘gotcha’ that needs to be addressed if you decide to do this.

When you’re ready to convert, you’ll want to set the startup object of your Windows Service to the name of your class that contains the service code, including the standard service Protected Overrides OnStart, OnStop, etc., and remove any test forms or Sub Main code from your project. What you will see in the My Project Application tab after doing this is that the old startup objects will remain on the list while your desired class isn’t on the list as shown here:

Service Startup Object Screen Capture

So, what can you do to correct this problem?

To handle this, you’ll need to edit a hidden generated Designer file because when you switch project types, certain code is not automatically generated. To get to the hidden file, bring up the Solution Explorer window and click on the ‘Show All Files’ button. It’s at the top and is the button circled in red below:

Solution Explorer Screen Capture

Next, you’ll want to expand the your service’s module to reveal the Designer module, as circled in blue above. Open this file and add the following code to it:

' The main entry point for the process
<MTAThread()> _
<System.Diagnostics.DebuggerNonUserCode()> _
Shared Sub Main()

    Dim ServicesToRun() As System.ServiceProcess.ServiceBase

    ' More than one NT Service may run within the same process. To add
    ' another service to this process, change the following line to
    ' create a second service object. For example,
    '
    '   ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
    '

    ServicesToRun = New System.ServiceProcess.ServiceBase() {New MyService}

    System.ServiceProcess.ServiceBase.Run(ServicesToRun)

End Sub

Of course, you would replace ‘MyService’ with the name of your service class. Now, when you go back to the My Project Application tab and click on the StartUp Object drop down you’ll see your service class on the list. Select it and you’ll be ready to compile your application as a Windows Service.

Please let me know if this article was helpful to you or if you have any other questions about this or other Windows Service issues by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

6 comments August 14th, 2007

8 Ways to Get To Know Your User’s Computer

A User’s PCOften you’ll find in your programs that you need to get information about the computer it’s running on. Fortunately, the .NET Framework makes it easy to get a lot of this information and the My namespace in VB.NET can make it even easier. Here are 8 key areas where you can get the info you need for your programs.

1. Memory

The My namespace provides four functions to retrieve the amount of available and total physical and virtual memory on a system. This can be important if you’re tracking memory related error issues or need to track available memory for other reasons. Here’s an example of these functions in action

Dim VirtualMemoryUsed As ULong = My.Computer.Info.TotalVirtualMemory - _
                                 My.Computer.Info.AvailableVirtualMemory

Dim PhysicalMemoryUsed As ULong = My.Computer.Info.TotalPhysicalMemory - _
                                  My.Computer.Info.AvailablePhysicalMemory

.

2. Windows Version

As I pointed out in my previous article, 10 Things to Avoid When Moving From VB6 to VB.NET, it is easy to get the Windows version using the My namespace, like so:

lblWindowsVersion.Text = String.Concat(My.Computer.Info.OSFullName, "  ", My.Computer.Info.OSVersion)

.

These functions can be quite useful for support purposes and to detect Windows patch levels on users’ systems.

3. Computer Name

The My.Computer.Name function simply returns a string with the current system’s name. I’ve found this very useful in situations where I have users who don’t have a set seating arrangement, such as in a call center, for tracking and audit purposes.

4. Mouse

If you have a special use for a mouse scroll wheel in your application, it’s important to know if the user has a scroll wheel or not and what their scroll lines setting is. My.Computer.Mouse makes this easy:

If My.Computer.Mouse.WheelExists Then
    ScrollValue = My.Computer.Mouse.WheelScrollLines
Else
    ScrollValue = 0
End If

5. UI Culture

As applications become more and more internationalized, developers often find that they have to take the user’s culture settings into account when formatting strings, numbers and dates. To retrieve this information, do the following:

Dim CurrentCulture As System.Globalization.CultureInfo = My.Computer.Info.InstalledUICulture

.

6. Internet Connection

How can you tell if the client app has a connection to the Internet? There are a number of ways to do this, some complex, some easy, some reliable, some not so reliable. One method I like is to ping the site(s) that my application will need to access.

If My.Computer.Network.Ping("www.mywebservicehost.com") Then
    'Internet should be available
End If

Of course, this might not work depending of firewalls and other security measures on both the client and server ends.

7. IP Address

To get this information, we’ll have to use the System.Net.Dns namespace and the GetHostEntry function. Here’s what it looks like:

Dim CurrentIP As String = System.Net.Dns.GetHostEntry(My.Computer.Name).AddressList(0).ToString

.

8. Current User

We often need to know who the current user is on the system and what their rights are. The My.User functions make this quite easy. My.User.Name gets the currently logged in user’s name. If we wanted to have separate settings for administrative users vs. regular users, we could write code like this:

If My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
    'do admin stuff
Else
    'do regular user stuff
End If

Sometimes a user might be running under an alias. This can happen if the user is running a program with elevated permissions and your program is shelled out to from it. In this case, you can use a function like this to discover the logged in user by finding the owner of the Windows shell program, explorer.exe.

Public Function GetActualUserName() As String
    Dim ActualUserName As String = ""
    Dim CurrentProcesses As Management.ManagementObjectCollection
    Dim ProcessSearch As Management.ManagementObjectSearcher
    Dim ProcessItem As Management.ManagementObject
    ProcessSearch = New Management.ManagementObjectSearcher("Select * from Win32_Process")
    CurrentProcesses = ProcessSearch.Get
    For Each ProcessItem In CurrentProcesses
        Dim ProcessOwner(2) As String
        ProcessItem.InvokeMethod("GetOwner", ProcessOwner)
        If (ProcessItem("Name").ToString = "explorer.exe") Then
            ActualUserName = ProcessOwner(0).ToString
            Exit For
        End If
    Next
    Return ActualUserName
End Function

I hope you found these tips helpful. If you would like further information on any of these items or if you have a question or additional information about any of these that you would like to share, please leave a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

1 comment August 10th, 2007

Next Posts Previous Posts


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives