使用C#检查在远程计算机上运行的服务的状态

我正在使用下面的代码。

ServiceController MyController = new ServiceController(); MyController.MachineName = server_txt.Text.Trim(); MyController.ServiceName = "Service1"; string msg = MyController.Status.ToString(); Label1.Text = msg; 

此代码适用于有权访问的networking计算机。 如何改变这个,使它适用于使用凭证的不同域中的系统?

如果您使用WMI,则可以在“ConnectionOptions”中设置凭据。

 ConnectionOptions op = new ConnectionOptions(); op.Username = "Domain\\Domainuser"; op.Password = "password"; ManagementScope scope = new ManagementScope(@"\\servername.Domain\root\cimv2", op); scope.Connect(); ManagementPath path = new ManagementPath("Win32_Service"); ManagementClass services; services = new ManagementClass(scope, path, null); foreach (ManagementObject service in services.GetInstances()) { if (service.GetPropertyValue("State").ToString().ToLower().Equals("running")) { // Do something } } 

MSDN是你的朋友。

 using System.ServiceProcess; ServiceController sc = new ServiceController("YourService", "MachineName"); if (sc.Status.Equals(ServiceControllerStatus.Stopped) || sc.Status.Equals(ServiceControllerStatus.StopPending) { // it is stopped } 

我知道,如果你在那台机器上拥有管理员权限,只需要上面的代码。 但是,如另一条评论所述,如果您正在运行的帐户在该计算机上没有管理员权限,则可能必须使用模拟进行设置,如下所示:

 string userName = "domain\\user"; // there's really just one slash, //but you have to escape it if hard-coding.. //if brought in by a text box, it would be just domain\user string password = "whatever"; WindowsImpersonationContext adminContext = Impersonation.getWic(userName, password); if (adminContext != null) { try { ServiceController sc = new ServiceController("YourService", "MachineName"); if (sc.Status.Equals(ServiceControllerStatus.Stopped) || sc.Status.Equals(ServiceControllerStatus.StopPending) { // it is stopped } } catch (Exception ex) { Console.Out.WriteLine("\nUnable to set profile to Mandatory:\n\t" + ex.Message); Impersonation.endImpersonation(); adminContext.Undo(); } finally { Impersonation.endImpersonation(); // The above line just basically does this on the tokens -- //if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); adminContext.Undo(); } } 

这是我单独的模拟类。 它有2个主要的入口点, getWic()doImpersonation()getWic()将采取一个用户名,看起来像domain\usermachinename\user并把它们分成他们的组成部分,然后交给doImpersonation()doImpersonation()接受已经分割的部分,如果你有这样的,并不需要getWic()的代码。 两者都返回一个WindowsImpersonationContext

 using System; using System.Data; using System.Configuration; using System.Security.Permissions; using System.Security.Principal; using System.Runtime.InteropServices; [assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)] [assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")] public class Impersonation { [DllImport("advapi32.dll", EntryPoint = "LogonUser")] public static extern bool LogonUser( string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle); // Declare the Logon Types as constants const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_LOGON_NETWORK = 3; const int LOGON32_LOGON_BATCH = 4; const int LOGON32_LOGON_SERVICE = 5; const int LOGON32_LOGON_UNLOCK = 7; const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8; // Win2K or higher const int LOGON32_LOGON_NEW_CREDENTIALS = 9; // Win2K or higher // Declare the Logon Providers as constants const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_PROVIDER_WINNT50 = 3; const int LOGON32_PROVIDER_WINNT40 = 2; const int LOGON32_PROVIDER_WINNT35 = 1; // Declare the Impersonation Levels as constants const int SecurityAnonymous = 0; const int SecurityIdentification = 1; const int SecurityImpersonation = 2; const int SecurityDelegation = 3; private static WindowsIdentity newId; private static IntPtr tokenHandle = new IntPtr(0); private static IntPtr dupeTokenHandle = new IntPtr(0); [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] public static WindowsImpersonationContext doImpersonation(string svcUserName, string domainName, string password) { // Initialize tokens tokenHandle = IntPtr.Zero; dupeTokenHandle = IntPtr.Zero; // Call LogonUser to obtain a handle to an access token bool returnValue = LogonUser(svcUserName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_WINNT50, ref tokenHandle); if (returnValue == false) { int ret = Marshal.GetLastWin32Error(); //Check for errors if (ret != NO_ERROR) throw new Exception("LogonUser failed with error code : " + GetError(ret)); } bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle); if (retVal == false) { CloseHandle(tokenHandle); throw new Exception("Exception thrown in trying to duplicate token."); } else { // Begin Impersonation bool bRetVal = DuplicateToken(tokenHandle, (int)SecurityImpersonation, ref dupeTokenHandle); newId = new WindowsIdentity(dupeTokenHandle); WindowsImpersonationContext impersonatedUser = newId.Impersonate(); return impersonatedUser; } } public static void endImpersonation() { if (dupeTokenHandle != IntPtr.Zero) CloseHandle(dupeTokenHandle); if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle); } public static WindowsImpersonationContext getWic(string userNameStringFromTextbox, string password) { try { // Establish impersonation string svcUser = userNameStringFromTextbox; string[] arrUser = new string[2]; arrUser = svcUser.Split('\\'); string domain = arrUser[0]; string svcUserName = arrUser[1]; // Get Password: Convert from Base-64 String to decrypted string //string keyLength = ConfigurationManager.AppSettings["keyLength"].ToString(); //string keyLocation = ConfigurationManager.AppSettings["keyLocation"].ToString(); //password = RSAEncrypt.DecryptData(password, keyLength, keyLocation); WindowsImpersonationContext wic = doImpersonation(svcUserName, domain, password); return wic; } catch (Exception ex) { ErrorLog.ErrorRoutine(new Exception("getWic() Error: " + ex.ToString()), ErrorMessage.NOTIFY_APP_ERROR); return null; } } #region Errors const int NO_ERROR = 0; const int ERROR_ACCESS_DENIED = 5; const int ERROR_ALREADY_ASSIGNED = 85; const int ERROR_BAD_DEVICE = 1200; const int ERROR_BAD_NET_NAME = 67; const int ERROR_BAD_PROVIDER = 1204; const int ERROR_CANCELLED = 1223; const int ERROR_EXTENDED_ERROR = 1208; const int ERROR_INVALID_ADDRESS = 487; const int ERROR_INVALID_PARAMETER = 87; const int ERROR_INVALID_PASSWORD = 1216; const int ERROR_MORE_DATA = 234; const int ERROR_NO_MORE_ITEMS = 259; const int ERROR_NO_NET_OR_BAD_PATH = 1203; const int ERROR_NO_NETWORK = 1222; const int ERROR_SESSION_CREDENTIAL_CONFLICT = 1219; const int ERROR_BAD_PROFILE = 1206; const int ERROR_CANNOT_OPEN_PROFILE = 1205; const int ERROR_DEVICE_IN_USE = 2404; const int ERROR_NOT_CONNECTED = 2250; const int ERROR_OPEN_FILES = 2401; private struct ErrorClass { public int num; public string message; public ErrorClass(int num, string message) { this.num = num; this.message = message; } } private static ErrorClass[] ERROR_LIST = new ErrorClass[] { new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"), new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"), new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"), new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"), new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"), new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"), new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"), new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"), new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"), new ErrorClass(ERROR_MORE_DATA, "Error: More Data"), new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"), new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"), new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"), new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"), new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"), new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"), new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"), new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"), new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"), new ErrorClass(ERROR_SESSION_CREDENTIAL_CONFLICT, "Error: Credential Conflict"), }; private static string GetError(int errNum) { foreach (ErrorClass er in ERROR_LIST) { if (er.num == errNum) return er.message; } return "Error: Unknown, " + errNum; } #endregion } 

参考文献:
ServiceController类。 https://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller(v=vs.110).aspx
WindowsIdentity.Impersonate方法。 https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx

这是一个尝试类似方法的人的链接 ; 他们的发现是他们需要在运行程序的机器上登录的远程机器上登录。