RSAT: Remote Server Administration Tools for Windows 10

The last standalone package for Remote Server Administration Tools was released for Windows 10 Version 1803 & the same was integrated into Windows 10 as optional packages with later versions of Windows.

There are many detailed installation instructions floating over dozens of tech blogs and sites, explaining how to enable/install RSAT on Windows 10. Today we will go through a quick how to without breaking much sweat & details.

As a Windows Domain Administrator, I need the following features at times:

  1. Active Directory Users and Computers
  2. DNS Manager

For the rest, usually I use the remote desktop connection to domain controllers.

Please note, with each version of Windows 10, there might be minor changes with the way software is installed. Hence, make sure that you double check your version of Windows 10 before attempting the below instructions. These instructions are valid for Windows 10, Version 2004 with September 2020 cumulative updates.

Open Add or remove programs (Modern App management console)

Click on “Optional Features”

Click on “Add Feature” that will open up a list of available optional features. Remote Server Administration Tools or RSAT could be filtered by entering RSAT in the search area.

As I needed only “Active Directory users and computers” and “DNS Server” components, I chose them. You might need more components to be available to carry out your server administration. Choose everything that applies to your requirements & Press the “Install” button.

That’s all. Now you can access the features those were installed based on your selection from the start menu or by searching for them in the taskbar search box.



C# (CSharp, C-Sharp) Windows Active Directory last logon

Hi guys

Please note, many threads were referred in order to compile the script attached below & all I did was re-arranging in order for better reading/formatting

(And I insure that the script works under following scenarios:

  1. You are a domain administrator
  2. You are administrating Windows 2003 onwards Windows domain
  3. Your puter is connected to the domain network ;)


