Skip to content
MutonUfoAI edited this page Feb 14, 2013 · 9 revisions

Welcome to the pgina wiki!

This repo differs only marginal from the original pGina 3.1.6.0

it splits apart after Nov 02, 2012

I hope to see some changes to be merged ...

An installer to play arround with it is available here and here the newer one


To wiew the differences take a look into the changelog

This repo

pGina repo

or the commits

This repo

pGina repo


If you create your own plugin there is only one minor change.

There is a new interface called IPluginLogoffRequestAddTime.

The purpose of this interface is, to let the plugin know if the system is trying to shut down.

An example

    //a directory containing all useres with active running tasks
    private Dictionary<string, Boolean> RunningTasks = new Dictionary<string, Boolean>();
    //a locker for the directory
    private ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
    //a bool to be set from the pgina service. True means the system is shutting down
    public static Boolean IsShuttingDown = false;
    
    // is called in a loop from the pgina service while the system is shutting down
    // be sure to clean the Dictionary from any logged of user
    public Boolean LogoffRequestAddTime()
    {
        IsShuttingDown = true;
        try
        {
            Locker.TryEnterReadLock(-1);
            if (RunningTasks.Values.Contains(true))
                return true;
        }
        catch (Exception ex)
        {
            m_logger.InfoFormat("LogoffRequestAddTime() error {0}", ex.Message);
        }
        finally
        {
            Locker.ExitReadLock();
        }

        return false;
    }

    // is called from the pgina service during a login attempt
    // its possible that a user that has logged of retries to relogin while a cleanup task is running
    // (yes the logoff can and should be non blocking)
    // To prevent a messed up profile we check the Dictionary
    public Boolean LoginUserRequest(string username)
    {
        try
        {
            Locker.TryEnterReadLock(-1);
            if (RunningTasks.Keys.Contains(username))
            {
                m_logger.InfoFormat("LoginUserRequest() logoff in process for {0}", username);
                return true;
            }
            else
            {
                m_logger.InfoFormat("LoginUserRequest() {0} free to login", username);
                return false;
            }
        }
        catch (Exception ex)
        {
            m_logger.InfoFormat("LoginUserRequest() {0} error {1}", username, ex.Message);
        }
        finally
        {
            Locker.ExitReadLock();
        }

        return false;
    }

    // this requires IPluginEventNotifications interface to work
    public void SessionChange(System.ServiceProcess.SessionChangeDescription changeDescription, SessionProperties properties)
    {
        UserInformation userInfo = properties.GetTrackedSingle<UserInformation>();

        if (changeDescription.Reason == System.ServiceProcess.SessionChangeReason.SessionLogoff)
        {
            try
            {
                Locker.TryEnterWriteLock(-1);
                RunningTasks.Add(userInfo.Username, true);
            }
            finally
            {
                Locker.ExitWriteLock();
            }

            // dont block others, run your stuff in its own thread
            Thread rem_smb = new Thread(() => cleanup(userInfo, changeDescription.SessionId));
            rem_smb.Start();
        }
    }

    private void cleanup(UserInformation userInfo, int sessionID)
    {
        // do your stuff
        try
        {
            Locker.TryEnterWriteLock(-1);
            RunningTasks.Remove(userInfo.Username);
        }
        finally
        {
            Locker.ExitWriteLock();
        }
    }

Developer Notes

Clone this wiki locally