Advanced Basics: Compile Options, Loading Images into PictureBoxes, Deploying .NET Apps, and More

MSDN Magazine

Compile Options, Loading Images into PictureBoxes, Deploying .NET Apps, and More
Ken Spencer
S

tarting this month, I am going to answer some of the questions that folks are asking about Visual Basic® .NET. These questions span a wide range of topics, from how to compile applications to specific coding issues.

Q
I have a question about the compile options for a Visual Basic .NET application. What happens when you compile a Visual Basic .NET application using either Visual Studio® .NET or the command-line compiler?

A
Well, in this process, the compiler takes your source code, and generates Microsoft® Intermediate Language (MSIL) code from the source then generates either an EXE or DLL file. The result is then processed by the common language runtime (CLR) upon execution.
So far, so good. Now, what control do you have over the compile process—the process of generating the MSIL? Let's discuss the options with Visual Studio .NET first. Using Visual Studio .NET, you can right-click a solution and select Build or press Ctrl-Shift-B or use the Build command on the Build menu to compile the entire solution. When you perform this task, the solution is compiled using the current build options.
What are build options? They allow you to configure how your application will be compiled. First, you must decide whether to compile the application with a Debug or Release configuration. The Debug configuration causes your application to be compiled with full symbolic debug information and no optimization. This results in an assembly that can be debugged but is not optimized. Changing the configuration to Release and recompiling causes the resulting assembly to be fully optimized, but it will contain no debug information.
You can change the configuration setting for a project by selecting the correct configuration on the standard toolbar. The Debug and Release settings are shown in the list to the right of the start icon in Figure 1.

Figure 1 Visual Studio .NET IDE
Figure 1 Visual Studio .NET IDE

You can also change these settings on a per-project basis by using the Configuration Manager settings. You open the Configuration Manager from the Build menu Configuration Manager option (see Figure 2). Using this dialog, you can set the debug and release options for each project in the solution. You can also set options so that particular projects are not built when the solution is compiled simply by unchecking the box for that particular project.

Figure 2 Configuration Options
Figure 2 Configuration Options

When you use the Build command, the application is compiled as mentioned before. You can compile and run the application by pressing F5 (or Debug | Start). You can also compile and run the application without debugging by pressing Ctrl+F5. This is a bit faster than F5 (especially for ASP .NET applications) because with this option, the debugger is not started when the application loads.
Now, those of you who pay attention when you right-click a project may have noticed the Rebuild option. This particular option can be confusing. When you rebuild a project, Visual Studio .NET first cleans up all intermediary files and output directories before compiling the application. Some folks think Rebuild builds the entire project while Build does not, but that is not the case. They both do a complete compile of the project files.
What happens if you have several projects in a single solution and there is some dependency among them? Dependencies can occur in this case when one or more of the projects are components that are then used by one or more of the other projects in the solution. For instance, if project A uses a component called DBLayer, and project B is DBLayer, then you probably want project B to compile first, then project A.

Figure 3 Dependencies for DBLayer
Figure 3 Dependencies for DBLayer

You can control this using the Project Dependencies dialog. You can open this dialog for a project by right-clicking the project name and selecting Project Dependencies. Figure 3 and Figure 4 show dependencies for a solution with two projects. Figure 3 shows the dialog for DBLayer. Notice there are no dependencies for this particular project. However, selecting NWTradersTravel in the Project list shows that DBLayer is checked as a dependency for NWTradersTravel.

Figure 4 Dependencies for NWTradersTravel
Figure 4 Dependencies for NWTradersTravel

Setting the dependency for NWTradersTravel causes DBLayer to compile first when you compile the solution. This is really handy because you can set the dependency and be assured that the projects will compile in the right order. It's sort of like visually creating a make file to build projects.
Another compile option is the Batch Build dialog (see Figure 5). This dialog allows you to build one or all solutions and control the options in the dialog before you build.

Figure 5 Batch Build
Figure 5 Batch Build

You may wonder why you have options to build both debug and release configurations at the same time. Well, when you build a project in a Debug configuration, the compiler puts debug information into the compiled assembly and does not perform any optimizations on the output. The assembly is placed in the project's Obj\Debug folder. When you compile a release configuration, the assembly is optimized by the compiler and does not include any debug information, so a release assembly is optimized for performance and will run faster than a debug-compiled assembly. The resulting output of a release configuration is placed in the project's \Bin directory.
Once you have set your batch build options, you can build the projects by clicking the Build button or the Rebuild button. If you just want to clean the project's output, you can click Clean.
Now, let's quickly review the command-line compiler options. The Microsoft .NET Framework includes a command-line compiler for Visual Basic .NET (VBC. EXE). You can also use command-line switches for Visual Studio .NET to build projects. You can use this compiler from the command line in the following manner:

