tags:

views:

40

answers:

3

I have a winforms application that includes an Administration form (call it 'adminForm') and another form (call it 'userForm') that is on a timer that opens and runs it on a set time interval.

How do I prevent the userForm from opening when the adminForm is open?

Until recently the userFrom was prevented from opening by using the 'MainWindowTitle' value in code like this:

           // Retrieving all running processes for checking admin interface running or not
            Process[] objArrPrs = Process.GetProcesses();

            foreach (Process objProces in objArrPrs)
            {
                string strMainWindowTitle = string.Empty;
                strMainWindowTitle = objProces.MainWindowTitle.ToString();

                if (strMainWindowTitle != string.Empty || strMainWindowTitle != "") 
                {
                    // Retrievig process name
                    string strProcess = objProces.ProcessName;
                    if ((strMainWindowTitle == "XXXXX" && strProcess == "XXXXX")
                        || ((strMainWindowTitle == "XXXXX" && strProcess == "XXXXX.vshost")))
                    {
                        blnAdminScrOpen = true;
                        break;
                    }
                }
            }

Where "XXXXX" is the adminForm.Text value (e.g., 'this.Text="XXXXX"). This method was working fine.

However, both forms have now been redesigned and there are no form title bars so now the forms' Text values are null and the code shown above no longer works.

Does anyone have a suggestion on a new c# strategy I can use to prevent the userFrom from opening when the adminForm is open? It's appreciated if you can point me in the direction of some sample code.

Cheers, Frederickenter code here

A: 

You can implement the Singleton pattern on your forms, then get the member variable for the adminForm and check its Visible property. I can provide code if you're not familiar with the Singleton pattern. It basically changes your class so there can only be a single instance. It requires some modification of existing code, but would ultimately be a cleaner solution.

The gist of the singleton pattern is as follows:

public class MyForm : Form
{
    //this is used to keep a reference of the single
    //instance of this class
    private static MyForm _instance; 

    //your constructor is private, this is important.
    //the only thing that can access the constructor is 
    //the class itself.
    private MyForm()
    {
        //do stuff
    }

    public static MyForm GetInstance()
    {
        //the check to IsDisposed is important
        //if the form is closed, the _instance variable
        //won't be null, but if you return the closed 
        //form (ie, disposed form) any calls to the form
        //class (ie, Show()) will throw in exception.
        if (_instance == null || _instance.IsDisposed)
        {
            _instance = new MyForm();
        }
        return _instance;
    }

    //other code
}

Where you used to do this:

MyForm f = new MyForm();

You would now do this:

MyForm f = new MyForm.GetInstance();
Tim Coker
Hello Tim, thank you for responding. I am not familiar with the Singleton pattern. I just read the Wikipedia entry for it and another Stackoverflow entry about it, but that didn't clarify it for me.Before asking you to provide code samples on it, let me ask what ramifications occur from when you say the Singleton pattern changes my class to allow only a single instance. I ask this because the userForm can also be opened from a link on the adminForm, so, when this happens, both the adminForm and the userForm need to be opened at the same time. Does that violate the single instance condition?
Frederick
No, that doesn't violate the single instance condition. The implication is that there can only be one of each form implementing the pattern. If you have 15 different forms that implement the pattern, you can have 15 forms open in the application.
Tim Coker
+1  A: 

If the forms are both from the same application, loop through all open forms instead OpenForms and check their to see if it is open.

Checking all the processes is not a very nice way of checking and could easily break if the process name changes, for example

w69rdy
Thank you for your response. I used OpenForms in code like this: FormCollection fc = Application.OpenForms; for (int i = 0; i < fc.Count; i++) { if (fc[i].Name == "formAdmin") { blnAdminScrOpen = true; break; } }and was able to identify if the adminForm was open. I also could do this using fc[i].Tag after giving the adminForm a Tag value.
Frederick
Glad I could help, to return the favour could you mark it as the answer or up vote it pls. Thanks
w69rdy
My question is, if a cleaver user wanted to fool my application into thinking the adminForm was open when it is not could they create their own application with a form that has the same name (or Tag value) as my adminForm and then install and open that form on their computer? That is, would doing this cause the OpenForms code in my application to prevent the userForm from opening?
Frederick
@Fred: your original code was just completely unnecessary, the form isn't opened in another process. By using OpenForms, you no longer are subject to DOS attacks.
Hans Passant
A: 

As an alternative to what Tim said, you can also implement a static class with a reference to primary instance of your AdminForm. For example:

public static class Global {
    public static AdminForm AdminFormInstance { get; set; }
}

In the constructor for your AdminForm, you can add this line:

public AdminForm() {
    // -snip-
    Global.AdminFormInstance = this;
}

And then if you need to check if it's visible, just check the Visible property:

if (Global.AdminFormInstance.Visible == false)
    DoSomethingWhenItsNotVisible();

Keep in mind that your static member is not thread safe, though it doesn't appear that you are doing any multithreading.

rakuo15