LDAP Vb.net simple query - vb.net

I'm trying to create a vb.net code for a simple query through LDAP but having an issue and can't find where it is.
Dim ldapServerName As String = "xxx.test.intranet.xxx.ca"
Dim oRoot As DirectoryEntry = New DirectoryEntry("LDAP://" & ldapServerName & "/c=ca, DC=xxx,DC=corp,DC=xxx,DC=ca")
oRoot.Username = "ou=Tool,ou=applications,o=xxx,c=ca"
oRoot.Password = "something#2015"
Dim LDAPSearcher As New DirectorySearcher()
LDAPSearcher.Filter = "(&(employeenumber=6012589))"
Dim SearchResult As SearchResult = LDAPSearcher.FindOne()
Dim UserEntry As DirectoryEntry = SearchResult.GetDirectoryEntry()
EDTEST.Text = UserEntry.Properties("employeenumber").Value.ToString
it is giving me an error saying that the object is not valid. The searcher variable is in fact empty so it has to do with my query somehow.
This is my first time with LDAP¨and I have tried some of the solution i could find on the net but nothing is working so far.
Error: Object not set to an instance of an object.

Unless you're adding another attribute to search by, you don't need the AND operator in your filter syntax - a search for simply (employeenumber=6012589) should work just fine.
If do you have another attribute you'd like to search by, the filter syntax would be similiar to what you have now, only with the additional attribute :
(&(employeenumber=6012589)(objectClass=user))
EDIT:
I put together an example using the lower level System.DirectoryServices and System.DirectoryServices.Protocols namespaces. This helps break up the actual login and search functions, and will also provide better context when errors occur. For the example, I've replaced all of my variables with the ones you're using in your question. I tested this against our own Active Directory instance over unsecured port 389 using my creds and a base domain similar to the one you're using.
Imports System.DirectoryServices.Protocols
Imports System.Net
Module Module1
Sub Main()
' setup your creds, domain, and ldap prop array
Dim username As String = "ou=Tool,ou=applications,o=xxx,c=ca"
Dim pwd As String = "something#2015"
Dim domain As String = "DC=xxx,DC=corp,DC=xxx,DC=ca"
Dim propArray() As String = {"employeenumber"}
' setup your ldap connection, and domain component
Dim ldapCon As LdapConnection = New LdapConnection("xxx.test.intranet.xxx.ca:389")
Dim networkCreds As NetworkCredential = New NetworkCredential(username, pwd, domain)
' configure the connection and bind
ldapCon.AuthType = AuthType.Negotiate
ldapCon.Bind(networkCreds)
' if the above succceeded, you should now be able to issue search requests directly against the directory
Dim searchRequest = New SearchRequest(domain, "(employeenumber=6012589)", SearchScope.Subtree, propArray)
' issue the search request, and check the results
Dim searchResult As SearchResponse = ldapCon.SendRequest(searchRequest)
Dim searchResultEntry As SearchResultEntry
If (searchResult.Entries.Count > 0) Then ' we know we've located at least one match from the search
' if you're only expecting to get one entry back, get the first item off the entries list
searchResultEntry = searchResult.Entries.Item(0)
' continue to do whatever processing you wish against the returned SearchResultEntry
End If
End Sub
End Module

Related

Display operatingsystem property in a message box

I am having trouble getting the operatingsystem property for computers in Active Directory(AD). Here is the code I am having trouble with and the function that gets the property from AD. The hostname works perfectly but the OS_Name displays a blank message box.
Alternatively, I would also like help formatting the filter to make things easier down the road. My goal is to check the operating system and only process the Windows 10 Enterprise and Windows 7 Enterprise operating systems but I can't even display the operating system in a message box. Please help.
Dim enTry As DirectoryEntry = New
DirectoryEntry("GC://my.work.com/DC=AB27,DC=my,DC=work,DC=com")
Dim mySearcher As DirectorySearcher = New DirectorySearcher(enTry)
mySearcher.Filter = ("(objectClass=computer)")
mySearcher.PropertiesToLoad.Add("dNSHostName")
mySearcher.PropertiesToLoad.Add("operatingSystem")
Dim ds As SearchResult
For Each ds In mySearcher.FindAll()
Dim OS_Name As String = GetProperty(ds, "operatingSystem")
Dim hostName As String = GetProperty(ds, "dNSHostName")
MessageBox.Show(hostName)
MessageBox.Show(OS_Name)
Next
Function GetProperty(ByVal searchResult As SearchResult, ByVal
PropertyName As String)
If searchResult.Properties.Contains(PropertyName) Then
Return searchResult.Properties(PropertyName)(0).ToString()
Else
Return String.Empty
End If
End Function
I expect the message for the operating system to display the operating system property. Instead it displays a blank message box.
When I use debug.writeline instead of a message box it leaves a blank line between each hostname as if it reads the OS but just adds a line to hold the space.
Not sure what is in your DirectoryEntry nor if why you have structured your filter is causing a problem but the following shows me my hostname and operating system...
Dim enTry As DirectoryEntry = New DirectoryEntry
Dim mySearcher As DirectorySearcher = New DirectorySearcher(enTry)
mySearcher.PropertiesToLoad.Add("dNSHostName")
mySearcher.PropertiesToLoad.Add("operatingSystem")
mySearcher.PropertiesToLoad.Add("operatingSystemVersion")
mySearcher.Filter = "(&(objectClass=computer)(operatingSystem=*server*))"
Dim resEnt As SearchResult
For Each resEnt In mySearcher.FindAll()
Dim OS_Name As String
Dim hostName As String
hostName = GetProperty(resEnt, "dNSHostName")
OS_Name = GetProperty(resEnt, "operatingSystem")
Next

