2015-06-26 11 views
6

Znów wracam, tym razem z pytaniem o pisanie usługi w F #. Nie mogę zainstalować usługi przy użyciu installutil. Daje mi następujący błąd.Pisanie usługi w F #

$ installutil atfwindowsservice.exe 
Microsoft (R) .NET Framework Installation utility Version 4.0.30319.18408 
Copyright (C) Microsoft Corporation. All rights reserved. 

Running a transacted installation. 

Beginning the Install phase of the installation. 
See the contents of the log file for the C:\Dev\ATF\output\bin\Debug\atfwindowsservice.exe assembly's progress. 
The file is located at C:\Dev\ATF\output\bin\Debug\atfwindowsservice.InstallLog. 
Installing assembly 'C:\Dev\ATF\output\bin\Debug\atfwindowsservice.exe'. 
Affected parameters are: 
    logtoconsole = 
    logfile = C:\Dev\ATF\output\bin\Debug\atfwindowsservice.InstallLog 
    assemblypath = C:\Dev\ATF\output\bin\Debug\atfwindowsservice.exe 
No public installers with the RunInstallerAttribute.Yes attribute could be found in the C:\Dev\ATF\output\bin\Debug\atfwindowsservice.exe assembly. 

Kod jest podany poniżej. Każda pomoc jest doceniana i z góry dziękuję.

Ramesh

namespace service 

open System.ServiceProcess 
open System.Runtime.Remoting 
open System.Runtime.Remoting.Channels 

type atf() = 
    inherit ServiceBase(ServiceName = "atf win service") 

    override x.OnStart(args) =() 
    override x.OnStop() =() 

rejestracji kod serwisowy:

// Learn more about F# at http://fsharp.net 
// See the 'F# Tutorial' project for more help.= 
open System 
open System.ComponentModel 
open System.Configuration.Install 
open System.ServiceProcess 

[<RunInstaller(true)>] 
type FSharpServiceInstaller() = 
    inherit Installer() 
    do 
     // Specify properties of the hosting process 
     new ServiceProcessInstaller(Account = ServiceAccount.LocalSystem) |> base.Installers.Add |> ignore 

     // Specify properties of the service running inside the process 
     new ServiceInstaller(DisplayName = "F# ATF Service", ServiceName = "atf",StartType = ServiceStartMode.Automatic) |> base.Installers.Add |> ignore 

// Run the chat service when the process starts 
module Main = 
    ServiceBase.Run [| new service.atf() :> ServiceBase |] 

Odpowiedz

2

zorientowali się, jak napisać Samoobsługowe Instalacja przy użyciu innych przykładów na stron internetowych, szczególnie ten post na stosie była przydatna: http://pingfu.net/programming/2011/08/11/creating-a-self-installing-windows-service-with-csharp.html

open System 
open System.ServiceProcess 
open System.Windows 
open System.Threading 
open System.Windows.Forms 
open System.ComponentModel 
open System.Configuration.Install 
open System.Reflection 
open Microsoft.Win32 

type ATFServiceInstaller() = 
    inherit Installer() 


let spi_ = new ServiceProcessInstaller(Account = ServiceAccount.LocalSystem) 
    let si_ = new ServiceInstaller(DisplayName = "ATF Service", Description="ATF service", ServiceName = "atf",StartType = ServiceStartMode.Automatic) 
    let dic_ = new System.Collections.Hashtable() 
    let SVC_SERVICE_KET = @"SYSTEM\CurrentControlSet\Services" 

    member this.install() = 
     base.Installers.Add(spi_) |> ignore 
     let ret = base.Installers.Add(si_) 
     let apath = sprintf "/assemblypath=%s" (Assembly.GetExecutingAssembly().Location) 
     let ctx = [|apath; "/logToConsole=false"; "/showCallStack"|] 
     this.Context <- new InstallContext("atfserviceinstall.log", ctx) 

     base.Install(dic_) 
     base.Commit(dic_) 

    member this.uninstall() = 

     base.Installers.Add(spi_) |> ignore 


     let ret = base.Installers.Add(si_) 
     let apath = sprintf "/assemblypath=%s" (Assembly.GetExecutingAssembly().Location) 
     let ctx = [|apath; "/logToConsole=false"; "/showCallStack"|] 
     this.Context <- new InstallContext("atfserviceinstall.log", ctx) 
     base.Uninstall(null) 

