Variable from read-host not working in select-object - powershell

i encountered a problem when trying to build a small read-host script that pipes the result into an AD script:
when doing an AD search, i can select objects like that:
get-aduser exampleuser | select-object name,enabled
though when i enter
name,enabled
into the read-host that stores the input as a variable which later gets used in the script, it turns into this:
name,enabled
------------
{}
instead of this (when typing it manually)
get-adcomputer CTXTEST | select-object name,enabled
name enabled
---- -------
CTXTEST False
I assume that I overlook something rather simple, but I tried a lot of things and didnt find a solution through master Google.

Thats because the Select-Object cmdlet takes an array of strings, the Read-Host cmdlet only returns a singe string, even if the string contains a comma.
You can simply create an array by splitting the input on a comma. (I also use the regex to trim whitespaces):
$selectResult = (Read-Host "Which properties?") -split '\s*,\s*'

Related

Issues getting get-adcomputer to recognize variable in filter

Below is the code I am working with. I have verified that the initial import-csv is working as it should be, and if I change out the variable object for a concrete object, the script works as it should. It just seems to not recognize/use the variable the way that it should.
$CSVOutput = "C:\temp\output.csv"
$Output = foreach($u in $userlastname)
{
Get-ADComputer -Filter {Description -Like '*$u*'} -properties Description | Select Name, Description
}
$Output | Export-Csv $CSVOutput
If I replace the $u in the filter with one of the values from the $userlastname variable, it works, but it just runs the search with the set value as many times as it runs the foreach loop. I am expecting to see several different computer objects that have the different values from $userlastname in their description. Currently it returns nothing, as if it found no values that matched in the description field.
While it’s technically possible to use a scriptblock as a filter in the ADCommands, it isn’t recommended - use a string instead:
Get-ADComputer -Filter "Description -like '*$($u.name)*'" -Properties ...
Using a string will solve your variable substitution issue.
ETA: Comments indicated that you were getting #{Name=User} as the expansion for $u in the filter expression. This is because $u was a structured [PSCustomObject], and you were looking for a single field from that object. The easiest way to get the value of the desired field of the object is simply to use the PowerShell evaluation construct, as given in the edited answer.

Find missing prefix for computer name

I am trying to write a script that will automatically find the full asset tag based on the ID of the computer.
For example:
The PC ID is: PC0001
$computerID = PC0001;
But the full asset tag that I need is: WKSPC0001
But these asset tags might have different prefixes, for example DSTPC0002, TBLPC0003 etc. But they all have common pattern: Prefix+PC+ID (the ID is unique and there is no repetition).
I am trying to figure out how to write a query for that in PowerShell but I cant figure it out. I've tried:
$current = Get-ADComputer -Filter {Name -like "*$computerId.text"} |
Select -Property Name
But I was having issues to get it to work.
What am I doing wrong?
A few observations.
You want $computerId to be a string, so $computerID = "PC0001";
The filter expression for Get-ADComputer is expected to be a string also, using curly braces here is wrong. So Get-ADComputer -Filter "..."
Powershell can expand variable values in strings, but it only does that in double-quoted strings. "Name -like '$variable'" will work, but 'Name -like "$variable"' won't.
There is no .text in your $computerId variable. It's a plain string.
Knowing that, try:
$current = Get-ADComputer -Filter "Name -like '*$computerId'"
Other notes
Don't do ... | Select Name unless you really must. Storing the computer object itself will be more versatile. You can do $current.Name when you need it anytime.
Querying the AD with a filter that begins with a wildcard is slow. Try to avoid.
If you have a fixed number of possible prefixes, an LDAP filter like the following will be much faster:
$current = Get-ADComputer -LDAPFilter "(|(cn=WKS$computerId)(cn=DST$computerId)(cn=TBL$computerId))"

(Powershell) Ensure variable is interpreted as literal string

I'm working on Powershell scripts to take a selection of AD principal names, pull full DNs for them, and take action on the accounts in question.
The active parts are all working fine now, but I've run into an unfortunate problem - several of the AD objects have names that start with $, IE $DUPLICATE-c1870
This means that when I output them to a variable, then read that variable in later, it tries to interpret the variable. For the time being I've bodged a fix by manually defining
$duplicate='$duplicate'
But that A: depends on that being the only such name and B: offends my sense of elegance.
I'm fairly new to powershell, so it's entirely possible I'm missing something obvious, but I can't find a way to either add the single quotes to the string (because it's pulled from a variable itself) or to the insertion step.
Relevant section of code follows:
# Import AD Module
import-module ActiveDirectory
# Define fake variable for edge cases
$duplicate='$duplicate'
# Import the data from CSV file and assign it to variable
$Imported_csv = Import-Csv -Path
"C:\scripts\ADremediation\threecomputers.csv" -delimiter ';'
$Imported_csv | ForEach-Object{
# Retrieve DN of User.
$1=$_.PrincipalName
Write-output $1 |timestamp
$UserDN = (Get-adcomputer -Identity $1).distinguishedName
Echo $userDN
( Get-ADComputer -Identity ('{0}' -f $1) ).distinguishedName
try using the format operator, not sure it will help, but it might

Read-Host execution order

I'm trying to do the following:
Display a list from a multidimensional array:
$AssetList | Where-Object {$_.agenttype -eq "N"} | Select-Object number, hostname, agentstatus | Write-Output
Then read in a number from the user:
$Victim = Read-Host -Prompt 'Enter the number of the host you want rid of...'
What happens in reality is the Read-Host is displayed before the Write-Output. How can I flip it and reverse it?
I think the issue here is that you're using Write-Output (which writes to the output stream for your script/function). If you just want the data to be displayed on the console before the Read-Host cmdlet, try using Out-String | Write-Host. You can probably get away with just Out-String on its own.
Out-String
The Out-String cmdlet converts the objects that Windows PowerShell
manages into an array of strings. By default, Out-String accumulates
the strings and returns them as a single string, but you can use the
stream parameter to direct Out-String to return one string at a time.
This cmdlet lets you search and manipulate string output as you would
in traditional shells when object manipulation is less convenient.
https://technet.microsoft.com/en-us/library/hh849952.aspx

-contains operator failing when it should not be

I am writing a script to create new AD users and doing a test to make sure an existing displayname is not found because New-ADUser will fail if one is found. Can someone help me understand why I might never get a true outcome from the following array list?
$ExistingDNs= Get-ADUser -SearchBase 'OU=whateverOU' -Filter * -Property displayname | select displayname | Out-string
My goal is to load up all the existing displaynames in an OU and then compare this with a method in which I read a CSV file to create a displayname, but I can't seem to get it to return as true.
If ($ExistingDNs.DisplayName -contains $DisplayName)
I was told this should work, but when I try looking at the array it is empty? Only $ExistingDSs shows me the list visually in ISE, where I can see clearly that a name exists that is the same in my CSV file, but the match is never found and never comes back as true even though both are string values I believe.
I'm sure it is because you are using Out-String which breaks the object array that select displayname would have created. Currently your $ExistingDNs is a newline delimited string when you really want a string array.
$ExistingDNs = Get-ADUser -SearchBase 'OU=whateverOU' -Filter * -Property displayname | select -ExpandProperty displayname
Also we use -ExpandProperty so you just end up with an array of strings. That way your conditional statement can be reduced to...
If ($ExistingDNs -contains $DisplayName)