2009-08-26 10 views
14

次のコードを使用しています。C#を使用してリモートコンピュータで実行されるサービスのステータスを確認します

ServiceController MyController = new ServiceController(); 
MyController.MachineName = server_txt.Text.Trim(); 
MyController.ServiceName = "Service1"; 

string msg = MyController.Status.ToString(); 
Label1.Text = msg; 

このコードは、アクセスできるネットワークコンピュータでうまく機能します。これを変更して、資格情報を使用して異なるドメインのシステムで動作するようにするにはどうすればよいですか?同様のアプローチを試みている誰かに、

+0

おそらくWMI –

答えて

0

Here's a link彼らの発見は、プログラムを実行しているマシン上のログインと一致するリモートマシン上のログインが必要であるということです。

+0

でそうしようとすると、リンクのみの回答は推奨されません。そう。リンクされているコンテンツが移動/アーカイブされた場合、リンクが壊れているとは限りません。コンテンツを要約してここに投稿する必要があります。 – vapcguy

11

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 } 

} 
+0

それは確かに動作します。 OPによって投稿されたコードスニペットと概念的にどのように違うのですか?また、この方法でサービスを開始または停止することはできますか? –

+2

@ViralJain ServiceControllerクラスの代わりにWMIを使用します。 ServiceControllerクラスにはuserオプションがありません。そしてafaikを使用して偽装を使用する唯一の方法です。はい、WMIで開始/停止/一時停止などが可能です。 codeprojectには良い例があります:http://www.codeproject.com/Articles/28161/Using-WMI-to-manipulate-services-Install-Uninstall – user797717

3

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()からdoImpersonation()はすでに分割部分を受け入れながら、あなたはそれを持っている場合getWic()は、domain\userまたはmachinename\userのように見えると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

関連する問題