安装服务时,有一个名为ServiceProcessInstaller
的有用.NET类。此类有一个属性Account
,它是一个ServiceAccount
枚举,可能包含LocalService,LocalSystem,NetworkService和User。
这在安装时很好,但是有人知道如何为现有服务更改此值吗?
我假设我需要远离实际的安装类型,并且一直在研究如何挂钩advapi32 ChangeServiceConfig方法,WMI和ManagementObjects等。
确实,我找到的代码实际上会改变服务运行的帐户,
ManagementObject mo = new ManagementObject("Win32_Service.Name='" + myService + "'");
object[] configParams = new object[11];
configParams[6] = userName;
configParams[7] = password;
object result = mo.InvokeMethod("Change", configParams);
(它本身看起来有点像黑魔法但在使用ChangeServiceConfig签名查看时有意义)
但是,当我将此代码应用于恰好安装为LocalSystem的服务时,它没有任何效果(尽管当我解释result
时,呼叫报告成功)。这并不让我感到惊讶,因为我只设置用户名和密码,我不是说“而不是作为本地服务运行,这项服务需要在特定的用户帐户下运行”。
现在,我的直觉是我正沿着正确的方向前进。问题是ChangeServiceConfig中的所有参数似乎都没有提供这样做的机会。
有什么想法吗? TIA,Pete
答案 0 :(得分:1)
错误代码16表示“Service marked for deletion”。有时,当您更改服务参数时,尤其是在删除/重新创建服务时,您需要重新启动PC才能完成操作。虽然它仍处于未决状态,但您无法操纵服务,并且会收到错误代码16。
此外,可能不是这样,您的问题与调用在dll中的事实有关。如果你把代码放在一个测试工具dll中并从测试工具exe中调用它(就像你在测试工具exe中测试它一样)并且不在中间创建/删除服务我认为它无论如何都会工作。
我认为它在您的应用程序中不起作用的原因与您之前使用该服务所做的事情有关(这很可能在您的问题中没有描述)。
答案 1 :(得分:1)
您需要模拟一个线程在用户的上下文中运行
试试这堂课:
A small C# Class for impersonating a User
或者这一个:
Impersonate User
答案 2 :(得分:0)
返回代码为21:"无效参数"。
我遇到了同样的问题:尝试将新用户/密码应用于当前具有" LocalSystem"的服务时出现问题。使用"允许服务与桌面交互"启用。
要解决此问题,请设置" DesktopInteract"标志在"变化"查询
var query = new ManagementPath(string.Format("Win32_Service.Name='{0}'", serviceName)); // string.Format("SELECT * FROM Win32_Service where Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(query))
{
object[] wmiParams = new object[10];
//WMI update doesn't work if the service's user is currently set to LocalSystem
// with Interact with desktop on
wmiParams[5] = false;
wmiParams[6] = serviceUserName;
wmiParams[7] = password;
//update credentials for the service
var rtn = service.InvokeMethod("Change", wmiParams);
}