EngineHost: A Sample Hosting Application


EngineHost: A Sample Hosting Application

This section introduces EngineHost, a new sample application. EngineHost is a commandline program that hosts the engine for any SQL-NS instance. It takes the instance name as a command-line argument, starts the engine, and waits for the user to press a key before stopping the engine. If a fatal error occurs while the engine is running, the program displays an error message and then quits.

EngineHost doesn't do anything other than host the SQL-NS engine. As such, it doesn't offer much beyond the standard SQL-NS Windows service, but its source code illustrates how the SQL-NS Hosting API is used. The same techniques and coding patterns used in the EngineHost sample can be used in a real hosting application.

The EngineHost Visual Studio Solution

The Visual Studio solution containing the EngineHost code is located at C:\SQL-NS\Samples\EngineHost. The solution file is called EngineHost.sln. Open this solution in Visual Studio now and use it to refer to the source code as you read through this section.

The Visual Studio Solution Explorer shows the various files that make up the EngineHost source code. The following two files relate to the SQL-NS Hosting API:

  • Program.cs

  • App.config

Program.cs contains the main driver code for the application, including the calls to the Hosting API. We examine parts of this code in the following sections. App.config is a configuration file that specifies settings for the SQL-NS engine's log switches, as shown in Listing 17.1. At build time, App.config is copied to the output directory in which the program's executable file is created, and it is renamed EngineHost.exe.config. The configuration settings specified in this file are read by the engine at runtime.

Use of the Hosting API in the EngineHost Code

The calls to the SQL-NS Hosting API in the EngineHost source code are made in the file Program.cs. This file contains the main driver code for the application, in the Program class. Listing 17.2 shows some of the code in the Program class's Main() method and some of its private member variables.

Listing 17.2. Use of the Hosting API in the EngineHost Program

