Click here to Skip to main content
15,885,278 members
Articles / Desktop Programming / Windows Forms

Visual Application Launcher

Rate me:
Please Sign up or sign in to vote.
4.91/5 (37 votes)
23 Jan 2012CPOL23 min read 107K   3.7K   116  
A WinForms UI using WCF services, Entity Framework, repository data access, repository caching, Unit of Work, Dependency Injection, and every other buzz work you can think of!
namespace VAL
{
    using System;
    using System.Configuration;
    using System.IO;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using VAL.Common;
    using VAL.Common.Properties;

	/// <summary>
	/// WorkgroupHelper helps when new users are being created by cloning user
	/// permissions in the main network workgroup used to secure MS Access
	/// database
	/// </summary>
	public class WorkgroupHelper : IDisposable
	{
        private const int adStateOpen = 1;

        /// <summary>
        /// Access to the log4Net logging object
        /// </summary>
        protected static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        private Type connectionType;
        private Type catalogueType;

        private object connection;
        private object catalogue;

        private bool disposed;

        /// <summary>
        /// Default ctor
        /// </summary>
		public WorkgroupHelper()
		{
            connectionType = Type.GetTypeFromProgID("ADODB.Connection");
            connection = Activator.CreateInstance(connectionType);

            catalogueType = Type.GetTypeFromProgID("ADOX.Catalog");
            catalogue = Activator.CreateInstance(catalogueType);

            Connect();
		}

        /// <summary>
        /// Creates a new user in the workgroup and clones all the permissions for 
        /// the user from a source user
        /// </summary>
        /// <param name="sourceUser">The user to base the new user on. Clones permissions</param>
        /// <param name="user">The user to create</param>
        public void CloneUser(string sourceUser, string user)
        {
            try
            {
                InvokeMethod(connectionType, connection, "BeginTrans");
                CreateUser(user);

                List<string> groups = GetUsersGroups(sourceUser);
                foreach (var group in groups)
                {
                    AddUserToGroup(user, group);
                }

                InvokeMethod(connectionType, connection, "CommitTrans");
            }
            catch (Exception ex)
            {
                InvokeMethod(connectionType, connection, "RollbackTrans");
                log.Error(ex.Message, ex);
                throw;
            }
        }

        private void InvokeMethod(Type targetType, object target, string methodName)
        {
            targetType.InvokeMember(methodName,
                System.Reflection.BindingFlags.InvokeMethod,
                null,
                target,
                null);
        }

        /// <summary>
        /// Connects to the database via the enterprise workgroup
        /// </summary>
        private void Connect()
        {
            string workgroup = Session.Configuration.EnterpriseWorkgroupDirectory + Session.Configuration.EnterpriseWorkgroupName;
			
            if (string.IsNullOrEmpty(workgroup))
                throw new ConfigurationErrorsException(Resources.EnterpriseWorkgroupException);

            if (!File.Exists(workgroup))
                throw new FileNotFoundException("The enterprise workgroup definied in the application configuration file could not be found");


            if (!File.Exists(Session.Configuration.AccessDatabaseLocation))
                throw new FileNotFoundException("The access database defined in the application configuration file could not be found");


            string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=";
            connectionString += Session.Configuration.AccessDatabaseLocation;
            connectionString += ";Jet OLEDB:System Database=" + workgroup;

            string decryptedAdminPassword = EncryptionHelper.Decrypt(Session.Configuration.EnterpriseAdminPassword, 
                Session.Configuration.EnterpriseAdminUserName);

            connectionType.InvokeMember("Open",
                BindingFlags.InvokeMethod,
                null,
                connection,
                new object[] { connectionString, 
                    Session.Configuration.EnterpriseAdminUserName, 
                    decryptedAdminPassword, 
                    0 
                });

            catalogueType.InvokeMember("ActiveConnection",
                BindingFlags.SetProperty,
                null,
                catalogue,
                new object[] {connection});
        }

        /// <summary>
        /// Creates a user in the workgroup
        /// </summary>
        /// <param name="userName"></param>
        private void CreateUser(string userName)
        {
            object users = catalogueType.InvokeMember("Users",
                BindingFlags.GetProperty,
                null,
                catalogue,
                null);

            object user = GetUser(userName);
            if (user != null)
                catalogueType.InvokeMember("Delete",
                    BindingFlags.InvokeMethod,
                    null,
                    users,
                    new object[] { userName });

            catalogueType.InvokeMember("Append",
                BindingFlags.InvokeMethod,
                null,
                users,
                new object[] { userName, string.Empty });

            if (user != null)
            {
                Marshal.ReleaseComObject(user);
            }
        }

        /// <summary>
        /// Adds the specified user to a group
        /// </summary>
        /// <param name="userName">the user to add to the group</param>
        /// <param name="groupName">the name of the group to add them to</param>
        private void AddUserToGroup(string userName, string groupName)
        {
            try
            {
                object user = GetUser(userName);

                object groups = catalogueType.InvokeMember("Groups",
                                BindingFlags.GetProperty,
                                null,
                                user,
                                null);

                catalogueType.InvokeMember("Append",
                                BindingFlags.InvokeMethod,
                                null,
                                groups,
                                new object[] {groupName});                
            }
            catch
            {
                // will throw exception if user already belongs to group, ignore
            }
        }

        private object GetUser(string userName)
        {
            object user = null;

            try
            {
                user = catalogueType.InvokeMember("Users",
                    BindingFlags.GetProperty,
                    null,
                    catalogue,
                    new object[] { userName });
            }
            catch (Exception ex)
            {
                log.Error(string.Format("Could not get user object for {0}", userName), ex);
            }

            return user;
        }

        /// <summary>
        /// Gets the groups a user is a member of
        /// </summary>
        /// <param name="userName">the username to get the groups from</param>
        /// <returns>ArrayList of groups</returns>
        private List<string> GetUsersGroups(string userName)
        {
            List<string> usersGroups = new List<string>();   
            object user = GetUser(userName);                    

            if (user != null)
            {
                object groups = catalogueType.InvokeMember("Groups",
                    BindingFlags.GetProperty,
                    null,
                    user,
                    null);

                int length = (int)catalogueType.InvokeMember("Count",
                    BindingFlags.GetProperty,
                    null,
                    groups,
                    null);


                for (int i = 0; i < length; ++i)
                {
                    object group = catalogueType.InvokeMember("Item",
                        BindingFlags.GetProperty,
                        null,
                        groups,
                        new object[] {i});

                    string groupName = catalogueType.InvokeMember("Name",
                        BindingFlags.GetProperty,
                        null,
                        group,
                        null).ToString();

                    usersGroups.Add(groupName);
                }
                Marshal.ReleaseComObject(user);
            }
            return usersGroups;
        }

        #region Implementation of IDisposable

        /// <summary>
        /// Protected overide of the Dispose pattern
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // Clean up our COM objects

                    if (connection != null)
                    {
                        int connectionState = (int)connectionType.InvokeMember("State",
                            BindingFlags.GetProperty,
                            null,
                            connection,
                            null);

                        // Close the connection if it's open
                        if (connectionState == adStateOpen)
                        {
                            InvokeMethod(connectionType, connection, "Close");
                        }

                        Marshal.ReleaseComObject (connection);
                        Marshal.ReleaseComObject (catalogue);
                    }

                }
                disposed = true;
            }
        }

        /// <summary>
        /// Dispose of the object
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
        }

        #endregion

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions