Here is a screenshot from a window where I'm using sp_mgGetConnectedUsers() to show the system administrator what users are connected and the open tables they each have. It also allows the administrator to disconnect a user and to stop new connections from happening. Useful when you wish to install an update or update the data dictionary:
*------------------------------------------------------------------------------------------------------
METHOD ShowConnectedUsers() CLASS MpAdmin
LOCAL cSql := "EXECUTE PROCEDURE sp_mgGetConnectedUsers()"
LOCAL cSeek , cUser, cTable
LOCAL aData := {}
LOCAL aCursor, bChange, bGetConnUsers
LOCAL aChildData := {}
LOCAL bDelete
LOCAL oSelf := Self
LOCAL oDlg, oGet1, oBrw, oChildBrw, oSay, oChkBx
LOCAL isLoginsEnabled := !ADSDDGetDatabaseProperty( ADS_DD_LOGINS_DISABLED )
IF ifOpenOption( 'CONNECTEDUSERS' )
RETURN NIL
ENDIF
aCursor := ExecuteSqlScript( cSql, .f. )
aEval( aCursor, { |e,n| aadd( aData, { e[ 3 ], e[ 4 ], e[ 1 ] } ) } )
bGetConnUsers := { || aCursor := ExecuteSqlScript( cSql, .f. ), ;
aData := {}, ;
aEval( aCursor, { |e,n| aadd( aData, { e[ 3 ], e[ 4 ], e[ 1 ] } ) } ),;
oBrw:aArrayData := aData,;
oBrw:Refresh() ,; //needed here in case nArrayAt was past eof. to avoid run time error
Eval( bChange ),;
oDlg:Update(),;
oBrw:Refresh() }
bChange := { || oChildBrw:aArrayData := ;
IF( Len( oBrw:aArrayData ) > 0 .and. Len( oBrw:aArrayData[ oBrw:nArrayAt ] ) > 2, ;
ExecuteSqlScript( "EXECUTE PROCEDURE SP_mgGetUserTables('" + ;
alltrim( oBrw:Computer:Value() ) + "' );", .f. ),;
{} ),;
aEval( oChildBrw:aArrayData, { |e,n| hb_FNameSplit( e[ 1 ],,@cTable ),;
oChildBrw:aArrayData[ n,1 ] := Lower( cTable ) } ),;
oChildBrw:Refresh() }
bDelete := { || IF( len( oBrw:aArrayData ) > 0 .and. ;
( cUser := alltrim( oBrw:aArrayData[ oBrw:nArrayAt, 3 ] ),;
MsgYesNo( "Disconnect User " + cUser ) ), ;
( ExecuteSqlScript( "EXECUTE PROCEDURE sp_mgKillUser( '"+cUser+"' );", .f. ),;
Eval( bGetConnUsers ) ), NIL ) }
DEFINE DIALOG oDlg RESOURCE "CONNECTED_USERS" OF ::oPanelBrowse ;
TRANSPARENT COLOR CLR_BLACK, RGB(240,240,240)
REDEFINE XBROWSE oBrw ID 1 OF oDlg ;
ARRAY aData AUTOCOLS AUTOSORT;
HEADER "User", "ip", "Computer" ;
SIZES 120,100, 100 ;
ON CHANGE Eval( bChange )
oBrw:nMarqueeStyle := MARQSTYLE_HIGHLWIN7
oBrw:bClrStd := { || If( oBrw:KeyNo % 2 == 1, { CLR_BLUE, CLR_WHITE }, { CLR_BLUE, RGB(242,242,255)} ) }
oBrw:bKeyDown := {|nkey| IF( nkey = K_DEL, ( Eval( bDelete ), ;
Eval( bGetConnUsers ) ), NIL ) }
REDEFINE GET oGet1 Var cSeek ID 101 OF oDlg WHEN .f.
oBrw:oSeek := oGet1
REDEFINE SAY oSay PROMPT "Total Connections: " + cValToChar( Len( aData ) ) ;
ID 102 OF oDlg COLOR CLR_BLACK UPDATE
REDEFINE CHECKBOX oChkBx VAR isLoginsEnabled ID 4 OF oDlg
oChkBx:bChange := { || AdsDDSetDatabaseProperty( ADS_DD_LOGINS_DISABLED, !isLoginsEnabled ) }
setGridProperties( oBrw, .f. )
REDEFINE XBROWSE oChildBrw ID 2 OF oDlg ;
ARRAY aChildData AUTOCOLS AUTOSORT;
HEADER "Table Alias" ;
SIZES 150
setGridProperties( oChildBrw, .f. )
oChildBrw:bClrStd := { || If( oChildBrw:KeyNo % 2 == 1, { CLR_BLUE, CLR_WHITE }, { CLR_BLUE, RGB(242,242,255)} ) }
REDEFINE BUTTONBMP ID 201 OF oDlg BITMAP "Cancel16" TEXTRIGHT ACTION Eval( bDelete )
REDEFINE BUTTONBMP ID 202 OF oDlg BITMAP "run16" TEXTRIGHT ;
ACTION Eval( bGetConnUsers )
REDEFINE BUTTONBMP ID 203 OF oDlg BITMAP "exit16" TEXTRIGHT ACTION oDlg:END()
oDlg:lHelpIcon := .F.
FONDOBOTONES 1003, oDlg
ACTIVATE DIALOG oDlg NOWAIT ;
ON INIT ( oDlg:Center( oSelf:oPanelBrowse ), Eval( bChange ), oBrw:setFocus() ) ;
VALID closeOption( 'CONNECTEDUSERS' )
AADD( aOpenOptions, { 'CONNECTEDUSERS', oDlg } )
RETURN NIL
Reinaldo.