C# 部署:this.Context.Parameters在整个安装过程中不可用

C# 部署:this.Context.Parameters在整个安装过程中不可用,c#,deployment,windows-installer,C#,Deployment,Windows Installer,我有以下代码,但尽管我可以访问属性并检索值 this.Context.Parameters["SERVICENAME"] 在BeforeInstall中,同一属性在OnCommitted中返回“” 这些数据到哪里去了,它是如何被擦除的,我在哪里可以找到这些方法的顺序的细分,在哪里传递什么 [RunInstaller(true)] public partial class ProjectInstaller : System.Configuration.Install.Installe

我有以下代码,但尽管我可以访问属性并检索值

 this.Context.Parameters["SERVICENAME"] 
在BeforeInstall中,同一属性在OnCommitted中返回“”

这些数据到哪里去了,它是如何被擦除的,我在哪里可以找到这些方法的顺序的细分,在哪里传递什么

[RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {

        public string ServiceName { get; protected set; }

        /// <summary>
        /// 
        /// </summary>
        public ProjectInstaller()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="savedState"></param>
        protected override void OnBeforeInstall(IDictionary savedState)
        {
            base.OnBeforeInstall(savedState);
            this.ServiceName = this.Context.Parameters["SERVICENAME"].ToString();
            this.serviceInstaller1.ServiceName = this.ServiceName;
            this.serviceInstaller1.DisplayName = this.ServiceName;
        }

        /// <summary>
        /// /
        /// </summary>
        /// <param name="savedState"></param>
        protected override void OnCommitted(IDictionary savedState)
        {
            base.OnCommitted(savedState);
            string targetDirectory = Path.GetDirectoryName(Context.Parameters["AssemblyPath"]); ;
            string path = System.IO.Path.Combine(targetDirectory, "Services.Win32.exe.config");
            System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
            xDoc.Load(path);
            System.Xml.XmlNode node = xDoc.SelectSingleNode("/configuration/applicationSettings/Services.Win32.Properties.Settings/setting[@name='TaskManagerServiceName']/value");
            node.InnerText = (this.ServiceName); // here this.ServiceName is "" so was this.Context.Parameters[""SERVICENAME"] when i was using that
            xDoc.Save(path);
        }
[运行安装程序(true)]
公共分部类ProjectInstaller:System.Configuration.Install.Installer
{
公共字符串ServiceName{get;protected set;}
/// 
/// 
/// 
公共项目安装程序()
{
初始化组件();
}
/// 
/// 
/// 
/// 
安装前受保护的覆盖无效(IDictionary savedState)
{
base.onbefore安装(savedState);
this.ServiceName=this.Context.Parameters[“ServiceName”].ToString();
this.serviceInstaller1.ServiceName=this.ServiceName;
this.serviceInstaller1.DisplayName=this.ServiceName;
}
/// 
/// /
/// 
/// 
已提交受保护的覆盖无效(IDictionary savedState)
{
基础。未提交(保存状态);
字符串targetDirectory=Path.GetDirectoryName(Context.Parameters[“AssemblyPath”]);
字符串path=System.IO.path.Combine(targetDirectory,“Services.Win32.exe.config”);
System.Xml.XmlDocument xDoc=new System.Xml.XmlDocument();
xDoc.Load(路径);
System.Xml.XmlNode node=xDoc.SelectSingleNode(“/configuration/applicationSettings/Services.Win32.Properties.Settings/Settings[@name='TaskManagerServiceName']/value”);
node.InnerText=(this.ServiceName);//这里this.ServiceName是“”,this.Context.Parameters[“”ServiceName“]在我使用它时也是如此
xDoc.Save(路径);
}

最简单、最干净、最健壮的解决方案是不使用installer类自定义操作来安装服务。请使用Windows installer的内置mechansim:The table

问题是您可能正在使用未公开此功能的Visual Studio部署项目。没问题。请使用Windows Installer XML编写一个合并模块,封装XE/Service组件。然后将此合并模块添加到VDPROJ安装程序中

请参阅以下文章,了解如何将其连接起来:


我在尝试向现有部署项目添加其他参数时遇到了这个问题。参数已传递给安装程序,但在
上下文中不可见。参数
。事实证明,要访问的参数需要添加到该自定义操作的“自定义操作数据”中

您可以通过右键单击.vdproj项目并选择
查看->自定义操作来实现这一点。
从那里,您可以找到自定义操作的主要输出。通过右键单击所需步骤(安装、提交、回滚或卸载)中的主要输出并选择属性,您可以编辑该步骤的自定义操作数据。您可以找到该属性的格式


希望它能为其他人节省时间,因为我花了很长时间才弄明白这一点。

可以在安装程序类的安装和卸载覆盖时访问它:

这里有一个完整的例子:

[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{

    public ProjectInstaller()
    {
        InitializeComponent();              
    }

    public override void Install(System.Collections.IDictionary stateSaver)
    {
        UpdateServiceName();
        base.Install(stateSaver);
    }

    public override void Uninstall(System.Collections.IDictionary savedState)
    {
        UpdateServiceName();
        base.Uninstall(savedState);
    }
    private void UpdateServiceName()
    {
        var serviceName = Context.Parameters["servicename"];

        //if service name was set has install parameter then override the value set on the designer:
        if (!string.IsNullOrEmpty(serviceName))
        {

            //serviceInstaller1 is the `ServiceInstaller` component drag to install designer.
            this.serviceInstaller1.ServiceName = serviceName;

            //Since user can change service name and do multiple side installs, by keep the display names similar it can help to keep those side installs packed in Service Management Console.
            this.serviceInstaller1.DisplayName = $"{this.serviceInstaller1.DisplayName} ({serviceName})";
        }
    }
}