C# and Active Directory : test if an OU exist - c#

How can i Test if and Organizational Unit Exists in Active Directory before creating it with C# ?

There's a .Exists() method on the DirectoryEntry which you can use - assuming you have the correct LDAP path for your OU!
if (DirectoryEntry.Exists("LDAP://" + objectPath))
{
// ......
}
Your main problem will be: the path you're using is wrong - the Users is a generic container and thus needs to be addressed like this:
LDAP://192.168.0.1/CN=Users
Note the CN= prefix. If you had an actual organizational unit, it would have to be prefixed with OU=
For a great resource, check out Howto: (almost) everything in Active Directory

Related

Directory.Exists(#"\\SERVERIP\aFolder\bFolder"); always returns false

The following path always returns false:
Directory.Exists(#"\\SERVERIP\aFolder\bFolder");
// where SERVERIP is the server-IP which is being accessed using Impersonation
After debugging the code, it places double-slashes in the Debugger.
I have accessed the above file path without the # and double-quotes in WindowsExplorer.
What am I doing wrong?
[ The code will run on a network ]
The problem might be in the paths-[Source/Destinations] (both or one of it[source/destination] might be causing the problem) due to the default-paths used by Visual-Studio. So let me explain how to check wether the paths are correct/incorrect step by step.
Configuring ** SOURCE-PATH **:
Some times this path DRIVE:\ProgramFiles\IISExpress (or some other path depending on the installation location of IIS) gets concatenated with the SOURCE-PATH you give in the input To solve this problem, follow/verify these steps:
Ensure that the SOURCE-PATH or File you are using is in the Project-Folder
To Access the SOURCE-PATH or File. Always use this path/way:
// 1. SOURCE-PATH + fileName with Extension<br>
Server.MapPath("~\FolderInsideProjectFolder\", "fileName.extension");
Configuring ** DESTINATION-PATH (to a Mapped-NETWORK) **:
This path creates a problem if the path you entered has some words mispelled OR if you don't have access to the specified Server-IP[DestinationServerIP]. To solve this problem, follow/verify these steps:
Before Accessing the DESTINATION-PATH or File , ensure that the IP-Address you are referring to is Accessible to the Account under which your Application-code is running.To learn how to run Applications under an Account. See Impersonization
To Access the DESTINATION-PATH or File. Always use this path/way:
// 2. DESTINATION-PATH + fileName with Extension
#"\\SERVERIP\aFolder\bFolder" + "fileName.extension";
NOTE:
Remember that the SOURCE-PATH can be checked if it (exists/does not exist) by addressing its Fully-Qualified-Address and in that case, it will return true if it exists (The full-path that windows-explorer shows you in the Address Bar (Windows-Explorer) like DRIVE:/....../
EXTRA-INFORMATION: (as it was the basic INTENSION)
One line instruction to Copy the file from local-system → networked-mapped drive/path is:
System.IO.File.Copy(
Server.MapPath("~\FolderInsideProjectFolder\", "fileName.extension"),
#"\\SERVERIP\aFolder\bFolder" + "fileName.extension"
[, true ] // Optional if you want the file to be over-written or not
);
Please inform, if any thing still is not cleared (but after some nice searching ☋ ☛ )
Many a times I have seen file (or directory) access problems when the user (a human, system user such as IIS_IUSR or an application) lacks required privileges.
According to this question where the asker is facing similar problem, I believe that this may help you.
Let us know, if it helps.

Remove domain name from machine name

Is there a safe way to remove the domain name from a machine name in C#?
Example:
MYMACHINE.mydomain.com
should be resolved to
MYMACHINE
Naive String Approach:
string fullName = "MYMACHINE.mydomain.com";
string resolvedMachineName = fullName.Split('.')[0];
If you want the 'basic' understanding of machine name, then use :
Environment.MachineName
It provides the machine name without the domain (traditionally the COMPUTERNAME variable at a command prompt). See: http://msdn.microsoft.com/en-us/library/system.environment.machinename.aspx
Edit #1
#Antineutrino - as I re-read my answer I realized we don't have enough information to give you a correct answer. When you say 'machine name', however, it is not clear if you want to know how to parse the string you have, or the proper way to retrieve what you want. If you simply want to know how to parse a string, the other answers are correct. On the other hand...
Do you want the NetBios name or Cluster Name? Then Environment.MachineName
Do you want the underlying name of a the machine running a cluster? You'll need to dig into the WMI classes.
Do you want the most specific name from all DNS strings that resolve to the current machine? i.e. web1 from web1.mysite.com? You'll need to resolve all the IP's bound to the machine.
If you go back and edit/revise your question with more details -- you'll get better/more-specific answers.
Edit #2
If I understand correctly, your scenario is as follows: You have similar code that runs on both client and server machines in a desktop environment. In all machines registries you've saved a DNS name for the server (server.myapp.com). Now in the code you want to determine if a machine is the server or not.
What You Asked For
string serverName = Registry.GetValue(REG_KEY, REG_VALUE, "key missing");
string currentMachine = Environment.MachineName;
if (currentMachine.ToLower() == serverName.ToLower().Split('.')[0] ) {
//do something fancy
};
Another Idea
Instead of shrinking the server name, you can grow the machine name.
string serverName = Registry.GetValue(REG_KEY, REG_VALUE, "key missing");
string currentMachine = Environment.MachineName +
Environment.GetEnvironmentVariable("USERDNSDOMAIN");
if (currentMachine.ToLower() == serverName.ToLower() ) {
//do something fancy
};
What you may want
Distributing registry keys seems a bit cumbersome. If it were me I would probably do one/some/many of the following:
Create different build configurations and use pre-processor directives to change the code. Something very roughly like: #if(RELEASE_SERVER) { /*do server code*/} #if(RELEASE_CLIENT) { /*do server code*/}
Use app.config ---that's what it's there to store configuration data. No need to pollute the registry. app.config can be transformed on build/deployment, or simply modified manually on the one server.
Store the majority of the configuration data in a central location. This way the app only need to know were to retrieve it's configuration from (even if that's itself).

ActiveDirectory error 0x8000500c when traversing properties

I got the following snippet (SomeName/SomeDomain contains real values in my code)
var entry = new DirectoryEntry("LDAP://CN=SomeName,OU=All Groups,dc=SomeDomain,dc=com");
foreach (object property in entry.Properties)
{
Console.WriteLine(property);
}
It prints OK for the first 21 properties, but then fail with:
COMException {"Unknown error (0x8000500c)"}
at System.DirectoryServices.PropertyValueCollection.PopulateList()
at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
at System.DirectoryServices.PropertyCollection.PropertyEnumerator.get_Entry()
at System.DirectoryServices.PropertyCollection.PropertyEnumerator.get_Current()
at ActiveDirectory.Tests.IntegrationTests.ObjectFactoryTests.TestMethod1() in MyTests.cs:line 22
Why? How can I prevent it?
Update
It's a custom attribute that fails.
I've tried to use entry.RefreshCache() and entry.RefreshCache(new[]{"theAttributeName"}) before enumerating the properties (which didn't help).
Update2
entry.InvokeGet("theAttributeName") works (and without RefreshCache).
Can someone explain why?
Update3
It works if I supply the FQDN to the item: LDAP://srv00014.ssab.com/CN=SomeName,xxxx
Bounty
I'm looking for an answer which addresses the following:
Why entry.Properties["customAttributeName"] fails with the mentioned exception
Why entry.InvokeGet("customAttributeName") works
The cause of the exception
How to get both working
If one wants to access a custom attribute from a machine that is not
part of the domain where the custom attribute resides (the credentials
of the logged in user don't matter) one needs to pass the fully
qualified name of the object is trying to access otherwise the schema
cache on the client machine is not properly refreshed, nevermind all
the schema.refresh() calls you make
Found here. This sounds like your problem, given the updates made to the question.
Using the Err.exe tool here
http://www.microsoft.com/download/en/details.aspx?id=985
It spits out:
for hex 0x8000500c / decimal -2147463156 :
E_ADS_CANT_CONVERT_DATATYPE adserr.h
The directory datatype cannot be converted to/from a native
DS datatype
1 matches found for "0x8000500c"
Googled "The directory datatype cannot be converted to/from a native" and found this KB:
http://support.microsoft.com/kb/907462
I have the same failure. I´m read and saw a lot of questions about the error 0x8000500c by listing attribute from a DirectoryEntry.
I could see, with the Process Monitor (Sysinternals), that my process has read a schema file. This schema file is saved under
C:\Users\xxxx\AppData\Local\Microsoft\Windows\SchCache\xyz.sch.
Remove this file and the program works fine :)
I just encountered the issue and mine was with a web application.
I had this bit of code which pulls the user out of windows authentication in IIS and pulls their info from AD.
using (var context = new PrincipalContext(ContextType.Domain))
{
var name = UserPrincipal.Current.DisplayName;
var principal = UserPrincipal.FindByIdentity(context, this.user.Identity.Name);
if (principal != null)
{
this.fullName = principal.GivenName + " " + principal.Surname;
}
else
{
this.fullName = string.Empty;
}
}
This worked fine in my tests, but when I published the website it would come up with this error on FindByIdentity call.
I fixed the issue by using correct user for the app-pool of the website. As soon as I fixed that, this started working.
I had the same problem with a custom attribute of a weird data type. I had a utility program that would extract the value, but some more structured code in a service that would not.
The utility was working directly with a SearchResult object, while the service was using a DirectoryEntry.
It distilled out to this.
SearchResult result;
result.Properties[customProp]; // might work for you
result.Properties[customProp][0]; // works for me. see below
using (DirectoryEntry entry = result.GetDirectoryEntry())
{
entry.Properties[customProp]; // fails
entry.InvokeGet(customProp); // fails as well for the weird data
}
My gut feel is that the SearchResult is a little less of an enforcer and returns back whatever it has.
When this is converted to a DirectoryEntry, this code munges the weird data type so that even InvokeGet fails.
My actual extraction code with the extra [0] looks like:
byte[] bytes = (byte[])((result.Properties[customProp][0]));
String customValue = System.Text.Encoding.UTF8.GetString(bytes);
I picked up the second line from another posting on the site.

How to get the exact path of notepad.exe in order to associate a file extension

I need to associate a file extension I have created “.rulog” with notepad.exe as part of a setup project installation for a windows 7 machine (it’s here since we require admin privileges to write to the registry).
Basically I need to obtain programmatically the exact path of the notepad.exe. Now, I understand that it typically lives in C:\Windows\system32. This is part of PATH system environment variable, so I guess I could loop through all the PATH variables and test if “notepad.exe” exists by combining “notepad.exe” with the current path using File.Exists. However this feels very clumsy.
Essentially I need to add an entry to
Computer\HKEY_CLASSES_ROOT\.rulog\shell\open\command\
with the value of the path of notepad.
Incidentally I can see that .txt in:
Computer\HKEY_CLASSES_ROOT\.txt\ShellNew
has a value for ItemName of
“#%SystemRoot%\system32\notepad.exe,-470”
Perhaps I can just copy this value? Or is this dangerous?(e.g. does not exist).
You can use:
Environment.GetEnvironmentVariable("windir") + "\\system32\\notepad.exe";
Or even easier:
Environment.SystemDirectory + "\\notepad.exe";
That way it doesn't matter which drive the os is on.
Copying the value with %systemroot% should be just fine. If it works for the OS, it should work for you!
Fool-proof solution:
string NotepadPath = Environment.SystemDirectory + "\\notepad.exe";
if (System.IO.File.Exists(NotepadPath))
{
Microsoft.Win32.Registry.SetValue("HKEY_CLASSES_ROOT\\.rulog\\shell\\open\\command\\", "", NotepadPath + " %1");
}
else
{
//do something else or throw new ApplicationException("Notepad not found!");
}

Get directory where executed code is located

I know that in the same directory where my code is being executed some files are located. I need to find them and pass to another method:
MyLib.dll
Target1.dll
Target2.dll
Foo(new[] { "..\\..\\Target1.dll", "..\\..\\Target2.dll" });
So I call System.IO.Directory.GetFiles(path, "*.dll"). But now I need to get know the path:
string path = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName)
but is there more short way?
You may try the Environment.CurrentDirectory property. Note that depending on the type of application (Console, WinForms, ASP.NET, Windows Service, ...) and the way it is run this might behave differently.
Environment.CurrentDirectory returns the current directory, not the directory where the executed code is located. If you use Directory.SetCurrentDirectory, or if you start the program using a shortcut where the directory is set this won't be the directory you are looking for.
Stick to your original solution. Hide the implementation (and make it shorter) using a property:
private DirectoryInfo ExecutingFolder
{
get
{
return new DirectoryInfo (
System.IO.Path.GetDirectoryName (
System.Reflection.Assembly.GetExecutingAssembly().Location));
}
}

Categories