使用 WMI 操作服务(安装、卸载、启动、暂停等)
仅使用 WMI 即可对服务执行所有可用的操作。
引言
最近,我被要求组装一个类,用于处理许多 Windows 服务操作。 在 Google 上花费了数小时寻找帮助后,我得到的只是一些非常复杂的 API,仅仅是编写它们的声明就如此繁琐,以至于我立即放弃了该解决方案。
另一种解决方案是使用 Visual Studio 安装和部署向导(非常浪费),或者使用 InstallUtil(.NET Framework 附带),或者使用 sc.exe(这很好,但仍然是外部的)。
最后,我决定使用 WMI,它是 Windows Management Instrumentation 的缩写。 这些类提供对许多 Windows 管理设备的访问,包括服务。 唯一的缺点是它主要为 VBScript 设计,因此我必须进行一些更改才能使其适应此处。
一般信息
WMI 包括一个名为 Win32_Service
的类(有关此类的更多信息可以在这里找到:MSDN)。 在我的类中,我必须将其用于两个对象:服务管理器和服务本身。 服务管理器的使用主要用于安装服务(因为我们需要在其中创建一个新服务); 在那之后(当服务安装完成后),我将使用服务本身。
第一部分:安装服务
假设你遇到了和我一样的问题——你有一个 exe 文件(它是服务),并且你想安装它。 你的选择是
- 创建一个安装项目(Visual Studio)——我认为这太多了。
- 使用 InstallUtil.exe – 外部程序。
- 使用 sc.exe – 比 InstallUtil 更好(至少我是这么认为的),但同样 – 外部程序。
所以这里是另一种更好的方法,使用 WMI
public static ReturnValue InstallService(string svcName, string svcDispName,
string svcPath, ServiceType svcType,
OnError errHandle, StartMode svcStartMode,
bool interactWithDesktop, string svcStartName, string svcPassword,
string loadOrderGroup, string[] loadOrderGroupDependencies,
string[] svcDependencies)
{
ManagementClass mc = new ManagementClass("Win32_Service");
ManagementBaseObject inParams = mc.GetMethodParameters("create");
inParams["Name"] = svcName;
inParams["DisplayName"] = svcDispName;
inParams["PathName"] = svcPath;
inParams["ServiceType"] = svcType;
inParams["ErrorControl"] = errHandle;
inParams["StartMode"] = svcStartMode.ToString();
inParams["DesktopInteract"] = interactWithDesktop;
inParams["StartName"] = svcStartName;
inParams["StartPassword"] = svcPassword;
inParams["LoadOrderGroup"] = loadOrderGroup;
inParams["LoadOrderGroupDependencies"] = loadOrderGroupDependencies;
inParams["ServiceDependencies"] = svcDependencies;
try
{
ManagementBaseObject outParams = mc.InvokeMethod("create", inParams, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{ throw ex; }
}
在这里,我们使用 Win32_Service
将一个新服务添加到服务管理器中。(所有枚举都在代码中声明,我不想让这篇文章太臃肿。)
第二部分:对服务执行所有其他操作
所以,是的,我们只在想要安装新服务(或遍历所有服务)时才使用服务管理器,但是现在,我们希望对我们的服务进行各种操作。 在这里,我们将使用这一行代码,它最终将为我们提供对服务的控制权
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{…}
...
在这里,“service”保存了我们服务的实例,现在,我们所要做的就是调用此实例上的方法(您可以在上面的 URL 中找到所有方法)。
public static ReturnValue UninstallService(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
ManagementBaseObject outParams = service.InvokeMethod("delete", null, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{
if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
return ReturnValue.ServiceNotFound;
else
throw ex;
}
}
}
public static ReturnValue StartService(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
ManagementBaseObject outParams = service.InvokeMethod("StartService",
null, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{
if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
return ReturnValue.ServiceNotFound;
else
throw ex;
}
}
}
public static ReturnValue StopService(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
ManagementBaseObject outParams = service.InvokeMethod("StopService",
null, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{
if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
return ReturnValue.ServiceNotFound;
else
throw ex;
}
}
}
public static ReturnValue ResumeService(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
ManagementBaseObject outParams = service.InvokeMethod("ResumeService",
null, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{
if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
return ReturnValue.ServiceNotFound;
else
throw ex;
}
}
}
public static ReturnValue PauseService(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
ManagementBaseObject outParams = service.InvokeMethod("PauseService",
null, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{
if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
return ReturnValue.ServiceNotFound;
else
throw ex;
}
}
}
public static ReturnValue ChangeStartMode(string svcName, StartMode startMode)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
ManagementBaseObject inParams = service.GetMethodParameters("ChangeStartMode");
inParams["StartMode"] = startMode.ToString();
try
{
ManagementBaseObject outParams = service.InvokeMethod("ChangeStartMode",
inParams, null);
return (ReturnValue)Enum.Parse(typeof(ReturnValue),
outParams["ReturnValue"].ToString());
}
catch (Exception ex)
{ throw ex; }
}
}
public static bool IsServiceInstalled(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
ManagementBaseObject outParams = service.InvokeMethod("InterrogateService",
null, null);
return true;
}
catch (Exception ex)
{
if (ex.Message.ToLower().Trim() == "not found" || ex.GetHashCode() == 41149443)
return false;
else
throw ex;
}
}
}
public static ServiceState GetServiceState(string svcName)
{
ServiceState toReturn = ServiceState.Stopped;
string _state = string.Empty;
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
_state = service.Properties["State"].Value.ToString().Trim();
switch (_state)
{
case "Running":
toReturn = ServiceState.Running;
break;
case "Stopped":
toReturn = ServiceState.Stopped;
break;
case "Paused":
toReturn = ServiceState.Paused;
break;
case "Start Pending":
toReturn = ServiceState.StartPending;
break;
case "Stop Pending":
toReturn = ServiceState.StopPending;
break;
case "Continue Pending":
toReturn = ServiceState.ContinuePending;
break;
case "Pause Pending":
toReturn = ServiceState.PausePending;
break;
}
}
catch (Exception ex)
{ throw ex; }
}
return toReturn;
}
public static bool CanStop(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
return bool.Parse(service.Properties["AcceptStop"].Value.ToString());
}
catch
{
return false;
}
}
}
public static bool CanPauseAndContinue(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
return bool.Parse(service.Properties["AcceptPause"].Value.ToString());
}
catch
{
return false;
}
}
}
public static int GetProcessId(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
return int.Parse(service.Properties["ProcessId"].Value.ToString());
}
catch
{
return 0;
}
}
}
public static string GetPath(string svcName)
{
string objPath = string.Format("Win32_Service.Name='{0}'", svcName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
try
{
return service.Properties["PathName"].Value.ToString();
}
catch
{
return string.Empty;
}
}
}
结论
嗯,这一切有点混乱,但如果你仔细观察 - 所有这些都非常相似的模板......只需获取对象,然后对其执行任何你想要的操作。
您可以使用以下方式找到许多对象的属性
foreach (PropertyData pd in service.Properties)
if (pd.Value!= null)
MessageBox.Show(pd.Name + " = " + pd.Value.ToString());
我希望这篇文章对你们很多人都有用。 我认为这是第一个使用 WMI 处理服务的迷你综合指南。
欢迎任何评论。 感谢您的阅读。