Retrieving the actual user account that started a process - c#

I am trying to retrieve the user account under which a process has been started. So far i have not found any answers that retrieve the good information. All of them return the string of the username which is not the account. I have tried WMI and Diagnostic all with the same results which are half correct.
Let's say i start notepad twice.
First one i open it with the account : \MyDomain\Franck
Second on i open it with the account : \MyComputer\Franck
Then use either WMI or Diagnostics and both return username "Franck" and i have not way to know if it's running under the local user or the domain one.
One way could be to use Diagnostics
var procs = Process.GetProcessesByName("Notepad").ToList();
var notepad1 = procs[0].StartInfo.Environment["Username"];
var notepad2 = procs[1].StartInfo.Environment["Username"];
Both return Franck but one is the domain account and the other is the local.

tasklist /v gives the relevant info that you are interested in, i.e., the user name with the domain name.
The official documentation does not show any sample outputs.
tasklist
Displays a list of currently running processes on the local computer or on a remote computer.
/v Displays verbose task information in the output.
You can use it together with /fo csv option to get the result and parse it.
This answer from SuperUser has screen shots showing the output.
You can run this command as a separate process from your application similar to this, but passing the other parameters.

If you want the name of the domain that contains the user's account, then you're looking for UserDomain Environment Variable
If you want which domain controller authenticated the client's logon request, then you're looking for LogonServer Environment Variable
var procs = Process.GetProcessesByName("Notepad").
var userDomain = procs[0].StartInfo.Environment["UserDomain"];
var logonServer = procs[0].StartInfo.Environment["LogonServer"];
Values on my windows machine (local user):
userDomain: "LAPTOP-DDK137L8"
logonServer: "\\LAPTOP-DDK137L8"
So from this you should be able to determine if it's running under the local user or the domain one.

Related

NT AUTHORITY\Local Service is not listed in the Access Control List of a directory

I'm having this issue where I'm trying to check if NT\Authority Local Service has read\execute permissions on a directory (folder). The product that I work on REQUIRES that the folder the user is installing to has read\execute permissions set for Local Service.
The problem is that when I get the Access Control List (ACL) recursively (groups-within-groups), Local Service is not listed so I can't check if he has permissions to that folder or not.
By default, Local Service does not have read/execute permissions to user profiles (My Documents, Desktop, etc...) but I won't know if Local Service has access to other directories the user chooses to install to.
NOTE: Local Service DOES have access to Program Files, even though it is NOT listed in the ACL. Is it hidden somewhere else?
This is a short snippet on how I'm pulling the ACL:
GroupPrincipal groupPrincipal =
GroupPrincipal.FindByIdentity(principalContext, identityReferenceValue);
// GetMembers(true) is recursive (groups-within-groups)
foreach (var member in groupPrincipal.GetMembers(true)) {
if (member.SamAccountName.Equals("LOCAL SERVICE")) {
foundLocalService = true;
break;
}
}
Is there any other way I should be doing this? (Other than adding an access rule for Local Service on that directory)
Is Local Service just not listed in Directories ACL's?
Any help would be greatly appreciated.
It's notoriously difficult to calculate "effective permissions" for an account. But the simple answer to your question is that you will likely want to look for either on of:
The local Users group, sometimes shown as BUILTIN\Users or COMPUTERNAME\Users, or
Authenticated Users, sometimes shown as NT AUTHORITY\Authenticated Users.
Authenticated Users is one of the well-know SIDs. It is "a group that includes all users whose identities were authenticated when they logged on.". As long as you can prove who you are, you are included in Authenticated Users. The SID for this is always S-1-5-11 on every Windows computer.
However, it's not really considered a real group. To find it when adding permissions to a folder, you have to have "Built-in security principals" selected under "Select this object type":
The local Users group contains Authenticated Users by default. On my computer, I actually see both Users and Authenticated Users in the default permissions on the file system.
That's what you will most likely see, and that's likely all that matters.
But that's not the only way. You could see Everyone (S-1-1-0), which includes every user, authenticated or not.
Or, it could be a file or folder that has the LOCAL SERVICE account as the owner.
Or, there could be a local group that was created manually and LOCAL SERVICE was added to.
One way to get a more authoritative list of what you can look for is to run this under the LOCAL SERVICE account:
whoami /groups
That will tell you every group in the authentication token, which is every group that you are considered a member of for authentication purposes.
But you can't just open a command prompt as LOCAL SERVICE. So one way to do this is to open the Task Scheduler and create a task that runs under LOCAL SERVICE, with the action of:
Program: cmd
Arguments: /c "whoami /groups > C:\temp\localservice.txt"
Then run the task and, when it's done, look at C:\temp\localservice.txt. It will have a table of group names and their SIDs that you can look for.

How to use %username% variable in Active Directory user paths using C#?

