Статус службы С# на удаленной машине

Я опытный программист, поэтому понятия не имею, ЧТО я делаю :)

На серьезной ноте; нет, я ни в коем случае не эксперт. Но у меня есть проблема, и я не знаю, как ее решить. Хорошо, что я (думаю, я) знаю, в чем проблема, и я надеюсь, что кто-то здесь может помочь.

Вот краткое содержание проблемы. Я создаю форму на С#, которая будет выполнять для меня некоторые задачи по администрированию сервера и базы данных. У меня есть кнопка, которая при нажатии должна возвращать статус службы службы «x» на сервере «y». Статус печатается на экране в текстовом поле.

Вот мой код:

     private void button2_Click(object sender, EventArgs e)
    {
        string fs = "Service X Status = ";
        string mr = "Service A Status = ";
        string qp = "Service B Status = ";
        string sp = "Spooler Service Status = ";
        ServiceController fssc = new ServiceController("xService", "yServer");
        ServiceController mrsc = new ServiceController("aService", "yServer");
        ServiceController qpsc = new ServiceController("bService", "yServer");
        ServiceController spsc = new ServiceController("Spooler", "yServer");

        try
        {
            txtGtwySts.AppendText(sp + spsc.Status.ToString());
            txtGtwySts.AppendText(Environment.NewLine);
            txtGtwySts.AppendText(fs + fssc.Status.ToString());
            txtGtwySts.AppendText(Environment.NewLine);
            txtGtwySts.AppendText(mr + mrsc.Status.ToString());
            txtGtwySts.AppendText(Environment.NewLine);
            txtGtwySts.AppendText(qp + qpsc.Status.ToString());
        }
        catch (Exception crap)
        {
            string msg = "";
            int i;
            for (i = 0; i < crap.Message.Count(); i++)
            {
                msg += "Error # " + i + " Message: " + crap.Message + "\n";

            }
            MessageBox.Show(msg);
            MessageBox.Show(i.ToString());
        }
    }

Я получаю исключения, в основном говоря: «Не удается открыть «Сервис» на «Сервере». Поскольку это удаленный сервер, я предполагаю, что это проблема учетных данных/безопасности. У меня НЕТ, однако, никаких проблем со службой Spooler.

У меня вопрос... Как я могу передать идентификатор пользователя и пароль на этот сервер, чтобы он аутентифицировался или запускался, чтобы я мог проверить статус этих служб, вот в чем проблема. Если кто-то не думает, что это проблема, то, пожалуйста, сообщите мне, где я ошибся :)


person Jason    schedule 28.07.2011    source источник
comment
Хорошо, я нашел, как это сделать, но я не совсем понимаю, как кодировать. Из того, что я прочитал, мне нужно обернуть то, что я хочу сделать выше, в некоторый код, который олицетворяет идентификатор пользователя, а затем, после получения запрошенной информации, отменяет олицетворение. Я понимаю, что жесткое кодирование информации о пользователе — не самый безопасный способ сделать это, но этого будет достаточно для того, для чего это будет использоваться. Я буду продолжать исследовать, как олицетворять в C#.   -  person Jason    schedule 02.08.2011


Ответы (1)


Наконец-то разобрался...

Создал новый класс и показан ниже:

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Security.Permissions;

public class ImpersonateUser
{
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
    String lpszUsername,
    String lpszDomain,
    String lpszPassword,
    int dwLogonType,
    int dwLogonProvider,
    ref IntPtr phToken);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public extern static bool CloseHandle(IntPtr handle);
    private static IntPtr tokenHandle = new IntPtr(0);
    private static WindowsImpersonationContext impersonatedUser;
    // If you incorporate this code into a DLL, be sure to demand that it
    // runs with FullTrust.
    [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
    public void Impersonate(string domainName, string userName, string password)
    {
        //try
        {
            // Use the unmanaged LogonUser function to get the user token for
            // the specified user, domain, and password.
            const int LOGON32_PROVIDER_DEFAULT = 0;
            // Passing this parameter causes LogonUser to create a primary token.
            const int LOGON32_LOGON_INTERACTIVE = 2;
            tokenHandle = IntPtr.Zero;
            // ---- Step - 1
            // Call LogonUser to obtain a handle to an access token.
            bool returnValue = LogonUser(
            userName,
            domainName,
            password,
            LOGON32_LOGON_INTERACTIVE,
            LOGON32_PROVIDER_DEFAULT,
            ref tokenHandle); // tokenHandle - new security token
            if (false == returnValue)
            {
                int ret = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(ret);
            }
            // ---- Step - 2
            WindowsIdentity newId = new WindowsIdentity(tokenHandle);
            // ---- Step - 3
            {
                impersonatedUser = newId.Impersonate();
            }
        }
    }
    // Stops impersonation
    public void Undo()
    {
        impersonatedUser.Undo();
        // Free the tokens.
        if (tokenHandle != IntPtr.Zero)
        {
            CloseHandle(tokenHandle);
        }            
    }        
}    

}

и исходный код, который я разместил, обернут:

ImpersonateUser iu = new ImpersonateUser();
iu.Impersonate("[domain]","[username]","[password]");
// code you want to execute as impersonated user.....
iu.Undo();
person Jason    schedule 02.08.2011
comment
Это работает только в средах, где все подключено к контроллеру домена? - person Brad Gagne; 11.09.2012
comment
Это будет работать между доменами, только если между ними установлено доверие. - person Igor Malin; 14.09.2016