C:> VBC /out:MyApp.exe  MyApp.vb

This compiles MyApp.vb into MyApp.exe. The command-line compiler is useful when you need to create make files (batch files) with numerous compile commands or when you need to compile an application on a system that does not have Visual Studio .NET installed. You can find compiler options in the MSDN® documentation.
The Visual Studio .NET developer environment also has switches you can use to compile applications. The syntax is:

C:> devenv projectname.vb /option

You can compile them using the options shown in Figure 6.
Q** How do you load images into the picture control at runtime? I need to let users select images to load into a PictureBox control on a Windows® Form. The application should let the user find the image using a common dialog, then select the image and load it.
A** One easy way to solve this is to use the OpenFileDialog and the Image class. The following code creates a stream variable (oStream) of a Stream type and then uses it to get the image.

Dim oStream As Stream

Next, the code creates a reference to the OpenFileDialog:

Dim openFileDialog1 As New OpenFileDialog()

Then the code sets certain properties of OpenFileDialog to their initial settings before opening the dialog. The InitialDirectory property is set to the \Images folder and the Filter property is set to .gif and .jpg images.

openFileDialog1.InitialDirectory = "\images"
openFileDialog1.Filter = "\image files (*.gif)|*.jpg
openFileDialog1.FilterIndex = 2
openFileDialog1.RestoreDirectory = True

Next, the OpenFileDialog is opened by calling its ShowDialog method, as shown here:

If openFileDialog1.ShowDialog() = DialogResult.OK Then

After the user selects an image, the image is loaded with the OpenFile method and it is returned to the stream object from the dialog, like so:

oStream = openFileDialog1.OpenFile()

If the stream is valid, then a Try / Catch block is used to bracket the image loading process. The Image property of the PictureBox is set by calling the FromStream method of the image object and passing it the stream variable returned from the dialog:

If Not (oStream Is Nothing) Then
'Try block is used to catch errors with files
    Try
'Set picture image to stream
        PictureBox1.Image = Image.FromStream(oStream)
    Catch exc As Exception
        'Set message in status control
        stsStatus.Text = "Errr loading image — " & exc.Message
    Finally
        ' Close stream
        oStream.Close()
    End Try
End If

You can also load images directly from a file simply by using the following syntax:

Dim path As String = "\images\banneryellow.gif"
PictureBox1.Image = Image.FromFile(path)

The Image class provides several methods that you can use to load images. Both FromStream and FromFile can be used to load images into the PictureBox or other items.
Q** How can you deploy applications built for .NET?
A** This is an interesting question. Most of you have seen how you can simply copy an application from one place to another using XCopy or Windows Explorer. This simply copies the files from one system to another and as long as the assemblies are in place, the application will run fine.
Moving into the real world, there are many times when you will need a more robust solution than simply copying the files. For instance, let's take two scenarios. First, say you are deploying your first ASP .NET Web application and you need to install the application and the .NET Framework on your servers. You could install the framework, then load your application. Or you can use Visual Studio .NET to create a new deployment package that does both at the same time.
There is a .NET Framework merge module that is automatically added as a dependency for any deployment package created with Visual Studio .NET. The setup basically creates a Microsoft Installer (MSI) file that includes both your application and the .NET Framework. If you install the application using the .MSI on a system where the framework has been installed, the .NET Framework will not be installed, only the application will be. If you install on a system that does not have the .NET Framework, then both the framework and the application will be installed. You can create a deployment project by following these steps:

  1. Open Visual Studio .NET, then open the project that you want to deploy.
  2. Right-click the solution name and select Add | New Project.
  3. Select Setup and Deployment Projects in the Project Type pane, then select Web Setup Project in the Templates pane.
  4. Set the name to a name representing the .MSI file that you create. The .MSI will be named with the deployment project name and a .MSI extension. The new deployment project will then be added to Solution Explorer and the File System Editor will open.
  5. In the Properties window, select the ProductName property and enter a name for the application you are deploying. In the File System Editor, select the Web Application folder.
  6. Select Add from the Action menu, then choose Project Output. In the Add Project Output Group dialog box, select the project that you are going to deploy from the Project dropdown list.
  7. Select the Primary Output and Content Files groups from the list, then select the Web Application folder. In the Properties window, set the VirtualDirectory property to the name of the virtual directory you will deploy the project to. The directory should not exist yet on the target machine.
  8. In the Properties Window, set the DefaultDocument property to your default .aspx page. Then, on the Build menu, choose Build Solution. This will create the .MSI package for the project.

