Stop asking “What Computer are You On”! Instead use Active Directory and Group Policy to search for you! In this post, we are going to set Active Directory to automatically record where users login. And when a user calls, Active Directory Users and Computers will let us instantly remote into their computer and will find out what computer a user logged into. In short, you will be able to click on any computer in your domain and see the current logged in user. All within Active Directory Users and Computers!
Delegate Control in Active Directory
Every computer in your domain has an attribute named “Managed By”. This attribute allows you to manually specify who manages (or uses) this computer. As a note, this ManagedBy attribute is different than the new Primary Computer Attribute. In order for us to see what user used a computer, we need to delegate a single extra Active Directory permission.
Within Active Directory Users and Computers, right click on the OU (or OUs) containing your domain computers. Next, select Properties, then the Security Tab, and finally the Advanced button. Select Add. We are going to apply this permission to Domain Users. For the Applies To button, select Descendant Computer objects.
Scroll down the properties list until you come to Read Managed By and Write Managed By. Check both of these options and hit OK three times. Domain Users can now write to the ManagedBy attribute for the computers in the OUs that you selected.
Tracking User Logins with Group Policy
Create a new GPO named something like Script: Set ManagedBy Attribute. Edit the GPO and navigate to User Configuration\Policies\Windows Settings\Scripts. Now, you have a choice to make. Our script is going to look at the current logged in user and write that User’s name to the computer account. This can be done on logon or logoff. Here are the pros and cons:
Logon: The computer attribute will always have the current logged in user because it processes on logon. It will make the logon slightly slower. If your users constantly change computers, this would probably be the better route.
Logoff: The computer attribute may not always be accurate. Because it writes on logoff, you will only be able to see the last logged on user (not the current user). If your environment is very static, this would be the solution to go with. As a bonus, your logon speed is not impacted.
For our environment, we went with the logon route. It is more important to see the current logged in user. Now that you’ve decided, copy this script into either the logon or logoff scripts folder for that GPO. Save it with a .VBS extension.
Set objSysInfo = CreateObject("ADSystemInfo") On Error Resume Next Set objComputer = GetObject("LDAP://" & objSysInfo.ComputerName) objComputer.Put "managedBy", objSysInfo.Username objComputer.SetInfo
Add the script as a logon or logoff script in the GPO now. Finish any other GPO edits that you desire (such as comments). Be sure to link the GPO to an OU containing your Users. After logging on as a user to any computer, you can easily test the GPO. Find the computer that the user used, open its properties, and select the Managed By tab. You should see something like this:
Pretty cool but it gets better! Open up the AD search tool and search for that computer. You should see something like this:
If you don’t see the owner column, select view and choose columns to add the owner column. In part 2, learn how to automatically remote into a user’s computer through Active Directory Tasks!
Finally, if you want to learn more about Active Directory Management and how it will make your life easier, then subscribe to DeployHappiness and get great weekly tips (plus your free guide to the Windows 8 Administrative Start Menu)!
Special Thanks to Pber for putting together the VB script for me!
Is there anyway to then clear the managed by field as a logoff script so it shows when a user is not logged onto a PC on AD?
Maybe this is out of date…but I am having trouble getting started. When i right click on the OU i want to use, there is no security tab!
using Server 2012 R2…is that the issue? if so whats the updated way to do this?
Make sure that you have advanced features turned on in Active Directory Users and Computers: https://deployhappiness.com/3-changes-to-active-directory-users-and-computers/
@ Joseph Moody – First thank you for the valuable post. I have brought this to the attention of our Manager to possibly add this feature to AD, but my Manager had a question that i did not know the answer to so i thought i would ask you or anyone who may know the answer.
What if a single user was simultaneously logged into multiple computers at the same time? Would AD list all the computer names of every pc the the end user was logged into? If not, do you think this is possible? Thank you in advance.
AD would show each computer that the user was logged into.
@ Joseph Moody. Quick question – Just to clarify, after this is implemented, how would this scenario play out at a call center/help-desk environment….
User calls for assistance, analyst needs computer name to add to the case, yet he only knows the users name. So he opens his AD search tool, and this is where i’m stuck. Does search under Users, Contacts, and Groups, or does the analyst search under Computers and then in the Owner search box enter the users first and last name? Sorry if it is a dumb question but before i present to management i need to clarify exactly how AD will locate the computer name from only the users name. Thanks for the quick response for my 1st question a while back!!!
Sorry for the delay in getting back with you! He would search for computer objects and would look at the managed by attribute
Thank you for the response Joseph. Sorry for just getting back with you but its been really hectic lately. So i’m finally going to be presenting this tomorrow to leadership. Hopefully they will implement it!!! Thank you for everything!!!
Jon
Awesome news! Let me know how it ends.
I am not able to set write managed by Even i select when i put ok 3 times and come bacjk and see the check box it is un checked .
Am I missing something? The article starts “Stop asking “What Computer are You On”!.”
So, after adding the user to the Owner attribute I find the computer name by searching for the computer name?
That was just a screenshot showing the Owner attribute in AD. You can search by the owner attribute if you want. See the second part for a powershell script that does that: https://deployhappiness.com/find-the-last-user-logged-on-to-a-computer-and-automatically-remote-in/
This script works a treat, thanks!
Is there a way I can limit the script from writing to citrix servers? For example, every time a user logs on to citrix, this information will be written to the citrix servers which is not ideal. I can use the delegation and deny policy from applying to domain admins so that it doesn’t write this information to other servers. I can deny the policy from applying for citrix users group but this would mean that if anyone in citrix users group logs on to a workstation, this information won’t be populated in AD. Since this is a user policy, excluding citrix servers from the scope wouldn’t work either 🙁
Any ideas how to best achieve this? Thanks.
You could do this two ways.
1. Use Loopback policy processing to apply this GPO to every computer OU but your citrix servers. Here is a guide on loopback: https://deployhappiness.com/loopback-policy-how-a-computer-gets-a-transgender-operation/
2. Modify the script to check the machine type (if it is a server or if the machine name equals some value). Exit the script if it matches.
Hi Joseph,
I like the idea of checking the machine type. Could you please explain how the script can be modified to check for machine name equals some value?
Many thanks.
As an update, I have implemented loop back policy and this works beautifully now 🙂
Once again thanks for this wonderful script.
Awesome! Glad you got it working!
Joseph
Thank you very much as it workd perfect. Only question I have is how to refine the objsysinfo.username to just the display name ? I have been searching and testing for days with no luck.
Thank you
Joe
I’m glad it worked so great! Check out http://technet.microsoft.com/en-us/magazine/2007.08.heyscriptingguy.aspx . It will show you the attributes to change.
Joseph we have tried those and we get an error that the result is nul even if we display the results as we are walking through the script. We have gone this far with no luck
Set objSysInfo = CreateObject(“ADSystemInfo”)
On Error Resume Next
Set objComputer = GetObject(“LDAP://” & objSysInfo.ComputerName)
wrkSysInfo = objSysInfo.Username
x = Split(wrkSysInfo,”,”)
wrkUserName = mid(x(0),4)
objComputer.Put “managedBy”, wrkUserName
objComputer.SetInfo
In my case it does not work. Managed By attribute stays empty. (Windows Server 2008 R2 domain/forest functional level, client machine Windows 8.1)
Hey, we have Server 2008 R2 domain controllers as well and this example seems to be for 2012. I was never able to set or set the Read/Write Managed by for descendant computer objects because in 2008 it isn’t there. Do you know what the equivalent object permission is named for 2008?
Thanks
It should be there for 2008 R2. Do you have advanced view enabled in Active Directory users and computer?
Yes we do have advanced view enabled but the permissions and the object names should have nothing to do with the view in AD. We go to properties and then advanced and select descendant computer objects and there is no permission name of read managed by and write managed by, it just isn’t there at all.
Use the contact button in the top right of this page and email me some screenshots. I set this up on a 2008 R2 domain.
need to select the “properties” tab not the “object” tab in the “Permissions entry for ou”
For a bit of variety try these:
Set objSysInfo = CreateObject(“ADSystemInfo”)
WScript.echo “1 = ” & objSysInfo.UserName
Set wshShell = CreateObject(“WScript.Shell”)
strUserName = wshShell.ExpandEnvironmentStrings( “%USERNAME%” )
WScript.Echo “2 = ” & strUserName
Set objUser = GetObject(“LDAP://” & objSysInfo.UserName)
arrUserLogon = Split(objUser.userPrincipalName, “@”)
WScript.Echo “3 = ” & objUser.userPrincipalName
WScript.Echo “4 = ” & arrUserLogon(0)
arrUserOU = Split(Replace(Replace(Replace(objUser.AdsPath, “CN=”, “”), “OU=”, “”), “LDAP://”, “”), “,”)
WScript.Echo “5 = ” & arrUserOU(0)
I like it Ken! Thanks for sharing!
Actually those don’t work too well. Something to do with exactly what you can and cannot use in the vbscript.
But, to make up for it I’m working on a PowerShell script to read it all back. Not quite done but what is there works pretty well so far. I’m trying to work out the final glitches. The script can be found here: http://kcmjr.blogspot.com/2014/04/how-to-use-powershell-to-find-what.html
That is quite the script that you have there!!
I want to implement this great idea, but getting Line 3 Character 43 expected ‘)’ ??
Set objComputer = GetObject(“LDAP://” & objSysInfo.ComputerName)
What am I missing, do I need to add something to above line.
Try copying the script directly again and pasting it into notepad. Then rename the file to scriptname.vbs
Sometimes, that “&” symbol messes up on the blog.
Thanks Joseph, it worked this time 🙂
Wonderful! Codes on webpages can appear very strange. Today, I posted a script showing how to install office 2013. I had a :DeployOffice Line in the script. The webpage changed the 😀 to a smile emoticon.
This is probably simple to most guys reading this but I managed to fix an issue with a similar task. I was using the method described in this article: http://.4sysops.com/archives/automatically-fill-the-computer-description-field-in-active-directory/ .it writes the username, serial and model to the computer description field in AD.
I came across an issue with HP Pro 3405, 3505 and HP 500B desktops (worked for my 6300 and all laptop series out of the box), where the script would not report the serial number. It updated the computer object description field with username and model just fine so i knew the script was executing correctly with correct permissions to the computer objects.
I tested on the local machine using wmi queries: “wmi bios get serialnumber” which worked. i then used “wmi systemenclosure get serialnumber” ( i spotted the system enclosure reference after analysing the vb.
when I changed For Each objSMBIOS in objWMI.ExecQuery(“Select * from Win32_systemenclosure”)
serviceTag = replace(objSMBIOS.SerialNumber, “,”, “.”)
manufacturer = replace(objSMBIOS.Manufacturer, “,”, “.”)
to
For Each objSMBIOS in objWMI.ExecQuery(“Select * from Win32_BIOS”)
it began to work, but also wrote ‘AMI’, (my BIOS manufacturer), into the AD description field! I then removed the manufacturer line, and ” ” & manufacturer & ” ” from later in the script.
It now works brilliantly and saves me time updating AD. Thanks to Geoff Kendall for the original script Joseph Moody for deployhappiness and the original idea for this kind of project after stumbling onto the site and troubleshooting assistance.
Good troubleshooting Sam! Thank you for letting us know about this issue and how you fixed it!
You can get the serial from several locations. I use the unattend install with a powershell script to run from setup complete and have encountered numerous issues with serial numbers. Just a suggestion
# Change “bad” serial number to empty string
function FixSerialNumber([string]$SerialNumber)
{
$serial = $SerialNumber
if($serial -ne [String]::Empty)
{
if($serial.ToLower() -eq ‘none’ -or $serial.ToLower() -eq ‘not available’)
{
$serial = [String]::Empty
}
# also
if($serial.ToLower() -eq ‘to be filled by o.e.m.’)
{
$serail = [String]::Empty
}
}
return $serial
}
# Get serial number
function Get-SerialNumber
{
[string]$serialNumber = (get-wmiobject Win32_SystemEnclosure -EnableAllPrivileges).serialnumber
$serialNumber = FixSerialNumber($serialNumber)
if($serialNumber -eq [String]::Empty)
{
$serialNumber = (get-wmiobject Win32_ComputerSystemProduct -EnableAllPrivileges).IdentifyingNumber
}
$serialNumber = FixSerialNumber($serialNumber)
if($serialNumber -eq [String]::Empty)
{
$serialNumber = (get-wmiobject Win32_Bios -EnableAllPrivileges).serialnumber
}
$serialNumber = FixSerialNumber($serialNumber)
return $serialNumber
}
That is a good suggestion! Thanks for sharing your code!
Thank you!
The script editor I used in this post messed up the formatting. I have corrected it now. Just copy the edited script. Let me know if you have any problems.
Great idea. Excuse the noob Question, Do I need add a LDAP query specific for my domain as Im getting Line 3 Character 43 expected ‘)’ ??
eg GetObject(“LDAP://DC=mydomain,DC=local”
Thanks a bunch this really helps.
I get that sometimes when trying to display a script on a blog when handling the & sign.
Example:
Set objComputer = GetObject(“LDAP://” & objSysInfo.ComputerName)
Should be correctly displayed as
Set objComputer = GetObject(“LDAP://” & objSysInfo.ComputerName)
Hi Samuel – thank you for clarifying that & symbol problem!