65.9K
CodeProject 正在变化。 阅读更多。
Home

创建 Web 服务方法以获取 NT 服务信息

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (16投票s)

2006 年 11 月 17 日

CPOL

2分钟阅读

viewsIcon

51163

downloadIcon

280

一篇关于创建 Web 服务方法以获取 NT 服务信息的文章。

引言

最近,我创建了一个移动应用程序 - Siccolo,它允许我通过托管在公共域上的 Web 服务来管理 SQL Server(有关如何开发移动管理工具的更多信息,请参见此处)。
作为管理工具的一部分,我需要显示有关所选 NT 服务的一些信息,例如服务可执行文件的路径。 例如,services.msc 这样显示

在我的移动管理工具中,我需要以类似的方式显示

提供的代码检索有关所选 NT 服务的可执行文件路径的信息。

背景

我的“管理”Web 服务托管在 SSL 下,并设置了“集成 Windows”身份验证。 因此,移动应用程序需要传递网络凭据。 这是需要能够远程访问以从远程计算机上的注册表中获取信息。

Using the Code

使用的组件

  • serviceprocessor.asmx.cs - Web 服务接口
  • NTServiceInfo.cs - 用于检索 NT 服务信息的小型“包装器”

.NET 提供了此任务的工具 - System.ServiceProcess.ServiceController类。 要创建 System.ServiceProcess.ServiceController 的实例

// C# //

...
System.ServiceProcess.ServiceController Service;
if (this.m_MachineName!="")
    {Service = new ServiceController(this.m_ServiceName, this.m_MachineName ) ;}
else
    {Service = new ServiceController(this.m_ServiceName ) ;}
...

IIS 上存在身份验证(集成 Windows 身份验证或基本身份验证)的事实实际上有所帮助。 为了能够访问与 Web 服务主机不同的计算机上的服务,Web 服务需要“承担”已验证用户的身份。 通常,Web 服务以具有最低权限的 ASP.NET 用户身份运行,我需要模拟通过 Web 服务验证的用户。

在服务器端,要检索经过身份验证的用户,我们需要使用 System.Web.Services.WebService.User 然后模拟:代码正是这样做的 - “模拟由 WindowsIdentity 对象表示的用户。”

// C# //

...

System.Security.Principal.WindowsImpersonationContext impersonationContext;
        impersonationContext =
            ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
...    

要检索可执行文件的路径,我们可以查看 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,找到所选服务,并获取 ImagePath

要读取注册表项的值(在远程计算机上或在本地计算机上)

private string ReadRegestryKey(string RegistryKey, out string ErrorInfo)
{
    try
    {
        string Value="";
        ErrorInfo ="";

        RegistryKey Key;
        RegistryKey KeyHKLM = Registry.LocalMachine;
        try
        {
            if (this.m_MachineName !="" )    //open on remote machine

                Key = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(
                RegistryHive.LocalMachine, this.m_MachineName
                ).OpenSubKey(RegistryKey);
            else
                Key = KeyHKLM.OpenSubKey(RegistryKey);

            Value = Key.GetValue("ImagePath").ToString();
            Key.Close();
        }
        catch (Exception ex_open_key)
        {
            ErrorInfo = "Error Accessing Registry [" + ex_open_key.ToString() + "]";
            return "";
        }
        return Value;
    }
    catch (Exception ex_read_registry)
    {
        ErrorInfo =   ex_read_registry.Message;
        return "";
    }
}

提取可执行文件的路径后,我们需要检查是否需要从 %SystemRoot%\system32\... 之类的路径“提取”到实际路径。
%SystemRoot% 的值可以在注册表中找到

private string ExpandEnvironmentString(string Path)
{
    string SystemRootKey = "Software\\Microsoft\\Windows NT\\CurrentVersion\\";
    RegistryKey Key;

    if (this.m_MachineName !="" )
        Key = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(
        RegistryHive.LocalMachine, this.m_MachineName
        ).OpenSubKey(SystemRootKey);
    else
        Key = Registry.LocalMachine.OpenSubKey(SystemRootKey);

        string ExpandedSystemRoot ="";
        ExpandedSystemRoot = Key.GetValue("SystemRoot").ToString();
        Key.Close();

        Path = Path.Replace ("%SystemRoot%", ExpandedSystemRoot);

        return Path;
}

