Export (0) Print
Expand All
This topic has not yet been rated - Rate this topic

Adding a DTS User Interface to the Custom Task Framework

SQL Server 2000

Adding a DTS User Interface to the Custom Task Framework

To build a custom task that supports a custom task user interface, create a project from the Active Template Library (ATL) custom task basic template, add another class and the interface and other elements required by tasks that support a custom user interface, and then add the features of the specific custom task.

This topic explains how to add the elements required by a Data Transformation Services (DTS) task with a custom user interface. You can also use the ATL custom task user interface templates supplied as samples with Microsoft® SQL Server™ 2000. Even if you plan to use the custom task user interface templates, you need to understand the features that were added to create the custom task user interface templates from the basic custom task template. For more information, see Building a Custom Task with User Interface from the ATL Custom Task Templates.

Building a Custom Task Framework with a UI Class

You can create a Custom Task Framework that includes a class for the custom user interface using Microsoft Visual C++® version 6.0.

To build a custom task framework with a user interface class

  1. Create a framework for a custom task using the ATL custom task basic template.

    Assume you named the component DTSCusTskWUI and the custom task class TaskUISupp. For more information, see Building a Custom Task from the ATL Custom Task Basic Template.

  2. Add another class for the user interface. On the Insert menu, click New ATL Object. On the ATL Object Wizard screen, click Objects, and then click Simple Object. Click Next.

  3. On Names, enter a short name.

    Assume you entered UserIF. The wizard will fill in the other fields.

  4. Click the Attributes tab, and then do the following:
    • Under Threading Model, click Apartment.

    • Under Interface, click Dual.

    • Under Aggregation, click Yes.

      The user interface class will not work unless it can be aggregated.

The wizards will create files for the DTSCusTskWUI component and the TaskUISupp and UserIF classes, and save them to the project location folder specified when you created the framework in the first step.

Adding Features to Support a Custom UI

After creating the custom task framework with TaskUISupp and UserIF class files, you need to add features to support the user interface. In this section, all files will have the same names you specified for the classes.

File Features
TaskUISupp.h Function prototypes, private declarations, and COM map entries for the elements that connect the custom task class to the user interface class.
TaskUISupp.cpp Definitions for the functions that connect the task class to the user interface class.
UserIF.h Function prototypes, private declarations, and COM map entries for the IDTSCustomTaskUI interface elements.
UserIF.cpp Initial function definitions for the IDTSCustomTaskUI interface methods.
DTSCusTskWUI.idl Declaration of the IDTSCustomTaskUI interface elements in the IUserIF interface.

TaskUISupp.h

In this header file, you need to add the following:

  • Prototypes for the functions that connect the custom task class to the user interface class

  • COM Map entries for the IDTSCustomTask and IDTSCustomTaskUI interfaces

  • A declaration of an interface pointer variable
Adding Hook Function Prototypes

These prototypes are for functions that are called when a QueryInterface request for the IDTSCustomTaskUI interface is made to the task class.

Following the constructor and destructor prototypes for the task class:

    CTaskUISupp();
    ~CTaskUISupp();

add these lines of code:

    static HRESULT WINAPI FuncPreQueryInterface(void* pv, REFIID riid, 
                                                LPVOID* ppv, DWORD dw);
    HRESULT PreQueryInterface(REFIID riid, LPVOID *ppv);
Adding COM Map Entries

You need to replace the COM map entry for the ITaskUISupp interface so that it responds when presented with the interface ID for the IDTSCustomTask. You need to add a COM map entry that invokes the hook function when presented with the interface ID for IDTSCustomTaskUI.

Replace the following COM map entries:

    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY2(IDTSCustomTask, ITaskUISupp)

with these lines:

    COM_INTERFACE_ENTRY2(IDispatch, ITaskUISupp)
    COM_INTERFACE_ENTRY_IID(IID_IDTSCustomTask, ITaskUISupp)
    COM_INTERFACE_ENTRY_FUNC(IID_IDTSCustomTaskUI, 0, CTaskUISupp::FuncPreQueryInterface)
Adding an Interface Pointer Variable

This declaration is for a pointer variable for the user interface class, which is set by the hook functions.

Immediately following these lines:

    BSTR        m_bstrName;
    BSTR        m_bstrDescription;

add this declaration:

    IUnknown    * m_pIUnkDTSCustomTaskUI;
TaskUISupp.cpp

In this Visual C++ file for the task class, you need to add the following:

  • An external reference for the class id of the user interface class

  • Code to initialize the user interface class interface pointer variable in the task class constructor

  • Code to release the pointer to the user interface class in the task class destructor

  • Functions that create an instance of the user interface class and issue a QueryInterface for IDTSCustomTaskUI
Adding an External Reference for the class id

Following this include statement:

#include "TaskUISupp.h"

add this external reference:

extern  const CLSID         CLSID_UserIF;
Initializing the User Interface Pointer

At the end of the task class constructor (before the right curly bracket):

CTaskUISupp::CTaskUISupp()

add this line of code:

    m_pIUnkDTSCustomTaskUI = NULL;
Releasing the Interface Pointer

Release the reference to the IDTSCustomTaskUI interface if it exists in the task class destructor.

At the end of the destructor (before the right curly bracket):

CTaskUISupp::~CTaskUISupp()

add these lines of code:

    if(m_pIUnkDTSCustomTaskUI)
        if(m_pIUnkDTSCustomTaskUI->Release() != 0)
            /* _ASSERT(0) */    NULL;
Adding Hook Function Definitions

These functions first obtain a reference to the aggregating object, which is the custom task class. If the QueryInterface request is for the IDTSCustomTaskUI interface and the user interface has not yet been created, an instance of the user interface is created. Then the QueryInterface is requested from the aggregated object, the user interface class.

After the task class destructor:

CTaskUISupp::~CTaskUISupp() { ... }

add these lines of code:

HRESULT WINAPI CTaskUISupp::FuncPreQueryInterface(void* pv, REFIID riid, LPVOID* ppv, DWORD dw)
{
    HRESULT hr = E_FAIL;
    _ASSERT(pv);
    CTaskUISupp * pDTSCustTask = (CTaskUISupp *)pv;
    return pDTSCustTask->PreQueryInterface(riid, ppv);
}

HRESULT CTaskUISupp::PreQueryInterface(REFIID riid, LPVOID *ppv)
{
    HRESULT     hr = S_FALSE;
    IUnknown    * pIUnknownOuter;

    if (!ppv)
    {
        hr = E_POINTER;
        goto error;
    }
    if FAILED(hr = QueryInterface(IID_IUnknown, (void **)&pIUnknownOuter))
        goto error;

    *ppv = NULL;
    if (IID_IDTSCustomTaskUI == riid) 
    {
        if(!m_pIUnkDTSCustomTaskUI)
            if FAILED(hr = CoCreateInstance(CLSID_UserIF,
                                            pIUnknownOuter, CLSCTX_INPROC_SERVER,
                                            IID_IUnknown, (LPVOID*)&m_pIUnkDTSCustomTaskUI))
                goto error;

        hr = m_pIUnkDTSCustomTaskUI->QueryInterface(riid, ppv);
    }
    else
        hr = S_FALSE;

error:
    return hr;
}
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.