Finding the index of a key and value within an array using a wildcard in Powershell - powershell

I have been working on an issue and I was able to get done what I need to get done in a relatively decent and acceptable way but I am curious as to why I ran into some of the problems I did.
I'm not too savvy with PowerShell or C# but I have some experience with Java, C++, and a few others. So, if I overlook something really simple, you'll have to forgive me. I'm not looking for a critique of my solution, just some insight into some of the blockades I came across.
What I needed to do was use Powershell to query an LDAP setting. I needed to know MaxConnIdleTime and I needed that either assigned to a variable or accessible through a subroutine [sic] (ex $ldapPolicies.MaxConnIdleTime) so that I could run it through a conditional statement.
Here is how I accomplished it:
$ldap = Get-ADObject -SearchBase "CN=Query-Policies,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=$ENV:COMPUTERNAME,DC=$dc" -Filter 'ObjectClass -like "queryPolicy"' -Properties ldapadminlimits
$ldap = #($ldap.ldapadminlimits)
$ldap | %{
if($_.startswith("MaxConnIdleTime")) {
$match = $_
}
}
I tried NTDSUtil.exe, however, I couldn't redirect the "Show Values" to a text file to read from later and I couldn't write it to a variable in PowerShell.
I tried Start-Transcript and then ran NTDSUtil but it only recorded what occurred within PowerShell and not what happened in NTDSUtil.
Also, I tried giving all of the commands to NTDSUtil at once (NTDSUtil "ldap policies" "connections" "connect to server $ENV:COMPUTERNAME" q "Show Values") but PowerShell doesn't show anything in the console and I have press the exit sequence to return back to PS>.
I know that I could use LDP but I'm not too familiar with ADSI. Research appeared to say that going about attempting to get an LDPdump is a bit antiquated and I pretty much abandoned that attempt.
One of the issues that I had that caused me a small bit of frustration (and the reason I am asking this question) is why can I not search an array and find the index of an item using a wildcard? I tried doing this:
$ldap.IndexOf("MaxConnIdleTime*")
AND
$ldap.IndexOf($ldap -like "MaxConnIdleTime*")
but it always returned -1.
It would work correctly if I tried:
$ldap.IndexOf("MaxConnIdleTime=100")
given that the value was indeed 100. But I am validating that the value was correct.
I know that I could just do something like this:
if($ldap -contains "MaxConnIdleTime=100") {
DO SOMETHING...
} else {
DO SOMETHING ELSE...
}
Why is it that I can't search an array using a wildcard operator? There was no ambiguity, so, it should have worked, right?
I'm not looking for a critique of how I accomplished this, I'm just wanting to understand why it behaved like it did.
Thanks.

I don't think there's a straightforward "search an array by wildcard and return an index" cmdlet, method, statement, etc. in PowerShell.
.IndexOf is not designed to work with a wildcard.
When you used the -like operator on the array, you likely found only a single matching object, but -like returns an array of matches when used on an array.
Passing the array into .IndexOf() then looks for an array element that is itself an array, even if that array only has one object.
This would work:
$ldap.IndexOf(($ldap -like "MaxConnIdleTime*")[0])
As long as you always wanted to find the first one.

Related

Get-Recipient to Get-EXORecipient? Powershell and Exchange

Had a quick and hopefully easy question for you guys. I've tried googling and searching but I haven't been able to find much info.
We've been asked to try and streamline and improve some scripts we have. I was trying to convert some Get-Recipient commands to the newer and quicker Get-EXORecipient module.
I'm having some issues with the below though and would appreciate any help or advice:
As part of one of my scripts, I use the below command to find a specific DDL. This works fine
$var1 = Get-DynamicDistributionGroup -Identity "DDLName"
The issue I have is trying to get details from this DDL using the new module
Extract of old code which works but is quite time consuming depending on the size of the DDL
$var2 = Get-Recipient -RecipientPreviewFilter $var1.RecipientFilter
The new code I'm trying which spits out an error
$var2 = Get-ExoRecipient -RecipientPreviewFilter $var1.RecipientFilter
The error I get from the above is "Get-ExoRecipient : RecipientPreviewFilter is not a supported parameter"
I haven't been able to find out how to apply the DDL filter to this command, I tried putting the entire filter in as a string but that didn't work either. That wasn't an ideal solution as the filter may change on the exchange side.
Would appreciate any help on this one!
Thanks
According to the Get-EXORecipient documentation, the -RecipientPreviewFilter parameter has been reserved for 'internal Microsoft use'.
You should be able to use the -Filter parameter instead though like this:
Get-ExoRecipient -Filter "Title -eq 'Teaching Staff'"
However, the format of the filter returned by the dynamic distribution group may differ slightly and require some changes before it can be used with -Filter

Get-ADUser Filter comparison [duplicate]

