0

I followed the steps at here to install a windows service.

1.Structure the Main() function of your service like this

static void Main(string[] args)
{
    if (args.Length == 0) {
       // Run your service normally.
       ServiceBase[] ServicesToRun = new ServiceBase[] {new YourService()};
       ServiceBase.Run(ServicesToRun);
     } else if (args.Length == 1) {
       switch (args[0]) {
           case "-install":
              InstallService();
              StartService();
              break;
           case "-uninstall":
              StopService();
              UninstallService();
              break;
           default:
              throw new NotImplementedException();
      }
   }
} 

2. The support code like the below

public static bool  InstallService(string svcPath, string svcName, string svcDispName)
    {
        #region Constants declaration.
        int SC_MANAGER_CREATE_SERVICE = 0x0002;
        int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
        //int SERVICE_DEMAND_START = 0x00000003;
        int SERVICE_ERROR_NORMAL = 0x00000001;
        int STANDARD_RIGHTS_REQUIRED = 0xF0000;
        int SERVICE_QUERY_CONFIG = 0x0001;
        int SERVICE_CHANGE_CONFIG = 0x0002;
        int SERVICE_QUERY_STATUS = 0x0004;
        int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
        int SERVICE_START = 0x0010;
        int SERVICE_STOP = 0x0020;
        int SERVICE_PAUSE_CONTINUE = 0x0040;
        int SERVICE_INTERROGATE = 0x0080;
        int SERVICE_USER_DEFINED_CONTROL = 0x0100;
        int SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
        SERVICE_QUERY_CONFIG |
        SERVICE_CHANGE_CONFIG |
        SERVICE_QUERY_STATUS |
        SERVICE_ENUMERATE_DEPENDENTS |
        SERVICE_START |
        SERVICE_STOP |
        SERVICE_PAUSE_CONTINUE |
        SERVICE_INTERROGATE |
        SERVICE_USER_DEFINED_CONTROL);
        int SERVICE_AUTO_START = 0x00000002;
        #endregion Constants declaration.
        try
        {
            IntPtr sc_handle = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
            if (sc_handle.ToInt32() != 0)
            {
                IntPtr sv_handle = CreateService(sc_handle, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, svcPath, null, 0, null, null, null);
                if (sv_handle.ToInt32() == 0)
                {
                    CloseServiceHandle(sc_handle);
                    return false;
                }
                else
                {
                    //now trying to start the service
                    int i = StartService(sv_handle, 0, null);
                    // If the value i is zero, then there was an error starting the service.
                    // note: error may arise if the service is already running or some other problem.
                    if (i == 0)
                    {
                        Console.WriteLine("Couldnt start service");
                        return false;
                    }
                    Console.WriteLine("Service started successfully");
                    CloseServiceHandle(sc_handle);
                    return true;
                }
            }
            else
            {
                Console.WriteLine("SCM not opened successfully");
                return false;
            }
        }
        catch (Exception e)
        {
            throw e;
        }
    }

Then I run the command in bin/debug folder xxx.exe -install

Everything is fine and the service was deployed successfully. But the thing is I have to run the command in the debug folder, I guess that because it contains a bunch of dlls. If I move the executable file only to a different place and to install it. An exception was thrown,

System.IO.FileNotFoundException: Could not load file or assembly  'VoiceElementsCommon, Version=8.3.12.111, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

I don't know why the install code was looking for the dll as I think the exe file contains it.

Is the problem when the code run at

IntPtr sv_handle = CreateService(sc_handle, svcName, svcDispName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, svcPath, null, 0, null, null, null);

It tried to find the assembly in the debug folder?

  • Yes, the install command `xxx.exe -install` actually runs your exe, so you need all the dependent DLLs to run the exe (the DLLs are referenced, but not included in the exe) -- another option would be to write another program that just creates and starts the service. – Edward Clements Nov 06 '13 at 16:44
  • The thing is that in my code there are using statement dlls(C#), which include all dependent DLLs already. Why I still need these when run my exe? –  Nov 06 '13 at 16:51
  • 1
    The DLLs are referenced in c#, but they are not included in the exe when it is built. – Edward Clements Nov 06 '13 at 16:56
  • Why? Can you provide me MSDN for building exe process? –  Nov 06 '13 at 16:57
  • Not very sure where they say that specifically, but [this Doc](http://msdn.microsoft.com/en-us/library/3707x96z(v=vs.110).aspx) says `An assembly, or a dynamic linking library (DLL), is linked to your program at run time`; [this Doc](http://msdn.microsoft.com/en-us/library/yabyz3h4(v=vs.110).aspx) also mentions that when you compile, it only import metadata from the DLLs (i.e., it does not package the DLLs into the exe) – Edward Clements Nov 06 '13 at 17:16
  • @Love: You have a fundamental misconception about .net here. The using statement just adds the namespaces to your source file, so that you can shorten the fully qualified class names. The referenced assemblies are not statically linked to your exe, they are loaded at run time. If you really want to create an exe that also contains referenced dlls, consider using ilmerge: http://www.microsoft.com/en-us/download/details.aspx?id=17630 – cdoubleplusgood Nov 06 '13 at 18:39
  • Great, please write it as the answer so I can mark it. –  Nov 06 '13 at 18:47
  • Please refer to the response already provided to the same question below: [Installing Windows Service programmatically](http://stackoverflow.com/questions/2072288/installing-windows-service-programmatically) – Daniel Ferreira Apr 08 '15 at 17:18

1 Answers1

-2

If you want to install programatically your services you can do something like this(for me is easy and work like a charm):

static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            if (args[0].Equals("/i", StringComparison.InvariantCultureIgnoreCase))
            {
                System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] {
                    System.Reflection.Assembly.GetExecutingAssembly().Location});
            }
            else if (args[0].Equals("/u", StringComparison.InvariantCultureIgnoreCase))
            {
                System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] {"/u",
                    System.Reflection.Assembly.GetExecutingAssembly().Location});
            }
        }
        else
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new MyService() 
            };
            ServiceBase.Run(ServicesToRun);
        }
    }
majimenezp
  • 302
  • 2
  • 3