F# 安装Windows服务时出错(在F中)

F# 安装Windows服务时出错(在F中),f#,windows-services,service-installer,F#,Windows Services,Service Installer,我的问题如下: 当我尝试安装Windows服务时,出现以下错误: 片段: ... 在程序集中找不到具有RunInstallerAttribute.Yes属性的公共安装程序。 ... 我明白这一点 我有一个Program.fs文件,其中包含: [<RunInstaller(true)>] type public FSharpServiceInstaller() = inherit Installer() do < some logic, doe

我的问题如下: 当我尝试安装Windows服务时,出现以下错误:

片段:

...
在程序集中找不到具有RunInstallerAttribute.Yes属性的公共安装程序。
...

我明白这一点

我有一个
Program.fs
文件,其中包含:

[<RunInstaller(true)>]
type public FSharpServiceInstaller() =
    inherit Installer()
    do
        < some logic, doesn't really matter >

我曾尝试以管理员和普通帐户的身份在PowerShell、cmd和Visual Studio CLI中运行此脚本,但始终出现相同的错误。如果有人知道我做错了什么,我将非常感谢您的帮助。

但我认为它需要与InstallUtil.exe一起安装

可能不是编码的最佳时刻,但特定的服务代码或多或少来自Don Syme:,因此这可能很好,但该存储库中其余的“周围”代码可能不是惯用的;-)

唐·赛姆斯的博客也解释了很多,所以它应该很容易适应你的需要。它还链接到VS Gallery上的Win服务模板:

好的,下面是

我查看了user1758475提供的代码,然后随机开始将解决方案复制粘贴到应用程序中。Don Symes的解决方案“刚刚起作用”,我终于找到了原因:我的源代码中没有(他也没有)名称空间声明。看来这就是罪魁祸首!在我添加了名称空间之后,安装程序工作得非常出色

正如Curt Nichols指出的,安装程序不应该在模块中,因为模块有效地隐藏了调用代码中的类型

谢谢你帮我解决这个问题

对于希望看到工作示例的人:

namespace FileWatcher
open System
open System.Reflection
open System.ComponentModel
open System.Configuration.Install
open System.ServiceProcess
open System.IO
open System.Configuration

type FileWatcherService() =
    inherit ServiceBase(ServiceName = "FileWatcher")

    let createEvent = fun (args: FileSystemEventArgs) -> 
                    printf "%s has been %s\n" args.FullPath (args.ChangeType.ToString().ToLower()) 
                    |> ignore

    override x.OnStart(args) =
        let fsw = new FileSystemWatcher ()
        fsw.Path                    <- "C:\TEMP"
        fsw.NotifyFilter            <- NotifyFilters.LastAccess ||| NotifyFilters.LastWrite ||| NotifyFilters.FileName ||| NotifyFilters.DirectoryName ||| NotifyFilters.CreationTime
        fsw.Filter                  <- "*.txt"
        fsw.EnableRaisingEvents     <- true
        fsw.IncludeSubdirectories   <- true
        fsw.Created.Add(createEvent)

    override x.OnStop() =
        printf "Stopping the FileWatcher service"

[<RunInstaller(true)>]
type public 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 = "AAA FileWatcher Service", 
            ServiceName = "AAAFileWatcherService",
            StartType = ServiceStartMode.Automatic )
        |> base.Installers.Add |> ignore


module Program =
    [<EntryPoint>]
    let main args =

        printf "starting the application...\n"


        if Environment.UserInteractive then
            let parameter = String.Concat(args);
            match parameter with
            | "-i" -> ManagedInstallerClass.InstallHelper [| Assembly.GetExecutingAssembly().Location |]
            | "-u" -> ManagedInstallerClass.InstallHelper [| "/u"; Assembly.GetExecutingAssembly().Location |]
            | _ -> printf "Not allowed!\n" 
        else 
            ServiceBase.Run [| new FileWatcherService() :> ServiceBase |];
        0
