Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 安装Windows服务以作为虚拟用户运行_.net_Windows Services_Installation - Fatal编程技术网

.net 安装Windows服务以作为虚拟用户运行

.net 安装Windows服务以作为虚拟用户运行,.net,windows-services,installation,.net,Windows Services,Installation,我有一个安装.NET Windows服务的 如果我执行以下任一操作,安装过程将完美运行: 将服务设置为作为系统运行(serviceProcessInstaller1.Account=ServiceAccount.LocalSystem) 通过指定用户名和密码属性,或让安装过程提示我,将服务设置为以普通用户身份运行(serviceProcessInstaller1.Account=ServiceAccount.user) 但是,我希望该服务作为虚拟用户运行,即laNT service\Serv

我有一个安装.NET Windows服务的

如果我执行以下任一操作,安装过程将完美运行:

  • 将服务设置为作为系统运行(
    serviceProcessInstaller1.Account=ServiceAccount.LocalSystem
  • 通过指定
    用户名
    密码
    属性,或让安装过程提示我,将服务设置为以普通用户身份运行(
    serviceProcessInstaller1.Account=ServiceAccount.user
但是,我希望该服务作为虚拟用户运行,即la
NT service\ServiceName
。如果您查看一些SQL Server服务,您将看到它们默认作为自己的虚拟用户帐户登录。虽然信息有限,但还有更多信息


我已尝试设置
serviceProcessInstaller1.Username=@“NT Service\ServiceName”
,但无论我以何种方式提供密码,安装程序都会抛出以下错误(我已尝试
String.Empty
,与用户名相同,我自己的密码,
null
以打开交互式对话框,甚至随机垃圾):

未完成帐户名和安全ID之间的映射

但是,如果我正常安装该服务(例如,作为系统运行),那么我可以从
services.msc
管理单元进入该服务的属性,在登录页面上将用户更改为
NT service\ServiceName
,它工作得很好

我也调查过这个问题,但我似乎也无法让它改变任何事情



如何从我的
ServiceProcessInstaller
中的代码将登录用户设置为虚拟用户
NT Service\ServiceName

您不能直接使用
ServiceProcessInstaller
对象。但是,您可以在安装服务后,在
ServiceInstaller.Committed
事件中使用设置用户名。将用户名指定为
wmiparms[6]
,并将密码保留为空:


最后,不要忘记授予用户对服务exe和配置文件的读取/执行权限,否则将出现访问被拒绝错误。

您不能直接使用
ServiceProcessInstaller
对象执行此操作。但是,您可以在安装服务后,在
ServiceInstaller.Committed
事件中使用设置用户名。将用户名指定为
wmiparms[6]
,并将密码保留为空:


最后,别忘了向用户授予对服务exe和配置文件的读取/执行权限,否则将出现访问被拒绝的错误。

上述解决方案的替代方法(使用
ServiceInstaller.Committed
事件)被描述为解决方法。其想法是通过反射调整私有字段
haveLoginInfo
,以允许
null
作为有效密码

    const string s_ServiceName = "myservice1";
    const string s_DisplayName = "Tell admin what it is";
    const string s_Description = "Tell admin what it does";

        var procesServiceInstaller = new ServiceProcessInstaller
        {
            Account = ServiceAccount.User,
            Username = string.Format("NT Service\\{0}", s_ServiceName),
            Password = null,
        };

        //Here comes the hack.
        // ReSharper disable once PossibleNullReferenceException
        procesServiceInstaller
            .GetType()
            .GetField("haveLoginInfo", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(procesServiceInstaller, true);



        var serviceInstaller = new ServiceInstaller();
        var path = string.Format(
              "/assemblypath={0}",
              Assembly.GetExecutingAssembly().Location);
        string[] cmdline = { path };

        var context = new InstallContext("", cmdline);
        serviceInstaller.Context = context;
        serviceInstaller.DisplayName = s_DisplayName;
        serviceInstaller.ServiceName = s_ServiceName;
        serviceInstaller.Description = s_Description;
        serviceInstaller.StartType = ServiceStartMode.Manual;
        serviceInstaller.Parent = procesServiceInstaller;

        try
        {
            var state = new ListDictionary();
            serviceInstaller.Install(state);
        }
        catch (Win32Exception win32Exception)
        {
            //TODO: HandleException(win32Exception); 
        }
        catch (InvalidOperationException ex)
        {
            //TODO: HandleException(ex);
        }
即使是这个解决方案也不那么粗糙,至少在视觉上不那么难看


注意:处的解决方案描述中有错误。此处提到的私有字段名是
hasLoginInfo
,但必须是
haveLoginInfo

上述解决方案的替代方法(使用
ServiceInstaller.Committed
事件)被描述为解决方法。其想法是通过反射调整私有字段
haveLoginInfo
,以允许
null
作为有效密码

    const string s_ServiceName = "myservice1";
    const string s_DisplayName = "Tell admin what it is";
    const string s_Description = "Tell admin what it does";

        var procesServiceInstaller = new ServiceProcessInstaller
        {
            Account = ServiceAccount.User,
            Username = string.Format("NT Service\\{0}", s_ServiceName),
            Password = null,
        };

        //Here comes the hack.
        // ReSharper disable once PossibleNullReferenceException
        procesServiceInstaller
            .GetType()
            .GetField("haveLoginInfo", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(procesServiceInstaller, true);



        var serviceInstaller = new ServiceInstaller();
        var path = string.Format(
              "/assemblypath={0}",
              Assembly.GetExecutingAssembly().Location);
        string[] cmdline = { path };

        var context = new InstallContext("", cmdline);
        serviceInstaller.Context = context;
        serviceInstaller.DisplayName = s_DisplayName;
        serviceInstaller.ServiceName = s_ServiceName;
        serviceInstaller.Description = s_Description;
        serviceInstaller.StartType = ServiceStartMode.Manual;
        serviceInstaller.Parent = procesServiceInstaller;

        try
        {
            var state = new ListDictionary();
            serviceInstaller.Install(state);
        }
        catch (Win32Exception win32Exception)
        {
            //TODO: HandleException(win32Exception); 
        }
        catch (InvalidOperationException ex)
        {
            //TODO: HandleException(ex);
        }
即使是这个解决方案也不那么粗糙,至少在视觉上不那么难看


注意:处的解决方案描述中有错误。这里提到的私有字段名是
hasLoginInfo
,但必须是
haveLoginInfo

,托管和虚拟服务帐户是一项全新的Windows功能。您需要在像serverfault.com这样的网站上询问相关问题,在那里您可以找到系统管理员来修补它@HansPassant我意识到这有点边缘化,但我的问题是如何从代码中设置用户,因为我可以清楚地手动设置用户。因此,我认为这更像是一个编程问题,而不是一个系统管理员问题,并将其发布在这里。关于安装一项服务,似乎还有比SF更多的问题——我想这并不意味着什么。托管和虚拟服务帐户是一项全新的Windows功能。您需要在像serverfault.com这样的网站上询问相关问题,在那里您可以找到系统管理员来修补它@HansPassant我意识到这有点边缘化,但我的问题是如何从代码中设置用户,因为我可以清楚地手动设置用户。因此,我认为这更像是一个编程问题,而不是一个系统管理员问题,并将其发布在这里。关于安装服务,似乎还有比SF更多的问题——我想这并不意味着什么。如果你像我一样是个傻瓜,那么你在
wmiparms[6]
行中给出的帐户名与你的服务名匹配其实很重要。如果你像我一样是个傻瓜,实际上,您在
wmiparms[6]
行中提供的帐户名称必须与您的服务名称匹配,这一点非常重要。