.net 安装Windows服务以作为虚拟用户运行
我有一个安装.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
- 将服务设置为作为系统运行(
)李>serviceProcessInstaller1.Account=ServiceAccount.LocalSystem
- 通过指定
和用户名
属性,或让安装过程提示我,将服务设置为以普通用户身份运行(密码
)serviceProcessInstaller1.Account=ServiceAccount.user
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]
行中提供的帐户名称必须与您的服务名称匹配,这一点非常重要。