Powershell acting different for values vs. arrays? - powershell

I'm trying to grab out some information from Active Directory using Powershell, but I get some strange behavior. Here's my script:
$toFind = ( 'bobjones', 'samsmith' )
filter Get-AdUser {
$strFilter = "(&(objectCategory=User)(sAMAccountName=$_))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$colProplist = ("name", "department")
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
($objSearcher.FindAll() | %{$_.Properties})
}
"paul" | get-aduser # Works
$toFind | get-aduser # Doesn't work?!
The former prints out what I expect, a table of properties; the latter ends up just printing "0 1" repeatedly though I'm not sure why. Why would the single case work but not the array?

Figured it out, it has nothing to do with PowerShell. When you create the DirectoryEntry:
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
It will return results for your domain only (i.e. if you have an AD forest like "NorthAmerica" and "Europe", it'll only query the one you're in). It just happened that all of the names I was searching for were in another domain.
If you use the constructor to manually specify the Domain, it works pretty well (still haven't figured out how to query all domains yet though...)

Related

Populate Checkedlistbox with Servers

I am trying to populate a list with the servers in my domain, and i have partial success. There are 5 items in my list, which is as many servers as i have.
Unfortunately they are all just called [Collection]
Form is generated with Sapien Powershell Studio
$strCategory = "computer"
$strOperatingSystem = "Windows*Server*"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("OperatingSystem=$strOperatingSystem")
$colProplist = "name"
foreach ($i in $colPropList) { $objSearcher.PropertiesToLoad.Add($i) }
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{
$objComputer = $objResult.Properties;
$objComputer.name
$checkedlistbox1.Items.add($objComputer.name)
}
What can I do to have the proper name show up in the checkedlist.
Thanks for any assistance :)
The result object from DirectorySearcher.FindAll() method contains a special property named Properties that returns a typed collection containing the values of properties of the object found in the AD.
This means that you can simply do
. . .
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults) {
$checkedlistbox1.Items.add($objResult.Properties['name'][0])
}
I suggest you use Get-ADComputer instead to get the list of your servers.
The you just loop thrue the list and add the servername to your checkedlist
$Servers= Get-ADComputer -Filter {OperatingSystem -Like 'Windows *Server*'} #-Property * #the property flag is not needed if you just want the Name (see comment from Theo)
foreach ($srv in $Servers) {
#Unmark to debug
#$srv.Name
#$srv.OperatingSystem
$checkedlistbox1.Items.add($srv.Name)
}

Directory Search to array to populate Windows form datagrid

I'm creating a windows form via Powershell where users can search for the computers registered to a person, or search for a person's registered computers. The registered user is stored in the description field, the computer names in the name field. $SearchIn holds the value to search for, $field indicates the field to search in.
I can get the results I want via the console, but I'm attempting to push the results into a datagrid view on a windows form. The datagrid in the script below is called $dataGrid1. What I have below is an attempt to push the directory services search to an array, then set the datagrid datasource to an array. I thought because the $objectComputer is an object rather than an array I had to create an array using New-Object System.Collections.ArrayList and populate it using the addrange method set to the $objComputer object.
Ultimately what I get no matter what I'm trying is a blank datagrid view. Can someone point me in the right direction?
Function Get-Info
{
param($SearchIn,$Field)
if ($field -eq "Name"){
$filter="name=*$SearchIn*"
}
else
{
$filter="description=*$SearchIn*"
}
$strCategory = “computer”
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = $filter
$colResults = $objSearcher.FindAll()
$objComputer=#()
foreach ($objResult in $colResults)
{
$objComputer+=($objResult.Properties.item("Name"), $objResult.Properties.item("Description"))}
$array=New-Object System.Collections.ArrayList($null)
$array=.addrange($objComputer)
$dataGrid1.DataSource = $array
$fComputerSearch.refresh()
}#End Get-Info
Uff your code is rather hard to read, next time please check the brackets {}
I think the end is incorrect:
$array=New-Object System.Collections.ArrayList($null)
$array=.addrange($objComputer)
$dataGrid1.DataSource = $array
$fComputerSearch.refresh()
I think it should be something like this:
# the fastest way to create empty ArrayList
[System.Collections.ArrayList]$list = #()
$list.AddRange($objComputer)
$dataGridView = New-Object System.Windows.Forms.DataGridView -Property #{
Size=New-Object System.Drawing.Size(1024,768)
ColumnHeadersVisible = $true
DataSource = $list
}
$form.Controls.Add($dataGridView)
$form.ShowDialog()

Some computers on a powershell GPO script not recognizing parameter

