Powershell accessing an object in AD SearchResultCollection - powershell

I have the following Powershell code:
$directorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$directorySearche.PageSize = 100
$directorySearcher.SearchScope = [System.DirectoryServices.SearchScope]::SubTree
$searchResults = $directorySearcher.FindAll()
#$searchResults
$searchResults.Item(0).Path
If I uncomment #$searchResults then I can see hundreds of entries with "Path" and "Properties" as the objects' properties.
However when $searchResults.Item(0).Path is executed, it just says "Running script/selection. Press ctrl+break to stop." and has been like that for 10 mins so far.
Why can't I access an individual object from the SearchResultCollection ?

Turns out there were just way too many results.
I used a filter to narrow it down and now I can access individual objects since there are now only 347 results.
Before I couldn't even find out the count because there were too many.

Related

PowerShell SetAccessRule for ACL failing

The script I've done creates a folder and security groups that is later added to the folder in question with special permissions. The problem is that the script fails on "$acl.SetAccessRule($rule_modify)" and complains about the identity.
Error:
"Exception calling "SetAccessRule" with "1" argument(s): "Some or all identity references could not be translated."
If I run the script row by row by simply using copy/paste from ISE into a regular PowerShell window everything goes through without errors using the same location and user.
This is the important bit that isn't working.
#Get ACL list
$acl = Get-Acl -Path $Path
$acl.SetAccessRuleProtection($false,$false)
#Add permission for modify
$set_modify = "INTRA\FIL_$($Department)_$($Group)_Modify", 'DeleteSubdirectoriesAndFiles, Write, ReadAndExecute, Synchronize', 'ContainerInherit, ObjectInherit', 'None', 'Allow'
$rule_modify = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $set_modify
$acl.SetAccessRule($rule_modify)
$acl | Set-Acl $path
I had basicly the same issue but with "AddAccessRule".
$Acl.AddAccessRule($Ar)
My Script failed with the above mentioned error.
Just as Patrik Persson mentioned, in my case it was also because AD was slow on showing new groups and the Ar could not be added until the security group showed up in my AD.
So i added a try/catch with a do/until loop to my script which i want to share:
do {
$check = 'ok'
try {
$Acl.AddAccessRule($Ar)
} catch [System.Management.Automation.RuntimeException] {
$_.Exception.Message
$check = 'error'
Start-Sleep -Seconds 2
}
} until (
$check -eq 'ok'
)
So the loop continues until AD registers the security group correctly. After that the Ar is added to the acl and my script continues as expected.
I have found the solution and it fails because ActiveDirectory is too slow to recognize that the security group is created propery before adding it to the ACL.
Solution I went with was to add a 10 second sleep after groups and folder was created and it now works as intended.
You might want to expand all the strings you're using to build your security group name into a clean variable - I find that can be touchy. Make sure that $secgroup contains the right string value when you've constructed it.
You can create the rule together with the object type on one line as well.
$secgroup = "INTRA\FIL_$($Department)_$($Group)_Modify"
$modifyRule = New-Object System.Security.AccessControl.FileSystemAccessRule($secgroup,'DeleteSubdirectoriesAndFiles, Write, ReadAndExecute, Synchronize','ContainerInherit, ObjectInherit','None','Allow')
By the way, if essentially you want your users to have Modify rights on the contents without being able to delete the parent folder, it should work if you set the InheritOnly flag (I haven't tested it).
$modifyRule = New-Object System.Security.AccessControl.FileSystemAccessRule($secgroup,'Modify, Synchronize', 'ContainerInherit, ObjectInherit','InheritOnly','Allow')
Had a similar issue while creating shares on remote file servers.
At first, I'd used the proposed solution (start-sleep), but it was not good enough as it significantly increased the time consumed while processing a lot of shares.
It turns out that you may use SID while defining your ACE and operation is instant:
$TempSID = (Get-ADGroup "FIL_$($Department)_$($Group)_Modify").SID
$PermissionModify = "Write, Read, ListDirectory, ReadAndexecute, DeleteSubdirectoriesAndFiles"
$Inherit = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
$Propagation = [system.security.accesscontrol.PropagationFlags]"None"
$Type = "Allow"
$modifyRule = New-Object System.Security.AccessControl.FileSystemAccessRule($TempSID, $PermissionModify, $Inherit, $Propagation, $Type)
Seems that Active Directory needs some time (in my case 2 seconds) to translate SID to the group name (in DOMAIN\groupName format).
Another case: I have got the error Exception calling SetAccessRule... because I have set the account without the domain, so - with the question's example - I have put .\FIL_$($Department)_$($Group)_Modify instead of INTRA\FIL_$($Department)_$($Group)_Modify.

O365 Powershell | Breaking up a long list into two sets of 100

I am looking to create a rule in Office 365 applied to all of the members in our org.
I would like this rule to append a warning on all incoming email from outside the organization with the same Display Names as our users.
When I attempt to apply it to all of the users in our org I get an error stating that the rule is too long.
In order to solve that I pulled a group, but I am still about 1000 characters over the limit.
I would like to make two variables, that each hold one half of the list, created by this command:
(Get-DistibutionGroupMember -Identity email#contoso.com -ResultSize Unlimited).DisplayName
I have attempted to modify the ResultSize parameter, but what I would need is result 1-100 and then 100-200 from the same list.
Another caveat to this problem is that the list cannot be static. It is something that the script will have to update every time it is run.
There is a sub-string command that you can use on a particular username that I have utilized when I made something for AD, but I am not aware of any way to break up a list like this.
If anyone has any other ways to solve this issue I would be more than open to any suggestion.
Thanks for taking the time to read this!
There are many ways of doing it. I found it very readable.
My favorite one is this one:
$ObjectList = 1..1000
$Step = 100
$counter = [pscustomobject] #{ Value = 0 }
$ObjectListSplitted = $ObjectList | Group-Object -Property { math]::Floor($counter.Value++ / $step) }
Then if you want to show the third subset just use this format :
$ObjectListSplitted[3].Group
Have a look to this solution already explained.
As a note other languages are capable of slicing an array of object with a start, stop and a step, have a look here if you're curious.

ews GetSearchableMailboxes only return 1500 mailboxes paging

I have this very simple script to get all the searchable mailboxes. I have 2000 mailboxes but this API return only 1500 every time. Wondering if the results are paged but there is no documentation regarding it.
Import-Module "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll";
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1);
#$Service.UseDefaultCredentials = $true;
$Service.Credentials = New-Object System.Net.NetworkCredential("test#test.com", "test123!");
$Service.Url ="https://exch2013.test.com/EWS/Exchange.asmx";
$Service;$m = $Service.GetSearchableMailboxes([string]::Empty,$false);
$count = 1;
#$m.SearchableMailboxes | %{$_.SmtpAddress; $count++;}#$count;
Sounds like throttling - use a paged search.
See if ECP's ediscovery search repros - if it does then its probably not an issue with your code.
There is an example of paged searches in EWSEdtior's code (you will find the code in Github). Find the form called EDiscoverySearch.cs. The call to GetSearchable Mailboxes does not do paging, however another piece of code in the same form does - you can adapt it for the call to GetSearchableMailboxes.

