我有一个安装.NET Windows服务的ServiceProcessInstaller
。
如果我要么安装过程完美无缺:
serviceProcessInstaller1.Account = ServiceAccount.LocalSystem
)运行。 serviceProcessInstaller1.Account = ServiceAccount.User
和Username
属性或让安装过程提示我来将服务设置为以普通用户(Password
)运行。但是,我希望该服务以虚拟用户身份运行, a la NT Service\ServiceName
。如果查看某些SQL Server服务,您将看到它们默认以自己的虚拟用户帐户登录。 http://technet.microsoft.com/en-us/library/dd548356.aspx上有更多(尽管有限)的信息。
我已尝试设置serviceProcessInstaller1.Username = @"NT Service\ServiceName"
,但安装程序会抛出以下错误,无论我提供什么密码(我已尝试String.Empty
,与用户名相同,我自己的密码,{ {1}}调出交互式对话框,甚至是随机垃圾邮件:
帐户名和安全ID之间没有映射
但是,如果我正常安装服务(例如以SYSTEM身份运行),我可以从null
管理单元转到服务的属性,在登录页面上将用户更改为{{1它很漂亮。
我也调查了ChangeServiceConfig2
function,但我似乎无法改变它。
如何从我services.msc
中的代码中将用户登录设置为虚拟用户NT Service\ServiceName
?
答案 0 :(得分:3)
您无法直接使用ServiceProcessInstaller
对象执行此操作。但是,您可以使用the Change method in WMI在ServiceInstaller.Committed
事件中设置安装服务后的用户名。将用户名指定为wmiParams[6]
,将密码保留为:
void serviceInstaller1_Committed(object sender, InstallEventArgs e)
{
using (ManagementObject service = new ManagementObject(new ManagementPath("Win32_Service.Name='ServiceName'")))
{
object[] wmiParams = new object[11];
wmiParams[6] = @"NT Service\ServiceName";
service.InvokeMethod("Change", wmiParams);
}
}
最后,不要忘记为您的服务exe和配置文件授予用户读/写权限,否则您将收到Access Denied错误。
答案 1 :(得分:1)
上面建议的另一种解决方法(使用ServiceInstaller.Committed
事件)被描述为connect.microsoft.com的变通方法。我们的想法是通过反射来调整私有字段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);
}
即使是这种解决方案也不会少于黑客,至少它在视觉上不那么难看。
注意:connect.microsoft.com的变通方法说明中存在错误。这里提到的私人字段名称为hasLoginInfo
,但必须为haveLoginInfo
。