VsaRpcl Example

   

The code below is a working test application, fully equipped with the WinMain function. Note that within the WinMain function you will need to change pszNetworkAddress to point to your own IP address, as described in the code comments.

You can find the files you are required to include in Program Files\Microsoft Visual Studio\Common\Tools\VS-Ent98\Vanalyzr\VAProg, if you accepted the default file locations during installation.

In order for your application to use the Visual Studio Analyzer RPC API calls, you must start the NT service, Visual Studio Analyzer RPC Bridge. For information on how to start this service, see Starting the Visual Studio Analyzer RPC Listener Service.

// Include required files
#include "windows.h"   // Required by WinMain
#include "varpc_c.c"   // Defines RPC Interface proxy functions
#include "varpc.h"      // For the declarations of the RPC Interface
                        // functions
#include "vaids.h"      // Defines constants for system-defined
                        // categories and events

// Now define GUIDs for the component that will generate VSA events, as
// well as a GUID for a custom event category, a user-defined event and a
// GUID for a parameter that can hold a GUID if you wanted to pass a GUID
// as a parameter to FireEvent.
static wchar_t str_SAMPLE_SOURCE_GUID[]      = L"{4ED47050-FD2D-11d0-86B9-00AA006C1D08}";
static wchar_t str_SAMPLE_CATEGORY_GUID[]   = L"{4ED47051-FD2D-11d0-86B9-00AA006C1D08}";
static wchar_t str_SAMPLE_EVENT_GUID[]      = L"{4ED47052-FD2D-11d0-86B9-00AA006C1D08}";
static wchar_t str_SAMPLE_GUID_PARAMETER[]   = L"{4ED47055-FD2D-11d0-86B9-00AA006C1D08}";

// Define constants for a system-defined event and category
static wchar_t str_DEBUG_EVENT_CALL[]         = L"{6c736d61-bcbf-11d0-8a23-00aa00b58e10}";
static wchar_t str_DEBUG_EVENT_CATEGORY_ALL[]   = L"{6c736d85-bcbf-11d0-8a23-00aa00b58e10}";

// Declare and initialize a variable to hold error codes
static unsigned long LastErrorCode = 0;

// Check to see whether a component is already registered.
// str_SAMPLE_SOURCE_GUID is the GUID for the component (defined in 
// preceding code); substitute the GUID for your component.
static bool RpcSampleIsSourceRegistered()
{
   HRESULT hr = S_FALSE;

   RpcTryExcept
   {
      hr = VSAIsSourceRegistered(str_SAMPLE_SOURCE_GUID);  
      if( (S_OK != hr) && (S_FALSE != hr ) )
         MessageBox( NULL, "Unexpected return code", "VSAIsSourceRegistered", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAIsSourceRegistered", MB_OK );
   }
   RpcEndExcept;

   return( S_OK == hr );
}

// Register the component we checked for in preceding code.
// str_SAMPLE_SOURCE_GUID is defined in preceding code; substitute the 
// GUID for your component. Assign a name for the component 
// (Sample Event Source) using Unicode characters.
static void RpcSampleRegisterSource()
{
   HRESULT hr = S_FALSE;

   RpcTryExcept
   {
      hr = VSARegisterSource( L"Sample Event Source", str_SAMPLE_SOURCE_GUID );  
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSARegisterSource", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSARegisterSource", MB_OK );
   }
   RpcEndExcept;
}

// Register a system-defined event for the component to generate. 
// str_SAMPLE_SOURCE_GUID is the component that will generate the event
// being registered; str_DEBUG_EVENT_CALL is the event.
static void RpcSampleRegisterStockEvent()
{
   HRESULT hr = S_FALSE;

   RpcTryExcept
   {
      hr = VSARegisterStockEvent(str_SAMPLE_SOURCE_GUID, str_DEBUG_EVENT_CALL);
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSARegisterStockEvent", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSARegisterStockEvent", MB_OK );
   }
   RpcEndExcept;
}

// Register a custom event category for the component.
// str_SAMPLE_SOURCE_GUID is the component for the category being
// registered.
// str_SAMPLE_CATEGORY_GUID is a unique GUID for the category (defined
// in preceding code); substitute the GUID for your component.

// If you want the category to appear in a hierarchy, specify a parent
// (str_DEBUG_EVENT_CATEGORY_ALL will be the parent of this category).
// If you do not specify a parent, your category will appear at the top
// level in the Filter Editor.
// Assign a name (Sample Event Category) and description
// (Category for all sample events) using Unicode characters.
static void RpcSampleRegisterCategory()
{
   HRESULT hr = S_FALSE;

   RpcTryExcept
   {
      hr = VSARegisterEventCategory(
         str_SAMPLE_SOURCE_GUID,
         str_SAMPLE_CATEGORY_GUID, 
         str_DEBUG_EVENT_CATEGORY_ALL, 
         L"Sample Event Category", 
         L"Category for all sample events"
         );
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSARegisterEventCategory", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSARegisterEventCategory", MB_OK );
   }
   RpcEndExcept;
}

