How to write a Web Farm Framework provider?

Overview
The IIS Web Farm Framework 2.0 (WFF) allows users to not only setup and a provision a group of servers, define routing and load balancing support in ARR, but also extends the management support to enable very powerful experiences. WFF 2.0 has completely extensible model for building custom providers to aggregate log files, performance counters, event log data, or take custom actions.

The intent of this article is to showcase the extensibility of Web Farm Framework and illustrating it by a sample provider. This provider allows an administrator to do windows update on a particular server or on all the servers in the Web Farm. The code in this article also serves as a sample to help write your own provider.

Download and Install
You need to download the zip files with the projects. Windows Update provider contains the following files:

  • WindowsUpdateProvider.cs- an entry point to the provider that asks you about the metadata of the provider which is shown in the UI. It implements two main methods, BeginRunOperation and EndRunOperation, which is the crux of the provider. The class internally has a private class(SimpleAsyncResult) which implements IAsyncResult to do operations asynchronously.

    SimpleAsyncResult stops the server using inbuilt provider StopOperationProvider.
    RunOperationOptions options _operationContext.Server.CreateRunOperationOptions(StopOperationProvider.ProviderName);

    _operationContext.Server.BeginRunOperation(_operationContext, options, StopCompleteCallback, 
    null);

    If the operation throws then whole operation is short circuited and the exception is thrown to the controller machine. If stopping the server is successful, it calls the custom method (InstallUpdatesRemoteMethod) passing in the arguments (which in this case is null) and the callback method address to call when the operation is complete.

    _operationContext.Server.BeginRunRemote(_operationContext,
                            
    typeof(InstallUpdatesRemoteMethod),
                            
    new object[] { },
                            InstallUpdatesCompleteCallback,
                            
    null);

    The operation is executed on the server. If operation on the server throws an exception, the whole process is short circuited, to complete the process and throw the exception. If the operation is completed successful, the callback method passed to the method is called.

    _operationContext.Server.BeginRunRemote(_operationContext,
                            
    typeof(InstallUpdatesRemoteMethod),
                            
    new object[] { },
                            InstallUpdatesCompleteCallback,
                            
    null);

    It checks to see if a reboot is required. If a value of true is returned, it calls in the inbuilt reboot provider to reboot the server, also passing in the operation complete callback method.

    bool rebootRequired (bool)_operationContext.Server.EndRunRemote(result);
    if 
    (rebootRequired)
    {
      RunOperationOptions options 
    _operationContext.Server.CreateRunOperationOptions(RebootOperationProvider.ProviderName);
      
    options.Parameters[0].Value Resources.RebootRequiredForInstall;

      
    _operationContext.Server.BeginRunOperation(_operationContext,
                                options,
                                RebootCompleteCallback,
                                
    null);

      return;
    }
  • InstallUpdatesRemoteMethod.cs-The class implements IServerRemoteMethod interface which tells the framework that method RunRemote method will be executed on the remote machines.
    public interface IServerRemoteMethod
    {
     
    object RunRemote(ServerRemoteMethodContext methodContext, object[] parameters);
    }

    The method is passed in with the ServerRemoteMethodContext object which can be used to trace messages.

    private void TraceMessage(TraceLevel traceLevel, string message)
    {
     _methodContext.TraceMessage(
    new TraceMessage(TraceLevel.Verbose, message));
    }

    The remote method trace messages of the operations its performing which are remoted back to the controller machine. Also, the call to perform windows update is performed as the local system, that’s the reason; the call to Windows Update API code is elevated to be executed as the local system. Once the updates have been performed, the thread is reverted back to its original identity.

  • Resources.resx-Contains the string resources.
  • NativeMethods.cs-Contains the interop to call into wuapi.dll.

To install this provider, on the controller machine you need to

  1. Compile the project (or just use this dll)
  2. Create folder called extensions under “%programfiles%\IIS\Microsoft Web Farm Framework”. The dll should be dropped in this folder.
  3. Restart the webfarmservice on the controller machine.

5 Comments

  • Hi Singh,
    Thanks for you reply in the WFF forum. I found your blog and it is the only place showing an example of custom provider. I downloaded the zip and managed to compile it. I dropped the dll into the newly created extensions folder. Restart web farm controller service and there is no entry showing in additional provider under application provision. Is the correct place to find the custom provider?

    Another question here is that a dll called Microsoft.SqlServer.BatchParser.dll will be automatically created whenever build the project. Is the file need to be put under extensions folder too? I tried to put it there and got a error saying it is invalid win32 application.

    Thanks.

  • Did you restart the web farm service? You should not require "Microsoft.SqlServer.BatchParser.dll". I will look into why its getting built.

  • I tried building the example from zip file, and looks like AssemblyInfo.cs file is missing. Once i got past that, successfully compiled the dll, and dropped the dll, when restarting the Web farm controller service i got following error

    Service cannot be started. Microsoft.Web.Farm.WebFarmException: Found duplicate provider for operation 'WindowsUpdateProvider' defined in type 'WFFWindowsUpdate.WindowsUpdateProvider' (assembly 'C:\Program Files\IIS\Microsoft Web Farm Framework\extensions\WFFWindowsUpdate.dll')
    at Microsoft.Web.Farm.ServerContext.GetOperationProviders()
    at Microsoft.Web.Farm.ServerContext.get_OperationProviders()
    at Microsoft.Web.Farm.ServerContext.GetProvider(String providerName)
    at Microsoft.Web.Farm.WebFarmContext.Add()
    at Microsoft.Web.Farm.WebFarmService.ReadConfiguration()
    at Microsoft.Web.Farm.WebFarmService.OnStart(String[] args)
    at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)

    Then i changed the ProviderName property to MyWindowsUpdateProvider, the service started fine, but i dont see the provider in the list of providers when trying ApplicationProvisioning

  • just to update, i was able to get this work after i changed the name of class also

  • I know it is a while later that I post this question, maybe somebody still reads here and may answer: I wrote a provider myself and came across the above mentioned problems, solved them as described. It seems that the provider is in use, since I can't delete the dll because "its in use by web farm agent...".

    Still it seems the provider is not fully used, since the loadbalancer I try to control with it doesn't show any action. Debugger never gets to the breakpoint I set.

    So my question: How can I verifiy the provider is not only loaded but really used? To which process do I have to attach? InetMgr, Web Farm Agent Service and Web Farm Service do not lead to the breakpoint.

    Thanks for any help,
    Cheers, Christiantar

Comments have been disabled for this content.