I am running into an issue where about 10% of computers on my network are throwing a very strange errors when processing. The error I get is "Where-Object : A Parameter cannot be found that matches paramter name 'Property'" the code I'm using is as follows.
#Create ADSI Search object to query Active Directory for usernames
#Start-Transcript -Path "$env:userprofile\Desktop\log.txt"
$strFilter = "objectCategory=user"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://OU=SD25;DC=DC;DC=DC")
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 100000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
#Populate ADSI with the extra fields of samaccountname which is the username, and memberof which gives you roughly which groups they are a memberof
$colProplist = "samaccountname", "memberof"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
#Run the Search
$colResults = $objSearcher.FindAll()
#$colResults
$resultsarray = #()
#The way ADSI returns results, it populates all an array of every username listed within the scope, I then use this foreach recursive loop to find the name I need
foreach ($objResult in $colResults)
{
#Here I am taking each of the users, and finding the one which has the samaccountname of the user that is currently logged in
$objItem = $objResult.Properties | Where-Object -Property memberof -like ALL
#$groups = $objItem.memberof
#This is for diagnostics, if you output a logfile it will tell you the name and groups it is a member of
$objitem
}
#This is the beginnings of searching for a computer container in active directory.
$compFilter = "objectCategory=computer"
$compDomain = New-Object System.DirectoryServices.DirectoryEntry("LDAP://OU=OU;DC=DC;DC=DC")
$compSearcher = New-Object System.DirectoryServices.DirectorySearcher
$compSearcher.SearchRoot = $objDomain
$compSearcher.PageSize = 100000
$compSearcher.Filter = $strFilter
$compSearcher.SearchScope = "Subtree"
$compProplist = "name"
foreach ($i in $compPropList){$compSearcher.PropertiesToLoad.Add($i)}
$compResults = $compSearcher.FindAll()
foreach ($compR in $compResults)
{
}
#Stop-Transcript
IIRC -Property was introduced to Where-Object with PowerShell 3.0. Could you script be running on PowerShell 2.0?
Responding to comment
You need to create a filter script in the form of a scriptblock (i.e. PowerShell code in a set of braces) instead of using the comparison operator parameters they added for 3.0.
Try using
Where-Object { $_.memberof -like "ALL" }
or something like that. $_ refers to the current object in the pipeline. I couldn't find the docs for version 2.0 but I found Using the Where-Object Cmdlet for version 1.0 which was relevant for 2.0 AFAIK and should help you.

Get Current User URI for Lync 2013 via PowerShell

I'm am trying to get the current user's URI that is signed into Lync on the machine the PS script is run on. I've Googled to no avail. One method I thought of trying was to get the Windows logged in name and then parse that into an e-mail address but there will be instances in which this won't give the correct URI. Is this achievable?
Assuming I understand your question...
1) Getting sip-address for current user using the ActiveDirectory-module.
(Get-ADUser $env:USERNAME -Properties msRTCSIP-PrimaryUserAddress).'msRTCSIP-PrimaryUserAddress'
2) Getting sip-address for current user using DirectorySearcher.
$filter = "(&(objectCategory=User)(SamAccountName=$env:USERNAME))"
$property = 'msRTCSIP-PrimaryUserAddress'
$domain = New-Object System.DirectoryServices.DirectoryEntry
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = $domain
$Searcher.PageSize = 1000
$Searcher.Filter = $Filter
$Searcher.SearchScope = "Subtree"
$Searcher.PropertiesToLoad.Add($property) | Out-Null
# Value
($Searcher.FindAll()).Properties[$property]

Change user mail property with ADSI in PowerShell

I am trying to update the email address of a directory user with PowerShell.
I am unable to modify the mail property of a user entry with the following code:
$BadUser = [adsi] $Account.Path
$BadUser.mail.Clear()
$BadUser.mail.Add($User.Email) | Out-Null
$BadUser.SetInfo()
The mail.Clear() nor the mail.Add() seem to modify $BadUser when debugging with PowerGUI.
I have a working version that relies on the QAD plugin, and I would like to avoid using it if possible.
$suf = $AD.Parent.Substring(10)
Connect-QADService -Service "$($AD.dc[0]).$suf" -ErrorVariable AD_Conn_Error -ErrorAction Stop -WarningAction Stop | Out-Null
Set-QADObject $Account.Properties.distinguishedname[0] -ObjectAttributes #{mail=$User.Email} | Out-Null
Disconnect-QADService
Reasons I am avoiding QAD:
I am searching for users across 8 domain servers
ADSI allows me to save multiple connected entries in a list
QAD can connect to 1 domain at a time
ADSI seems relatively fast
QAD has memory leaks (1kB/s bad) that crash in large batches
QAD is unable to "identify" some users that ADSI found by cn
Here's some example code to do it:
$query= "(&(objectCategory=User)(cn=FirstName LastName))"
$OU = "LDAP://OU=Users,dc=subdomain,dc=company,dc=com"
$PageSize = 100
$objOU = New-Object System.DirectoryServices.DirectoryEntry($OU)
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objOU
$objSearcher.PageSize = $PageSize
$objSearcher.Filter = $query
$objSearcher.SearchScope = "Subtree"
$colResults = $objSearcher.FindAll()
foreach($objResult in $colResults) {
$dirObject = [ADSI]$objResult.GetDirectoryEntry()
$dirObject.mail = "newaddress#company.com"
$dirObject.CommitChanges()
}