Get desktop path for all administrators in C# - c#

I need to create desktop shortcuts to my app for all administratos in the system.
I'm using the following code to get user list.
var identifier = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
GroupPrincipal group = GroupPrincipal.FindByIdentity(new PrincipalContext(ContextType.Machine), identifier.Value);
foreach (Principal principal in group.Members)
{
Console.WriteLine(principal.Name);
}
I need somehow to get desktop path for each user. Could you suggest me solution? Many thanks.

You'll want to pinvoke the SHGetFolderLocation function (http://msdn.microsoft.com/en-us/library/bb762180.aspx) which allows you to pass in an access token that represents the user you're interested in.
No idea how difficult that will be though.

There are a few options that you can go with, depending on how you want to do it.
Option A:
Hard coded, but it works for default system setups
var userDirectory = Path.Combine("C:\Users\", principal.Name, "\Desktop");
Option B:
Find for the current user, then swap it out
var currentUser = Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
var newUser = currentUser.Replace("MyUser", principal.Name);
Now, option B hasn't been fully tested, but should work!

Related

Dropbox API, How to see each team member's folder permissions?

I am new to using the Dropbox API and I want to access every team member's folder permissions and put it into a database, but I'm having trouble on where to find this information. I am able to access each member's folders and can see the name of every folder, but not the permissions of each folder that the user has. How can I do this?
Here is what I have so far:
public MainPage()
{
this.InitializeComponent();
var task = Task.Run((Func<Task>)MainPage.Run);
task.Wait();
}
static async Task Run()
{
using (DropboxTeamClient DBTeamClient = new DropboxTeamClient("MY ACCESS KEY"))
{
//get all the dropbox members
var members = await DBTeamClient.Team.MembersListAsync();
//loop through all members ordered by email alphabetical
foreach (var member in members.Members.OrderBy(a => a.Profile.Email))
{
//get each user
var userClient = DBTeamClient.AsMember(member.Profile.TeamMemberId);
//get each user's file information
var list = await userClient.Files.ListFolderAsync(string.Empty);
//loop through the list of file and show permissions on folders
foreach (var item in list.Entries.OrderBy(b => b.PathDisplay))
{
//only display folder information
if (item.IsFolder)
{
//find out the user's permissions to this folder here?
//then I will output user information and permissions to a db
}
}
}
}
}
Am I approaching this the wrong way? Any guidance is appreciated, thanks in advance!
Thanks to Greg's comment and post on Dropbox I was able to solve my problem. Here is his solution:
"When you list files and folders using FilesUserRoutes.ListFolderAsync like this, you're listing the contents of the member's Dropbox folder, which will include both shared folders (where they have some specific permission level) as well as their private folders (where they don't have a specific permission level, since it's just their folders). For shared folders, the returned FolderMetadata.SharingInfo will be set, but it doesn't contain information about that user's permission level in that folder. (By the way, make sure you implement ListFolderContinueAsync as well, to make sure you can retrieve all results, when using ListFolderAsync. Check out the ListFolderAsync documentation for more information.)
Instead, if you want to list the shared folders the user has access to, including their level of access in each one, you should use SharingUserRoutes.ListFoldersAsync. Likewise, make sure you implement SharingUserRoutes.ListFoldersContinueAsync too, as this interface is also paginated. Each returned SharedFolderMetadata will list the user's AccessType and Permissions.
Here's a little example:
var actionsToCheck = new Dropbox.Api.Sharing.FolderAction[] { Dropbox.Api.Sharing.FolderAction.EditContents.Instance, Dropbox.Api.Sharing.FolderAction.InviteEditor.Instance };
var list = await userClient.Sharing.ListFoldersAsync(actions: actionsToCheck); // actions can optionally be supplied to check the permissions the user has for specific actions
foreach (var item in list.Entries)
{
Console.WriteLine(item.SharedFolderId);
Console.WriteLine(item.PathLower); // only set if the folder is mounted
Console.WriteLine(item.AccessType);
Console.WriteLine(item.Permissions);
}
// and so on, iterating over pages from userClient.Sharing.ListFoldersContinueAsync if list.Cursor is set
Hope this helps!"
I hope others find this as useful as I did.

How to use Windows built-in Find user, contacts and groups tool in .Net

I intend to create a manifest of Windows users and I need to hand-pick them from the valid users on an unknown computer.
There are lots of different types of environments:
single computer with local users only
domain computer with local and domain users
domain computer with local users and users from the various domains of the forest
So I don't want to implement a custom solution to handle all the various types and also there is a built-in solution in Windows:
Unfortunately, I couldn't find any code to access the Find users… dialog, but I guess, in the last 20 years someone has created a NuGet for that so there must be some code to rely on.
Can you point me in the right direction?
This is called the Directory Object Picker dialog.
Someone made a package that wraps the native calls for .NET: Active-Directory-Object-Picker
You can install it from NuGet: Tulpep.ActiveDirectoryObjectPicker
There is example code on the GitHub page:
DirectoryObjectPickerDialog picker = new DirectoryObjectPickerDialog()
{
AllowedObjectTypes = ObjectTypes.Computers,
DefaultObjectTypes = ObjectTypes.Computers,
AllowedLocations = Locations.All,
DefaultLocations = Locations.JoinedDomain,
MultiSelect = true,
ShowAdvancedView = true
};
if (picker.ShowDialog() == DialogResult.OK)
{
foreach (var sel in picker.SelectedObjects)
{
Console.WriteLine(sel.Name);
}
}

Query for retrieving account associated with ServicePrincipleName(SPN)

We have an internal site which was built on C# and has various tools for various functions to help the company like looking up/modifying/adding service accounts, for example. The tools are just C# code to automate these tasks. /vague
I've been asked to find/create a way to enter an SPN and have it return the service account which it's associated to.
So something like:
Input: HTTP/server1.company.com
Output: SVC_ACCT_AWESOME
The other request I got was for entering a service account name and have it give the KVNO back.
Issue, I have never done anything in C# before. I have Visual Studio 2013 loaded and I want to learn. I've spent hours pouring over the Googles and haven't found anything useful other than this:
https://msdn.microsoft.com/en-us/library/vstudio/system.servicemodel.configuration.identityelement.serviceprincipalname(v=vs.100).aspx
Unfortunately it doesn't mean anything to me.
Any direction that can be given for these specific tasks would be super appreciated!
Thanks.
I believe you can query AD for SPNs with something like this:
using (var root = new DirectoryEntry()) // or pass in something like "LDAP://dc=example,dc=com" to query a different domain
using (var searcher = new DirectorySearcher(root))
{
searcher.Filter = "(servicePrincipalName=HTTP/server1.company.com)";
using (var results = searcher.FindAll())
{
foreach (SearchResult result in results)
Console.WriteLine(result.Properties["samAccountName"][0]); // or whatever you want to do with it
}
}
(this needs a reference to System.DirectoryServices)

Getting the current logged in user (FullToken Context)

I have a Problem, which is... i start a programm with right click -> run as administrator.
Which means the programm is running in an administrative context.
WindowsIdentity.GetCurrent().Name;
if i try to get the user name that way i will get the user that started the programm as admin.. for example "administrator", but what i need is the name of the current logged in user which is for example: bob
Can anybody help me out? :)
You could try using WMI (System.Management.dll) to get the owner of the explorer.exe process.
string GetExplorerUser()
{
var query = new ObjectQuery(
"SELECT * FROM Win32_Process WHERE Name = 'explorer.exe'");
var explorerProcesses = new ManagementObjectSearcher(query).Get();
foreach (ManagementObject mo in explorerProcesses)
{
string[] ownerInfo = new string[2];
mo.InvokeMethod("GetOwner", (object[])ownerInfo);
return String.Concat(ownerInfo[1], #"\", ownerInfo[0]);
}
return string.Empty;
}
This relies on the fact that the explorer process is single instance an so you don't end up with the possibility of having several explorer processes running with different user credentials.
You will probably need to use win32 API for that. Read about Window Station and Desktop functions here: http://msdn.microsoft.com/en-us/library/ms687107%28v=vs.85%29.aspx
Also see this question:
Get the logged in Windows user name associated with a desktop
Maybe you could start as normal user, save user name, then programmatically request elevation :
Windows 7 and Vista UAC - Programmatically requesting elevation in C#
All .NET libraries will give you the user from the current context ('Administrator' in your case).
If you are trying to secure your code, you might consider reading about: Security in the .NET framework
1) Cassia should be able to give you a list of currently logged in users including RDC.
foreach (ITerminalServicesSession sess in new TerminalServicesManager().GetSessions())
{
// sess.SessionId
// sess.UserName
}
2) WMI (SO answer)
Select * from Win32_LogonSession
3) PInvoke to WTSEnumerateSessions
4) Enumerate all instances of "explorer.exe" and get the owner using PInvoke (OpenProcessHandle).
Process[] processes = Process.GetProcessesByName("explorer");
This is a bit hacky. WMI can also be used for this.
It might be a good idea to set winmgmt as a dependency for your service if you decided to go with solution that uses WMI.

