How to put computers on a network into a variable in PowerShell? - powershell

I've been using these lines of code:
$204computernames = Get-ADComputer -searchbase $sb -filter * | ?{$_.name -like "ptfg*-061*"} | select name
$onlineComputers = $204computernames |Where-Object { Test-Connection $_.name -Count 1 -Quiet }
to grab all of my computers on my network and put them into a variable so I can push all of my documents, updates, etc to them so that I dont have to go to each computer individually to get the files I want where I want. When I take the variable and put it into a line of code like this
Test-Connection $onlineComputers
I get errors like this:
Test-Connection : Testing connection to computer '#{name=PTFGW-0613618TN}' failed: A non-recoverable error occurred during a database lookup
At line:1 char:1
+ Test-Connection $onlineComputers
I'm assuming after extensive testing in different codes that there is a problem with the way my variable stores its values. Does anyone know how I can fix this issue?

As #boxdog already pointed out in the comments, with | select name you get objects with the single property Name. Therefore, you don't get a list of computer names, but a list of objects that have the computer name in the Name property. You can work with that and access each computer name like .Name.
But to solve your problem, you can replace | select name (which stands for | Select-Object -Property Name) by | Select-Object -ExpandProperty Name. That way, you filter out only the computer name and expand the result to just this property. After that, you really have just a list of computernames (an array of string objects).

Related

Modify local users property description in Powershell 4.0

I would like to modify the description property from local users.
I can retrieve all local users name and description in two ways.
One using WMI Win32_UserAccount class:
Get-CimInstance -ClassName Win32_UserAccount -Filter "LocalAccount='True'" | Select-Object -Property name, description | FL
And one using ADSI:
$Computername = $env:COMPUTERNAME
$adsi = [ADSI]"WinNT://$Computername"
$Users = $adsi.Children | Where-Object {$_.SchemaClassName -eq 'user'}
ForEach ($u in $Users) {
$u | Select-Object -Property Name, Description
}
However, I can't figure out how using commands similar to the ones above I can modify the local user property description. I did research and only found out how to do GETS and not SETS.
My final objective is to put this code in an Ansible playbook and run it in several remote servers. If you have an idea of how to solve this or how to help me I would be grateful.
Working with ADSI can be very tricky but, its super helpful since it usually doesnt rely on 3rd party modules.
Without going super in depth on ADSI, heres the easiest way you can change, or add a value to a property, the description property in this case:
$adsi = [ADSI]"WinNT://$env:Computername"
$User = $adsi.Children.Find('Abraham')
$User.Description = "Hi, this is a description"
$User.SetInfo()
Using $User.SetInfo method, we can write the changes to the database. It's not a method you would get either when piping to a Get-Member. Unfortunately, it's one that you would need to know already. Using Dot Notation we can reference the property you'd like to change, then assigning it a value just like we would when assigning a value to a variable: $var = value.

Group Membership of Servers