名称空间文件监视程序
开放系统
开放系统。反射
开放系统组件模型
打开System.Configuration.Install
开放系统.ServiceProcess
开放系统
开放系统配置
类型FileWatcherService()=
继承ServiceBase(ServiceName=“FileWatcher”)
让createEvent=fun(args:FileSystemEventArgs)->
printf“%s”已被%s\n“args.FullPath(args.ChangeType.ToString().ToLower())
|>忽略
重写x.OnStart(args)=
让fsw=newfilesystemwatcher()
fsw.Path ManagedInstallerClass.InstallHelper[| Assembly.getExecutionGassembly().Location |]
|“-u”->ManagedInstallerClass.InstallHelper[|“/u”Assembly.GetExecutionGassembly().Location |]
|->printf“不允许!\n”
其他的
运行[| new FileWatcherService():>ServiceBase;];
0

Related:感谢您的评论,我非常感谢。我已经检查了相关的问题,虽然op问了“相同”的问题,但没有答案;这只是一个实现示例。感谢您的发布,但在提供的代码链接中,我似乎找不到解决问题的方法。我试图用
InstallUtil.exe
和我的自定义安装程序安装该服务,两者都给我相同的错误。似乎安装程序无法找到具有该属性的安装程序类,尽管我在代码中明确指定了该属性。如果其他示例有效,而您的示例无效,则Occam会告诉我您有问题。假设你所做的正是例子所显示的,这可能是错误的。退一步,从头开始,按原样做这个例子,如果它不起作用,就给托马斯·佩特里切克发电子邮件,或者在这里调用他,告诉他他的代码是错误的。他不时在这里;-)谢谢你的帮助。我已经想出了解决这个问题的办法。好像我错过了一个名称空间声明。我已经在回答中发布了我的代码和解决方案。所以我的回答/评论是正确的,但没有像“这是有用的”这样的实际确认。。。好的,我会记住的;-)很好,不过你已经成功了。老实说,但是评论的第一行实际上是:“但是我似乎无法在提供的代码链接中找到解决问题的方法”,当遇到问题时,说“后退一步,重新开始”总是一个很好的建议,但是不够具体,不能向上投票,对吗?另外,不要将服务安装程序类型放在模块中,这样会有效地将其隐藏在查找它的代码中。
namespace FileWatcher
open System
open System.Reflection
open System.ComponentModel
open System.Configuration.Install
open System.ServiceProcess
open System.IO
open System.Configuration

type FileWatcherService() =
    inherit ServiceBase(ServiceName = "FileWatcher")

    let createEvent = fun (args: FileSystemEventArgs) -> 
                    printf "%s has been %s\n" args.FullPath (args.ChangeType.ToString().ToLower()) 
                    |> ignore

    override x.OnStart(args) =
        let fsw = new FileSystemWatcher ()
        fsw.Path                    <- "C:\TEMP"
        fsw.NotifyFilter            <- NotifyFilters.LastAccess ||| NotifyFilters.LastWrite ||| NotifyFilters.FileName ||| NotifyFilters.DirectoryName ||| NotifyFilters.CreationTime
        fsw.Filter                  <- "*.txt"
        fsw.EnableRaisingEvents     <- true
        fsw.IncludeSubdirectories   <- true
        fsw.Created.Add(createEvent)

    override x.OnStop() =
        printf "Stopping the FileWatcher service"

[<RunInstaller(true)>]
type public 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 = "AAA FileWatcher Service", 
            ServiceName = "AAAFileWatcherService",
            StartType = ServiceStartMode.Automatic )
        |> base.Installers.Add |> ignore


module Program =
    [<EntryPoint>]
    let main args =

        printf "starting the application...\n"


        if Environment.UserInteractive then
            let parameter = String.Concat(args);
            match parameter with
            | "-i" -> ManagedInstallerClass.InstallHelper [| Assembly.GetExecutingAssembly().Location |]
            | "-u" -> ManagedInstallerClass.InstallHelper [| "/u"; Assembly.GetExecutingAssembly().Location |]
            | _ -> printf "Not allowed!\n" 
        else 
            ServiceBase.Run [| new FileWatcherService() :> ServiceBase |];
        0