How to get streetaddress property of an organizational unit in windows active directory with LDAP in C#.Net

Each of our users is assigned to a primary organizational unit (OU) based on which global office they are in. So the "Chicago" OU contains all the associates in our Chicago office.
Using c# and .net 3.5, my task is to extract all of these users.
Unless the users are in a satellite or home office, their street address, city, state, etc. are empty, but the OU contains these details. When in Windows' Active Directory interface, right clicking on the OU and selecting properties gives a place to put all of this information just as on a user. However, when I try to access these properties like I do a user, I get an object reference error, suggesting these attributes do not exist the same way for an OU that they do for a user.
How do/can I access these location parameters from an OU object?
Here is a sample of the code I am using, showing streetaddress as an example, the statement trying to assign the value of streetaddress from the OU fails, where the assignment from associate succeeds.
foreach (SearchResult subOU in results)
{
ResultPropertyValueCollection subColl = subOU.Properties["distinguishedname"];
string subPath = subColl[0].ToString();
DirectoryEntry subEntry = new DirectoryEntry("LDAP://" + subPath);
DirectorySearcher userSearcher = new DirectorySearcher(subEntry);
userSearcher.SearchScope = SearchScope.OneLevel;
userSearcher.Filter = "(objectClass=user)";
foreach (SearchResult user in userSearcher.FindAll())
{
ResultPropertyValueCollection userColl = user.Properties["distinguishedname"];
string userPath = userColl[0].ToString();
DirectoryEntry userEntry = new DirectoryEntry("LDAP://" + userPath);
PropertyCollection associateProperties = userEntry.Properties;
PropertyCollection ouProperties = subEntry.Properties;
string streetAddress = string.Empty;
if (associateProperties["streetaddress"].Value == null)
{ streetAddress = ouProperties["streetaddress"].Value.ToString(); }
else
{ streetAddress = associateProperties["streetaddress"].Value.ToString(); }
}
}
If you change the Street-field on the General-tab in Active Directory Users & Computers for a user the value is stored in the streetAddress-attribute in the directory. If however you change the same field for an OU that value is stored in the street-attribute of that OU in the directory.
This is because OU objects are not (as defined in the Active Directory default schema) permitted to contain the streetAddress-attribute.
So (not having analyzed your code further) if you change ouProperties["streetaddress"] to ouProperties["street"] you'll might get the result you're looking for.
To avoid the ObjectReference exception you should check the collection contains the required attribute using the Contains(string) method. See here
I believe that AD will only stored valued attributes on an object, if a particular attribute has never been assigned a value it won't be available.
I found the AD schema references at:
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-ADA1%5D.pdf A-L
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-ADA2%5D.pdf Just M
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-ADA3%5D.pdf N-Z
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-ADTS%5D.pdf AD technical info
That would answer this question for you.
Also, the Win2K8 ADUC MMC snapin if you go to View, select Advanced Features, (enable the tick) then you get the Attribute Editor. (Something ConsoleOne for eDirectory has had for probably close to a decade now!).
One small note, in AD schema, first character is always lower case, and I run at sufficiently high res that the lower case L's are hard to see as L's. (Need a better screen font, but mea culpa).

Categories