Sunday, September 20, 2009

Cross-thread operation not valid.

In window application , when you need to use Threading and access control inside that thread, then you get this error “Cross-thread operation not valid.” The reason behind this control is working under main thread and you create another thread in which you are trying to access control.

There are two ways to solve this error.

1. Set property in Form constructor.
You need to set static property CheckForIllegalCrossThreadCalls  of control class to false value. This will disable cross thread checking.
       
       public Form1()
       {
         InitializeComponent();
           Control.CheckForIllegalCrossThreadCalls = false;
       }

Sample Code (C#):

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Test));
            th.Start(1000);           
        }

        public void Test(object o)
        {
            for (int i = 0; i < 10; i++)
            {
                label1.Text = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + " --- " + i.ToString();
                System.Threading.Thread.Sleep(int.Parse(o.ToString()));
            }
        }
    }



2. Use delegate and event.

Sample Code (C#) :

public partial class Form1 : Form
    {
        delegate void SetLabelText(string str);
        SetLabelText setLabel1Text = null;
        public Form1()
        {
            InitializeComponent();
            setLabel1Text = new SetLabelText(Label1Text);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread th = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Test));
            th.Start(1000);           
        }

        public void Test(object o)
        {
            for (int i = 0; i < 10; i++)
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(setLabel1Text, System.Threading.Thread.CurrentThread.ManagedThreadId.ToString() + " --- " + i.ToString());
                }
                System.Threading.Thread.Sleep(int.Parse(o.ToString()));
            }
        }

        public void Label1Text(string str)
        {
            label1.Text = str;
        }
    }

Please give your comment on this.

Sunday, June 14, 2009

Remove Focus Rectangle From Button

Article is about to remove focus rectangle or say cues from Button in window form application.

First let discuss what default focus rectangle. Please look at following image , in that image OK button has default focus so it display cues rectangle.

image 
(FlatStyle == System)

When we want to set background image of button to make button attractive in that case this default rectangle create problem with look and feel.

image
(FlatStyle = Standard)
 
 image
(FlatStyle = Flat)

In above two image need to set FlatApperance.BorderStyle =0. You can visualize that in all above case default focus rectangle make button look ugly with background image.

To remove this cues ( Default focus rectangle ) you need to set ShowFocusCues property of Button to false but this property does not directly available to Button. This property available in ButtonBase class with protected access specifier. In order to set this property to false we need to create class that inherits from Button or ButtonBase and set this property explicitly false.

class CustomButton : System.Windows.Forms.Button
    {
        protected override bool ShowFocusCues
        {
            get
            {
                return false;
            }
        }
}

image
Now see that default focus rectangle is removed.

More generic class for Button.

class CustomButton : System.Windows.Forms.Button
   {
       private bool _DisplayFocusCues = true;
       protected override bool ShowFocusCues
       {
           get
           {
               return _DisplayFocusCues;
           }
       }

       public bool DisplayFocusCues
       {
           get
           {
               return _DisplayFocusCues;
           }
           set
           {
               _DisplayFocusCues = value;
           }
       }
   }

Using this class you can set DisplayFocusCues at design time so CustomButton work with any case. ( Want to display focus rectangle or not).

image 

Hope this solution is help you to create button without cues.

Your suggestion is always invited.

Programmatically Install Window Service

This article is about to install / uninstall window service programmatically from C#. This is useful when you need to install / uninstall window service from some other application.

For this purpose you need to use ServiceProcessInstaller and ServiceInstaller class from another application. These two installer classes are responsible for Installation of service.

C# Example for Programmatically Install Window Service.

ServiceProcessInstaller ProcesServiceInstaller = new ServiceProcessInstaller();
ProcesServiceInstaller.Account =  ServiceAccount.User;
ProcesServiceInstaller.Username = "<<username>>";
ProcesServiceInstaller.Password = "<<password>>";

ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
InstallContext Context = new System.Configuration.Install.InstallContext();
String path = String.Format("/assemblypath={0}", @"<<path of executable of window service>>");
String[] cmdline = { path };

Context = new System.Configuration.Install.InstallContext("", cmdline);              
ServiceInstallerObj.Context = Context;
ServiceInstallerObj.DisplayName = "MyService";
ServiceInstallerObj.Description = "MyService installer test";
ServiceInstallerObj.ServiceName = "MyService";
ServiceInstallerObj.StartType =  ServiceStartMode.Automatic;
ServiceInstallerObj.Parent = ProcesServiceInstaller;          

System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
ServiceInstallerObj.Install(state);

C# Example to Programmatically Uninstall Window Service.

ServiceInstaller ServiceInstallerObj = new ServiceInstaller();
InstallContext Context = new InstallContext("<<log file path>>", null);
ServiceInstallerObj.Context = Context;
ServiceInstallerObj.ServiceName = "MyService";
ServiceInstallerObj.Uninstall(null);

other article related to window service.

http://dotnetstep.blogspot.com/2009/06/passing-parameter-to-installutil.html

http://dotnetstep.blogspot.com/2009/06/install-window-service-without-using.html

http://dotnetstep.blogspot.com/2009/06/install-windowservice-using-installutil.html

http://dotnetstep.blogspot.com/2009/06/get-windowservice-executable-path-in.html

Please give your idea about this article.

Saturday, June 13, 2009

Passing Parameter to InstallUtil

When installing window service or any installer ( class inherits from install class) required custom parameter at run time , Need to pass as parameter of installutil.

