Iset out to write this article about Visual Basic® 2005, but that left too many things to choose from. I could wander through the entire feature list, giving you a bit of information on cool IDE features like Edit and Continue, IntelliSense® Code Snippets, or the Exception Assistant; skim over the advanced language enhancements like generics, partial classes, and unsigned types; and barely touch on all the cool Microsoft® .NET Framework enhancements around Windows® Forms, data binding, ClickOnce deployment, and more. While these are all interesting features, I'm going to dig into one of the coolest features of Visual Basic 2005, the namespace called My.
Why My?
One of the biggest issues that programmers run into is the sheer breadth of .NET, which makes finding the best class for a particular task quite daunting. I have read many newsgroup postings from developers working very hard to call a Win32® API function from their Visual Basic .NET or C# code, when that exact function already exists in .NET. Why are they trying to call the API? They didn't find, notice, or perhaps understand how they could use existing parts of the Framework. The My namespaces provides an intuitive navigation hierarchy that exposes existing .NET functionality through easily understood root objects, targeting the practical tasks and concepts that you grapple with on a regular basis.
Wow, that sounds great, but what does it mean? To quickly illustrate the benefit of My, consider a very common question from the forums on GotDotNet: "How do I read the entire contents of a text file into a string?" The answer for the .NET Framework 1.1 is this: Dim sr As New IO.StreamReader("c:\mytextfile.txt")
contents = sr.ReadToEnd
sr.Close()
It doesn't require a lot of code, but it certainly isn't intuitive. For many people, the path to StreamReader would have led them through the Stream class, the FileStream class, and more before ending up with that code snippet. That exact same code will work just fine in Visual Basic 2005, but by using My I can get to the same information much more quickly by writing this: contents = My.Computer.FileSystem.ReadAllText("c:\mytextfile.txt")
The My.Computer.FileSystem class is just one of many classes included in the My language extensions, so the first thing to do is get familiar with what is available.
My is best described as a speed-dial for the .NET Framework. This type of simplification—making it easier to find and execute the right operation—is a common practice in programming. When I run into a multistep process that will be used repeatedly by me or by my development team, I generally create a helper function. The helper function is usually just a simple call that takes in the parameters that matter for the most common usage and then performs the multistep process under the covers, smoothing the development process. Most software development shops build such helper functions, and it is quite a common practice to combine groups of them into some set of code snippets or form of shared library such as MyCompany.Utilities or Duncan.NetworkUtilities.
There is a lot of duplication of effort going on in the creation of these libraries though, as many functions would be useful to almost any development group. The My namespace takes this idea of helper functions to a whole new level because these functions include so much functionality and because they are being shipped with Visual Basic. Just think of it as a library full of productivity-enhancing code that you don't have to write.
Exploring My
My exposes several distinct classes which organize a variety of functions into one of seven general areas: My.Application, My.Computer, My.Forms, My.Resources, My.Settings, My.User, and My.WebServices.
In general, the classes within My provide easy access to information in one of two categories, either the underlying .NET Framework or elements of the current project. My.Application, My.Computer, and My.User are all focused on Framework functionality, while My.Forms, My.Resources, My.Settings, and My.WebServices all deal with the contents of your current project. As I walk through each of these classes, starting with those that are focused on the underlying Framework, I will provide quick samples along with information on the properties and classes they contain.
As I mentioned earlier, it can sometimes be difficult to find the exact functionality that you need when you're working with the .NET Framework, but finding it isn't the only issue you need to be aware of. In some particular circumstances, even after you have found the class you need, the specific steps and constructor parameters needed to get it ready can take several lines of code and can be difficult to understand. The My classes focused on the Framework (My.Application, My.Computer, and My.User) are designed to help you navigate directly to the class you need, and to set it up so that you are ready to do your work.
My.Application
My.Application provides developers with an intuitive grouping of application information and services. Individual nodes under My.Application include Info (the application's copyright, title, description, and so on), OpenForms (a collection of all Forms currently open in the project), Log (a feature-rich, highly configurable logging facility that is integrated with the System.Diagnostics classes), and more.
Using the My.Application.Log class, logging exceptions is easier than it probably should be. How are developers supposed to feel like true code warriors when they can write code like this: Dim winINIFile As String
Try
winINIFile = My.Computer.FileSystem.ReadAllText("c:\windows\wind.ini")
Catch ex As IO.FileNotFoundException
My.Application.Log.WriteException(ex, TraceEventType.Error,
"Error Accessing INI File")
End Try
One of the more common feature requests that have come out of discussions with users of Visual Basic 6.0 and earlier verions has been answered with the addition of the OpenForms collection. This feature, which was available through the keyword Forms in Visual Basic 6.0, provides you with an easy way to loop through all of the currently open forms in your application, without the hassle of maintaining your own global list, as shown here: For Each f As Form In My.Application.OpenForms
Debug.WriteLine(f.Text)
f.WindowState = FormWindowState.Minimized
Next
My.Computer and My.User
My.Computer allows you to navigate to services and data related to the host computer. The functionality in this class alone deserves its own article, but I'll discuss a few of the highlights.
The FileSystem classes provide a very simple API for working with and inquiring about files; this should banish any lingering yearning for the FileSystemObject library. The following code uses the FileSystem class to copy all of the pictures from the current user's My Pictures folder to a new folder (C:\Desktop Wallpaper), displaying a progress bar if the file copy takes more than a few moments to complete: Dim myPics As String = _
My.Computer.FileSystem.SpecialDirectories.MyPictures
My.Computer.FileSystem.CopyDirectory( _
myPics, "C:\Desktop Wallpaper", _
FileIO.UIOption.AllDialogs, _
FileIO.UICancelOption.DoNothing)
MessageBox.Show(My.Computer.FileSystem.GetFiles( _
myPics, FileIO.SearchOption.SearchAllSubDirectories, _
"*.jpg", "*.bmp").Count)
Accomplishing the same file copy in the .NET Framework 1.1 would require quite a bit more code (see Figure 1), and that is without including the ability to show a progress dialog, which you would have to create yourself.
My.Computer.Ports turns reading and writing to a serial port into a simple process. This is one of the most common and difficult tasks to perform using the current version of the .NET Framework. The snippet shown here previously took an entire article to build! (See Serial Comm: Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications.) Dim comport As IO.Ports.SerialPort
comport = My.Computer.Ports.OpenSerialPort("COM1")
AddHandler comport.ReceivedEvent, AddressOf DataReceived
The My.Computer.Audio class allows you to play user-defined or system sounds, putting an end to the practice of P/Invoking the PlaySound API, as shown in the following code: Dim musicFile As String
musicFile = My.Computer.FileSystem. _
GetFiles("C:\WINDOWS\Media", _
FileIO.SearchOption.SearchAllSubDirectories, _
"*.wav")(0)
My.Computer.Audio.Play(musicFile)
My.Computer.Network makes a wide variety of networking calls easy to use, including receiving and sending Pings from and to a remote machine, uploading or downloading a file, determining if you are currently connected, and quite a bit more: If My.Computer.Network.IsAvailable Then
If My.Computer.Network.Ping("www.duncanmackenzie.net") Then
Debug.WriteLine("Site Available")
My.Computer.Network.DownloadFile( _
"http://www.duncanmackenzie.net/Articles/", _
System.IO.Path.Combine( _
My.Computer.FileSystem.SpecialDirectories.MyDocuments, _
"articles.html"))
End If
End If
There are quite a few more classes that I am not going to even start describing, including My.Computer.Keyboard, My.Computer.Registry, and My.Computer.Screen. I encourage you to explore these on your own.
My.User is one of the simplest classes in My, but don't let its simplicity fool you; it provides access to quite a few useful bits of information about the current user of the app. This includes methods for querying role membership, and status functions like IsAuthenticated: If My.User.IsAuthenticated Then
If My.User.IsInRole("BUILTIN\Administrators") Then
MsgBox("tsk, tsk... running as Admin are we?")
End If
End If
Note that the My.User properties and methods use Windows authentication by default, but will work seamlessly with custom security infrastructures as well, keeping the coding model the same regardless of the type of authentication you use.
Exposing Settings, Resources, and More From Your Project
The project-focused classes in My include Settings, Resources, WebServices, and Forms. The first two deal with your project's associated data while the clearly named Forms and WebServices classes provide direct access to forms and Web services that you have added to your project.
Working through the IDE of Visual Studio® 2005, you can set up a variety of resource elements and a strongly typed group of user or application-level settings for your application (through the designer interface shown in Figure 2).
Figure 2 Settings Designer
In both cases, you have to configure the settings or resources before the corresponding classes will become available through My, but once they have been added to your project, the My.Settings and My.Resources classes (respectively) make it easy for you to interact with either type of information. The following routine retrieves and modifies the value of a stored user setting, then uses the My.Resources class to retrieve a localized string (created using the IDE tools shown in Figure 3) for use in a message box: Dim lastRun As Date My.Settings.LastRun
My.Settings.LastRun = Now()
Dim myMessage As String = _
String.Format(My.Resources.LastRunMessage, _
lastRun.ToShortDateString)
MsgBox(myMessage)
Figure 3 Resource Editing
In addition to the two areas just described, all of the forms in your project are available through My.Forms and any Web services you have referenced in your project are exposed through the My.WebServices class. For Web services, this means you have the option of referencing them directly without manually creating an instance. So, after adding a reference to the WeatherForecast service from webservicex.net, you can retrieve the current temperature using the following code: Dim tempService As New net.webservicex.www.WeatherForecast()
Dim wf As net.webservicex.www.WeatherForecasts
wf = tempService.GetWeatherByZipCode("98052")
MsgBox(wf.ToString())
This can be expressed more simply as: MsgBox(My.WebServices.WeatherForecast.GetWeatherByZipCode("98052").ToString())
My.Forms is different from the My.Application.OpenForms collection that I discussed earlier because My.Forms exposes a default instance of each of your Form classes, not the currently open instances of those classes. If you have a background in programming in Visual Basic 6.0 or earlier, then these default instances will be extremely useful to you as they enable you to show, hide, or otherwise access your forms using the Form's class name directly: Private Sub showForm2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles showForm2.Click
My.Forms.Form2.Show()
End Sub
Private Sub updateForm2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles updateForm2.Click
My.Forms.Form2.Text = "Updated..."
End Sub
This was standard behavior in Visual Basic before the release of the .NET Framework, and it will be a welcome restoration to developers who became familiar with that style of programming in Visual Basic 6.0.
Conclusion
The My namespace in Visual Basic 2005 provides a quick and easy method for accessing some of the deeper areas of functionality in the .NET Framework without preventing you from using the Framework directly in any way you choose. In addition to exposing Framework functionality, some areas of My, such as the Forms collection, bring back familiar and convenient programming concepts from earlier versions of Visual Basic. Try it out in Visual Studio 2005 and Visual Basic 2005 Express, and I'm confident that you will find it useful.
Why My?
One of the biggest issues that programmers run into is the sheer breadth of .NET, which makes finding the best class for a particular task quite daunting. I have read many newsgroup postings from developers working very hard to call a Win32® API function from their Visual Basic .NET or C# code, when that exact function already exists in .NET. Why are they trying to call the API? They didn't find, notice, or perhaps understand how they could use existing parts of the Framework. The My namespaces provides an intuitive navigation hierarchy that exposes existing .NET functionality through easily understood root objects, targeting the practical tasks and concepts that you grapple with on a regular basis.
Wow, that sounds great, but what does it mean? To quickly illustrate the benefit of My, consider a very common question from the forums on GotDotNet: "How do I read the entire contents of a text file into a string?" The answer for the .NET Framework 1.1 is this: Dim sr As New IO.StreamReader("c:\mytextfile.txt")
contents = sr.ReadToEnd
sr.Close()
It doesn't require a lot of code, but it certainly isn't intuitive. For many people, the path to StreamReader would have led them through the Stream class, the FileStream class, and more before ending up with that code snippet. That exact same code will work just fine in Visual Basic 2005, but by using My I can get to the same information much more quickly by writing this: contents = My.Computer.FileSystem.ReadAllText("c:\mytextfile.txt")
The My.Computer.FileSystem class is just one of many classes included in the My language extensions, so the first thing to do is get familiar with what is available.
My is best described as a speed-dial for the .NET Framework. This type of simplification—making it easier to find and execute the right operation—is a common practice in programming. When I run into a multistep process that will be used repeatedly by me or by my development team, I generally create a helper function. The helper function is usually just a simple call that takes in the parameters that matter for the most common usage and then performs the multistep process under the covers, smoothing the development process. Most software development shops build such helper functions, and it is quite a common practice to combine groups of them into some set of code snippets or form of shared library such as MyCompany.Utilities or Duncan.NetworkUtilities.
There is a lot of duplication of effort going on in the creation of these libraries though, as many functions would be useful to almost any development group. The My namespace takes this idea of helper functions to a whole new level because these functions include so much functionality and because they are being shipped with Visual Basic. Just think of it as a library full of productivity-enhancing code that you don't have to write.
Exploring My
My exposes several distinct classes which organize a variety of functions into one of seven general areas: My.Application, My.Computer, My.Forms, My.Resources, My.Settings, My.User, and My.WebServices.
In general, the classes within My provide easy access to information in one of two categories, either the underlying .NET Framework or elements of the current project. My.Application, My.Computer, and My.User are all focused on Framework functionality, while My.Forms, My.Resources, My.Settings, and My.WebServices all deal with the contents of your current project. As I walk through each of these classes, starting with those that are focused on the underlying Framework, I will provide quick samples along with information on the properties and classes they contain.
As I mentioned earlier, it can sometimes be difficult to find the exact functionality that you need when you're working with the .NET Framework, but finding it isn't the only issue you need to be aware of. In some particular circumstances, even after you have found the class you need, the specific steps and constructor parameters needed to get it ready can take several lines of code and can be difficult to understand. The My classes focused on the Framework (My.Application, My.Computer, and My.User) are designed to help you navigate directly to the class you need, and to set it up so that you are ready to do your work.
My.Application
My.Application provides developers with an intuitive grouping of application information and services. Individual nodes under My.Application include Info (the application's copyright, title, description, and so on), OpenForms (a collection of all Forms currently open in the project), Log (a feature-rich, highly configurable logging facility that is integrated with the System.Diagnostics classes), and more.
Using the My.Application.Log class, logging exceptions is easier than it probably should be. How are developers supposed to feel like true code warriors when they can write code like this: Dim winINIFile As String
Try
winINIFile = My.Computer.FileSystem.ReadAllText("c:\windows\wind.ini")
Catch ex As IO.FileNotFoundException
My.Application.Log.WriteException(ex, TraceEventType.Error,
"Error Accessing INI File")
End Try
One of the more common feature requests that have come out of discussions with users of Visual Basic 6.0 and earlier verions has been answered with the addition of the OpenForms collection. This feature, which was available through the keyword Forms in Visual Basic 6.0, provides you with an easy way to loop through all of the currently open forms in your application, without the hassle of maintaining your own global list, as shown here: For Each f As Form In My.Application.OpenForms
Debug.WriteLine(f.Text)
f.WindowState = FormWindowState.Minimized
Next
My.Computer and My.User
My.Computer allows you to navigate to services and data related to the host computer. The functionality in this class alone deserves its own article, but I'll discuss a few of the highlights.
The FileSystem classes provide a very simple API for working with and inquiring about files; this should banish any lingering yearning for the FileSystemObject library. The following code uses the FileSystem class to copy all of the pictures from the current user's My Pictures folder to a new folder (C:\Desktop Wallpaper), displaying a progress bar if the file copy takes more than a few moments to complete: Dim myPics As String = _
My.Computer.FileSystem.SpecialDirectories.MyPictures
My.Computer.FileSystem.CopyDirectory( _
myPics, "C:\Desktop Wallpaper", _
FileIO.UIOption.AllDialogs, _
FileIO.UICancelOption.DoNothing)
MessageBox.Show(My.Computer.FileSystem.GetFiles( _
myPics, FileIO.SearchOption.SearchAllSubDirectories, _
"*.jpg", "*.bmp").Count)
Accomplishing the same file copy in the .NET Framework 1.1 would require quite a bit more code (see Figure 1), and that is without including the ability to show a progress dialog, which you would have to create yourself.
My.Computer.Ports turns reading and writing to a serial port into a simple process. This is one of the most common and difficult tasks to perform using the current version of the .NET Framework. The snippet shown here previously took an entire article to build! (See Serial Comm: Use P/Invoke to Develop a .NET Base Class Library for Serial Device Communications.) Dim comport As IO.Ports.SerialPort
comport = My.Computer.Ports.OpenSerialPort("COM1")
AddHandler comport.ReceivedEvent, AddressOf DataReceived
The My.Computer.Audio class allows you to play user-defined or system sounds, putting an end to the practice of P/Invoking the PlaySound API, as shown in the following code: Dim musicFile As String
musicFile = My.Computer.FileSystem. _
GetFiles("C:\WINDOWS\Media", _
FileIO.SearchOption.SearchAllSubDirectories, _
"*.wav")(0)
My.Computer.Audio.Play(musicFile)
My.Computer.Network makes a wide variety of networking calls easy to use, including receiving and sending Pings from and to a remote machine, uploading or downloading a file, determining if you are currently connected, and quite a bit more: If My.Computer.Network.IsAvailable Then
If My.Computer.Network.Ping("www.duncanmackenzie.net") Then
Debug.WriteLine("Site Available")
My.Computer.Network.DownloadFile( _
"http://www.duncanmackenzie.net/Articles/", _
System.IO.Path.Combine( _
My.Computer.FileSystem.SpecialDirectories.MyDocuments, _
"articles.html"))
End If
End If
There are quite a few more classes that I am not going to even start describing, including My.Computer.Keyboard, My.Computer.Registry, and My.Computer.Screen. I encourage you to explore these on your own.
My.User is one of the simplest classes in My, but don't let its simplicity fool you; it provides access to quite a few useful bits of information about the current user of the app. This includes methods for querying role membership, and status functions like IsAuthenticated: If My.User.IsAuthenticated Then
If My.User.IsInRole("BUILTIN\Administrators") Then
MsgBox("tsk, tsk... running as Admin are we?")
End If
End If
Note that the My.User properties and methods use Windows authentication by default, but will work seamlessly with custom security infrastructures as well, keeping the coding model the same regardless of the type of authentication you use.
Exposing Settings, Resources, and More From Your Project
The project-focused classes in My include Settings, Resources, WebServices, and Forms. The first two deal with your project's associated data while the clearly named Forms and WebServices classes provide direct access to forms and Web services that you have added to your project.
Working through the IDE of Visual Studio® 2005, you can set up a variety of resource elements and a strongly typed group of user or application-level settings for your application (through the designer interface shown in Figure 2).
Figure 2 Settings Designer
In both cases, you have to configure the settings or resources before the corresponding classes will become available through My, but once they have been added to your project, the My.Settings and My.Resources classes (respectively) make it easy for you to interact with either type of information. The following routine retrieves and modifies the value of a stored user setting, then uses the My.Resources class to retrieve a localized string (created using the IDE tools shown in Figure 3) for use in a message box: Dim lastRun As Date My.Settings.LastRun
My.Settings.LastRun = Now()
Dim myMessage As String = _
String.Format(My.Resources.LastRunMessage, _
lastRun.ToShortDateString)
MsgBox(myMessage)
Figure 3 Resource Editing
In addition to the two areas just described, all of the forms in your project are available through My.Forms and any Web services you have referenced in your project are exposed through the My.WebServices class. For Web services, this means you have the option of referencing them directly without manually creating an instance. So, after adding a reference to the WeatherForecast service from webservicex.net, you can retrieve the current temperature using the following code: Dim tempService As New net.webservicex.www.WeatherForecast()
Dim wf As net.webservicex.www.WeatherForecasts
wf = tempService.GetWeatherByZipCode("98052")
MsgBox(wf.ToString())
This can be expressed more simply as: MsgBox(My.WebServices.WeatherForecast.GetWeatherByZipCode("98052").ToString())
My.Forms is different from the My.Application.OpenForms collection that I discussed earlier because My.Forms exposes a default instance of each of your Form classes, not the currently open instances of those classes. If you have a background in programming in Visual Basic 6.0 or earlier, then these default instances will be extremely useful to you as they enable you to show, hide, or otherwise access your forms using the Form's class name directly: Private Sub showForm2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles showForm2.Click
My.Forms.Form2.Show()
End Sub
Private Sub updateForm2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles updateForm2.Click
My.Forms.Form2.Text = "Updated..."
End Sub
This was standard behavior in Visual Basic before the release of the .NET Framework, and it will be a welcome restoration to developers who became familiar with that style of programming in Visual Basic 6.0.
Conclusion
The My namespace in Visual Basic 2005 provides a quick and easy method for accessing some of the deeper areas of functionality in the .NET Framework without preventing you from using the Framework directly in any way you choose. In addition to exposing Framework functionality, some areas of My, such as the Forms collection, bring back familiar and convenient programming concepts from earlier versions of Visual Basic. Try it out in Visual Studio 2005 and Visual Basic 2005 Express, and I'm confident that you will find it useful.
No comments:
Post a Comment