【问题标题】:installutil bindingRedirectinstallutil 绑定重定向
【发布时间】:2011-04-25 19:17:00
【问题描述】:

我有一个依赖于 3:rd 方 API 的 Windows 服务

API 已安装在客户端计算机上的 GAC 中

API 有多个版本(1.0.0.0、1.1.0.0 等)

我的服务适用于所有版本的 API

我在 app.config 文件中使用了 bindingRedirect 标记,该标记在运行服务时可以正常工作。

问题是运行 InstallUtil 时没有使用 app.config 文件,所以在注册服务时出现绑定异常。

目前我使用“sc create”手动注册服务,但有更好的方法吗?
(无需编辑 machine.config 等)

【问题讨论】:

  • 我也遇到了同样的问题。

标签: windows-services installutil


【解决方案1】:

我刚刚遇到这个,我能找到的唯一解决方案是来自https://connect.microsoft.com/VisualStudio/feedback/details/525564/installutil-exe-does-not-honor-app-config-especially-binding-information

作为一种解决方法,您可以通过修改 InstallUtil.exe.config 文件以包含绑定信息来完成这项工作。 InstallUtil.exe.config 安装到 %WinDir%\Microsoft.NET\Framework\\InstallUtil.exe.config 您正在使用的框架版本。

【讨论】:

  • 链接失效
【解决方案2】:

我想出了另一种解决方法来安装具有绑定重定向的服务。由于我有很多服务,这就是我决定追求的。

  1. 将 Windows 安装程序更改为控制台应用程序并实现自行安装的功能(使用命令行和 ManagedInstallerClass.InstallHelper)。

  2. 实现一个能够在完全独立的程序集中执行命令行的安装程序类,例如CommandLineInstaller.DLL. CommandLineInstaller.DLL 应同样实现方法安装/卸载/回滚 - 使用以下参数执行命令行: FileName, WorkingDirectory, Args, WindowStyle.

  3. 修改设置项目以部署 1) 服务和 b) CommandLineInstaller.DLL

  4. 修改设置项目自定义操作:运行 CommandLineInstaller.DLL 的操作,而不是运行服务的操作。安装操作的 CustomActionData 属性如下所示: /FileName="[TARGETDIR]MyService.exe" /Args="/install" WindowStyle="Hidden"

    动作配置: 安装:我的服务/安装 回滚:myservice /uninstall 卸载:myservice /uninstall

无需编写 Commit,AFAIK。

现在,安装项目将在自己的进程中执行 CommandLineInstaller.DLL 安装程序。然后 CommandLineInstaller.DLL 将依次在其自己的进程中启动 MyService.exe,并按照应有的方式进行血腥绑定重定向。

PS MyService.exe 可以使用退出代码机制来通知安装程序失败,我强烈建议从 CommandLineInstaller 检查它们。

希望这是一个足够好的大纲。

PS 请注意,TARGETDIR 在将自身传递给目录时需要有一个斜杠: /WorkDir="[TARGETDIR]\"

安装 CustomActionData 的示例: /FileName="[TARGETDIR]\MyService.exe" /Args="/install" /WorkingDir="[TARGETDIR]\" /ValidExitCode="0" /WindowStyle="Normal"

一些代码:


using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;

namespace QT.Install
{
    [RunInstaller(true)]
    public partial class ExecuteCommandInstaller : System.Configuration.Install.Installer
    {
        public class CommandArgs
        {
            public string FileName { get; set; }
            public string WorkingDir { get; set; }
            public string Args { get; set; }
            public string ValidExitCode { get; set; }
            public ProcessWindowStyle WindowStyle { get; set; }
        }

        public ExecuteCommandInstaller()
        {
            InitializeComponent();
        }

        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            ExecuteCommand(stateSaver);
        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
            ExecuteCommand(savedState);
        }

        public override void Uninstall(IDictionary savedState)
        {
            base.Uninstall(savedState);
            ExecuteCommand(savedState);
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
            ExecuteCommand(savedState);
        }
        private void ExecuteCommand(IDictionary stateSaver)
        {
            CommandArgs commandArgs = new CommandArgs()
            {
                FileName = StripDoubleSlash(Context.Parameters["FileName"] ?? ""),
                WorkingDir = StripDoubleSlash(Context.Parameters["WorkingDir"] ?? ""),
                Args = Context.Parameters["Args"] ?? "",
                ValidExitCode = Context.Parameters["ValidExitCode"] ?? "*"
            };

            try
            {
                commandArgs.WindowStyle = (ProcessWindowStyle)Enum.Parse(typeof(ProcessWindowStyle), Context.Parameters["WindowStyle"] ?? "Hidden");
            }
            catch (Exception err)
            {
                throw new Exception($"Invalid WindowStyle parameter value: {Context.Parameters["WindowStyle"]}", err);
            }
            InternalExecuteCommand(commandArgs);
        }

        private void InternalExecuteCommand(CommandArgs commandArgs)
        {
            if (string.IsNullOrEmpty(commandArgs.FileName))
                throw new Exception("FileName is not specified.");

            System.Diagnostics.ProcessStartInfo startInfo = new ProcessStartInfo(commandArgs.FileName, commandArgs.Args);

            if (!string.IsNullOrEmpty(commandArgs.WorkingDir))
                startInfo.WorkingDirectory = commandArgs.WorkingDir;

            startInfo.WindowStyle = commandArgs.WindowStyle;

            using (var process = Process.Start(startInfo))
            {
                process.WaitForExit();

                if (commandArgs.ValidExitCode != "*")
                {
                    if (process.ExitCode.ToString() != commandArgs.ValidExitCode)
                        throw new Exception($"Executing {commandArgs.FileName} {commandArgs.Args} returned exit code {process.ExitCode}. Expected exit code is: {commandArgs.ValidExitCode}.");
                }
            }
        }

        private static string StripDoubleSlash(string value)
        {
            return value.Replace("\\\\", "\\");
        }
    }
}

【讨论】:

    猜你喜欢
    • 2010-10-02
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 2018-06-09
    • 2016-01-22
    • 2014-03-20
    相关资源
    最近更新 更多