|
|
In the previous section, you created a web service that lets you retrieve a file from the server’s Documents folder. Rather than restrict the web service to files that reside within a specific folder, you will likely want your web service to be able to retrieve files that reside throughout a disk. Unfortunately, to provide a web service with such flexibility may require that you change a wide range of file permissions on your server—which would make your system less secure.
As an alternative, you can create a web service that requests a Windows service to copy files that reside on your hard disk into a specific folder that the web service can access. In other words, you will use two programs: a web service and a Windows service. The Windows service will wait to receive requests from the web service for a specific file. After the service receives the request, it will copy the requested file into the folder that the web service makes available to client programs.
The Visual Basic .NET program in Listing 13.3, PlaceFileCopy.vb, implements a Windows service that monitors the server’s Request folder (which you must create) for a new file. The program uses a FileSystemWatcher to monitor the Request folder for new files. After the service identifies a new file (when the Created event occurs), the OnCreated subroutine opens the file’s contents to determine the name of the file the user desires. Then, the service copies the file the user desires into the server’s Download folder. To create the PlaceFileCopy.vb Windows service, perform these steps:
Within Visual Studio .NET, select the File menu New Project option. Visual Studio .NET will display the New Project dialog box.
Within the New Project dialog box Project Types list, click Visual Basic Projects. Then, within the Templates field, click Windows Service. Finally, within the Location field, specify the folder within which you want to store the program. Likewise, within the Name field, specify PlaceFileCopy. Select OK. Visual Studio .NET will display the service’s Design View page.
Right-click your mouse within the Design View window. The Visual Studio will display a popup menu.
Within the popup menu, select Properties. The Visual Studio will display the service’s properties.
Within the property list, assign the name PlaceFileCopy to the Service name property (not the Name property). Next, set to true the settings, shown in Figure 13.2, that enable the service to respond to PauseAndContinue, Stop, and Shutdown events.
Figure 13.2: Assigning a Windows service’s name and attributes
Click on the Code View option to display the service’s source code. Within the source-code window, enter the program statements in Listing 13.3.
Listing 13.3 PlaceFileCopy.vb
Imports System.IO Private WithEvents FileWatch As FileSystemWatcher Protected Sub OnCreated(ByVal From As Object, _ ByVal e As FileSystemEventArgs) Handles FileWatch.Created Dim Log As New EventLog("Application") Log.Source = "PlaceFileCopy" Log.WriteEntry("File " & e.FullPath & _ Ä " processed at " & DateTime.Now) Log.Close() Dim InputFile As FileStream Dim TargetFileName As String Dim FileLength As Long Try InputFile = File.Open(e.FullPath, FileMode.Open, _ Ä FileAccess.Read) FileLength = InputFile.Length Dim DataBuffer(FileLength - 1) As Byte InputFile.Read(DataBuffer, 0, FileLength) InputFile.Close() Dim I As Integer For I = 0 To DataBuffer.Length - 1 TargetFileName = TargetFileName + Chr(DataBuffer(I)) Next File.Copy(TargetFileName, "C:\Documents\" & _ Ä Path.GetFileName(TargetFileName)) Dim ResultLog As New EventLog("Application") ResultLog.Source = "PlaceFileCopy" ResultLog.WriteEntry("File " & TargetFileName & _ Ä " successfully copied at " & DateTime.Now) ResultLog.Close() Catch Ex As Exception Dim ResultLog As New EventLog("Application") ResultLog.Source = "PlaceFileCopy" ResultLog.WriteEntry("Error copying " & TargetFileName & _ Ä " " & DateTime.Now & " " & Ex.Message) ResultLog.Close() End Try End Sub Protected Overrides Sub OnStart(ByVal args() As String) Try FileWatch = New FileSystemWatcher("C:\Request") FileWatch.Filter = "*.*" FileWatch.EnableRaisingEvents = True Dim Log As New EventLog("Application") Log.Source = "PlaceFileCopy" Log.WriteEntry("PlaceFileCopy started at " & DateTime.Now) Log.Close() Catch E As Exception End Try End Sub Protected Shadows Sub OnPause(ByVal args() As String) Try FileWatch.EnableRaisingEvents = False Dim Log As New EventLog("Application") Log.Source = "PlaceFileCopy" Log.WriteEntry("PlaceFileCopy paused at " & DateTime.Now) Log.Close() Catch E As Exception End Try End Sub Protected Shadows Sub OnContinue(ByVal args() As String) Try FileWatch.EnableRaisingEvents = True Dim Log As New EventLog("Application") Log.Source = "PlaceFileCopy" Log.WriteEntry("PlaceFileCopy continued at " & _ ÄDateTime.Now) Log.Close() Catch E As Exception End Try End Sub Protected Overrides Sub OnStop() Try FileWatch.EnableRaisingEvents = False Dim Log As New EventLog("Application") Log.Source = "PlaceFileCopy" Log.WriteEntry("PlaceFileCopy stopped at " & DateTime.Now) Log.Close() Catch E As Exception End Try End Sub Protected Shadows Sub OnShutdown(ByVal args() As String) Try FileWatch.EnableRaisingEvents = False Dim Log As New EventLog("Application") Log.Source = "PlaceFileCopy" Log.WriteEntry("PlaceFileCopy shutdown at " & DateTime.Now) Log.Close() Catch E As Exception End Try End Sub
As discussed, a Windows service is a special program you install within Windows. Using the Services window, you can start, pause, continue, and later stop the service. Each time you perform one of these operations, the service will call the corresponding subroutine. In this case, several of the subroutines simply record an entry within the system’s event log that describes the event. The OnStart subroutine, in contrast, also creates the FileSystemWatcher object and directs the object to monitor the Request folder for new files.
Before you can install a Windows service, you must add special additional code to your project that provides information Windows uses to install the service. To add code to the PlaceFileCopy service, perform these steps:
Within Visual Studio .NET, select design view and then right-click on the design view window. Visual Studio .NET will display a popup menu.
Within the popup menu, select Add Installer. Visual Studio .NET will add two components to your project: a service process installer and a service installer.
When you install a Windows service, Windows performs the installation using a user-level context that defines the server’s privileges. Using the service process installer, you must specify a user account on the system (or an account you create for the service) that defines the service’s context. To begin, right-click on the service process installer and select Properties from the popup menu. Within the installer’s properties fields, use the pull-down list to specify the account type as shown in Figure 13.3. Next, enter the username and password of the account you want the service to use.
Figure 13.3: Specifying an account type, username, and password for the PlaceFileCopy service
Within the properties fields, you must first select the account type from the list of types specified in Table 13.1. Second, you must specify the username and password Windows will use to log into the account. If you do not specify the account context information, Windows cannot install the service.
Windows Account Type | Description |
---|---|
Local Service | Windows will run the service in the context of an account on the local system. The account may have extended privileges. |
Local System | Windows will run the service in the context of a non-privileged account on the local system. The service will present anonymous credentials to a remote server. |
Network Service | Windows will run the service in the context of a non-privileged account on the local system. The service will present the computer’s credentials to a remote server. |
User | Windows will prompt the user for a valid username and password each time the service runs. Windows will run the service in the context of the specified user account. |
Close the Service Process Installer Properties dialog box. Then, right-click the Service Installer icon. Visual Studio .NET will display the Service Installer Properties dialog box. Within the dialog box ServiceName field, type PlaceFileCopy as shown in Figure 13.4.
Figure 13.4: Specifying the service name within the Service Installer Properties dialog box
Close the Service Installer Properties dialog box. You are now ready to build the service by selecting the Build menu Build PlaceFileCopy service option. After you successfully compile the service, you are ready to install the service for use by Windows, as discussed next.
After you create a Windows service, you must direct Windows to install and run the service program as a background task each time your system starts. To install the service, you can use the InstallUtil program that Visual Studio .NET provides. The InstallUtil program is a command-line utility. To execute the InstallUtil command, you must specify the directory path on your system that contains the PlaceFileCopy.exe file. Pay close attention to the messages the InstallUtil program displays. If the utility cannot successfully install your service, the utility will display a message describing the cause of the error.
To direct Windows to install the PlaceFileCopy Windows service, select the Start menu Run option and type CMD to open the command window. Then, from the system prompt, issue the following InstallUtil command, replacing the directory path shown here with the path on your system that contains the PlaceFileCopy.exe program:
C:\> InstallUtil C:\SomeDirectory\PlaceFileCopy.exe <Enter>
After the InstallUtil command ends, your service will be installed within Windows, but it will not yet be running. To view and to start your service, perform these steps:
Select the Start menu Settings options and choose Control Panel. Windows, in turn, will display the Control Panel window.
Within the Control Panel, double-click the Administrative Tools icon. Windows will display the Administrative Tools window.
Within the Administrative Tools window, double-click the Service’s icon. Windows will open the Services window, as shown in Figure 13.5.
Figure 13.5: Using the Services window to start the PlaceFileCopy Windows service
Within the Services window, right-click on the service you desire and then choose Start.
If, in the future, you no longer need the PlaceFileCopy service, you can use the InstallUtil command to remove the service, by including the /U switch:
C:\> InstallUtil /U C:\SomeDirectory\PlaceFileCopy.exe <Enter>
The GetAnyFile web service in Listing 13.4 uses the PlaceFileCopy Windows service to help a user retrieve a specific file from any folder on the user’s disk. The web service provides three methods:
The first, RequestFile, lets a program request a file from a specific directory. When the program calls the method, the method will create a file in the Request folder that contains the path of the file the user desires.
The second method, FileAvailable, returns a true or false value that specifies whether or not the Windows service has moved the specified file into the Documents folder.
Finally, the third method, GetFile, retrieves the specified file from the Documents folder, returning a byte array that contains the file’s contents:
Boolean RequestFile(ByVal String) Boolean FileAvailable(ByVal String) Byte() GetFile(ByVal String)
To create the GetAnyFile web service, perform these steps:
Within Visual Studio .NET, select the File menu New Project option. Visual Studio .NET will display the New Project dialog box.
Within the New Project dialog box Project Types list, click Visual Basic Projects. Then, within the Templates field, click ASP.NET Web Service. Finally, within the Location field, specify the folder within which you want to store the program and the program name GetAnyFile. Select OK. Visual Studio .NET will display a page onto which you can drag and drop the service’s components.
Select the View menu Code option. Visual Studio .NET will display the program’s source code. Within the source code add the program statements in Listing 13.4.
Listing 13.4 GetAnyFile.asmx.vb
Imports System.IO <WebMethod()> Public Function RequestFile(ByVal Source As String) _ As Boolean Dim OutputFile As New StreamWriter("C:\Request\" & Now.Ticks) Try OutputFile.Write(Source) OutputFile.Close() RequestFile = True Catch Ex As Exception RequestFile = False End Try End Function <WebMethod()> Public Function FileAvailable(ByVal Source As String) _ ÄAs Boolean FileAvailable = File.Exists("C:\Documents\" & _ Ä Path.GetFileName(Source)) End Function <WebMethod()> Public Function GetFile(ByVal Source As String) As Byte() Dim InputFile As FileStream Dim FileLength As Long Try InputFile = File.Open(Path.GetFileName(Source), FileMode.Open, _ Ä FileAccess.Read) FileLength = InputFile.Length Dim DataBuffer(FileLength - 1) As Byte InputFile.Read(DataBuffer, 0, FileLength) InputFile.Close() GetFile = DataBuffer Catch Ex As Exception Throw New Exception("Unable to open specified file") End Try End Function
The Visual Basic .NET program in Listing 13.5, SpecifyFileAndFolder.vb, uses the GetAnyFile web service to retrieve a file from a server. When you run the program, it will display a form similar to that shown in Figure 13.6 that prompts the user for the pathname of the desired file. After the user enters a pathname and clicks the Get File button, the program calls the web service to retrieve the file.
Figure 13.6: Retrieving any file from a remote server
To create the SpecifyFileAndFolder.vb program, perform these steps:
Within Visual Studio .NET, select the File menu New Project option. Visual Studio .NET will display the New Project dialog box.
Within the New Project dialog box Project Types list, click Visual Basic Projects. Then, within the Templates field, click Windows Application. Finally, within the Location field, specify the folder within which you want to store the program and the program name SpecifyFileAndFolder. Select OK. Visual Studio .NET will display a form onto which you can drag and drop the program’s controls.
Using the Toolbox, drag and drop the button and text boxes, list box, label, and hyperlink label previously shown in Figure 13.6 onto the page.
Select the Project menu Add Web Reference option. Visual Studio .NET will display the Add Web Reference dialog box.
Within the Address field, type localhost/GetAnyFile/Service1.asmx?WSDL and press Enter. The dialog box will load the file’s contents. Click the Add Reference button.
Select the View menu Code option. Visual Studio .NET will display the program’s source code. Within the source code add the program statements in Listing 13.5.
Listing 13.5 SpecifyFileAndFolder.vb
Imports System.IO Private Sub Button1_Click(ByVal sender As System.Object, _ Ä ByVal e As System.EventArgs) Handles Button1.Click Dim DataFile As Byte() Dim WS As New localhost.Service1() Dim Filename As String = TextBox1.Text If (Filename.Length > 0) Then Try If (WS.RequestFile(Filename)) Then While (Not WS.FileAvailable(Filename)) TextBox2.Text = "Waiting for server to move file" End While DataFile = WS.GetFile(Filename) Dim OutputFile As FileStream Try Filename = "C:\TEMP\" + Path.GetFileName(Filename) OutputFile = File.Open(Filename, FileMode.Create, _ Ä FileAccess.Write) OutputFile.Write(DataFile, 0, DataFile.Length) OutputFile.Close() TextBox2.Text = "File copied to C:\Temp" Catch Ex As Exception TextBox2.Text = "Error writing file " + Ex.Message End Try Else TextBox2.Text = "Error requesting file" End If Catch Ex As Exception TextBox2.Text = ex.Message End Try Else TextBox2.Text = "Must specify file" End If End Sub
After a user types a pathname for a file on the remote server and then clicks the Get File button, the code will first call the web service’s RequestFile method that directs the Windows service that is running on the server to copy the file to the Documents folder. Then, the program code uses a While loop to wait until the Windows service moves the file. Finally, the program uses the web service’s GetFile method to retrieve the file. In this case, the program stores the file’s contents within the C:\Temp folder.
|
|