Now you can use Windows Explorer to navigate to the projects directory and find the installer (.MSI) file. The default path for Visual Studio projects is C:\documents and settings\yourloginname\my documents\visual studio projects.
As mentioned earlier, you can also build a setup file without the .NET Framework. You should exclude the merge module only if you are sure that the application will only be installed where the .NET runtime files are already installed. In the deployment project you just created, follow these steps to exclude the runtime:

  1. Open Solution Explorer and select your deployment project, then open the Detected Dependencies folder.
  2. Select Dotnetfxredist_x86_enu.msm. The enu designation just before the .msm extension represents the locale for your version of Visual Studio .NET.
  3. Open the properties window for the .msm file, and select the Exclude property and set it to true.

This will prevent the merge module for the .NET CLR from being included in the generated .MSI file. This is useful when you are creating deployment packages for your own servers or any server where the CLR is already installed.
Of course, you can also create deployment projects for Windows-based applications and components as well. The process is very similar to creating a deployment package for a Web application. The difference is that each application type has its own particular options. For instance, a Web application needs a virtual directory or Web site to install into. A Windows-based application will need things like Start menu options, folder locations, and such.
Q** How do I parse a folder tree with Visual Basic .NET?
A** All developers need access to the file system at one time or another. With ASP applications, you would use the FileSystem object to access files. In Visual Basic 6.0, you can use either the FileSystem object or the intrinsic Visual Basic file access features. So, what is the approach when working with .NET?
You can use the DirectoryInfo class to interact with the file system. This works from either an ASP .NET or Windows-based application since you are using Visual Basic .NET and the .NET Framework in both cases. The following code demonstrates how to use the DirectoryInfo class to work through a directory structure in your file system.

Private Sub Button1_Click_1(ByVal sender As System.Object, 
    ByVal e As System.EventArgs) Handles Button1.Click
    Dim dir As DirectoryInfo
    dir = New DirectoryInfo(txtDirectory.Text)
    PrintFiles(dir)
End Sub

This code creates a new reference (dir) to the DirectoryInfo class. Then a new instance of DirectoryInfo is created with the New operator and the value from txtDirectory.Text property is passed to the DirectoryInfo constructor. This allows the DirectoryInfo class to set the starting directory when the class is instantiated. Then, the PrintFiles subroutine is called and passed the dir object. This subroutine is called to actually do the work of parsing the directory. The code simply does a For Each operation on the DirectoryInfo object (dir) and pulls out the attributes it needs. For instance, the file name, size, and other information is returned from the FileInfo object for each file. This simple architecture lets you go right through the files without a lot of complex code (see Figure 7).
Q** How do I handle ASP .NET projects when there are many developers on a team?
A** Teams with groups of developers always pose an interesting problem to the development process. This has been an issue with application development for a long time. You should decide upon an approach for your development teams to use in dealing with applications. For instance, a common scenario is to have a group of developers working against a single development site on an intranet application. These developers can all access the site, but must be careful to not step on each other's code.
With ASP .NET, you must be concerned with the same thing. One of the things to watch carefully is the build process. When you build an ASP .NET project that contains a number of .aspx files, all of the files in the project are compiled into one .dll. If you have nine people that are working on the project, each time a developer compiles his code, the .dll on the server will be updated. This will cause the .dll to be updated each time an application is compiled.
How do you work around this? There are a couple of good options. One way is to have each developer work in offline mode and only post source files to the server. You can work in offline mode by selecting Web Project | Work Offline from the Project menu. When you build your app, your offline copy is built. You can check in single pages or groups of pages as they are built. Another technique is to break your ASP .NET application into multiple projects. Then all the developers can work on individual projects and when each one builds his project, he will have a separate .dll.
Send questions and comments for Ken to basics@microsoft.com.**

Ken Spencer works for 32X Tech Corporation (https://www.32X.com), which provides software development services, consulting, and courseware for developers. Ken spends much of his time consulting and teaching private courses.

From the September 2001 issue of MSDN Magazine.