[View full width]

 class Program {     ...     private static string instanceName;     private static AuthenticationMode authenticationMode;     private static string sqlUserName;     private static string sqlPassword;     private static NSInstance nsInstance = null;     static int Main(string[] args)     {         // Assume failure code - set this to success at the end.         int returnCode = 1;         ...         // Declare and initialize flag that tracks whether we         // successfully started the instance.         bool instanceStarted = false;         try         {             // Create the NSInstance object.             if (AuthenticationMode.WindowsAuthentication ==                 authenticationMode)             {                 nsInstance = new NSInstance(instanceName);             }             else             {                 nsInstance = new NSInstance(                     instanceName,                     sqlUserName,                     sqlPassword);             }               // Attach the error handler delegate to the error event.             nsInstance.Error +=                 new NSInstance.ErrorEventHandler(nsInstance_Error);             // Start the instance.             nsInstance.StartInstance();             instanceStarted = true;             Console.WriteLine(                 "Notification Services Engine for {0} instance has been started. Press any  key to stop.",                 instanceName);             // Wait for the user to stop the program.             Console.ReadKey();         }         catch (NSException nsEx)         {             // Display an error message that includes             // the Notification Services error code.             Console.WriteLine("A Notification Services error has occurred.");             Console.WriteLine(                 "Notification Services Error Code: {0}",                 (int)nsEx.ErrorCode);             Console.WriteLine("Message: {0}", nsEx.Message);             goto Exit;         }         catch (Exception ex)         {             // Display a generic error message.             Console.WriteLine("An error has occurred.");             Console.WriteLine(                 "Exception type: {0}",                 ex.GetType().Name);             Console.WriteLine("Message: {0}", ex.Message);             goto Exit;         }         finally         {             // Check that NSInstance isn't null and that we             // did actually succeed in starting the engine.             if (null != nsInstance && instanceStarted)             {                 // Stop the engine.                 nsInstance.StopInstance();             }         }         // Everything succeeded, so set success return code.         returnCode = 0;     Exit:         return returnCode;     } ... } 

The EngineHost program takes up to four command-line arguments. Two of these are required: an instance name and an authentication mode. The other two arguments are optional: they are used to specify a SQL username and password, if SQL Server Authentication is the chosen authentication mode. (The following section, "Testing the EngineHost Program," explains the program's command-line syntax in detail.)

The command-line arguments are processed and their values are stored in the private member variables instanceName, authenticationMode, sqlUserName, and sqlPassword. The code that validates and processes the command-line arguments is not shown in Listing 17.2 (although you can see this code in the Visual Studio solution). When looking at the code in Listing 17.2, assume that these private member variables contain the values of the command-line arguments.

The Main() method code shown in Listing 17.2 begins by declaring and initializing a Boolean flag that records whether the engine has been successfully started. This flag is checked in the cleanup phase of the program, to determine whether the engine should be stopped. The flag is initialized to false.

Next, the program creates an NSInstance object, using the appropriate constructor for the authentication mode specified in the command-line arguments. In the case of Windows Authentication, the constructor is passed just the instance name. In the case of SQL Server Authentication, the constructor takes the SQL username and password, along with the instance name.

After creating the NSInstance object, the code connects an error event handler to the object's Error event. The event handler is the method, nsInstance_Error(); its code is shown later, in Listing 17.3. In the code in Listing 17.2, an ErrorEventHandler delegate to this method is created and attached to the Error event.

After attaching the event handler delegate, the StartInstance() method is called on the NSInstance object. If StartInstance() returns without throwing an exception, the instanceStarted flag is set to true. This will cause the cleanup code to call the StopInstance() method later, to stop the engine.

The program then displays a message indicating that the engine has been started. Thereafter, it waits for keyboard input by calling the blocking method, Console. ReadKey(). This method returns only after the user presses a key. While waiting for a keypress, the SQL-NS engine continues to run on its own threads, processing events and generating and delivering notifications.

When Console.ReadKey() returns (after the user presses a key), control falls through to the finally block, which performs cleanup for the application. The code in the finally block checks that the NSInstance object isn't null and that the flag indicates the engine was started. If both conditions are true, it calls the NSInstance object's StopInstance() method to stop the engine's execution.

Listing 17.3 shows the code in the nsInstance_Error() event handler, which is called whenever the Error event is raised by the NSInstance object created in Listing 17.2.

Listing 17.3. Handler for the NSInstance.Error Event

 class Program {     ...     static void nsInstance_Error(         object sender,         System.IO.ErrorEventArgs e)     {         // Display an overall error message.         Console.WriteLine(             "A fatal error occurred during the engine's execution.");         // Get the exception object.         Exception ex = e.GetException();         // If the exception is an NSException, show the NS         // error code.         if (ex is NSException)         {             NSException nsEx = ex as NSException;             Console.WriteLine(                 "Notification Services Error Code: {0}",                 (int)nsEx.ErrorCode);          }          // Write the exception message.          Console.WriteLine("Message: {0}", ex.Message);          // This event is only fired for fatal errors, meaning the          // engine has stopped. Alert the user.          Console.WriteLine("The engine has stopped.");     }     ... } 

The first line of the event handler prints a message indicating that a fatal error occurred. Next, the exception object that encapsulates the fatal error is obtained by calling the GetException() method on the ErrorEventArgs object passed in. If the exception object turns out to be of the SQL-NS-specific NSException class, the event handler prints the SQL-NS error code. It then prints the error message from the exception object and a message indicating that the engine has stopped.

Together, Listings 17.2 and 17.3 include all the code required to host the SQL-NS engine. As you can see, not much code is involved.

The following section explains how to test the EngineHost program on your system, to see its hosting capabilities in action. Although this sample application doesn't have any functionality beyond hosting the engine and printing status and error messages, it illustrates the fundamental coding patterns common to most hosting applications. These same patterns can be applied in a real application that may perform other useful functions while hosting the SQL-NS engine.

Testing the EngineHost Program

To test the EngineHost program, we can use it to host the SQL-NS engine for the StockBrokerNMO instance defined in the previous chapter. Before you invoke EngineHost (as described in this section), first make sure the StockBrokerNMO instance has been created, enabled, and registered on your system. To do this, refer back to the instructions in the section "Testing the StockBrokerNMO Sample Application" (p. 554) in Chapter 16, and complete steps 1 through 6. Do not execute step 7, which starts the SQL-NS Windows servicewe will use the EngineHost program to host the SQL-NS engine instead.

Caution

If the StockBrokerNMO instance was previously created on your system and the service is currently running, stop it before continuing with the rest of the instructions in this section. You can stop the StockBrokerNMO instance's service with the following command:

 net stop NS$StockBrokerNMO 


If you have not already done so, build the EngineHost program from its Visual Studio solution. (Instructions for opening the solution are provided in the earlier section "The EngineHost Visual Studio Solution" p. 573.) After successfully building, you can run EngineHost by invoking EngineHost.exe from the C:\SQL-NS\Samples\EngineHost\bin\Debug directory. The EngineHost usage syntax is

[View full width]

EngineHost -instanceName <InstanceName> -authenticationMode <Mode> [-sqlUserName <SqlUser> -sqlPassword <SqlPassword>]



The argument value placeholders (shown between angle brackets) should be replaced as follows:

  • <InstanceName> specifies the name of the SQL-NS instance for which the engine should be hosted.

  • <Mode> specifies the authentication mode the hosted engine should use to connect to the SQL Server. Allowed values are the string "Windows" (to specify Windows Authentication) or the string "SQL" (to specify SQL Server Authentication).

  • <SqlUser> specifies the name of the SQL user account with which the engine should connect to the SQL Server if SQL Server Authentication is specified. If Windows Authentication is specified, omit the -sqlUserName argument.

  • <SqlPassword> specifies the password of the SQL user account with which the engine should connect to the SQL Server if SQL Server Authentication is specified. If Windows Authentication is specified, omit the -sqlPassword argument.

Invoke EngineHost now, specifying "StockBrokerNMO" as the instance name, the appropriate authentication mode for your system, and, if you're using SQL Server Authentication, the SQL username and password of your test account. If you're using Windows Authentication, the command-line syntax is

[View full width]

C:\SQL-NS\Samples\EngineHost\bin\Debug\EngineHost.exe -instanceName StockBrokerNMO -authenticationMode Windows


If you're using SQL Server Authentication and, for example, your SQL test account username and password are "SQL-NS_Test" and "testPassword", respectively, the commandline syntax is

[View full width]

C:\SQL-NS\Samples\EngineHost\bin\Debug\EngineHost.exe -instanceName StockBrokerNMO -authenticationMode SQL -sqlUserName "SQL-NS_Test" -sqlPassword "testPassword"


When EngineHost is invoked, it displays a message saying the engine has been started; it then continues running until you press a key. With EngineHost running, you can proceed to exercise the functionality of the StockBrokerNMO instance in the same way you would if the engine had been running in the SQL-NS Windows service.

To see the engine at work, go back to the instructions in the section "Testing the StockBrokerNMO Sample Application" (p. 554) in Chapter 16, and complete step 8. This enters a few sample subscriber and subscription records and then submits a batch of test events. Within 30 seconds, you'll notice new notifications written to the same output file as before, C:\SQL-NS\Samples\StockBrokerNMO\FileNotifications.txt. As this shows, the SQL-NS engine, hosted in the EngineHost application, behaves exactly as it does when hosted in the SQL-NS Windows service.




Microsoft SQL Server 2005 Notification Services
Microsoft SQL Server 2005 Notification Services
ISBN: 0672327791
EAN: 2147483647
Year: 2006
Pages: 166
Authors: Shyam Pather

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net