Get IP From Google

I'm writing an app in vb.net that needs public IP address in text only format. I'd knew there is lots of site that give you your IP in text format. But where is always a chance of being closed or getting out of service. But the Google will not ever stop! Now I want to get my ip from google searching. For example if you search "my ip" in google it will bring your ip like this:
Sample of search
Is anyway to get IP from Google?
Thanks guys but I found a way:
At first import some namespaces:
Imports System.Net
Imports System.Text.RegularExpressions
Now lets write a function:
Dim client As New WebClient
Dim To_Match As String = "<div class=""_h4c _rGd vk_h"">(.*)"
Dim recived As String = client.DownloadString("https://www.google.com/search?sclient=psy-ab&site=&source=hp&btnG=Search&q=my+ip")
Dim m As Match = Regex.Match(recived, To_Match)
Dim text_with_divs As String = m.Groups(1).Value
Dim finalize As String() = text_with_divs.Split("<")
Return finalize(0)
It's now working and live!
Hard-coded Div Class names make me a bit nervous because they can easily change at any time, so, I expanded on Hirod Behnam's example a little bit.
I removed the Div Class pattern, replacing it with a simpler IP address search, and it'll return only the first one found, which for this search, should be the first one shown on the page (your external IP).
That also removed the need for splitting the results into the array, and those related vars. I also simplified the Google search string to the bare minimum.
It'd still probably be a nice touch to include a timeout or two for the .DownloadString() and the .Match() respectively, if speed is of the essence.
Private Function GetExternalIP() As String
Dim m As Match = Match.Empty
Try
Dim wClient As New System.Net.WebClient
Dim strURL As String = wClient.DownloadString("https://www.google.com/search?q=my+ip")
Dim strPattern As String = "\b(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\b"
' Look for the IP
m = Regex.Match(strURL, strPattern)
Catch ex As Exception
Debug.WriteLine(String.Format("GetExternalIP Error: {0}", ex.Message))
End Try
' Failed getting the IP
If m.Success = False Then Return "IP: N/A"
' Got the IP
Return m.value
End Function

Breaking Inheritence for all Items in sharepoint list

I'm trying to build a for-loop in Visual Basic that will go over each item in a sharepoint database list and stop it from inheriting permissions from its parent. I'm getting a Null Exception because my query object is null. I've searched and all the code snippets i found didnt define a value for the query and wrote the code exactly like i did, why is this a problem.
Imports System
Imports Microsoft.SharePoint.Client
Imports SP = Microsoft.SharePoint.Client
Module Module1
Sub Main()
Dim siteUrl As String = "https://cws1.conti.de/content/00009504"
Dim clientContext As New ClientContext(siteUrl)
Dim oList As List = clientContext.Web.Lists.GetByTitle("TestBI")
Dim query As CamlQuery
query.ViewXml = "<Where><Eq><FieldRef Name='Account' /><Value Type='Text'></Value></Eq></Where>"
Dim oListItems As ListItemCollection = oList.GetItems(query)
For numItems As Integer = 0 To 2
oListItems(numItems).BreakRoleInheritance(True, False)
Next
clientContext.ExecuteQuery()
End Sub
End Module
I've never programmed VB before and i'm not familiar with automating anything on Sharepoint so I would really appreciate any help.
you need to assign an instance of an object to the query variable before you can use it. Right now, you only declare a variable.
Change the line:
Dim query AS CamlQuery
to
Dim query AS new CamlQuery
Also, CamlQuery expects a full <View> tag. So change your CAML to <View><Query><Where><Eq><FieldRef Name='Account' /><Value Type='Text'></Value></Eq></Where></Query></View> and you should be good to go.
If you wish to retrieve all items from the list, use the CamlQuery.CreateAllItemsQuery() method.
Dim query AS CamlQuery = CamlQuery.CreateAllItemsQuery()

Using DirectoryEntry.Invoke("SetPassword", ...) to set initial AD account password, I get "RPC server is unavailable" error