Referenced websites/threads

  3. (for formatting the C# code)

How to test the code

Start Visual Studio (I am using 2013 Professional edition, you can use any of the community editions to test the scripts)

Create a new C# Console Application and name it llogon (else you need to change the namespace name “llogon” according to the name you have chosen for your new project.

Add the following references to your project

  1. “Framework -> System.DirectoryServices”
  2. “Browse and add -> C:\Windows\System32\activeds.tlb”


[code language=”csharp” gutter=”false”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Added by Rajesh

//using System.Management;
//using System.Data;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
//ActiveDS namespace
using ActiveDs; // Namespace added via ref to C:\Windows\System32\activeds.tlb

namespace llogon
class Program
static void Main(string[] args)
// Get the root entry
DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
string configurationNamingContext =
string defaultNamingContext =
Dictionary<string, Int64> lastLogons = new Dictionary<string, Int64>();
// Get all the domain controllers
DirectoryEntry deConfig = new DirectoryEntry("LDAP://" + configurationNamingContext);
DirectorySearcher dsConfig = new DirectorySearcher(deConfig);
dsConfig.Filter = "(objectClass=nTDSDSA)";
foreach (SearchResult srDomains in dsConfig.FindAll())
DirectoryEntry deDomain = srDomains.GetDirectoryEntry();
if (deDomain != null)
string dnsHostName =
// Get all the users for that domain
DirectoryEntry deUsers =
new DirectoryEntry("LDAP://" + dnsHostName + "/" + defaultNamingContext);
DirectorySearcher dsUsers = new DirectorySearcher(deUsers);
dsUsers.Filter = "(&(objectCategory=person)(objectClass=user))";
foreach (SearchResult srUsers in dsUsers.FindAll())
DirectoryEntry deUser = srUsers.GetDirectoryEntry();
if (deUser != null)
// Get the distinguishedName and lastLogon for each user
// Save the most recent logon for each user in a Dictionary object
string distinguishedName = deUser.Properties["distinguishedName"].Value.ToString();
Int64 lastLogonThisServer = new Int64();
if (deUser.Properties["lastLogon"].Value != null)
IADsLargeInteger lgInt =
lastLogonThisServer = ((long)lgInt.HighPart << 32) + lgInt.LowPart;

// Save the most recent logon for each user in a Dictionary object
if (lastLogons.ContainsKey(distinguishedName))
if (lastLogons[distinguishedName] < lastLogonThisServer)
lastLogons[distinguishedName] = lastLogonThisServer;
lastLogons.Add(distinguishedName, lastLogonThisServer);
string readableLastLogon = DateTime.FromFileTime(lastLogonThisServer).ToString();
Console.WriteLine("User: " + distinguishedName + "Last logon: " +readableLastLogon);



Try the code & if you are stuck somewhere, do let me through the comments. I am working on a WPF C# project for a simple Active Directory Reporter / Asset Management System using WMI. Stay tuned & I will soon post the entire solution here :)




VB.Net | Active Directory | Windows Form Application for listing users & details in a grid view

Have you read our previous post about finding last logon date time value for a domain member computer or user yet? If not, please read about it here

Now, we are going to provide you a decent (Warning: Amateurish code blocks possible) Windows forms based application that could list all your domain users and few of their details including last logon date time values.


Above image demonstrates the run time interface of the application. Application has a search textbox, that could accept values before and after the user details are populated.

Before the population, the users will be limited to matching string, after population, the list could be refined against the combination of keystrokes

Mandatory References as seen with the below image


You can download the solution from here



Oracle 10g | Get Windows User Details from Active Directory

Hello guys! 9th December 2014 : Minor update The following exercise will not materialize if you have a middleware sever, as the client information will not be available for your forms. Missed us? :) Recently we were challenged with a very interesting task, and that was to send emails to the requester of a particular activity once after the completion. Usually, we can look into the HR/Payroll enrollments and get the email address for the user without much troubles. Our case was different, our HR/Payroll records are not always up to date and we were forced to capture the Windows login name and get the email addresses straight away from the AD database! As usual, after hours of googling and trying out few scripts, We came up with a tailored script that fetches us the full Name and email address against value derived from

[code language=”sql”]
Select sys_context(‘userenv’,’os_user’) from dual;

query Here, we are sharing the scripts with you Complete credits go to the following few & many others (Our script is a complete rip-off from article)

[sourcecode language=”sql” gutter=”false” wraplines=”true”]
/* Formatted on 12/9/2014 2:56:10 PM (QP5 v5.163.1008.3004) */
   /*This block commented never worked for us
      — Adjust as necessary.
      —   l_ldap_host    VARCHAR2(256) := ‘’;
      —  l_ldap_port    VARCHAR2(256) := ‘389’;
      —  l_ldap_user    VARCHAR2(256) := ‘cn=orcladmin’;
      —  l_ldap_passwd  VARCHAR2(256) := ‘password’;
      —  l_ldap_base    VARCHAR2(256) := ‘cn=Users,dc=tshcomputing,dc=com’;
   –Active Directory Component Windows 2008 R2
   l_ldap_host     VARCHAR2 (256)
                      := ‘fully qualitifed name of your domain controller’; –eg (
   l_ldap_port     VARCHAR2 (256) := ‘389’;
   l_ldap_user     VARCHAR2 (256) := ‘fully qualified user name’; –eg: (make sure paul is a member of Administrators group)
   l_ldap_passwd   VARCHAR2 (256) := ‘password’; — clear text password for user
   l_ldap_base     VARCHAR2 (256) := ‘DC=xyz,DC=com’;
   — l_ldap_base     VARCHAR2 (256) := ‘OU=GEN Managers,DC=xyz,DC=com’; –Restrict the query to a particular OU within AD
   –AD 2008 R2
   l_retval        PLS_INTEGER;
   l_session       DBMS_LDAP.session;
   l_attrs         DBMS_LDAP.string_collection;
   l_message       DBMS_LDAP.MESSAGE;
   l_entry         DBMS_LDAP.MESSAGE;
   l_attr_name     VARCHAR2 (256);
   l_ber_element   DBMS_LDAP.ber_element;
   l_vals          DBMS_LDAP.string_collection;
   — Choose to raise exceptions.
   — Connect to the LDAP server.
   l_session := DBMS_LDAP.init (hostname => l_ldap_host, portnum => l_ldap_port);
   l_retval :=
      DBMS_LDAP.simple_bind_s (ld       => l_session,
                               dn       => l_ldap_user,
                               passwd   => l_ldap_passwd);
   — l_attrs(1) := ‘*’; — Get all attributes(Complete AD details will be read, use carefully)
   l_attrs (1) := ‘mail’;
   l_attrs (2) := ‘displayName’;
   –Common Attributes you can pass to the AD query
   —  l_attrs(1)  := ‘sAMAccountName’;
   —   l_attrs(2)  := ’employeeNumber’;
   —    l_attrs(3)  := ‘displayName’;
   —    l_attrs(4)  := ‘description’;
   —    l_attrs(5)  := ‘telephoneNumber’;
   —    l_attrs(6)  := ‘facsimileTelephoneNumber’;
   —   l_attrs(7)  := ‘department’;
   —   l_attrs(8)  := ‘company’;
   —    l_attrs(9)  := ’employeeID’;
   —   l_attrs(10) := ‘streetAddress’;
   —   l_attrs(11) := ‘mail’;
   —   l_attrs(12) := ‘c’;
   —  l_attrs(13) := ‘l’;
   —   l_attrs(14) := ‘postalCode’;
   — retrieve all attributes
   l_retval :=
      DBMS_LDAP.search_s (ld         => l_session,
                          base       => l_ldap_base,
                          scope      => DBMS_LDAP.SCOPE_SUBTREE,
                          —          filter   => ‘objectclass=*’, –All the objects will be read
                          filter     => ‘sAMAccountName=paul’, –Record for User with windows login account as &quot;Paul&quot; will be fetched
                          attrs      => l_attrs,
                          attronly   => 0,
                          res        => l_message);
   IF DBMS_LDAP.count_entries (ld => l_session, msg => l_message) > 0
      — Get all the entries returned by our search.
      l_entry := DBMS_LDAP.first_entry (ld => l_session, msg => l_message);
      WHILE l_entry IS NOT NULL
         — Get all the attributes for this entry.
         DBMS_OUTPUT.PUT_LINE (‘—————————————‘);
         l_attr_name :=
            DBMS_LDAP.first_attribute (ld          => l_session,
                                       ldapentry   => l_entry,
                                       ber_elem    => l_ber_element);
         WHILE l_attr_name IS NOT NULL
            — Get all the values for this attribute.
            l_vals :=
               DBMS_LDAP.get_values (ld          => l_session,
                                     ldapentry   => l_entry,
                                     attr        => l_attr_name);
            FOR i IN l_vals.FIRST .. l_vals.LAST
               DBMS_OUTPUT.PUT_LINE (
                     ‘ATTIBUTE_NAME: ‘
                  || l_attr_name
                  || ‘ = ‘
                  || SUBSTR (l_vals (i), 1, 200));
            END LOOP values_loop;
            l_attr_name :=
               DBMS_LDAP.next_attribute (ld          => l_session,
                                         ldapentry   => l_entry,
                                         ber_elem    => l_ber_element);
         END LOOP attibutes_loop;
         l_entry := DBMS_LDAP.next_entry (ld => l_session, msg => l_entry);
      END LOOP entry_loop;
   END IF;
   — Disconnect from the LDAP server.
   l_retval := DBMS_LDAP.unbind_s (ld => l_session);
   DBMS_OUTPUT.PUT_LINE (‘L_RETVAL: ‘ || l_retval);

Try it & let us know the experiences! regards,