// Register a user-defined event for the component to generate. 
// str_SAMPLE_SOURCE_GUID is the component that will generate the event
// being registered.
// str_SAMPLE_EVENT_GUID is a unique GUID for the event (defined in 
// preceding code); substitute the GUID for your component.
// Assign a Name (Sample Event) and Description (Event generated by the
// component) using Unicode characters. 
static void RpcSampleRegisterCustomEvent()
{
   HRESULT hr = 0;

   RpcTryExcept 
   {
      hr = VSARegisterCustomEvent(
         str_SAMPLE_SOURCE_GUID, 
         str_SAMPLE_EVENT_GUID, 
         L"Sample Event", 
         L"Event fired by the sample event source", 
         DEBUG_EVENT_TYPE_GENERIC, 
         str_SAMPLE_CATEGORY_GUID
         );
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSARegisterCustomEvent", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSARegisterCustomEvent", MB_OK );
   }
   RpcEndExcept;
}

// Normally, you would unregister your components only during uninstall.
// The following code would be placed in your component's uninstall
// code.

//Unregister the component
static void RpcSampleUnRegisterSource()
{
   HRESULT hr = 0;

   RpcTryExcept 
   {
      hr = VSAUnregisterSource(str_SAMPLE_SOURCE_GUID);  
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSAUnregisterSource", MB_OK );
   }
   RpcExcept(1) {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAUnregisterSource", MB_OK );
   }
   RpcEndExcept;
}

// The OpenConnection and CloseConnection functions are the equivalents
// of creating and destroying an event creator object, as in the
// COM-based interface ISystemDebugEventFire.
// The VSAOpenConnection function returns an ID that is used to uniquely
// identify this session of the component.
static long RpcSampleOpenConnection()
{
   HRESULT hr = S_FALSE;
   long VSAId = 0;

   RpcTryExcept
   {
      hr = VSAOpenConnection(&VSAId);  
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSAOpenConnection", MB_OK );
      else if( 0 == VSAId )
         MessageBox( NULL, "VSAId is NULL", "VSAOpenConnection", MB_OK );
   }
   RpcExcept(1) {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAOpenConnection", MB_OK );
   }
   RpcEndExcept;
      
   return VSAId;
}

// Begin a session with the component.
// str_SAMPLE_SOURCE_GUID identifies the component. VSAId should be the
// unique ID returned by VSAOpenConnection.
// Specify a name (Sample Session Name) to uniquely identify the session
// to Visual Studio Analyzer. The session name must be unique for each
// time, each component, and each run of the component. 
static void RpcSampleBeginSession(long VSAId)
{
   HRESULT hr = 0;

   RpcTryExcept
   {
      hr = VSABeginSession(VSAId,str_SAMPLE_SOURCE_GUID,L"Sample Session Name");
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSABeginSession", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSABeginSession", MB_OK );
   }
   RpcEndExcept;
}

// Verify whether there is any active event collector interested in the
// events fired. 
static bool RpcSampleIsActive(long VSAId)
{
   HRESULT hr = S_FALSE;

   RpcTryExcept
   {
      hr = VSAIsActive(VSAId);
      if( (S_OK != hr) && (S_FALSE != hr ) )
         MessageBox( NULL, "Unexpected return code", "VSAIsActive", MB_OK );
   }
   RpcExcept(1) {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAIsActive", MB_OK );
   }
   RpcEndExcept;
      
   return( S_OK == hr );
}

// Prepare to generate an event. Define an array to hold
// event parameters

#define MAXPARAMS 2

// Generate the event.
// str_SAMPLE_EVENT_GUID is the GUID of the registered event to generate
static void RpcSampleFireCustomEvent(long VSAId)
{
   HRESULT hr = S_FALSE;

    // Event data is passed in arrays of parameter names (keys) and
    // values.
    // This array holds the parameter names.
   wchar_t * rgKeys[MAXPARAMS];
   wchar_t * rgValues[MAXPARAMS];
      
   rgKeys[0] = L"Custom Field 1";
   rgKeys[1] = L"Custom Field 2";
   rgValues[0] = L"Custom Value 1";
   rgValues[1] = L"Custom Value 2";
      
   RpcTryExcept
   {
      hr = VSAFireEvent(VSAId,str_SAMPLE_EVENT_GUID, 
         MAXPARAMS, rgKeys, rgValues, 0, 0, // dwTimeLow and dwTimeHigh
                                             // values
         cVSAEventDefaultSource | cVSAEventDefaultTarget);
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSAFireEvent (Custom)", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAFireEvent (Custom)", MB_OK );
   }
   RpcEndExcept;
}

