There is an API you can call from PowerBuilder:
https://www.citrix.com/community/citrix-developer/xenapp-xendesktop/wfapi-sdk.html
Here is the source code of an NVO I wrote many years ago:
forward
global type n_citrixapi from nonvisualobject
end type
end forward
global type n_citrixapi from nonvisualobject autoinstantiate
end type
type prototypes
Function ulong GetLastError( ) Library "kernel32.dll"
Function ulong FormatMessage( &
ulong dwFlags, &
ulong lpSource, &
ulong dwMessageId, &
ulong dwLanguageId, &
Ref string lpBuffer, &
ulong nSize, &
ulong Arguments &
) Library "kernel32.dll" Alias For "FormatMessageW"
Function long GetSystemMetrics( &
long nIndex &
) Library "user32.dll"
Function ulong WNetGetUser( &
string lpname, &
Ref string lpusername, &
Ref ulong buflen &
) Library "mpr.dll" Alias For "WNetGetUserW"
Function ulong RtlMoveMemoryPtr( &
Ref ulong dest, &
ulong source, &
ulong size &
) Library "kernel32.dll" Alias For "RtlMoveMemory"
Function ulong RtlMoveMemoryStr( &
Ref string dest, &
ulong source, &
ulong size &
) Library "kernel32.dll" Alias For "RtlMoveMemory"
Function Boolean LookupAccountSid( &
String lpSystemName, &
ulong Sid, &
Ref String Name, &
Ref ulong cbName, &
Ref String DomainName, &
Ref ulong cbDomainName, &
Ref ulong peUse &
) Library "advapi32.dll" Alias For "LookupAccountSidW"
Function ulong WFOpenServer( &
string pServerName &
) Library "wfapi.dll" Alias For "WFOpenServerW"
Subroutine WFCloseServer( ulong hServer ) Library "wfapi.dll"
Subroutine WFFreeMemory( ulong pMemory ) Library "wfapi.dll"
Function Boolean WFEnumerateServers( &
string pDomainName, &
ulong Reserved, &
ulong Version, &
Ref ulong ppServerInfo, &
Ref ulong pCount &
) Library "wfapi.dll" Alias For "WFEnumerateServersW"
Function Boolean WFEnumerateProcesses( &
ulong hServer, &
ulong Reserved, &
ulong Version, &
Ref ulong ppProcessInfo, &
Ref ulong pCount &
) Library "wfapi.dll" Alias For "WFEnumerateProcessesW"
Function Boolean WFTerminateProcess( &
ulong hServer, &
ulong pProcessId, &
ulong exitCode &
) Library "wfapi.dll"
Function Boolean WFEnumerateSessions( &
ulong hServer, &
ulong Reserved, &
ulong Version, &
Ref ulong ppSessionInfo, &
Ref ulong pCount &
) Library "wfapi.dll" Alias For "WFEnumerateSessionsW"
Function Boolean WFQuerySessionInformation( &
ulong hServer, &
ulong SessionId, &
ulong WFInfoClass, &
Ref ulong ppBuffer, &
Ref ulong pBytesReturned &
) Library "wfapi.dll" Alias For "WFQuerySessionInformationW"
Function Boolean WFSendMessage( &
ulong hServer, &
ulong SessionId, &
string pTitle, &
ulong TitleLength, &
string pMessage, &
ulong MessageLength, &
ulong Style, &
ulong timeOut, &
Ref ulong pResponse, &
boolean bWait &
) Library "wfapi.dll" Alias For "WFSendMessageW"
end prototypes
type variables
// Constants for GetSystemMetrics
Constant long SM_REMOTESESSION = 4096
// Constants for WFQuerySessionInformation
Constant ulong WFVersion = 0
Constant ulong WFInitialProgram = 1
Constant ulong WFWorkingDirectory = 2
Constant ulong WFOEMId = 3
Constant ulong WFSessionId = 4
Constant ulong WFUserName = 5
Constant ulong WFWinstationName = 6
Constant ulong WFDomainName = 7
Constant ulong WFConnectState = 8
Constant ulong WFClientBuildNumber = 9
Constant ulong WFClientName = 10
Constant ulong WFClientDirectory = 11
Constant ulong WFClientProductID = 12
Constant ulong WFClientHardwareId = 13
Constant ulong WFClientAddress = 14
Constant ulong WFClientDisplay = 15
Constant ulong WFClientCache = 16
Constant ulong WFClientDrives = 17
Constant ulong WFICABufferLength = 18
Constant ulong RESERVED2 = 19
Constant ulong WFApplicationName = 20
Constant ulong WFAppInfo = 21
Constant ulong WFClientInfo = 22
Constant ulong WFUserInfo = 23
Constant ulong WFClientLatency = 24
Constant ulong WFSessionTime = 25
end variables
forward prototypes
public function unsignedlong of_getpointer (unsignedlong aul_baseptr, unsignedinteger ai_ptrnum, unsignedinteger ai_arraynum, unsignedinteger ai_ptrcnt)
public function string of_wnetgetuser ()
public function boolean of_find_process (string as_server, string as_program)
public function unsignedlong of_wfenumerateprocesses (unsignedlong aul_hserver, ref unsignedlong aul_sessionid[], ref unsignedlong aul_processid[], ref string as_process[], ref string as_userid[])
public function unsignedlong of_wfenumeratesessions (unsignedlong aul_hserver, ref unsignedlong aul_sessionid[], ref string as_stationname[])
public function string of_formatmessage (unsignedlong aul_error)
public subroutine of_wfcloseserver (unsignedlong aul_hserver)
public function unsignedlong of_wfenumerateservers (ref string as_servers[])
public function string of_lookupaccount (unsignedlong aul_usersid)
public function unsignedlong of_wfopenserver (string as_server)
public function string of_wfquerysessioninformation (unsignedlong aul_hserver, unsignedlong aul_sessionid, unsignedlong aul_infoclass)
public function boolean of_wfterminateprocess (unsignedlong aul_hserver, unsignedlong aul_processid, unsignedlong aul_exitcode)
public function boolean of_wfsendmessage (unsignedlong aul_hserver, unsignedlong aul_sessionid, string as_title, string as_msg)
public function boolean of_iscitrixsession ()
public function unsignedlong of_getlasterror ()
end prototypes
public function unsignedlong of_getpointer (unsignedlong aul_baseptr, unsignedinteger ai_ptrnum, unsignedinteger ai_arraynum, unsignedinteger ai_ptrcnt);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_GetPointer
//
// PURPOSE: This function returns a pointer from an array of structures.
//
// ARGUMENTS: aul_baseptr - base address of buffer
// ai_ptrnum - which pointer in the structure is needed
// ai_arraynum - which array occurrence
// ai_ptrcnt - how many pointers in the structure
//
// RETURN: The pointer value
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
ULong lul_bufptr, lul_strptr
// calculate memory location
lul_bufptr = aul_baseptr + ((ai_arraynum - 1) * (ai_ptrcnt * 4)) + ((ai_ptrnum - 1) * 4)
// copy pointer into local variable
RtlMoveMemoryPtr(lul_strptr, lul_bufptr, 4)
Return lul_strptr
end function
public function string of_wnetgetuser ();// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WNetGetUser
//
// PURPOSE: This function retrieves the current default user name, or
// the user name used to establish a network connection.
//
// RETURN: Network user name
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
String ls_userid
Ulong lul_result, lul_buflen
lul_buflen = 32
ls_userid = Space(lul_buflen)
lul_result = WNetGetUser("", ls_userid, lul_buflen)
Return ls_userid
end function
public function boolean of_find_process (string as_server, string as_program);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_Find_Process
//
// PURPOSE: This function searches for a process on a Citrix server running
// under the current user's userid.
//
// ARGUMENTS: as_server - Name of a Citrix server
// as_program - Name of the program to look for
//
// RETURN: True = Program found, False = Program not found
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
ULong lul_hServer, lul_ppProcessInfo, lul_pCount
ULong lul_ppBuffer, lul_pBytesReturned, lul_loop
ULong lul_strptr, lul_ProcessId, lul_pUserSid
String ls_process, ls_userid, ls_acctname
Boolean lb_rc, lb_found
// get userid of current user
ls_userid = this.of_WNetGetUser()
// open handle to citrix server
lul_hServer = this.of_WFOpenServer(as_server)
// gather array of processes for the server
lb_rc = WFEnumerateProcesses(lul_hServer, 0, 1, lul_ppProcessInfo, lul_pCount)
// loop through each occurrence
for lul_loop = 1 to lul_pCount
// process id zero is a system task
lul_ProcessId = this.of_GetPointer(lul_ppProcessInfo, 2, lul_loop, 4)
If lul_ProcessId > 0 Then
// get process name from array
lul_strptr = this.of_GetPointer(lul_ppProcessInfo, 3, lul_loop, 4)
ls_process = String(lul_strptr, "address")
// get user name from array
lul_pUserSid = this.of_GetPointer(lul_ppProcessInfo, 4, lul_loop, 4)
ls_acctname = this.of_LookupAccount(lul_pUserSid)
// check to see if it matches
If Lower(as_program) = Lower(ls_process) And &
Lower(ls_userid) = Lower(ls_acctname) Then
lb_found = True
Exit
End If
End If
next
// free memory allocated by function
WFFreeMemory(lul_ppProcessInfo)
// close handle to citrix server
this.of_WFCloseServer(lul_hServer)
Return lb_found
end function
public function unsignedlong of_wfenumerateprocesses (unsignedlong aul_hserver, ref unsignedlong aul_sessionid[], ref unsignedlong aul_processid[], ref string as_process[], ref string as_userid[]);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFEnumerateProcesses
//
// PURPOSE: Return a list of the active processes on a
// specified MetaFrame XP server.
//
// ARGUMENTS: aul_hServer - Handle to a MetaFrame XP server.
// aul_sessionid - By ref array returning session id.
// aul_processid - By ref array returning process id.
// as_process - By ref array returning process name.
// as_userid - By ref array returning user acct name.
//
// RETURN: The count of processes
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
ULong lul_ppProcessInfo, lul_pCount, lul_loop, lul_empty[]
ULong lul_strptr, lul_SessionId, lul_ProcessId, lul_pUserSid
String ls_process, ls_acctname, ls_empty[]
Boolean lb_rc
// initialize output arrays
aul_processid = lul_empty
as_process = ls_empty
as_userid = ls_empty
// gather array of processes for the server
lb_rc = WFEnumerateProcesses(aul_hServer, 0, 1, &
lul_ppProcessInfo, lul_pCount)
For lul_loop = 1 To lul_pCount
// process id zero is a system task
lul_SessionId = this.of_GetPointer(lul_ppProcessInfo, 1, lul_loop, 4)
lul_ProcessId = this.of_GetPointer(lul_ppProcessInfo, 2, lul_loop, 4)
// get process name from array
lul_strptr = this.of_GetPointer(lul_ppProcessInfo, 3, lul_loop, 4)
ls_process = String(lul_strptr, "address")
If ls_process = "" Then
ls_process = "Nameless Process"
End If
// get user name from array
lul_pUserSid = this.of_GetPointer(lul_ppProcessInfo, 4, lul_loop, 4)
ls_acctname = this.of_LookupAccount(lul_pUserSid)
// populate output argument arrays
aul_sessionid[lul_loop] = lul_SessionId
aul_processid[lul_loop] = lul_ProcessId
as_process[lul_loop] = ls_process
as_userid[lul_loop] = ls_acctname
Next
// free memory allocated by function
WFFreeMemory(lul_ppProcessInfo)
Return lul_pCount
end function
public function unsignedlong of_wfenumeratesessions (unsignedlong aul_hserver, ref unsignedlong aul_sessionid[], ref string as_stationname[]);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFEnumerateSessions
//
// PURPOSE: Return a list of sessions on a specified MetaFrame XP server.
//
// ARGUMENTS: aul_hServer - Handle to a MetaFrame XP server.
// aul_sessionid - By ref array returning session id.
// as_stationname - By ref array returning winstation name.
//
// RETURN: The count of processes
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
ULong lul_ppSessionInfo, lul_pCount, lul_loop
ULong lul_strptr, lul_SessionId, lul_empty[]
String ls_empty[], ls_station
Boolean lb_rc
// initialize output arrays
aul_sessionid = lul_empty
as_stationname = ls_empty
// gather array of processes for the server
lb_rc = WFEnumerateSessions(aul_hServer, 0, 1, &
lul_ppSessionInfo, lul_pCount)
For lul_loop = 1 To lul_pCount
// get session id from array
lul_SessionId = this.of_GetPointer(lul_ppSessionInfo, 1, lul_loop, 3)
// get process name from array
lul_strptr = this.of_GetPointer(lul_ppSessionInfo, 2, lul_loop, 3)
ls_station = String(lul_strptr, "address")
If ls_station = "" Then
ls_station = "Nameless Session"
End If
// populate output argument arrays
aul_sessionid[lul_loop] = lul_SessionId
as_stationname[lul_loop] = ls_station
Next
// free memory allocated by function
WFFreeMemory(lul_ppSessionInfo)
Return lul_pCount
end function
public function string of_formatmessage (unsignedlong aul_error);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_FormatMessage
//
// PURPOSE: This function returns the error message that goes
// with the error code from GetLastError.
//
// ARGUMENTS: aul_error - Error code from GetLastError
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial coding
// -----------------------------------------------------------------------------
Constant ULong FORMAT_MESSAGE_FROM_SYSTEM = 4096
Constant ULong LANG_NEUTRAL = 0
String ls_buffer
ULong lul_rtn
ls_buffer = Space(200)
lul_rtn = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, &
aul_error, LANG_NEUTRAL, ls_buffer, 200, 0)
Return ls_buffer
end function
public subroutine of_wfcloseserver (unsignedlong aul_hserver);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFCloseServer
//
// PURPOSE: Close an open MetaFrame XP server handle.
//
// ARGUMENTS: aul_hServer - Handle to a MetaFrame XP server.
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
// close handle to citrix server
WFCloseServer(aul_hServer)
end subroutine
public function unsignedlong of_wfenumerateservers (ref string as_servers[]);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFEnumerateServers
//
// PURPOSE: Return a list of MetaFrame XP servers.
//
// ARGUMENTS: as_servers - By ref array returning server names.
//
// RETURN: The count of servers
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
ULong lul_loop, lul_pCount
ULong lul_ppServerInfo, lul_strptr
String ls_null, ls_empty[], ls_server
Boolean lb_rc
// initialize output array
as_servers = ls_empty
// gather array of servers
SetNull(ls_null)
lb_rc = WFEnumerateServers(ls_null, 0, 1, &
lul_ppServerInfo, lul_pCount)
For lul_loop = 1 To lul_pCount
// get process name from array
lul_strptr = this.of_GetPointer(lul_ppServerInfo, 1, lul_loop, 1)
ls_server = String(lul_strptr, "address")
// populate output argument array
as_servers[lul_loop] = ls_server
Next
// free memory allocated by function
WFFreeMemory(lul_ppServerInfo)
Return lul_pCount
end function
public function string of_lookupaccount (unsignedlong aul_usersid);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_LookupAccount
//
// PURPOSE: This function determines user name from Account SID.
//
// ARGUMENTS: aul_usersid - SID of a user.
//
// RETURN: User account name (userid)
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
String ls_system, ls_domain, ls_name
ULong lul_cbName, lul_cbDomainName, lul_peUse
Boolean lb_rc
SetNull(ls_system)
lul_cbName = 256
ls_name = Space(lul_cbName)
lul_cbDomainName = 256
ls_domain = Space(lul_cbDomainName)
lb_rc = LookupAccountSid(ls_system, aul_usersid, &
ls_name, lul_cbName, ls_domain, lul_cbDomainName, lul_peUse)
Return ls_name
end function
public function unsignedlong of_wfopenserver (string as_server);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFOpenServer
//
// PURPOSE: Open a handle to a specified MetaFrame XP server.
//
// ARGUMENTS: as_server - Name of a MetaFrame XP server.
//
// RETURN: Handle value
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
// open handle to citrix server
Return WFOpenServer(as_server)
end function
public function string of_wfquerysessioninformation (unsignedlong aul_hserver, unsignedlong aul_sessionid, unsignedlong aul_infoclass);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFQuerySessionInformation
//
// PURPOSE: Return information about a specified session on a
// specified MetaFrame XP server.
//
// ARGUMENTS: aul_hServer - Handle to a MetaFrame XP server.
// aul_sessionid - MetaFrame XP server session ID.
// aul_infoclass - Type of information to retrieve
// from the specified session.
//
// RETURN: The requested information
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
ULong lul_ppBuffer, lul_pBytesReturned, lul_strptr
String ls_infovalue
Choose Case aul_infoclass
Case WFApplicationName, WFUserName, WFDomainName, &
WFInitialProgram, WFWorkingDirectory, WFOEMId, &
WFClientName, WFClientDirectory, WFWinstationName
// these information classes return a pointer to a string
If WFQuerySessionInformation(aul_hserver, aul_sessionid, &
aul_infoclass, lul_ppBuffer, lul_pBytesReturned) Then
If lul_pBytesReturned > 0 Then
ls_infovalue = String(lul_ppBuffer, "address")
End If
End If
Case WFConnectState
ls_infovalue = "not coded"
Case WFClientAddress
ls_infovalue = "not coded"
Case WFClientBuildNumber, WFClientProductID
ls_infovalue = "not coded"
Case WFICABufferLength, WFSessionId
ls_infovalue = "not coded"
Case WFClientDisplay
ls_infovalue = "not coded"
Case WFVersion
ls_infovalue = "not coded"
Case WFUserInfo
ls_infovalue = "not coded"
Case WFAppInfo
ls_infovalue = "not coded"
Case WFClientInfo
ls_infovalue = "not coded"
Case WFClientCache
ls_infovalue = "not coded"
Case WFClientLatency
ls_infovalue = "not coded"
Case WFClientDrives
ls_infovalue = "not coded"
Case Else
ls_infovalue = "Invalid InfoClass Parm!"
End Choose
// free memory allocated by function
WFFreeMemory(lul_ppBuffer)
Return ls_infovalue
end function
public function boolean of_wfterminateprocess (unsignedlong aul_hserver, unsignedlong aul_processid, unsignedlong aul_exitcode);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFTerminateProcess
//
// PURPOSE: Terminate a specified process on a specified MetaFrame XP server.
//
// ARGUMENTS: aul_hServer - Handle to a MetaFrame XP server.
// aul_processid - Process ID of the process to terminate.
// aul_exitcode - Termination status for the process.
//
// RETURN: True = Success, False = Failed
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
Boolean lb_rc
// gather array of processes for the server
lb_rc = WFTerminateProcess(aul_hServer, aul_processid, aul_exitcode)
Return lb_rc
end function
public function boolean of_wfsendmessage (unsignedlong aul_hserver, unsignedlong aul_sessionid, string as_title, string as_msg);// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_WFSendMessage
//
// PURPOSE: Send a message box to a specified session.
//
// ARGUMENTS: aul_hServer - Handle to a MetaFrame XP server.
// aul_sessionid - MetaFrame XP server session ID.
// as_title - Title for message box to display.
// as_msg - Message to be displayed.
//
// RETURN: True = Success, False = Failed
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
Boolean lb_rc
ULong lul_titlelen, lul_msglen, lul_style, lul_response
CONSTANT ulong MB_OK = 0
CONSTANT ulong MB_OKCANCEL = 1
CONSTANT ulong MB_ABORTRETRYIGNORE = 2
CONSTANT ulong MB_YESNOCANCEL = 3
CONSTANT ulong MB_YESNO = 4
CONSTANT ulong MB_RETRYCANCEL = 5
CONSTANT ulong MB_ICONHAND = 16
CONSTANT ulong MB_ICONQUESTION = 32
CONSTANT ulong MB_ICONEXCLAMATION = 48
CONSTANT ulong MB_ICONASTERISK = 64
lul_titlelen = Len(as_title)
lul_msglen = Len(as_msg)
// display MessageBox to specified session
lb_rc = WFSendMessage(aul_hServer, aul_sessionid, &
as_title, lul_titlelen, as_msg, lul_msglen, &
lul_style, 0, lul_response, False)
Return lb_rc
end function
public function boolean of_iscitrixsession ();// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_IsCitrixSession
//
// PURPOSE: This function determines if running on Citrix.
//
// RETURN: True = On Citrix, False = Not on Citrix
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial Creation
// -----------------------------------------------------------------------------
Boolean lb_Citrix
long ll_rtn
ll_rtn = GetSystemMetrics(SM_REMOTESESSION)
If ll_rtn = 0 Then
lb_Citrix = False
Else
lb_Citrix = True
End If
Return lb_Citrix
end function
public function unsignedlong of_getlasterror ();// -----------------------------------------------------------------------------
// SCRIPT: n_citrixapi.of_GetLastError
//
// PURPOSE: This function returns last error number.
//
// DATE PROG/ID DESCRIPTION OF CHANGE / REASON
// ---------- -------- -----------------------------------------------------
// 03/10/2008 RolandS Initial coding
// -----------------------------------------------------------------------------
SetPointer(HourGlass!)
Return GetLastError()
end function
on n_citrixapi.create
call super::create
TriggerEvent( this, "constructor" )
end on
on n_citrixapi.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on