module Main = 
try 
    let args = Environment.GetCommandLineArgs() 

    match (args |> Seq.length) with 
    | 2 -> match (args.[1]) with 
      | "-install" -> let installer = new ATFServiceInstaller() 
          installer.install() 
          installer.Dispose() 
      | "-uninstall" -> let installer = new ATFServiceInstaller() 
          installer.uninstall() 
          installer.Dispose() 
      | _ -> failwith "Unrecognized param %s" args.[0] 
    | _ -> ServiceBase.Run [| new atfservice.ATFService() :> ServiceBase |] 
with 
    | _ as ex -> MessageBox.Show(ex.ToString()) |> ignore 
2

miałem ten sam problem. W końcu dodałem następujący kod, który działa ładnie i ma dodatkową zaletę nie wymagającą instalacji installutil.exe. Usługa może sam się zainstalować/odinstalować, przekazując poprawny parametr wiersza poleceń. Zachować swój kod i dodać następujące:

module Program = 

    let getInstaller() = 
    let installer = new AssemblyInstaller(typedefof<atf>.Assembly, null); 
    installer.UseNewContext <- true 
    installer 

    let installService() = 
    let installer = getInstaller() 
    let dic = new System.Collections.Hashtable() 
    installer.Install(dic) 
    installer.Commit(dic) 

    let uninstallService() = 
    let installer = getInstaller() 
    let dic = new System.Collections.Hashtable() 
    installer.Uninstall(dic) 

    [<EntryPoint>] 
    let main (args:string[]) = 
    match (args |> Seq.length) with 
    |1 -> match (args.[0]) with 
      |"-install" -> installService() 
      |"-uninstall" -> uninstallService() 
      |_-> failwith "Unrecognized param %s" args.[0] 
    |_ -> ServiceBase.Run [| new atf() :> ServiceBase |] 
    0 

Aby zainstalować można wykonać następujące z wiersza poleceń:

atfwindowsservice.exe -install 
+0

Dzięki za odpowiedź. Napisałem usługę samoinstalacji przy użyciu klas instalatora usług. Przyznam Ci pełne uznanie, ponieważ użyłem Twojego przykładu do zmodyfikowania mojego oryginalnego kodu. –

2

natknąłem to pytanie, mając ten sam problem. W dalszym ciągu potrzebowałem zainstalować InstallUtil.exe i dowiedzieć się, że problem z oryginalnym kodem był brakującym obszarem nazw w pliku głównym.

Znalazłem ten framework dla usług .NET. http://topshelf-project.com/, co znacznie ułatwia programowanie i umożliwia tworzenie aplikacji konsolowych, które można debugować, a także ma wbudowany instalator usług Windows/Mono. Jedynym minusem dla mnie była brakująca obsługa instalacji za pomocą InstallUtil.exe, ale jest też na to rozwiązanie. Zamiast dodawać ServiceProcessInstaller i ServiceInstaller do instalatorów w klasie odziedziczonej po Instalatorze zastąpić metody instalacji i deinstalacji i zmusić ich do uruchomienia pliku wykonywalnego za pomocą parametru install/unistall.

[<RunInstaller(true)>] 
type public FSharpServiceInstaller() = 
    inherit Installer() 

    override __.Install(stateSaver : System.Collections.IDictionary) = 
     let assemblyPath = __.Context.Parameters.["assemblypath"] 
     stateSaver.Add(assemblyIdentifier, assemblyPath) 

     // runProcess assemblyPath "install" 

     base.Install(stateSaver) 

    override __.Uninstall(savedState : System.Collections.IDictionary) = 
     let assemblyPath = savedState.[assemblyIdentifier].ToString() 

     // runProcess assemblyPath "uninstall" 

     base.Uninstall(savedState) 

Pełny kod w: https://gist.github.com/jbezak/eda4cc5864059b717e71beaec47db2d9