Restrict multiple logins of the same account and choose forced kicking

Keywords: Delphi SQL

Software type: CS

Development tool: Delphi

Function: restrict multiple logins of the same account and choose to kick others forcibly.

1. Use the temporary table to determine whether the current account has been logged in. Here is a brief introduction to the temporary table method. When the software is successfully logged in for the first time, create a temporary table create table user ID (id int); where user ID is the table name and user ID is the unique ID of the current user. When the software is shut down, including abnormal shutdown, the temporary table will be released automatically. The task manager forcibly shut down the software. The test is normal. The power failure is abnormal. The shutdown is not tested.

2. Judge whether the temporary table has the status of reading whether the current user is logged in.

 

function TLoginFrm.UserLogined(AdoConn: TADOConnection; AUserID: string): Boolean;
var
  Qry: TADOQuery;
  strSQL: string;
begin
  try
    QryCreate(Qry,AdoConn);
    try
      strSQL := Format('SELECT OBJECT_ID(N''tempdb..##%s'', N''U'') AS TabID', [AUserID]);
      Qry.SQL.Text := strSQL;
      Qry.Open;
      result := not Qry.FieldByName('TabID').IsNull;
    finally
      Qry.Free;
    end;
  except
    Result := False;
    Exit;
  end;
end;

 

3. The default value of "online" added to the current login user table is 0. When the login is successful, create a temporary table and update the current user status to 1. Note: 0 offline, 1 online;

 

function TLoginFrm.RegUserLogined(AdoConn: TADOConnection; AUserID: string): Boolean;
var
  Qry, QryComm: TADOQuery;
  strSQL: string;
begin
  try
    QryCreate(Qry,AdoConn);
    QryCreate(QryComm, adocCommon);
    try
      strSQL := Format('CREATE TABLE ##%s(ID int); ', [AUserID]);
      Qry.SQL.Text := strSQL;
      Qry.ExecSQL;
      strSQL := Format('update Personnel_set set online=1 where Per_id=%S', [QuotedStr(AUserID)]);
      QryComm.SQL.Text := strSQL;
      QryComm.ExecSQL;
    finally
      Qry.Free;
      QryComm.Free;
    end;
  except
    Result := False;
    Exit;
  end;
  Result := True;
end;

 

4. Click OK to log in

 

//Judge whether the current login user has registered
  if not UserLogined(adocWMS, adoqPersonnal.FieldByName('EmployeeCode').AsString) then
  begin
    //Update personnel status to 0 in case of abnormal exit without updating personnel online status
    if GetUserOnline(adocCommon, adoqPersonnal.FieldByName('EmployeeCode').AsString) then
      UpdateOnline(adocCommon, adoqPersonnal.FieldByName('EmployeeCode').AsString);
    //Create a temporary table to record the login status of the current person
    RegUserLogined(adocWMS, adoqPersonnal.FieldByName('EmployeeCode').AsString)
  end else begin
    if MessageBox(Handle, 'The current user is already logged in, Force login?', 'Tips', MB_YESNO)=id_yes then
    begin
      //Update login status = 0
      UpdateOnline(adocCommon, adoqPersonnal.FieldByName('EmployeeCode').AsString);
      //Set up timer If the event monitor status is 0 and the temporary table exists, the system will directly kick off the line. Waiting for users to log off/
      while UserLogined(adocWMS, adoqPersonnal.FieldByName('EmployeeCode').AsString) do
      begin
        //
      end;
      //Re register the temporary table.
      RegUserLogined(adocWMS, adoqPersonnal.FieldByName('EmployeeCode').AsString);
    end else
      Exit;
  end;

 

5. Monitor the login status of the personnel. If the personnel status is 0 and the temporary table exists, directly kick off the line. This involves a non blocking pop-up prompt box.

  

function WTSSendMessage(Server: HWND; SessionId: DWORD; Title: PChar;
  TitleLength: DWORD; AMessage: PChar; MessageLength: DWORD; Style: DWORD;
  Timeout: DWORD; var Response: DWORD; Wait: Boolean): Boolean; stdcall;
  external 'wtsapi32.dll' name 'WTSSendMessageA';

function WTSGetActiveConsoleSessionId: DWORD; stdcall;
  external kernel32 name 'WTSGetActiveConsoleSessionId';  


procedure TLoginFrm.Timer1Timer(Sender: TObject);
const
  WTS_CURRENT_SERVER_HANDLE = 0;
var
  nTitle, nMessage: string;
  nResponse: DWORD;
begin
  if UserLogined(adocCommon, Parameter[4]) and not GetUserOnline(adocCommon, Parameter[4]) then
  begin
    Timer1.Enabled := False;
    nTitle := 'Tips';
    nMessage := 'The current user is logged in elsewhere, You have been kicked off the line!';
    WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTSGetActiveConsoleSessionId,
        PChar(nTitle), Length(nTitle), PChar(nMessage), Length(nMessage),
        MB_OK, 0, nResponse, False);
    TerminateProcess(GetCurrentProcess, 0);
  end;
end;

 

6. Get and update the personnel status function.

 

function TLoginFrm.GetUserOnline(AdoConn: TADOConnection; AUserID: string): Boolean;
var
  QryComm: TADOQuery;
begin
  Result := False;
  QryCreate(QryComm, AdoConn);
  try
    QryComm.SQL.Text := Format('select online from Personnel_set where per_id=%S', [QuotedStr(AUserID)]);
    QryComm.Open;
    if QryComm.FieldByName('online').AsInteger = 1 then
      Result := True;
  finally
    QryComm.Free;
  end;
end;

function TLoginFrm.UpdateOnline(AdoConn: TADOConnection; AUserID: string; online: Integer): Boolean;
var
  T: TADOQuery;
begin
  QryCreate(T, AdoConn);
  try
    T.SQL.Text := Format('update Personnel_set set online=%D where Per_id=%S', [online, QuotedStr(AUserID)]);
    T.ExecSQL;
  finally
    T.Free;
  end;
end;

 

Effect

 

 

Posted by phlow on Fri, 15 Nov 2019 11:43:50 -0800