The company I'm working in has a web service that can create new Active Directory accounts based on information that is typed in e.g. username, firstname, lastname, OU1, OU2, etc.
This web service has been working fine on Windows Server 2003. Now I'm working on moving the web service to 2008 R2 servers. However a certain functionality doesn't work anymore, which is when it tries to set a random initial password to the newly created account.
The exception that is thrown is a TargetInvocationException containing an inner exception of COMException with a message of "The RPC Server is unavailable".
Imports System.DirectoryServices
Dim ldapPath As String = "..." 'assume valid LDAP path
Dim objContainer As DirectoryEntry = New DirectoryEntry(ldapPath, vbNullString, vbNullString, AuthenticationTypes.Secure)
objUser = objContainer.Children.Add("cn=" & Username.Trim, "user")
'sets objUser.Properties e.g. givenName, displayName, userPrincipalName, samAccountName, etc. Not important...
objUser.CommitChanges()
strPassword = RandomPassword() 'function that generates random password
objUser.Invoke("SetPassword", New Object() {strPassword})
objUser.Properties("useraccountcontrol").Value = "512" ' set as normal account
objUser.CommitChanges()
'and so on...
The error happens on the line that says:
objUser.Invoke("SetPassword", New Object() {strPassword})
Strangely the account creation itself works and I can see the new user from Active Directory Users and Computers.
I have consulted a few different people who manage the security of the DCs and the web servers, they don't really know why...
In the end I figured out a different way of setting the password, which is using the System.DirectoryServices.AccountManagement library.
So the code becomes something like this:
Imports System.DirectoryServices
Imports System.DirectoryServices.AccountManagement
Dim ldapPath As String = "..." 'assume valid LDAP path
Dim objContainer As DirectoryEntry = New DirectoryEntry(ldapPath, vbNullString, vbNullString, AuthenticationTypes.Secure)
Dim objUser As DirectoryEntry = objContainer.Children.Add("cn=" & Username.Trim, "user")
'sets objUser.Properties e.g. givenName, displayName, userPrincipalName, samAccountName, etc. Not important...
objUser.CommitChanges()
Dim domainContext As PrincipalContext = New PrincipalContext(ContextType.Domain, ...)
Dim user As UserPrincipal = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, Trim(Username))
strPassword = RandomPassword() 'function that generates random password
user.SetPassword(strPassword)
user.Enabled = True 'setting these two properties
user.PasswordNotRequired = False 'result in useraccountcontrol value = 512 (normal account)
user.Save()
'and so on...
I'm mixing old code with new code in this one, but it appears to be working really well on the new servers. One thing to note is that sometimes the UserPrincipal.FindByIdentity call initially returns Nothing, I believe due to delay in the account creation or with the replication. So I have to make sure that the user object is not Nothing by trying FindByIdentity multiple times until I get the object.
Despite finding a solution (more like a way around) to the problem, still I'm confused as to why the old code does not work on the new servers, but the new one does. The error is very generic and searching the internet for clues have resulted in nothing but more confusion.
Would really appreciate if experts out there can shed some lights or even comment on the way my new code looks, any problems?
Thanks in advance.

VB.NET Remove user from active directory

Hi I am trying to create a VB.NET application which will (hopefully) reduce some time spent on some of my departments helpdesk calls. The part that I am stuck with is how to use VB.NET to remove a user from a group. The following is code that I have been playing with:
Public Shared Sub RemoveUserFromGroup(ByVal deUser As String, ByVal GroupName As String)
Dim entry As DirectoryEntry = ADEntry()
Dim mySearcher As DirectorySearcher = New DirectorySearcher(entry)
mySearcher.Filter = "(&(ObjectClass=Group)(CN=" & GroupName & "))"
mySearcher.PropertiesToLoad.Add("OrganizationalUnit")
mySearcher.PropertiesToLoad.Add("DistinguishedName")
mySearcher.PropertiesToLoad.Add("sAMAccountName")
Dim searchResults As SearchResultCollection = mySearcher.FindAll()
If searchResults.Count > 0 Then
Dim group As New DirectoryEntry(searchResults(0).Path)
Dim members As Object = group.Invoke("Members", Nothing)
For Each member As Object In CType(members, IEnumerable)
Dim x As DirectoryEntry = New DirectoryEntry(member)
MessageBox.Show(x.Properties("sAMAccountName").Value)
If x.Properties("sAMAccountName").Value = deUser Then
MessageBox.Show(searchResults.Item(0).Path.ToString)
MessageBox.Show(x.Properties("sAMAccountName").Value)
'group.Invoke("Remove", New Object() {x.Properties("OrganizationalUnit").Value})
group.Properties("member").Remove(x.Properties("OrganizationalUnit").Value)
End If
Next
End If
When I run the program, I recevie a COMException was unhandled, unspecified error at the group.properties line. When using group.invoke I receive the error TargetInvocationException was unhandled.
My aim is to pass as a string the username (sAMAccountName) and the groupname (sAMAccountName) to the function which will locate the user and remove them from the group.
I am new to VB.NET and would appreciate any assistance people can provide.
I am coding in .NET 2.0 as I am unsure if the server it will live on will have 3.5 installed.
Well the error message 0x80004005 E_FAIL Unspecified failure is not very helpful. I often get frustrated when working with Active Directory.
Try changing line:
group.Properties("member").Remove(x.Properties("OrganizationalUnit").Value)
to
group.Invoke("Remove", New Object() {x.Path.ToString()})
If you need more reference take a look at this article on VB.net Heaven by Erika Ehrli. The article covers various use cases with Active Directory.
I hope that helps.