Перечислять членов группы пользователей Windows на удаленной системе, используя c #

В c # мне нужно уметь

  • Подключитесь к удаленной системе, указав имя пользователя / пароль в зависимости от ситуации
  • Список членов локальной группы в этой системе
  • Получить результаты обратно на исполняющий компьютер

Так, например, я бы подключился к \ SOMESYSTEM с соответствующими кредитами и получил список локальных администраторов, включая SOMESYSTEM \ Administrator, SOMESYSTEM \ Bob, DOMAIN \ AlanH, "DOMAIN \ Domain Administrators".

Я пробовал это с system.directoryservices.accountmanagement, но у меня проблемы с аутентификацией. Иногда я получаю:

Несколько подключений к серверу или общему ресурсу одним и тем же пользователем, используя более одного имени пользователя, не допускаются. Отключите все предыдущие подключения к серверу или общему ресурсу и повторите попытку. (Исключение из HRESULT: 0x800704C3)

Вышесказанное пытается, потому что будут ситуации, когда я просто не могу разархивировать существующие диски или соединения UNC.

В других случаях моя программа получает UNKNOWN ERROR, и журнал безопасности на удаленной системе сообщает об ошибке 675, код 0x19, который является KDC_ERR_PREAUTH_REQUIRED.

Мне нужен более простой и менее подверженный ошибкам способ сделать это!

22.08.2008 00:29:05
есть ли у вас решение по этому поводу? На самом деле, когда вы вызываете GroupDirectoryentry.Invoke («Участники»), он не освобождает соединение с событием удаленного компьютера, если мы располагаем объект GroupDirectoryentry. Та же проблема возникает при вызове UserDirectoryentry.Invoke («Группы»).
sagar 10.01.2013 06:35:21
5 ОТВЕТОВ
РЕШЕНИЕ

Это должно быть легко сделать с помощью WMI. Здесь у вас есть указатель на некоторые документы:

Документация WMI для Win32_UserAccount

Даже если у вас нет опыта работы с WMI, вам будет довольно легко превратить этот код VB Script внизу страницы в некоторый код .NET.

Надеюсь, это помогло!

1
22.08.2008 00:57:21

Вы должны быть в состоянии сделать это с System.DirectoryServices.DirectoryEntry. Если у вас возникли проблемы с его удаленным запуском, возможно, вы могли бы установить что-то на удаленных компьютерах, чтобы предоставить вам свои данные с помощью какого-либо RPC, например удаленного взаимодействия или веб-службы. Но я думаю, что то, что вы пытаетесь сделать, должно быть возможным удаленно, не слишком прихотливо.

0
22.08.2008 00:43:13

Если Windows не позволит вам подключиться через механизм входа в систему, я думаю, что ваш единственный вариант - запустить что-то на удаленной машине с открытым портом (либо напрямую, либо через удаленное взаимодействие, либо через веб-службу, как уже упоминалось).

0
22.08.2008 00:55:35

Я бы порекомендовал использовать функцию Win32 API NetLocalGroupGetMembers . Это гораздо проще, чем пытаться понять сумасшедший синтаксис LDAP, который необходим для некоторых других решений, рекомендуемых здесь. Пока вы олицетворяете пользователя, которого хотите запустить проверку, вызывая «LoginUser», вы не должны сталкиваться с какими-либо проблемами безопасности.

Вы можете найти пример кода для подражания здесь .

Если вам нужна помощь в выяснении того, как вызывать «NetLocalGroupGetMembers» из C #, я рекомендую вам обратиться к помощнику PInvoke Джареда Парсона, который можно загрузить из codeplex.

Если вы выполняете код в приложении ASP.NET, работающем в IIS, и хотите выдать себя за пользователя, обращающегося к веб-сайту, для совершения вызова, то вам может потребоваться предоставить разрешение «Доверенные для делегирования» производственному веб-серверу.

Если вы работаете на рабочем столе, то использование учетных данных активного пользователя не должно быть проблемой.

Возможно, ваш сетевой администратор мог отозвать доступ к «Защищаемому объекту» для конкретной машины, к которой вы пытаетесь получить доступ. К сожалению, этот доступ необходим для работы всех функций API управления сетью . Если это так, то вам нужно будет предоставить доступ к «Защищаемому объекту» тем пользователям, которых вы хотите выполнить. Однако с настройками безопасности Windows по умолчанию все аутентифицированные пользователи должны иметь доступ.

Надеюсь, это поможет.

-Скотт

1
22.08.2008 01:36:33

Давидг был на правильном пути, и я доверяю ему ответ.

Но необходимый WMI-запрос был немного меньше простого, так как мне нужен был не просто список пользователей для всей машины, а подмножество пользователей и групп , локальных или доменных, которые были членами локальной группы администраторов. Для записи, этот запрос WMI был:

SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = "Win32_Group.Domain='thehostname',Name='thegroupname'"

Вот полный фрагмент кода:

public string GroupMembers(string targethost, string groupname, string targetusername, string targetpassword)
        {
            StringBuilder result = new StringBuilder(); 
            try
            {
                ConnectionOptions Conn = new ConnectionOptions();
                if (targethost != Environment.MachineName) //WMI errors if creds given for localhost
                {
                    Conn.Username = targetusername; //can be null
                    Conn.Password = targetpassword; //can be null
                }
                Conn.Timeout = TimeSpan.FromSeconds(2);
                ManagementScope scope = new ManagementScope("\\\\" + targethost + "\\root\\cimv2", Conn);
                scope.Connect();
                StringBuilder qs = new StringBuilder();
                qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='");
                qs.Append(targethost);
                qs.Append("',Name='");
                qs.Append(groupname);
                qs.AppendLine("'\"");
                ObjectQuery query = new ObjectQuery(qs.ToString());
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                ManagementObjectCollection queryCollection = searcher.Get();
                foreach (ManagementObject m in queryCollection)
                {
                    ManagementPath path = new ManagementPath(m["PartComponent"].ToString());                                        
                    { 
                        String[] names = path.RelativePath.Split(',');
                        result.Append(names[0].Substring(names[0].IndexOf("=") + 1).Replace("\"", " ").Trim() + "\\"); 
                        result.AppendLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace("\"", " ").Trim());                    
                    }
                }
                return result.ToString();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error. Message: " + e.Message);
                return "fail";
            }
        }

Итак, если я вызову членов группы («Server1», «Administrators», «myusername», «mypassword»); Я получаю одну строку, возвращенную с:

SERVER1 \ Администратор MYDOMAIN \ Администраторы
домена

Фактическое возвращение WMI больше похоже на это:

\\ server1 \ корень \ cimv2: Win32_UserAccount.Domain = "SERVER1", Name = "Администратор"

... так что, как вы можете видеть, мне пришлось сделать небольшую манипуляцию строк, чтобы украсить его.

2
23.08.2008 08:23:05
Примечание для пользователей: вам нужно добавить System.Management.dll в ваш проект, чтобы использовать приведенный выше код.
Ram 15.01.2013 07:07:59