Why does powershell executes my property getters

I have a C# project that I'm consuming with PowerShell.
A method returns an object that have not been fully initialized and that calls P/Invoke under the hood through get properties.
When I call the method, the script crashes because of an accessViolationException that is caused by the call of a property on that partially initialized object, but I didn't call it.
Why do Powershell act like this? is there an option to disable that "eager property evaluation"?
The original issue is the one posted here: https://github.com/ZeBobo5/Vlc.DotNet/issues/330
Add-Type -Path ".\Other\VLC\Vlc.DotNet.Core.dll"
Add-Type -Path ".\Other\VLC\Vlc.DotNet.Core.Interops.dll"
$Cameras = New-Object System.Collections.ArrayList
$Test = New-Object System.Uri("rtsp://192.168.0.50/axis-media/media.amp?camera=1")
$Cameras.Add($Test)
$VlcLibDirPath = (Get-Location).Path + ".\Other\VLC\libvlc_x64"
$VlcLibDir = New-Object System.IO.DirectoryInfo($VlcLibDirPath)
$VlcOpt = "--rtsp-user=admin", "--rtsp-pwd=12345"
$Plyr = New-Object Vlc.DotNet.Core.VlcMediaPlayer($VlcLibDir, $VlcOpt)
for ($i=0; $i -lt $Cameras.Count; $i++)
{
$Plyr.SetMedia($Cameras[$i]) #Fails here with System.AccessViolationException
$Plyr.Play
$Plyr.Stop
}
SetMedia returns a VlcMedia, which contains a Statistics property, which is automatically invoked by PowerShell.
Code for VlcMedia can be found here : https://github.com/ZeBobo5/Vlc.DotNet/blob/develop/src/Vlc.DotNet.Core/VlcMedia/VlcMedia.cs
It's difficult to tell without seeing your code, but there's tons of ways this could be happening. If the object is being displayed at all, the properties are probably all being read.
You should change those to methods, and then they won't get read without specifically being invoked.
Or, change your getters to detect an uninitialized object (you should be doing this already if it's possible for consumers to end up with such an object).
Edit:
With your code posted, it's clear:
$Plyr.SetMedia($Cameras[$i]) #Fails here with System.AccessViolationException
SetMedia returns a VlcMedia, which contains a Statistics property, which is automatically invoked by PowerShell.
Everything returned in PowerShell goes somewhere. If you don't assign it or redirect it, it gets sent to the pipeline.
It seems that you don't want or need the output from this method, so you should either assign it to a variable or dispose of the return in one of a few ways:
[null]$Plyr.SetMedia($Cameras[$i])
$null = $Plyr.SetMedia($Cameras[$i])
$Plyr.SetMedia($Cameras[$i]) | Out-Null
(note: piping to Out-Null is the least performant, which is magnified since you're doing this in a loop)
If you want to use the value later (not shown in your code), assign it and use it later.

How to query for members of an LDAP group using Powershell not in MS Active Directory

All I am trying to accomplish is to return if an LDAP group has any members in it. So, I have a list of groups, and I want to query each one for a list of members to ensure there is at least 1 member in every group.
I am using powershell and this is NOT Active Directory.
This is currently what I am trying
$user = "username"
$pwd = "password"
$de = "LDAP://[SERVERNAME]/cn=user,ou=people,o=company"
$deObject = New-Object -TypeName System.DirectoryServices.DirectoryEntry($de,$user,$pwd,'FastBind')
This returns a DirectoryEntry object (at least as far as I can tell). I can't really see any attributes or anything except for if I do the following:
$deObject.Name
This returns the cn of "user" and that's it. Any suggestions?
I've tried:
$deObject.Properties
$deObject.Properties['member']
$deObject.Properties.Values['member']
Thanks in advance!
This will show you all the properties there are:
$deObject | Format-List * -force
And this will return you the number of members in a group:
$deObject.member.Count