question

DerekStevens-3578 avatar image
0 Votes"
DerekStevens-3578 asked BonnieDeWitt-QnA commented

ServiceInstaller.Install() throws a NullReferenceException. Any ideas?

Hello,

I am making a simple WPF graphical installer for a Windows Service, and need to call Installer.Install() directly from the InstallerGUI.

Here is the rather trivial definition of the derived Installer:

public class ProjectInstaller : System.Configuration.Install.Installer
    {
        private ServiceInstaller serviceInstaller1;
        private ServiceProcessInstaller processInstaller;

        public ProjectInstaller()
        {
            processInstaller = new ServiceProcessInstaller();
            serviceInstaller1 = new ServiceInstaller();
            
            processInstaller.Account = ServiceAccount.LocalSystem;
            
            serviceInstaller1.StartType = ServiceStartMode.Automatic;
            
            serviceInstaller1.ServiceName = "SiroonianMonitorService";
            
            Installers.Add(serviceInstaller1);
            Installers.Add(processInstaller);
        }
    }


And here is the exception I get when calling Install():

System.NullReferenceException: Object reference not set to an instance of an object.
   at System.ServiceProcess.ServiceInstaller.Install(IDictionary stateSaver)
   at System.Configuration.Install.Installer.Install(IDictionary stateSaver)
   at InstallerGUI.Pages.ViewModels.InstallationViewModel.DoInstall(Object sender, DoWorkEventArgs e) in C:\Users\dstevens\src\MonitoringDeviceProject\MonDevService\InstallerGUI\Pages\ViewModels\InstallationViewModel.cs:line 97


I'm pretty stumped, I don't know why this is happening. I made sure the ServiceName of my service class that derives from ServiceBase is also "SiroonianMonitorService". Any other ideas why this might be occurring would be immensely helpful!

Thank you,
Derek

EDIT: I have made a new solution from scratch to test and make sure I didn't get anything twisted, and I get the same results (.NET Framework 4.7.2):

Startup project InstallerWrapper:

using testService;
using System.Collections;

namespace InstallerWrapper
{
    public class Program
    {
        static void Main()
        {
            TestInstaller self = new TestInstaller();

            self.Install(new Hashtable());
        }
    }
}


Implementation project testService:

namespace testService
{
    public class TestService : ServiceBase
    {
        public TestService()
        {
            ServiceName = "TestService";
        }

        public static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new TestService()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }

    public class TestInstaller : Installer
    {
        private ServiceInstaller serviceInstaller;
        private ServiceProcessInstaller processInstaller;

        public TestInstaller()
        {
            processInstaller = new ServiceProcessInstaller();
            serviceInstaller = new ServiceInstaller();

            processInstaller.Account = ServiceAccount.LocalSystem;

            serviceInstaller.Context = new InstallContext();
            serviceInstaller.Parent = processInstaller;
            serviceInstaller.StartType = ServiceStartMode.Automatic;

            serviceInstaller.ServiceName = "TestService";
            Installers.Add(serviceInstaller);
            Installers.Add(processInstaller);
        }
    }

}


dotnet-csharp
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DerekStevens-3578 avatar image
0 Votes"
DerekStevens-3578 answered BonnieDeWitt-QnA commented

I figured out what I had to do was set the Installer.Context and include /assemblypath=.\{exefile} in the arguments. That is not really documented explicitly so it took me a while of staring at example code to figure it out. Hopefully this helps someone else in the future.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I'm glad you figured it out, Derek!! I hadn't responded here yet, but I had been looking at your problem off-and-on since last night. Something about Installer.Context caught my attention as well, but I guess I didn't stare at enough example code to notice the assemblypath argument (although I figured that somewhere you had tell the installer where the EXE is)!!.

I've used that same Installer and Service code that you had for my Services, but the difference is that I was using the InstallUtil in a batch file to do my Service installations and it obviously works slightly different when calling from code.

Anyway, thanks for coming back here and letting readers know how your fixed it! =0)


~~Bonnie DeWitt [MVP since 2003]
http://geek-goddess-bonnie.blogspot.com


0 Votes 0 ·
henrihan-8261 avatar image
0 Votes"
henrihan-8261 answered DerekStevens-3578 commented

The documentation at system.serviceprocess.serviceprocessinstaller
adds
[RunInstaller(true)]
to avoid instantiation


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I actually do have that attribute on the class, but that doesn't help in this situation -- I need to directly call the code, not shell out to InstallUtil.

0 Votes 0 ·