I developed an Active Directory user management tool in C# that does some things automatically. This is better for my particular case than the "Active Directory Users and Computers" tool from Microsoft. I have to use roaming profiles and home directories which contain the username of a user.
Now I want to change the username of a user with my program in C#. Everything works fine, but I want to use the "%username%" variable instead of putting the new username directly into these paths (home directory and roaming profile), because, by using the variable, I ensure that the new username will be placed into these paths if I copy the user object using Microsoft's AD management tool (right click --> "copy").
If I enter "%username%" when creating or editing a user with Microsoft's AD tool, this variable gets replaced by the username, so it works. But if I put this variable into a path using C#, it just puts the string "%username%" at the end of the path (e.g. "\fileserver1\UserHomes\%username%"). It doesn't replace it with the actual username and "stores" that placeholder.
How can I use this variable within my C# code properly, so that it get's replaced with the actual username?
I'm using this code (reduced, it's just an example) to change the users username (SamAccountName) and, for example, the home directory. "user" is my UserPrincipal object. Of course, I'm renaming the actual folder after this:
[...]
string newUsername = "NewUsername"; // New username
user.SamAccountName = newUsername;
user.UserPrincipalName = $"{ newUsername }#{ domain }";
user.HomeDirectory = "\\fileserver1\UserHomes\%username%";
user.Save(); // Save changes
The %username% environment variable and the one used AD Users and Computers is not the same. AD Users and Computers replaces it with the actual username value immediately when you click OK. It is not something that AD understands, just a token used by the AD Users and Computers application.
Considering you already constructed a string using the username, you shouldn't find it hard to fix this.
user.HomeDirectory = $"\\fileserver1\UserHomes\{newUsername}";
Also powershell would probably be more appropriate for something like this.
see Renaming a User Account Does Not Automatically Change the Profile Path

Get current windows user first name when the app is executed through network

I have an app (C#, .NET4.5) placed on a remote computer, accessed and executed via local network. Let's call the computer where the app is placed "AppPC" and the computer that is exeuting the app "UserPC".
I want to achieve the same I would get with this, which is the first name (not username) of the current Windows User:
System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName;
This code works just fine when the app is located on the same UserPC, but it throws an exception if the app is located on AppPC. More precisely is a System.DirectoryServices.Protocols.LdapException: "Can't establish connection. "
I can find the name of UserPC using this:
PrincipalContext ctx = new PrincipalContext(ContextType.Machine,null);
string pcName = ctx.ConnectedServer;
But from there, I do not know how to get the current user name.
I have tried getting all the UserPrincipal in ctx through a loop over a PrincipalSearcher.FindAll() but this only shows two users "Administrator" and "Guest" which is false, at least on UserPC. Maybe AppPC has that users, I'm not sure.
With System.Environment.UserName I can get the username but not the first name, which is what I'm interested in.
EDIT: Forgot to say that I have already checked this and doesn't work also (null):
How do I get the current username in .NET using C#?

Correct way to find Users/<name> directory in C#

I have tried a lot of solutions but I am unable to get the desired result. I am privy to the fact that one can use Environment.SpecialFolder enumeration. I have already tried them all but in vain. I am writing a service that needs to access this folder in C#>
C:\Users\Shahbaaz\efb
Working on Win 7, .Net 4, VS13
UPDATE:
MY problem is that I can't programmatically access C:\Users\Shahbaaz.Shahbaaz is the name of the logged in account. The efb folder was used for illustration only. Sorry about that. I had used UserProfile enum but ended up with C:\SYSTEM directory. CommonDocuments et al give me the C:\Users\Public... directories. Also, if I just use Environment.Username, it gives me SYSTEM instead of the logged in username. Hope this helps!
I think I know what's going on. Wrote a small test:
[Test]
public void PrintAllSpecialFolders()
{
var values = Enum.GetValues(typeof(Environment.SpecialFolder));
Console.WriteLine("Printing special folder paths:");
foreach (Environment.SpecialFolder value in values)
{
Console.WriteLine("{0}: {1}", value, Environment.GetFolderPath(value, Environment.SpecialFolderOption.None));
}
}
That clearly shows the expected result (Windows 7):
...
UserProfile: C:\Users\<myusername>
...
But: You're using a service (which your tag indicates) and you're probably running the service under the LocalSystem account. The local system account doesn't have an user folder in the expected place. Either run your service under your user account or accept the given path as profile folder for the LocalSystem account. Do not try to access your user account from LocalSystem. You'll probably get a permission error.

How to get "primary" user of a remote computer

I need to know how to get the name and domain of the primary user of a computer, remotely. I define the primary user preferably as the user logged on most times, or longest time over a period. Alternatively, if this is impossible, as the user currently/last logged on.
Currently, i scan an Active Directoy for all computer objects in an OU. I then loop though them, and try to get the name of the user using WMI.
I look in Win32_ComputerSystem to see if UserName returns a value. If this is not the case, i look in Win32_LogonSession and get the username for all LogonTypes that equal 2 or 10. If this returns none, or multiple values, i discard the result and look in Win32_Process for all non-system processes and define the primary user as the user with most processes running.
There are several problems with my approach:
Win32_ComputerSystem - UserName is often null.
Win32_LogonSession often return multiple or no values. There can be only 1 primary user.
Looking in Win32_Process is kinda ridiculous, since this will only return me the user with most processes, most likely not the primary user.
If no user is currently logged on, looking in Win32_Process returns no value and none of the 3 steps might return a value.
My 3 approaches might get me the current user. Does anyone know of a way to get the primary user? Or at least a better way to get the current. Not necessarily using WMI.
Thanks
If you have administrator privileges on the remote computer and sharing access
you can use Computer Management and select to
connect to other computer and see what users and groups are on that computer.
Or you can use TS Remote Administration or Remote Desktop if the remote computer has that capability.
Use psexec.exe (www.sysinternals.com) to run commands on a remote pc:
psexec \\pc1 net user | find /i "Steve"
psexec \\pc1 c:\tool\psloggedon | find /i "Steve"
1) Find if John Black has an account on PC1.
2) Find if he is currently logged on.
Use psloggedon.exe that uis is another SysInternals tool.
Check this also: http://www.wisesoft.co.uk/scripts/vbscript_display_username_of_user_on_a_remote_computer.aspx
Also if you want to find the User Name of the currently logged user on a remote computer using the remote computer IP then Go to the command line an type nbtstat -A <IP of remote computer> This will return all of the NetBIOS names registered on the computer, one of which is the username.

Categories