static void RpcSampleFireStockEvent(long VSAId)
{
   HRESULT hr = S_FALSE;
      
    // Event data is passed in arrays of parameter names (keys) and
    // values.
    // This array holds the parameter names.
   wchar_t * rgKeys[MAXPARAMS];
   wchar_t * rgValues[MAXPARAMS];
      
   rgKeys[0] = L"Field 1";
   rgKeys[1] = L"Field 2";
   rgValues[0] = L"Value 1";
   rgValues[1] = L"Value 2";
      
   RpcTryExcept
   {
      hr = VSAFireEvent(VSAId,str_DEBUG_EVENT_CALL, 
         MAXPARAMS, rgKeys, rgValues, 0, 0, // dwTimeLow and dwTimeHigh
                                             // values
         cVSAEventDefaultSource | cVSAEventDefaultTarget);
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSAFireEvent (Stock)", MB_OK );
   }
   RpcExcept(1)
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAFireEvent (Stock)", MB_OK );
   }
   RpcEndExcept;
}

// End the session when you are finished generating events.
static void RpcSampleEndSession(long VSAId)
{
   HRESULT hr = S_FALSE;

   RpcTryExcept
   {
      hr = VSAEndSession(VSAId);
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSAEndSession", MB_OK );
   }
   RpcExcept(1) {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSAEndSession", MB_OK );
   }
   RpcEndExcept;
}

// Close the connection. After the call to this function,
// VSAId would no longer be valid.
static void RpcSampleCloseConnection(long VSAId)
{
   HRESULT hr = 0;

   RpcTryExcept 
   {
      VSACloseConnection(VSAId);  
      if( hr )
         MessageBox( NULL, "Non-zero return code", "VSACloseConnection", MB_OK );
   }
   RpcExcept(1) 
   {
      LastErrorCode = RpcExceptionCode();
      MessageBox( NULL, "Exception", "VSACloseConnection", MB_OK );
   }
   RpcEndExcept;
}

// The code that follows creates a test application you can use to
// call the above functions. If you choose to write your own RPC test
// application, make sure to use the end point "2000" when you do the
// RPC binding. Also, make sure to use the correct IP address of the server.
// MIDL allocate and free code is also included in the
// following code just to demonstrate. You can substitute your own MIDL
// allocate and free code.

int WINAPI WinMain(HINSTANCE hInstance,
                            HINSTANCE hPrevInstance,
                            LPSTR lpszCmdLine,
                            int nCmdShow)
                            
{
   RPC_STATUS status;
   unsigned char * pszUuid             = NULL;
   unsigned char * pszProtocolSequence = (unsigned char *)"ncacn_ip_tcp";

    // Change this address to the IP address of the machine where the
    // Visual Studio Analyzer RPC service is running.
   unsigned char * pszNetworkAddress   = (unsigned char *)"172.30.169.32";

    // 2000 is the end point used by the Visual Studio Analyzer RPC bridge
    // server
   unsigned char * pszEndpoint         = (unsigned char *)"2000";
   unsigned char * pszOptions          = NULL;
   unsigned char * pszStringBinding    = NULL;
   
   status = RpcStringBindingCompose(pszUuid,
      pszProtocolSequence,
      pszNetworkAddress,
      pszEndpoint,
      pszOptions,
      &pszStringBinding);
   
   if (status)
   {
      exit(status);
   }
   
   // Set the binding handle that will be used to bind to the server.
   status = RpcBindingFromStringBinding(pszStringBinding, &VsaRpcl_IfHandle);
   if (status)
   {
      exit(status);
   }
   
   // Call RegisterSource
   RpcSampleRegisterSource();
   
   // Call IsSourceRegistered
   if (RpcSampleIsSourceRegistered())
   {
      MessageBox(NULL, "Source is registered", "IsSourceRegistered", MB_OK);
   }
   else
   {
      MessageBox(NULL, "Source is not registered", "IsSourceRegistered", MB_OK);
   }

   // Call RegisterStockEvent
   RpcSampleRegisterStockEvent();

   // Call RegisterEventCategory
   RpcSampleRegisterCategory();

   // Call RegisterCustomEvent
   RpcSampleRegisterCustomEvent();

   // Call Open Connection
   long VSAId = RpcSampleOpenConnection();

   // Call BeginSession
   RpcSampleBeginSession(VSAId);
   
   // Call IsActive
   if (RpcSampleIsActive(VSAId))
   {
      MessageBox(NULL, "Ready to generate events", "IsActive", MB_OK);
   }
   else
   {
      MessageBox(NULL, "Not ready to generate events", "IsActive", MB_OK);
   }

   // Call FireEvent 10 times for Custom and Stock events
   for( int i = 0; i < 10; ++i )
   {
      RpcSampleFireCustomEvent(VSAId);
      RpcSampleFireStockEvent(VSAId);
   }
   
   // Call EndSession
   RpcSampleEndSession(VSAId);
   
   // Call CloseConnection
   RpcSampleCloseConnection(VSAId);
   
   // Call UnregisterSource
   RpcSampleUnRegisterSource();

   //  The calls to the remote procedures are complete.
   //  Free the string and the binding handle
   status = RpcStringFree(&pszStringBinding);
   if (status)
   {
      exit(status);
   }
      
   status = RpcBindingFree(&VsaRpcl_IfHandle);
   if (status) 
   {
      exit(status);
   }
   
   return 0;   
}

// MIDL allocate and free

void  __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
{
   return(malloc(len));
}

void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
{
   free(ptr);
}