Управление удаленной службой с использованием альтернативных учетных данных

- Исходное сообщение -

Я пытаюсь управлять (запускать / останавливать) службу Windows на удаленном компьютере, используя альтернативные учетные данные. Я знаю, что могу использовать класс ServiceController для управления службой, используя мои текущие учетные данные:

Dim sc As New ServiceController(ServiceName, ComputerName)

но я хочу использовать другие учетные данные. Другие классы, которые я использую (DirectoryEntry и System.Management), поддерживают использование альтернативных учетных данных ... Помощь будет принята с благодарностью.

- Рабочий код (основан на принятом ответе) -

Я должен признать, что скептически относился к этому, но ниже приведен код. Мне пришлось внести небольшие изменения в предложенный вами код. Всякий раз, когда я пробовал IPC $, он возвращал код результата 53, хотя я уверен, что общий ресурс существует. Поэтому по предложению другого веб-сайта я удалил общий ресурс и только имя компьютера, и это сработало.

Imports System.Runtime.InteropServices
Imports System.Net
Imports System.IO
Imports System.ServiceProcess

Module Module1

    Sub Main()
        Dim Computername As String = "SomeComputer"
        'Create connection to remote computer'
        Using nc As New NetworkConnection("\\" + Computername, New NetworkCredential("Domain\User", "Password"))
            Dim sc As New ServiceController("Windows Firewall/Internet Connection Sharing (ICS)", Computername)
            'now we can start/stop/whatever we want here'
        End Using
        Console.ReadLine()
    End Sub

    Public Class NetworkConnection
        Implements IDisposable


        Private _networkName As String

        Public Sub New(ByVal networkName As String, ByVal credentials As NetworkCredential)
            _networkName = networkName

            Dim netResource = New NetResource() With { _
             .Scope = ResourceScope.GlobalNetwork, _
             .ResourceType = ResourceType.Disk, _
             .DisplayType = ResourceDisplaytype.Share, _
             .RemoteName = networkName _
            }

            Dim result = WNetAddConnection2(netResource, credentials.Password, credentials.UserName, 0)

            If result <> 0 Then
                Throw New IOException("Error connecting to remote share", result)
            End If
        End Sub

        Protected Overrides Sub Finalize()
            Try
                Dispose(False)
            Finally
                MyBase.Finalize()
            End Try
        End Sub

        Public Sub Dispose() Implements System.IDisposable.Dispose
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub

        Protected Sub Dispose(ByVal disposing As Boolean)
            WNetCancelConnection2(_networkName, 0, True)
        End Sub

        <DllImport("mpr.dll")> _
        Private Shared Function WNetAddConnection2(ByVal netResource As NetResource, ByVal password As String, ByVal username As String, ByVal flags As Integer) As Integer
        End Function

        <DllImport("mpr.dll")> _
        Private Shared Function WNetCancelConnection2(ByVal name As String, ByVal flags As Integer, ByVal force As Boolean) As Integer
        End Function
    End Class

    <StructLayout(LayoutKind.Sequential)> _
    Public Class NetResource
        Public Scope As ResourceScope
        Public ResourceType As ResourceType
        Public DisplayType As ResourceDisplaytype
        Public Usage As Integer
        Public LocalName As String
        Public RemoteName As String
        Public Comment As String
        Public Provider As String
    End Class

    Public Enum ResourceScope As Integer
        Connected = 1
        GlobalNetwork
        Remembered
        Recent
        Context
    End Enum

    Public Enum ResourceType As Integer
        Any = 0
        Disk = 1
        Print = 2
        Reserved = 8
    End Enum

    Public Enum ResourceDisplaytype As Integer
        Generic = &H0
        Domain = &H1
        Server = &H2
        Share = &H3
        File = &H4
        Group = &H5
        Network = &H6
        Root = &H7
        Shareadmin = &H8
        Directory = &H9
        Tree = &HA
        Ndscontainer = &HB
    End Enum
End Module

person Peter    schedule 19.07.2010    source источник


Ответы (1)


Для удаленного входа в систему следует использовать WNetAddConnection2 (см. http://msdn.microsoft.com/en-us/library/aa385413.aspx) или NetUseAdd (см. http://msdn.microsoft.com/en-us/library/aa370645.aspx) API. Вы можете использовать \\RemoteComputer\IPC$ в качестве целевого ресурса.

ОБНОВЛЕНО на основе вопроса из комментария: объяснение сеансов IPC $ может быть длинным. Только основная информация.

Если вы хотите что-то сделать на удаленном компьютере, первое, что будет сделано, - это установить аутентифицированное «соединение» с удаленным компьютером. Будет выполнен сетевой вход (удаленный вход) на удаленном компьютере, который работает совсем иначе, чем локальный вход. Сеанс входа в сеть остается неизменным, и если у вас есть соединение, например, с \\RemoteComputer\share1 и еще одна программа на вашем компьютере, попробуйте получить доступ, например, \\RemoteComputer\share2, будет использоваться тот же сеанс.

Вы можете смоделировать ситуацию с помощью net.exe. Просто запустите cmd.exe и введите

net use \\RemoteComputer\IPC$ /u:Domain\User password

or

net use \\RemoteComputer\IPC$ /u:RemoteComputer\LocalRemoteUser password

тогда у вас будет соединение с конечным компьютером. Затем вы можете ввести \\RemoteComputer\AnyShare в проводнике и получить доступ к файловой системе с учетными данными пользователя Domain\User или RemoteComputer\LocalRemoteUser. Чтобы отключить использование

net use \\RemoteComputer\IPC /d

Если вы попытаетесь запустить / остановить службу на удаленном компьютере, будет предпринята попытка установить тот же сеанс IPC. Если у вас уже есть такой сеанс с одним из учетных данных пользователя, он будет использован. Функции WNetAddConnection2, NetUseAdd могут использоваться как замена "net use". Если вы постоянно хотите получить доступ к удаленному компьютеру с учетными данными другого пользователя, вы можете использовать CredWrite, CredWriteDomainCredentials или CredUIPromptForCredentials / CredUIPromptForWindowsCredentials. Cred-функция мне кажется не лучшим вариантом для вашего случая.

person Oleg    schedule 28.07.2010
comment
Можете ли вы предоставить лучший пример / дополнительную информацию? Например: как мне использовать один из этих API, чтобы остановить, а затем запустить службу на удаленном компьютере с именем xyz? - person Peter; 28.07.2010
comment
Спасибо за помощь. Я разместил свой код в своем вопросе, так как ваш код не включал. - person Peter; 29.07.2010