Session Recording provides the ability to record ICA sessions. The purpose of the Session Recording Event API is to allow third parties to augment session recordings with application specific event data. Arbitrary data can be added to the Session Recording stream in real-time during recording, and the same data can be retrieved in real-time during playback.
The Session Recording Agent provides a simple COM interface that third party applications can use to add application specific event data into the recorded session.
The above diagram shows a published application running on a Citrix VDA with Session Recording enabled. During the lifetime of the recorded session, the published application can add application-specific event data into the recorded stream using the LogData function provided by the IUserApi interface. Application-specific event data points are time stamped as they are added into the recorded stream. The same event data will be available during playback of the recorded session, synchronized with the playback stream in real-time.
The above diagram shows how application event data are consumed during session playback. Event data are displayed in the Events and Bookmarks panel of the Session Recording Player. The Player can also deliver the event data as recorded to a third party consumer application built using the Player SDK. The delivery of event data is synchronized with the playback in real-time.
The Session Recording Event API is provided as a COM Server hosted by the Session Recording Agent, installed on each VDA machine with Session Recording enabled.
The Session Recording Event API can be enabled or disabled on a per-server basis. The default setting for each Session Recording Agent installation is for the COM interface to be disabled. Any attempts to connect to the interface will fail until it is enabled by the administrator. Please refer to the Session Recording documentation for more information on configuring the Session Recording Agent.
When the Session Recording Event API is enabled, a COM interface called IUserApi is made available for third party applications to add event data to the recorded stream. The IUserApi interface contains only one function called LogData.
Event data is stored in the data stream within the recorded session. If the searchable flag is set when the data is added to the recording stream, a database entry will be created and indexed against the fully qualified type associated with the data. As there is some overhead in storing each searchable event, this flag should only be set if there is an intention to search on the event text.
Event data added to Session Recording files is automatically available during playback. Event data is organized in a similar manner as bookmarks, and are listed in the Events and Bookmarks panel of the Session Recording Player. The following screenshot shows the event data as seen in the Events and Bookmarks panel (lower left corner) of the Session Recording Player:
Event items are labelled with a yellow dot, both in the Events and Bookmarks panel and on the player window timeline bar. Note that only the event text is displayed in the Session Recording Player; event binary data can only be retrieved through custom applications built on the Session Recording Player SDK (see the next section for more details.)
Recordings containing event data originally recorded with the searchable flag set can be found using the Session Recording Player’s advanced search form as shown below.
This allows searching by both event text and event type name.
The Session Recording Event API is provided as a COM Server hosted by the Session Recording Agent, installed on each Citrix VDA machine with Session Recording enabled.
When the Session Recording Event API is enabled, a COM interface called IUserApi is made available for third party applications to add event data to the recorded stream. The IUserApi interface contains only one function called LogData.
ProgID
The ProgID for the Session Recording Agent COM server is Citrix.SmartAuditor.Agent.UserApi. The ProgID is used to locate and instantiate the COM objects within the third party application.
LogData
The LogData function will record provided event data into the recorded session file associated with the session ID specified. All parameters are validated for length and format before data is recorded.
If the supplied session ID is not a current session, or the supplied session is not being recorded by the Session Recording Agent, then the function call will be ignored and no error will be returned to the caller. This is to prevent the Event API being used as a means for detecting whether a particular session is actually being recorded.
The fully qualified type name associated with the event data is of the form typePart1.typePart2.typePart3. The type parts can be any string, but general good naming practice is CompanyName.Subsystem.Type. For example, AcmeInc.TradingApp.Transaction.
interface IUserApi : IDispatch { HRESULT LogData( [in] int sessionId, [in] BSTR typePart1, [in] BSTR typePart2, [in] BSTR typePart3, [in] BSTR text, [in] SAFEARRAY(byte)* data, [in] byte searchable); };
Parameters
sessionId
ID of session to log event data for. The session ID must be greater than or equal to 0. Logging data for unknown session IDs will simply be ignored (that is, no exception will be thrown).
typePart1
Event type first part of the fully qualified type name. Length of each part must be between 1 and 32 characters and must not contain any “.” (dot) characters.
typePart2
Event type second part of the fully qualified type name. Length of each part must be between 1 and 32 characters and must not contain any “.” (dot) characters.
typePart3
Event type third (and final) part of the fully qualified type name. Length of each part must be between 1 and 32 characters and must not contain any “.” (dot) characters.
text
Event text data. Length of string must be between 1 and 128 characters.
data
Event binary data. Length must be between 0 and 4096 bytes.
searchable
Flag indicating whether the text value is database searchable. If this flag is non-zero, a database entry indexed against the fully qualified type and text fields will be created in the Session Recording database for the event item.
Return Values
ERROR_SUCCESS (HRESULT value 0x00000000) if successful. If an invalid parameter value is detected, E_INVALIDARG (HRESULT value 0x8007057) is returned or if called from .NET managed code, a System.ArgumentException is thrown.
Requirements
Library Interface | Interop.UserApi.idl |
DLL | Requires Interop.UserApi.dll |
Session Recording added access control to Event API com interface in XenApp and XenDesktop (now Virtual Apps and Desktops) 7.15. Only authorized users are allowed to invoke the functionality to insert event metadata into a recording.
Local administrator is granted with this permission by default. If you want to grant other users to do this, a Session Recording administrator should use the Windows DCOM configuration tool to give them permission.
Open DCOM configuration tool on Session Recording Agent machine by running “dcomcnfg.exe”.
Right click “Citrix Session Recording Agent” and choose “Properties”.
Select “Security” tab, click “Edit” to add users with “Local Activate” permission in “Launch and Activation Permissions” section.
Note:
DCOM configuration will take effect immediately, there is no need to restart any services or reboot the machine.
The Session Recording installation includes an event recording COM application (API) that allows you to insert text from third-party applications into a recording. Listed below are some code samples for logging event data. Since the Session Recording Event API is implemented as a COM server, many programming languages are capable of being used as clients for logging event data.
In order to make use of the Session Recording Event API COM interface, you will need a .NET callable wrapper called Interop.UserApi.dll. You can find this DLL in the Session Recording Agent installation directory.
The following code sample assumes that Session Recording Interop.UserApi.dll has been added as a reference in the C# project.
using System; using System.Diagnostics; using System.Runtime.InteropServices; using Interop.UserApi; // Interop derived from IUserApi.idl namespace UserApiSample { /// <summary> /// Class for logging Session Recording Event Data /// </summary> public class EventDataLogger { /// <summary> /// ProgID for Session Recording Event API /// </summary> private const string EventApiProgID = "Citrix.SmartAuditor.Agent.UserApi"; /// <summary> /// COM interface for calling the Session Recording Event API /// </summary> private IUserApi m_EventApi = null; /// <summary> /// Log event data for specified session /// </summary> /// <param name="sessionId">session ID</param> /// <param name="dataType1">part 1 of event data type</param> /// <param name="dataType2">part 2 of event data type</param> /// <param name="dataType3">part 3 of event data type</param> /// <param name="textData">event text data</param> /// <param name="binaryData">event binary data</param> /// <param name="searchable">indicate whether text data is searchable</param> public void LogData( int sessionId, string dataType1, string dataType2, string dataType3, string textData, byte[] binaryData, bool searchable) { try { if (null == m_EventApi) { // create instance of Event API COM object Type type = Type.GetTypeFromProgID(EventApiProgID, true); if (null != type) { object obj = Activator.CreateInstance(type); m_EventApi = (IUserApi)obj; } } if (null != m_EventApi) { m_EventApi.LogData( sessionId, dataType1, dataType2, dataType3, textData, ref binaryData, Convert.ToByte(searchable) ); } else { Debug.WriteLine("Uninitialized Event API object"); throw new InvalidComObjectException("Uninitialized Event API object"); } } catch ( System.Exception ex) { Debug.WriteLine(ex.Message); throw ex; } } } }
The following code fragment illustrates how to obtain the Session ID for the current application. Please refer to Microsoft Platform SDK documentation for more information on Terminal Services related functions.
/// <summary> /// Enum for TS session information /// </summary> public enum WTS_INFO_CLASS { WTSInitialProgram, WTSApplicationName, WTSWorkingDirectory, WTSOEMId, WTSSessionId, WTSUserName, WTSWinStationName, WTSDomainName, WTSConnectState, WTSClientBuildNumber, WTSClientName, WTSClientDirectory, WTSClientProductId, WTSClientHardwareId, WTSClientAddress, WTSClientDisplay, WTSClientProtocolType } /// <summary> /// ID for querying current TS session /// </summary> public const int WTS_CURRENT_SESSION = -1; /// <summary> /// pinvoke for WTSQuerySessionInformation /// </summary> [DllImport("Wtsapi32.dll")] public static extern bool WTSQuerySessionInformation(System.IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned); /// <summary> /// Get the current TS session ID /// </summary> public int GetCurrentSessionID() { int sessionID = -1; uint bytesReturned = 0; System.IntPtr buffer = IntPtr.Zero; bool retCode = WTSQuerySessionInformation(System.IntPtr.Zero, WTS_CURRENT_SESSION, WTS_INFO_CLASS.WTSSessionId, out buffer, out bytesReturned); if (retCode) { sessionID = Marshal.ReadInt32(buffer); } return sessionID; }
The following code fragment illustrates how event data is added to the session recording. The application is assumed to be running as a published application, and the ICA session is currently being recorded. Note that no error will be generated if the ICA session is not being recorded; this is a security feature of the EventAPI to prevent users from determining if session recording is in effect.
try { // get the current Terminal Services session ID int sessionID = GetCurrentSessionID(); // create EventDataLogger instance EventDataLogger eventLogger = new EventDataLogger(); // log some event data eventLogger.LogData( sessionID, "AcmeInc", "TransactApp", "Transaction", "Order #123 completed", new byte[0], true ); } catch (System.Exception ex) { Debug.WriteLine(ex.Message); throw ex; }
In order to make use of the Session Recording Event API COM interface, you will need a .NET callable wrapper called Interop.UserApi.dll. You can find this DLL in the Session Recording Agent installation directory.
The following code fragment assumes that Session Recording Interop.UserApi.dll has been added as a reference in the VB.Net project.
Imports System.Runtime.InteropServices ' Sub routine for logging event data Sub LogData( _ ByVal sessionId As Int32, _ ByVal text As String, _ ByVal bytes As Byte(), _ ByVal searchable As Byte) Dim eventApi As IUserApi = _ CType(CreateObject("Citrix.SmartAuditor.Agent.UserApi"), IUserApi) eventApi.LogData( _ sessionId, _ "AcmeInc", _ "TransactApp", _ "Transaction", _ textLabel.Text, _ bytes, _ searchable) End Sub