This question already has answers here:
Why doesn't $PSItem behave as expected when using a bracket-based -Filter argument?
(2 answers)
Closed 3 years ago.
I'm beginning in PowerShell and trying to make this line working :
(Get-ADUser -Filter {userPrincipalName -eq $($ListUsers[100].UserPrincipalName)} -SearchBase "..." -Properties *).distinguishedName
I tried a lot of different things but nothing worked.
The call of $ListUsers[100].UserPrincipalName) works 100% sure, I tried it outside of the line, so it's just a logical or syntaxic problem.
Could someone tell me how to get it to work ? Thanks
Use double quotes.
The -Filter argument to the Get-AD* cmdlets takes a string (!), not a script block (even though it looks like it, because braces can also be used instead of quotes).
Get-ADUser -Filter "userPrincipalName -eq '$($ListUsers[100].UserPrincipalName)'"
This way you get proper variable substitution. Note you must end up with a valid filter string, so putting single quotes around the values is necessary when those values are strings.
If you have many objects to fetch from AD, it can be beneficial to fetch them all in one go, instead of one-by-one in a loop. Consider this:
$ListUsers = #(<# ...list of items... #>)
# build LDAP filter string
$upn_filter = $ListUsers.UserPrincipalName -join ')(userPrincipalName='
$upn_filter = "(|(userPrincipalName=$upn_filter))"
$users = Get-ADUser -LDAPFilter $upn_filter
$users.distinguishedName
This builds an LDAP filter in the following form:
(|(userPrincipalName=A)(userPrincipalName=B)(userPrincipalName=C)(userPrincipalName=D))
which would be able to fetch 4 matching objects from AD in one step. Of course you can also build a "PowerShell-style" filter string, but I find the LDAP syntax a lot easier to handle, and it's shorter.
LDAP filter strings can get pretty long without the server complaining, and doing only one round-trip to the domain controller saves time.

Check for File in multiple directories with an IF statement Powershell

I am facing some problems in powershell. I want to be able to let a powershell command search for multiple directories.
With the name being a variable like "$VM_DISK=VM_DISK.vhdx" and let powershell search in that manor so that if that file exists in a folder such as C:\VM_DISK\ it exit the script.
I have already tried the "Get-Childitem" but it doesn't seem to work when I put my variable in it. Here is an example:
$VM_DISK= "Example.vhdx"
$search=Get-ChildItem -Path C:\VM_DISK\* -Filter $VM_DISK -Recurse
if ($search -eq $VM_DISK) {write-host "Goodbye!" exit} else {write-host "Continue"}
I just cant seem to figure out why this isn't working, hope some can figure it out.
You need to alter your if statement.
if ($search.Name -contains $VM_Disk)
This way you are comparing an Array of names (which is what you want, names of objects, not objects) to a name of particular object (to a string, basically).
This makes little sense in your case, tbh. Since $search would always include $VM_Disk or would be null if nothing was found.
So the proper way to test would be if ($search) (just like Mathias advised). Which would test if anything was returned. Which, basically equals what you are trying to do.

Powershell dot notation not selecting data

I'm having a problem getting Powershell to behave the way I'm expecting.
I'm trying to use get-wmiobject win32_networkconnection to list the mapped drives for the current user, so I can loop through the drives.
When I run $var = get-wmiobject win32_networkconnection | select -expand localname I get exactly what I expect: a list of the drive letters for the mapped network connections.
However, when I run $var = (get-wmiobject win32_networkconnection).localname I get nothing. It doesn't seem to be selecting the property correctly.
This is problematic, because, ideally, I'd like to loop over all the drives, and then select the various properties for each drive. Instead, it seems like I'll be forced to kludge together an iterator, and then iterate over all the variables one at a time (not very elegant, in my opinion).
I'm not super experienced with Powershell, so there may be something I'm missing. However, from what I've read, this should be working. Is this a limitation of get-wmiobject?
What you're trying to do only works in PowerShell 3.0 and newer versions. The official documentation is very vague:
What's New in Windows PowerShell 3.0
Windows PowerShell Language Enhancements
Windows PowerShell 3.0
includes many features [...] The improvements include
property enumeration, count and length properties on scalar objects,
new redirection operators [...]
This blog post goes a bit more into depth: New V3 Language Features
Yes, this is a limitation of PowerShell 2.0.
Your call to Get-WmiObject is returning an array. In PS2, you would need to pipe the array into something like Select-Object or otherwise iterate over it and reference each individual item.
In PS3+, you can use $array.PropertyName and it does that for you, returning an array of properties.
intead of select propertyName, you can use select -exp propertyName

Issue with trying to pass variable into [adsisearcher]

I apologize in advance if this is something simple, but I've been researching for a few days now and unable to resolve on my own or find another route to explore.
Essentially I have the below which works and returns exactly what I need:
([adsisearcher]'(&(objectClass=user (samaccountname='*dland*'))').FindOne().Properties['samaccountname']
which returns the username containing dland in it. I want to replace the dland with a variable ($usrNme1), but it errors out with "Unexpected token '$usrNme1'))'' in expression or statement."
I was able to get it working locally with using the ActiveDirectory module using the following:
Get-ADUser -Filter {SAMAccountName -like $usrNme1} | select-object -Property SAMAccountName
But unfortunately I cannot use that against other computers in this environment and have to find another way and this is as far as I've gotten to finding a replacement.
Any assistance here would be greatly appreciated :) This is the last piece of the puzzle for me and its frustrating being so close and not being able to figure it out! Thanks in advance for taking the time :)
Edit: Forgot to comment, this script is going to be pushed out and run locally on windows 7 machines, which is part of the reason why I can't use Get-ADUser.
Thanks,
David
Your query is a little malformed as it is missing a bracket after user but you can put variables in the string easily like in the following example. Variables placed inside double quotes will expand just fine* (Most of the time. Object parameters require subexpressions).
$accountname = "mcame*"
$query = "(&(objectClass=user)(samaccountname=$accountname))"
([adsisearcher]$query).FindOne().Properties['samaccountname']
Note: if you look at this question you will see issues doing the wildcard search that your are. If you have a large organization you might need to reconsider using leading and trailing asterices or whatever the plural is.
You original query
Aside from the bracket the reason it was not working was since you were using the single quotes. If you look at this resource it goes on to say
Comparative strings do NOT appear in quotation marks. A filter for the
displayName 'Philipp Foeckeler' would read as follows:
(displayName=Philipp Foeckeler).
Query should have worked without those inner quotes.
Try this:
$foo = '*jsm*'
([adsisearcher]"(&(objectClass=user) (samaccountname=$foo))")