Crating window service using article (http://dotnetstep.blogspot.com/2009/06/install-windowservice-using-installutil.html).  This article suggest you add installer ( ProjectInstaller). Now we use installer class events to configure ServiceProcessInstaller and ServiceInstaller as per parameter pass to installutil.

[RunInstaller(true)]
public partial class ProjectInstaller : Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
           this.BeforeInstall += new InstallEventHandler(ProjectInstaller_BeforeInstall);
            this.BeforeUninstall += new InstallEventHandler(ProjectInstaller_BeforeUninstall);
        }       

        void ProjectInstaller_BeforeInstall(object sender, InstallEventArgs e)
        {
            // Configure Account for Service Process.
            switch(this.Context.Parameters["Account"])
            {
                case "LocalService":
                    this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;
                    break;
                case "LocalSystem":
                    this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
                    break;
                case "NetworkService":
                    this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.NetworkService;
                    break;
                case "User":
                    this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
                    this.serviceProcessInstaller1.Username = this.Context.Parameters["UserName"];
                    this.serviceProcessInstaller1.Password = this.Context.Parameters["Password"];
                    break;
            }      
            // Configure ServiceName
            if(!String.IsNullOrEmpty(this.Context.Parameters["ServiceName"]))
            {               
                this.serviceInstaller1.ServiceName = this.Context.Parameters["ServiceName"];
            }
        }

        void ProjectInstaller_BeforeUninstall(object sender, InstallEventArgs e)
        {
            if (!String.IsNullOrEmpty(this.Context.Parameters["ServiceName"]))
            {
                this.serviceInstaller1.ServiceName = this.Context.Parameters["ServiceName"];
            }
        }
    }

Above ProjectInstaller class handle two events : BeforeInstall and BeforeUninstall. BeforeInstall is called just before install method of installer (ProjectInstaller) called via InstallUtil and same way BeforeUninstall called just before Uninstall method of projectinstaller class. After adding that two event handler use following to configure service using installutil.

1. Install
installutil /Account=User /UserName=admin /Password=admin /ServiceName=WinService1 /i WindowService1.exe

2. Uninstall
installutil /ServiceName=WinService1 /u WindowService1.exe

This will also help you configure WindowService1.exe with two different name and different account.
installutil /Account=User /UserName=admin /Password=admin        /ServiceName=WinService1 /i WindowService1.exe

installutil /Account=LocalSystem /ServiceName=WinService2 /i WindowService1.exe

Install window service without using installutil

Article is about to install window service without using InstallUtil utility.
Windows XP or Later has command line utility called sc . (This utility talks with service controller and with services from command line).
SC is a window base utility. AS explain in article http://dotnetstep.blogspot.com/2009/06/install-windowservice-using-installutil.html sc does not required ProjectInstaller.

1. Start service using sc
          sc start ServiceName

2. Stop serivce
         sc stop ServiceName

3. Delete window service
        sc delete servicename
        Note : During delete call if service is in running state then service is delete when nexttime service is stop or PC restart.

4. Create window service
       sc create ServiceName binpath= “c:\windowservice1\windowservice1.exe”

       Apart from above many option available . For that just go to command prompt and type sc create /?

  For example configure service running account.

sc create servicename binpath= “c:\windowservice1\windowservice1.exe” obj= administrator password= pass

Hope this article will help you .

Please give your comment or idea about this.

In above all case Service ServiceName ( Mark as blue) , don’t use display name.

 image

Install WindowService using installutil.

This article is about to install to window service using installutil.exe. InstallUtil.exe or simply say installutil utility comes up with .NET Framework 2.0.

Steps.
1. Create new Window Service Project.
image 
2. After that open services1.cs in design mode . It looks like this.
image 
3. Now right click on design window. It open popup menu with installer option.
image
4. When you click on Add Installer. It will will add new class called projectinstaller.cs. It contain serviceprocessinstaller1 and serviceinstaller component. ServiceProcess installer is used to configure service account and serviceinstaller contain information about service.
image
5. Apart from above ProjectInstaller.cs contain following code which is used to call from installutil.
image
In above code RunInstaller attribute marked as true. So InstallUtil take this thing into consideration and use this information to call installer.

To install using installutil open VS 2005/VS 2008 command prompt or go to  %windir%\Microsoft.NET\Framework\v2.0.50727.

installutil.exe /i  WindowService1.exe ( To Install ).

installutil.exe /u WindowSerivce1.exe ( To uninstall).

Installutil use Installer class (Projectinstaller) to install service.

If you mark RunInstlaller as false then this installutil not work.

If you don’t want to use installutil to install wndow service then go to http://dotnetstep.blogspot.com/2009/06/install-window-service-without-using.html.

Tuesday, June 9, 2009

Get WindowService Executable Path In .NET

WindowService has a property called “Path to Executable” . This property contains path of window service that is going to execute. When you need this path in .NET Application there is no direct way to do it . You can not get it either via ServiceControler or any other way.

image 
To get that you need to read Registry. All information about all window service installed on machine storead at following location.
HKLM\SYSTEM\CurrentControlSet\Services.

C# Code to read Service Registry.

RegistryKey services = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services");
if (services != null)
{
object pathtoexecutable = services.OpenSubKey(<<ServiceName>>).GetValue("ImagePath");
}

In Above code replace <<ServiceName>> with your service name.

Also this is a registry operation so you need proper permission to read registry and apply any other registry operation at your own risk.

Give your comment or any new idea about this task.