Implementing the Task Class

DTS Programming

DTS Programming

Implementing the Task Class

To implement the task class in the Data Transformation Services (DTS) custom task user interface example, add code to the header file TaskGVUpdate.h and the Microsoft® Visual C++® file TaskGVUpdate.cpp.

Adding Code to TaskGVUpdate.h

In this header file for the task class, add declarations for storing the properties added above:

Immediately after the line in the private section:

    IUnknown    * m_pIUnkDTSCustomTaskUI;

insert these lines:

    // Storage for custom properties.
    BSTR        m_bstrGblVarName;
    BSTR        m_bstrGblVarValue;
Adding Code to TaskGVUpdate.cpp

Make these additions to the task class code file:

  • An include statement for the display and update dialog box header file.

  • Code to initialize and release the values of the added properties.

  • Code to retrieve and save the values of the added properties.

  • Code to retrieve the global variable value, display the dialog box, and update the global variable.
Adding an Include Statement

The include statement is necessary so the Execute method can access the dialog box class.

Immediately after the line:

#include "TaskGVUpdate.h"

insert the line:

#include "GVDialog.h"
Initializing and Releasing the Values of the Added Properties

The GblVarName and GblVarValue properties must be initialized to valid values. This is done in the task class constructor.

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

CTaskGVUpdate::CTaskGVUpdate()

add these lines:

    m_bstrGblVarName = SysAllocString( OLESTR("") );
    m_bstrGblVarValue = SysAllocString( OLESTR("") );

The allocated strings must be released before the custom task is removed from memory. This is done in the class destructor.

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

CTaskGVUpdate::~CTaskGVUpdate()

add these lines:

    if (m_bstrGblVarName) SysFreeString(m_bstrGblVarName);
    if (m_bstrGblVarValue) SysFreeString(m_bstrGblVarValue);
Retrieving and Saving the Values of the Added Properties

The property values must be retrieved in the get_property and saved in the put_property functions.

Example

Replace the // TODO comment in CTaskGVUpdate::get_GblVarName with the following code:

    if (!pVal)
        return E_POINTER;
    *pVal = SysAllocString(m_bstrGblVarName);
    if (!*pVal)
        return E_OUTOFMEMORY;

Replace the // TODO comment in CTaskGVUpdate::put_GblVarName with the following code:

    if (m_bstrGblVarName)
        SysFreeString(m_bstrGblVarName);
    m_bstrGblVarName = SysAllocString(newVal);
    if (!m_bstrGblVarName)
        return E_OUTOFMEMORY;

Replace the // TODO comment in CTaskGVUpdate::get_GblVarValue with the following code:

    if (!pVal)
        return E_POINTER;
    *pVal = SysAllocString(m_bstrGblVarValue);
    if (!*pVal)
        return E_OUTOFMEMORY;

Replace the // TODO comment in CTaskGVUpdate::put_GblVarValue with the following code:

    if (m_bstrGblVarValue)
        SysFreeString(m_bstrGblVarValue);
    m_bstrGblVarValue = SysAllocString(newVal);
    if (!m_bstrGblVarValue)
        return E_OUTOFMEMORY;
Global Variable Display and Update Execute Method

The Execute method implements the functionality of the custom task. It does a QueryInterface on the package reference to validate it, then performs the following steps:

  1. Gets a reference to the GlobalVariables collection.

  2. Forms a variant from the target global variable name, then gets a reference to the GlobalVariable object. The call can fail only if the ExplicitGlobalVariables property of the package is TRUE. Otherwise, the global variable is created if it does not exist.

  3. Gets the value of the global variable and converts it to BSTR type so it can be displayed. It sets the GblVarValue property to this value.

  4. Gets a reference to the custom task interface, then displays the dialog box. It passes the interface pointer to the dialog box so that it can retrieve task class properties.

  5. When the dialog box is closed by the user and control returns, Execute converts the global variable back to its original type and updates the global variable value.
Example

Replace the // TODO comment in CTaskGVUpdate::Execute with the following code:

    IDTSPackage             * pIDTSPackage;
    IDTSGlobalVariables     * pGlobVars;
    IDTSGlobalVariable      * pGlobVar;
    ITaskGVUpdate           * pTaskGVUpdate;
    CGVDialog               dlgDialog;
    VARIANT                 vGVName;
    VARIANT                 vGVValue;
    VARIANT                 vGVBSTR;

    // Preset for early return.
    *pTaskResult = DTSTaskExecResult_Failure;

    // Verify the package object.
    if FAILED(hr = pPackage->QueryInterface(IID_IDTSPackage, (void **) &pIDTSPackage) )
        return hr;

    // Get global variables collection.
    if( FAILED( hr = pIDTSPackage->GetGlobalVariables( &pGlobVars ) ) )
        return hr;
    pIDTSPackage->Release();

    // Create variant for global variable name.
    VariantInit( &vGVName );
    V_VT( &vGVName ) = VT_BSTR;
    V_BSTR( &vGVName ) = SysAllocString( m_bstrGblVarName );

    // Get named global variable.
    hr = pGlobVars->Item( vGVName, &pGlobVar );
    pGlobVars->Release();
    SysFreeString( V_BSTR( &vGVName ) );

    // Can just return status on no global variable. DTS puts out a good message.
    if( FAILED( hr ) )  return hr;

    // Get global variable value.
    VariantInit( &vGVValue );
    if( FAILED( hr = pGlobVar->GetValue( &vGVValue ) ) )
        return hr;

    // Convert GV value to BSTR.
    VariantInit( &vGVBSTR );
    if( FAILED( hr = VariantChangeType( &vGVBSTR, &vGVValue, 
                                        VARIANT_ALPHABOOL, VT_BSTR ) ) )
        return hr;

    // Release the value BSTR if necessary.
    if( V_VT( &vGVValue ) == VT_BSTR )
        SysFreeString( V_BSTR( &vGVValue ) );

    // Release previous vlaue of property, and save current value.
    SysFreeString( m_bstrGblVarValue );
    m_bstrGblVarValue = V_BSTR( &vGVBSTR );

    // Get user interface for this custom task.
    if FAILED(hr = QueryInterface(IID_ITaskGVUpdate, (void **) &pTaskGVUpdate) )
        return hr;

    // Put up dialog box to display global variable value.
    dlgDialog.DoModal( NULL, (long)pTaskGVUpdate ); 
    pTaskGVUpdate->Release();

    // Convert updated property back to variant of original type (or BSTR, if empty).
    V_BSTR( &vGVBSTR ) = SysAllocString( m_bstrGblVarValue );
    if( FAILED( hr = VariantChangeType( &vGVValue, &vGVBSTR, VARIANT_ALPHABOOL, 
                                        ( ( V_VT( &vGVValue ) == VT_EMPTY ) ? 
                                          VT_BSTR : V_VT( &vGVValue ) ) ) ) )
        return hr;
    SysFreeString( V_BSTR( &vGVBSTR ) );

    // Update global variable value.
    if( FAILED( hr = pGlobVar->SetValue( vGVValue ) ) )
        return hr;
    pGlobVar->Release();

    // Release the value BSTR if necessary.
    if( V_VT( &vGVValue ) == VT_BSTR )
        SysFreeString( V_BSTR( &vGVValue ) );