Using ATL to Create a Plug-in

To create a plug-in using the Active Template Library (ATL) and Microsoft Visual Studio® .NET, complete the following steps:

  1. Start Microsoft Visual Studio .NET and, on the File menu, click New and then click Project.

  2. In the New Project dialog box, click Visual C++ Projects and click the ATL Project template. Give the project a name, specify a location, and click OK.

  3. In the ATL Project Wizard, click Application Settings and clear the Attributed code check box. By using predefined attributes, you can instruct the compiler to insert code or make other modifications at compile time. This example does not use attributed programming. Click Finish.

  4. Right-click the proxy stub node in the solution explorer and select Remove. The proxy stub node is identified by the letters PS appended to the project name. Remove the ReadMe.txt file from the project in the same manner.

  5. After creating the project, click Add Class on the Project menu. Click ATL in the Visual C++ tree, click ATL Simple Object, and click Open. Give the object a name in the Short name text box.

  6. Click Options. To create COM interfaces that can be used by scripting languages, you must click Dual in the Interface group box. Otherwise, click Custom. Click No in the Aggregation group box. Click an appropriate radio button in the Threading Model group box. The free threaded model is recommended.

  7. Click Single to designate that the object can be run only on the primary thread of the client process that initializes COM. This is not recommended.

  8. Click Apartment to designate that the object can run only in a single-threaded apartment. Calls to the object are synchronized by COM. This is not recommended.

  9. Click Both to designate that the object can be run in either a single or free-threaded apartment. You must write code to synchronize calls to your object.

  10. Click Free to designate that the object can be called from any thread. You must write code to synchronize calls to your object. This is the recommended threading model.

  11. Include Wmsserver.h and Wmsbasicplugin.h in the stdafx.h file. You must also include any header files needed for the specific type of plug-in you are creating. For example, if you are building an event notification plug-in, you must also include the event.h file. For more information, see Custom Plug-in Header Files. If the compiler cannot find the header files, you can go to the property pages for the project and enter a path to the include directories. To access the property pages, right-click the project name in the solution explorer and select Properties. Click C++ and click General. Add the path to the Additional Include Directories.

  12. Implement the IWMSBasicPlugin IWMSBasicPlugin Interface and any interfaces needed by the plug-in you are creating.

  13. ATL can be used to create a minimal interface implementation. Click the ClassView tab, and then click the class for which you want to implement an interface. Right-click to view the shortcut menu, click Add, and click Implement Interface. In the drop-down box that displays the available type libraries, click Windows Media Services Server Object Model and Plugin 9.0 Type Library. In the scroll box that displays the available interfaces, click the interfaces you want to implement. Click Finish when you are done selecting interfaces to implement. ATL will automatically modify the COM map and the class declaration, and insert skeletons for the appropriate methods in the header file for the object. You can copy the method declarations from the .h file into the .cpp file and implement them.

  14. You can also implement interfaces without using a Wizard. In the header file for the object, add IWMSBasicPlugin to the COM map. Also add any interfaces needed by the specific type of plug-in you are creating. The following example illustrates the declarations and COM map in the header file for a class named CMyNewPlugin. Implement the methods in the corresponding .cpp file. The example assumes that you are creating an event notification plug-in and must inherit from the IWMSEventNotificationPlugin IWMSEventNotificationPlugin Interface.

    class ATL_NO_VTABLE CMyNewPlugin : 
        public CComObjectRootEx<CComMultiThreadModel>,
        public CComCoClass<CMyNewPlugin, &CLSID_MyNewPlugin>,
        public IMyNewPlugin,
        public IWMSBasicPlugin,
        public IWMSEventNotificationPlugin
    {
    public:
    
    BEGIN_COM_MAP(CMyNewPlugin)
        COM_INTERFACE_ENTRY(IMyNewPlugin)
        COM_INTERFACE_ENTRY(IWMSBasicPlugin)
        COM_INTERFACE_ENTRY(IWMSEventNotificationPlugin)
    END_COM_MAP()
    
        // Declare the IWMSBasicPlugin methods.
        STDMETHOD( InitializePlugin ) ( IWMSContext* pServerContext,
                                        IWMSNamedValues* pNamedValues,
                                        IWMSClassObject* pClassFactory );
        STDMETHOD( OnHeartbeat ) ();
        STDMETHOD( GetCustomAdminInterface ) (IDispatch** pVal);
        STDMETHOD( ShutdownPlugin ) ();
        STDMETHOD( EnablePlugin ) (long* plReserved,
                                   long* pdwHeartbeatPeriod);
        STDMETHOD( DisablePlugin ) ();
    
        // Declare methods for the IWMSEventNotificationPlugin
        // interface. This interface is used only if you are
        // creating an event notification plug-in. Each type
        // of plug-in must implement different interfaces.
        STDMETHOD( GetHandledEvents) (VARIANT* pvarHandledEvents);
        STDMETHOD( OnEvent) (WMS_EVENT* pEvent,
                             IWMSContext* pUserCtx,
                             IWMSContext* pPresentationCtx,
                             IWMSCommandContext* pCmdCtx);
    
    
  15. Modify the registry script to place additional information about your plug-in into the system registry. A Windows Media server uses the registry to identify your plug-in. This following example illustrates a common format for the registry script. For more information, see Registering Plug-ins.

    HKCR
    {
      TestProject.MyNewPlugin.1 = s 'MyNewPlugin Class'
      {
        CLSID = s '{0395BE65-5759-4652-83E8-E2EFE3638438}'
      }
      TestProject.MyNewPlugin = s 'MyNewPlugin Class'
      {
        CLSID = s '{0395BE65-5759-4652-83E8-E2EFE3638438}'
        CurVer = s 'TestProject.MyNewPlugin.1'
      }
      NoRemove CLSID
      {
        ForceRemove {0395BE65-5759-4652-83E8-E2EFE3638438} = 
                                           s 'MyNewPlugin Class'
        {
          val AppID = s '{0395BE65-5759-4652-83E8-E2EFE3638438}'
          ProgID = s 'TestProject.MyNewPlugin.1'
          VersionIndependentProgID = s 'TestProject.MyNewPlugin'
          InprocServer32 = s '%MODULE%'
          {
          val ThreadingModel = s 'Apartment'
          }
          'TypeLib' = s '{837A255A-B8A2-4402-A5E3-9D767062422F}'
          ForceRemove Properties
          {
            val Author = s 'Author name'
            val Name = s 'Sample Event Notification Plugin'
            val Copyright = s 'Copyright. All rights reserved.'
          }
        }
      }
    }
    
    HKLM 
    {
      NoRemove SOFTWARE
      {
        NoRemove Microsoft
        {
          NoRemove 'Windows Media'
          {
            NoRemove Server
            {
              NoRemove RegisteredPlugins
              {
                NoRemove 'Event Notification and Authorization'
                {
                  ForceRemove {0395BE65-5759-4652-83E8-E2EFE3638438} = 
                                    s 'Sample Event Notification Plugin'
                  {
                  }
                }
              }
            }
          }
        }
      }
    }
    
  16. Build the plug-in. The plug-in is automatically registered on the local computer during the build process. To learn how to register the plug-in on another machine, see Registering Plug-ins.

See Also

Concepts

Getting Started with ATL, C#, and Visual Basic