最后

public string PathToExecutable(WindowsPrincipal User)
{
    //HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services.

    string RegistryKey = "SYSTEM\\CurrentControlSet\\Services\\" +
    this.m_ServiceName;

    string ErrorInfo="";
    System.Security.Principal.WindowsImpersonationContext impersonationContext;
    impersonationContext =
        ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

    string Path= this.ReadRegestryKey(RegistryKey, out ErrorInfo);
    if ( Path.IndexOf("%")>0)
    {
        Path = ExpandEnvironmentString(Path);
    }
    impersonationContext.Undo();
    return Path;
}

请注意,对 ReadRegestryKey()ExpandEnvironmentString() 的调用是如何“包装在”中的

impersonationContext =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
...
...
impersonationContext.Undo();

然后,是实际的 Web 方法

[WebMethod]
public bool GetNTServiceInfo(string RemoteServerAddress ,
    string NTServiceName,
    out string ServiceInfo_XML ,
    out string ErrorInfo )
{
    try
    {
        string ToDebugSetting
            = System.Configuration.ConfigurationSettings.AppSettings.Get("DebugMode");
        bool ToDebug = (ToDebugSetting!="");

        ErrorInfo="";
        ServiceInfo_XML ="";
        System.ServiceProcess.ServiceController Service;
        if (RemoteServerAddress!="")
            {Service = new ServiceController(NTServiceName, RemoteServerAddress ) ;}
        else
            {Service = new ServiceController(NTServiceName ) ;}

        DataSet objDataSet = new DataSet("QueryResults");
        objDataSet.Tables.Add("ServiceInfo");
        objDataSet.Tables[0].Columns.Add("service_display_name",
            System.Type.GetType("System.String"));
        objDataSet.Tables[0].Columns.Add("status",
            System.Type.GetType("System.String"));
        objDataSet.Tables[0].Columns.Add("service_name",
            System.Type.GetType("System.String"));
        objDataSet.Tables[0].Columns.Add("path_to_executable",
            System.Type.GetType("System.String"));
        objDataSet.Tables[0].Columns.Add("can_stop",
            System.Type.GetType("System.Boolean"));
        objDataSet.Tables[0].Columns.Add("can_pause_and_continue",
            System.Type.GetType("System.Boolean"));
        objDataSet.Tables[0].Columns.Add("services_depend_on",
            System.Type.GetType("System.String"));
        objDataSet.Tables[0].Columns.Add("dependent_services",
            System.Type.GetType("System.String"));

        NTServiceInfo si  = new NTServiceInfo(NTServiceName,
                            RemoteServerAddress);

        Object[] r    = new Object[8] {Service.DisplayName,
                        Service.Status.ToString(),
                        Service.ServiceName,
                        si.PathToExecutable((WindowsPrincipal) this.User),
                        Service.CanStop.ToString(),
                        Service.CanPauseAndContinue.ToString(),
                        si.ServiceDependOnStringList(Service.ServicesDependedOn),
                        si.DependentServicesStringList(Service.DependentServices)
                        };

        objDataSet.Tables[0].Rows.Add(r);

        Service.Close();

        System.IO.StringWriter objStringWriter =new System.IO.StringWriter();
        objDataSet.WriteXml(objStringWriter, XmlWriteMode.WriteSchema);

        ServiceInfo_XML = "<?xml version='1.0' ?>" + objStringWriter.ToString();

        ErrorInfo = "";
        return true;
    }
    catch (Exception ex_get_service_info)
    {
        ServiceInfo_XML ="";
        ErrorInfo = ex_get_service_info.Message;
        return false;
    }
}

关注点

如果您想了解更多相关信息,请查看 Siccolo - 用于 SQL Server 的免费移动管理工具以及 如何开发移动管理工具的完整文章。

© . All rights reserved.