C# 是否获取已安装服务的版本信息?

C# 是否获取已安装服务的版本信息?,c#,windows-services,C#,Windows Services,我想以编程方式检查是否安装了最新版本的Windows服务。我有: var ctl = ServiceController.GetServices().Where(s => s.ServiceName == "MyService").FirstOrDefault(); if (ctl != null) { // now what? } 我在ServiceController界面上没有看到任何能告诉我版本号的内容。我该怎么做?恐怕除了从注册表获取可执行路径之外没有其他方法,因为Servi

我想以编程方式检查是否安装了最新版本的Windows服务。我有:

var ctl = ServiceController.GetServices().Where(s => s.ServiceName == "MyService").FirstOrDefault();
if (ctl != null) {
  // now what?
}

我在
ServiceController
界面上没有看到任何能告诉我版本号的内容。我该怎么做?

恐怕除了从注册表获取可执行路径之外没有其他方法,因为
ServiceController
不提供该信息

以下是我以前创建的一个示例:

private static string GetExecutablePathForService(string serviceName, RegistryView registryView, bool throwErrorIfNonExisting)
    {
        string registryPath = @"SYSTEM\CurrentControlSet\Services\" + serviceName;
        RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView).OpenSubKey(registryPath);
        if(key==null)
        {
            if (throwErrorIfNonExisting)
                throw new ArgumentException("Non-existent service: " + serviceName, "serviceName");
            else
                return null;
        }
        string value = key.GetValue("ImagePath").ToString();
        key.Close();
        if(value.StartsWith("\""))
        {
            value = Regex.Match(value, "\"([^\"]+)\"").Groups[1].Value;
        }

        return Environment.ExpandEnvironmentVariables(value);
    }

获取exe路径后,只需使用
FileVersionInfo.GetVersionInfo(exePath)
类获取版本。

如果您拥有该服务,您可以将版本信息放入
DisplayName
,例如
DisplayName=“MyService 2017.06.28.1517”
。这允许您查找服务的现有安装并解析版本信息:

var ctl = ServiceController
    .GetServices()
    .FirstOrDefault(s => s.ServiceName == "MyService");
if (ctl != null) {
    // get version substring, you might have your own style.
    string substr = s.DisplayName.SubString("MyService".Length);
    Version installedVersion = new Version(substr);
    // do stuff, e.g. check if installed version is newer than current assembly.
}

如果要避免使用注册表,这可能很有用。问题是,服务条目可能会根据安装例程转到注册表的不同部分。

如果您正在谈论从程序集属性自动获取当前版本的服务,则可以在
ServiceBase
类中设置如下属性

public static string ServiceVersion { get; private set; }
然后在
OnStart
方法中添加以下内容

ServiceVersion = typeof(Program).Assembly.GetName().Version.ToString();
完整示例

using System.Diagnostics;
using System.ServiceProcess;

public partial class VaultServerUtilities : ServiceBase
{

    public static string ServiceVersion { get; private set; }

    public VaultServerUtilities()
    {
        InitializeComponent();

        VSUEventLog = new EventLog();
        if (!EventLog.SourceExists("Vault Server Utilities"))
        {
            EventLog.CreateEventSource("Vault Server Utilities", "Service Log");
        }

        VSUEventLog.Source = "Vault Server Utilities";
        VSUEventLog.Log = "Service Log";

    }


    protected override void OnStart(string[] args)
    {

        ServiceVersion = typeof(Program).Assembly.GetName().Version.ToString();
        VSUEventLog.WriteEntry(string.Format("Vault Server Utilities v{0} has started successfully.", ServiceVersion));

    }

    protected override void OnStop()
    {
        VSUEventLog.WriteEntry(string.Format("Vault Server Utilities v{0} has be shutdown.", ServiceVersion));
    }
}
在上面的示例中,我的事件日志显示我的服务的当前版本。。。

你查过了吗…@Aaron-谢谢,这是一个很好的开始!:)+1谢谢!如何将
FileVersionInfo
与从
Assembly.GetAssembly(…).GetName().Version
返回的
Version
对象进行比较?您提到的是AssemblyVersion,它应该为您提供FileVersion。如果需要AssemblyVersion,则必须将其作为程序集加载(如您所述)。但是要注意,一旦加载了它,就已经锁定了文件(即使只作为ReflectionOnly加载),直到进程终止?我发现“如果值以引号开头,那么…”它似乎会去掉前导引号和尾随引号——与value=value.Trim(new[]{'''})相同;可以……但它也在做其他事情?@ckitel它会修剪它。但是正常的修剪不起作用,因为值的末尾有something:
”c:\Program Files\Microsoft SQL Server\MSSQL10\u 50.MSSQLSERVER\MSSQL\Binn\sqlservr.exe“-sMSSQLSERVER
非常有意义,谢谢。我没有想到命令行参数。