I want to get "WSUS" group membership of my ad computers (servers) in the entire domain.
The PowerShell Script is use:
$csvInfos=#()
$allservers=#(Get-ADComputer -SearchBase "OU=BRLN-Servers,OU=OU-BRLN,OU=DE,OU=Locations,DC=bla,DC=bla,DC=bla" -Filter * -Properties *)
foreach($server in $allservers){
$customobject = new-object -TypeName PSObject -Property #{
'Servername' = $server.Name
'WSUS Gruppen' = ($server | get-ADPrincipalGroupMembership |?{$_.Name -like '*wsus*'} | Select-Object Name )
'OS' = $server.OperatingSystem }
$csvinfos+= $customobject }
$csvinfos | export-csv c:\temp\wsus_server_groups.csv -Delimiter ";" -NoTypeInformation
The Script works ... kinda ok I think but I got some problems with the result.
The group names are displayed as #{Name=Groupname}, Is it possible that the group name will be displayed as "Groupname"?
If a server is in more than 1 "WSUS"-Group I get System.Object[]. How can I get all the groups the server is a member of as result?
I think my problems are not that difficult to fix, but I do not have that xp with PowerShell to do it on my own.
Best regards
Michael
EDIT: ORIGINAL QUESTION IS SOLVED ... BUT HERE IS A NEW PROBLEM!
The script is used on 3 different domains (US, EU, ASIA) The domain are built the same. Same OU structure, same settings, same everything.
Based on the updated script I am able to get the results I want for 2 of the 3 domains. On the third domain I get an error with the get-adprincipalgroupmembership command:
Get-ADPrincipalGroupmembership : The server was unable to process the request due to an internal error.
I googled very much about this error. Even here on stackoverflow is a topic with that error:
Get-ADPrincipalGroupMembership Fails when any user group name has "/"
but I don't think that is describes the same situation as mine. Or maybe I am blind....
so: Is there a way to fix that problem / error or do I have to use another command that does the same as Get-ADPrincipalGroupmembership?
Thank you, Michael
Use The -ExpandProperty parameter for the Select-Object property to get the property value without the column header.
See the Differnece:
Get-Process explorer | Select Name
Name
----
explorer
Get-Process explorer | Select -ExpandProperty Name
explorer
Join the Multiple results with comma , (in case there's only one element, no join occur)
To convert an array to string, you need to parse it in someway, for example join it with commas
Example:
1..3 # Array of 3 elements
1
2
3
(1..3).ToString() # Convert it to string will result:
System.Object[]
(1..3 -join ',').ToString() # using join will result:
1,2,3
# for one element, there's no effect:
(1 -join ',').ToString()
1
So, update this line to solve both problems:
'WSUS Gruppen' = ($server | get-ADPrincipalGroupMembership |?{$_.Name -like '*wsus*'} |
Select-Object -ExpandProperty Name ) -join ','

Get-ADComputer save results as string array?

What is the output format of Get-ADComputer? I'm trying to do something like this to take an inventory.
[string[]]$server_list = Get-ADComputer -Filter * -Property Name # Select-Object Name
However, when I use $server_list in a foreach, I see the object curly brackets like so
foreach ($machine_name in $server_list) {
"processing : $machine_name";
}
output:
#{Name=some-machine-name-123-here}
I just need the actual name value, how do i get that?
The -Property Name parameter is unnecessary, as Get-ADComputer always retrieves the Name property. (This doesn't select only the Name property, as you seem to have thought.)
Rather than -Property Name, append | Select-Object -ExpandProperty Name to your Get-ADComputer command line.
So, my query returned a different result. Thus you might need to do a little work on this.
Basically, -Property says that you want an object with a certain field. Select does more or less the same thing.
If you want to keep your existing solution, expand the property instead of selecting it. This is the best way to do that:
[string[]]$server_list = (Get-ADComputer -Filter * -Property Name).Name
You returned #{} which is powershell's way of representing an object inside a string. In this case, an object that contains properties about your ADComputers, of which you chose to only include "Name". If you included additional properties, you would see a larger comma separated list of type=value.
You can actually remove -Property Name, however this will take longer to run, since you're filtering on the right. (Gathering a lot of data and THEN filtering it to only Name.)

-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)

How to use a user's input variable as a search query in Get-ADComputer

thank you for visiting my first question on this website.
The purpose of this PowerShell script is to query the user for a partial name of a pre-existing computer on the domain. After the query is complete it retrieves the full computer name from a specific OU in active directory, and copies this full computer's name it to the user's clipboard. This is to help save time to the people I work with at the help desk(including myself) who have to perform this action manually every day.
Note:I'm pretty sure the problem isn't with the two 'Get-ADComputer' lines because if I manually enter the full computer name in the script it works exactly as intended. The issue seems to be either with how I'm defining the user input, or how it's being passed along to the variable($PCName) inside of the 'Get-ADComputer' cmdlet.
Here is the script in its entirety, the only thing I omitted is the specific active directory OU - I know it's looking in the right OU, because the lines taken individually and with a manually PC Name entered work great.
$global:PCName=(Read-Host "Enter partial PC name")
write-host "You entered the partial PC Name: $PCName"
return $PCName
#PCName Information Table Display.
Get-ADComputer -SearchBase 'OU=(Disregard)' -Filter 'Name -like "*$PCName*"' -Properties IPv4Address | Format-Table Name,DNSHostName,IPv4Address -A
#Progress indicator advisory message.
Write-Output "Converting $PCname to full computer name and copying result to your clipboard."
#Clip Line - Retrieves full PC name and copies resolved PC name to clipboard.
Get-ADComputer -SearchBase 'OU=(Disregard)' -Filter 'Name -like "*$PCName*"' | Select Name -ExpandProperty Name | Clip
#End of script advisory message.
Write-Output "Full PC Name:$PCName - Resolved and copied to clipboard."
If there's any other fault to be pointed out, I would appreciate it. I have been using PowerShell for less than a week and am a new programmer overall. I've performed no less than 40 google queries and spent at least 3 hours trying to get this to work.
Thank you!
do {
$computerName = read-host "Enter partial computer name [blank=quit]"
if ( -not $computerName ) {
break
}
$sb = [ScriptBlock]::Create("name -like '*$computerName*'")
$computer = get-adcomputer -filter $sb
if ( $computer ) {
$computer
$computer | select-object -expandproperty Name | clip
"Copied name to clipboard"
}
else {
"Not found"
}
""
}
while ( $true )
In PowerShell, single and double quotes each have a different meaning and significance. Variables will only be expanded in double quotes.
Your query does not work because you use single quotes for the parameter:
-Filter 'Name -like "*$PCName*"'
In this string, $PCName will not be replaced by its value. The double quotes are not significant here, because inside a single quoted string, they are just characters.
You can build the parameter like this:
-Filter ('Name -like "*' + $PCName + '*"')
Additionally, you should remove the return statement and in your example there is no need to create a global variable $global:PCName, you can use $PCName instead
Your main issue is how you were quoting your -Filter. Variables do not expand inside single quotes. Your query was looking for a computer matching the string literal $pcname as supposed to the variable contents.
Also you make the same call twice which is inefficient. You should also know that it is possible to have more than one match with this so you need to be aware of/ account for that possibility.
$PCName=(Read-Host "Enter partial PC name")
write-host "You entered the partial PC Name: $PCName"
#PCName Information Table Display.
$results = Get-ADComputer -SearchBase 'OU=(Disregard)' -Filter "Name -like '*$pcname*'" -Properties IPv4Address
$results | Format-Table Name,DNSHostName,IPv4Address -A
#Progress indicator advisory message.
Write-host "Converting $PCname to full computer name and copying result to your clipboard."
#Clip Line - Retrieves full PC name and copies resolved PC name to clipboard.
$results| Select -ExpandProperty Name | Clip
#End of script advisory message.
Write-host "Full PC Name:$PCName - Resolved and copied to clipboard."
I don't see a need for a global variable here so I removed it. Changed all the Write-Output to Write-Host as that is how you were treating them. If nothing else you have them mixed together so picking one would be more my point.
I had a similar issue with filter (building into an ASP application) and solved it by using curly brackets.
$searchterm = "*$($PCName)*"
-Filter {Name -like $searchterm}
The extra $() is most likely unnecessary in this particular instance as we aren't doing anything with the variable, but it's a habit of mine now.