Как получить информацию Active Directory удаленно с помощью С#?C#

Место общения программистов C#
Ответить
Anonymous
 Как получить информацию Active Directory удаленно с помощью С#?

Сообщение Anonymous »

Я пытаюсь получить информацию Active Directory, такую ​​как статус репликации AD и другие типы информации. На данный момент я просто концентрируюсь на статусе репликации AD. Я использовал этот код для удаленного входа в компьютер.
// P/Invoke for LogonUser
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword,
int dwLogonType, int dwLogonProvider, out IntPtr phToken);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[DllImport("kernel32.dll")]
public static extern int GetLastError();

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int FormatMessage(uint dwFlags,IntPtr lpSource,uint dwMessageId,uint dwLanguageId,StringBuilder lpBuffer,uint nSize,IntPtr Arguments);

private const uint FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
private const uint FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
private const uint FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
IntPtr tokenHandle;

public ADClass()
{
IntPtr tokenHandle = IntPtr.Zero;
_logonSuccess = LogonUser(user, domain, pass, 9, 3, out tokenHandle);
}

public void DomainControllerStatus(string machinenames)
{
try
{
if(_logonSuccess)
{
using (WindowsIdentity identity = new WindowsIdentity(tokenHandle))
{
// Now, you're running under the context of the impersonated user.
WindowsIdentity.RunImpersonated(identity.AccessToken, () =>
{
try
{
// Approach 1:
string repadminPath = $@"\\{machine}\C$\Windows\System32\repadmin.exe";

ProcessStartInfo processInfo = new ProcessStartInfo(repadminPath, "/replsummary")
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

Process process = Process.Start(processInfo);
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

Console.WriteLine($"Status: {output}"); // Output is always ""

// Approach 2:
Domain domain = Domain.GetCurrentDomain(); // Comes out with this message: System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException: Current security context is not
// associated with an Active Directory domain or forest.

// Loop through each domain controller in the domain
foreach (DomainController dc in domain.DomainControllers)
{
StringBuilder output = new StringBuilder();
Console.WriteLine($"Checking replication for Domain Controller: {dc.Name}");

_IsConnected = true;

// Get replication neighbors (replication partners)
foreach (ReplicationNeighbor neighbor in dc.GetAllReplicationNeighbors())
{
output.Append($"Neighbor: {neighbor.SourceServer};");
output.Append($"Last Attempt: {neighbor.LastAttemptedSync};");
output.Append($"Last Success: {neighbor.LastSuccessfulSync};");
output.Append($"Consecutive Failure Count: {neighbor.ConsecutiveFailureCount};");

Console.WriteLine($"AD Replication => {output.ToString()}");
}
}

// Approach 3:
//string ldapPath = $"LDAP://DC={domain},DC=com"; // Adjust the domain accordingly
string ldapPath = $"LDAP://{domain}"; // Adjust the domain accordingly

using (DirectoryEntry entry = new DirectoryEntry(ldapPath, user, pass))
{
// Ensure we can connect and authenticate
Console.WriteLine("Authenticated with LDAP: " + entry.Name); // Comes out with this message: System.Runtime.InteropServices.COMException (0x8007203A): The server is not operational.

// Create a DirectorySearcher to query the domain
DirectorySearcher searcher = new DirectorySearcher(entry)
{
Filter = "(objectClass=domain)"
};

SearchResult result = searcher.FindOne();

if (result != null)
{
Console.WriteLine("Domain found: " + result.Path);
}
else
{
Console.WriteLine("Domain not found or no results.");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception Error Message: {ex}");
}
}
}
}
else
{
int errorCode = Marshal.GetLastWin32Error();
string errorMessage = GetErrorMessage(errorCode);
Console.WriteLine($"LogonUser failed with error code: {errorCode}; Message: {errorMessage}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception Error Message: {ex}");
}
}

static string GetErrorMessage(int errorCode)
{
StringBuilder messageBuffer = new StringBuilder(512);
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,IntPtr.Zero,(uint)errorCode,0,messageBuffer,(uint)messageBuffer.Capacity,IntPtr.Zero);

return messageBuffer.ToString();
}

(Ошибки, которые я получаю, можно найти в каждом подходе в виде комментариев)
С помощью этого кода я могу войти в систему на компьютер удаленно, однако, когда дело доходит до получения информации о контроллере домена, например о состоянии репликации AD, я ничего не получаю из выходных данных. Как я могу решить эту проблему и какие ошибки я допустил в функции/подходе?
Обновление подхода 3
Когда я изменил эту часть кода
string username = $"{domain}\\{user}";

using (DirectoryEntry entry = new DirectoryEntry(ldapPath, username, pass))

Я получаю следующую ошибку:
System.Runtime.InteropServices.COMException: 'The specified domain either does not exist or could not be contacted.'


Подробнее здесь: https://stackoverflow.com/questions/790 ... ly-using-c
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»