Управление удаленным сервисом с использованием альтернативных учетных данных - PullRequest
1 голос
/ 19 июля 2010

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

Я пытаюсь управлять (запускать / останавливать) службой 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

1 Ответ

2 голосов
/ 28 июля 2010

Для удаленного входа в систему следует использовать 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

или

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

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

net use \\RemoteComputer\IPC /d

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

...