Problem with declaration of variables in powershell - powershell

I have declared 2 PowerShell variables
$prm=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" | Select-Object Name, Vendor, Version
$rgteng=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'WKFS'" | Select-Object Name, Vendor, Version
I want the output of this variable to a text file o/p #{Name=Wolters Kluwer Financial Services Regulatory Reporting FRA Param 11.2.0; Vendor=Wolters Kluwer Financial Services; Version=11.2.0}, I want this o/p to a text file.
I have tried using Write-Output and Write-Host, but none of them gives right o/p

What happens there looks like this (just the big picture):
Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" creates an WMI object and pipes it to the next command
Select-Object Name, Vendor, Version transforms that object into a new PSCustom type object (more like a table version of your WMI object wtih only the desired information)
Then it gets messy :
if you use write-host or display it on the screen , the output will be formatted according the the powershell's settings (those settings can be changed by altering xml files)
if you use export-csv you basically use a convertto-csv | out-file c:\sometheing.txt + some formatting rules that are applied. (I think the UTF-8 type of the file is changed but I am not sure...)
So if you want to know exactly how your variable / file will look like, without having powershell formatting interfering with your work, use convertto-csv | out-file.

Related

Get serialnumber from asset list

Started in recent weeks in a Junior infrastructure role, and begun playing around with powershell to help save some time here and there.
I am trying to do the following:
1- I'm port a CSV file with a single column names asset
2- Perform a "ForEach" check on each line to find the device's serial number
3- Output results to a CSV with two column "asset" and "serialnumber"
I have dabbled in a few areas, and am currently sitting at something like this:
$file1 = Import-Csv -path "c:\temp\assets.csv" | ForEach-Object {
$asset = $_.asset
}
wmic /node:$asset bios get serialnumber
Export-Csv -Path "c:\temp\assetandserial.csv" -NoTypeInformation
As you may or may not see, I tried to set the column labelled "asset" as the variable, however, not sure if I placed it correctly.
I have tried a few other things, but honestly it's all new to me, so I haven't the foggiest idea where to go from here.
wmic is deprecated, and, for rich type support (OO processing), using PowerShell-native cmdlets is preferable in general.
wmic's immediate PowerShell counterpart is Get-WmiObject, which, however, is equally deprecated, in favor of Get-CimInstance.
Important: The command below uses Get-CimInstance, but note that the CIM cmdlets use a different remoting protocol than the obsolete WMI cmdlets. In short: To use the CIM cmdlets with remote computers, those computers must be set up in the same way that PowerShell remoting requires - see this answer for details.
Get-CimInstance Win32_BIOS -ComputerName (Import-Csv c:\temp\assets.csv).asset |
Select-Object #{ n='Asset'; e='PSComputerName' }, SerialNumber |
Sort-Object Asset |
Export-Csv c:\temp\assetandserial.csv -NoTypeInformation
Note the use of member-access enumeration to extract all .asset values directly from the collection of objects returned from Import-Csv.
All computer (asset) names are passed at once to Get-CimInstance, which queries them in parallel. Since the ordering of the responses from the targeted remote machines isn't guaranteed, Sort-Object is used to sort the results.
A calculated property is used with Select-Object to rename the automatically added .PSComputerName property to Asset.

How to put computers on a network into a variable in 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).

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.

Import Member Group attribute from AD to .csv

I am using ActiveRoles Management Shell under Windows XP , Powershell ver 2 for retreiving Group data from AD and exporting it to csv file.Everything works well apart from getting member list it is so long that the program is writing in excel cells under member column System.String[] each time.How can I make it write whole list there , is it possible ? I could actually have only the name of the member don't need whole connection path.Is there a possibility to get from group field member only name ?
get-QADGroup -SearchRoot 'ou=User,ou=Groups,ou=PL,dc=test,dc=com'| Select-Object -property name,sAMAccountName,description,groupType,member|Export-Csv -path Y:\csv\groups.csv
Ok, as Matt suggested you want an expression in your Select statement. I would use something like this:
#{l="Members";e={$_.Members -join ", "}}
Which when inserted into your one-liner looks like:
get-QADGroup -SearchRoot 'ou=User,ou=Groups,ou=PL,dc=test,dc=com'| Select-Object -property name,sAMAccountName,description,groupType,#{l='Members';e={$_.member -join ", "}}|Export-Csv -path Y:\csv\groups.csv -NoTypeInfo
I also added -NoTypeInfo to the export to skip the annoying lead line telling you it's a PSCustomObject or some such and actually just get your data (and headers).
I don't have access to the quest cmdlets so I will provide a solution based on cmdlets from the activedirectory
Get-ADUser -Filter * -SearchBase "OU=Employees,DC=Domain,DC=Local" -Properties memberof |
Select-Object name,#{Name="Groups";Expression={$_.MemberOf |
ForEach-Object{(Get-ADGroup -Identity $_).Name + ";"}}} |
Export-Csv C:\temp\TEST.CSV -Append
To make sense of this by line:
Should be self explanatory. Get all users in the OU defined. You would need to change this to suit your needs.
The select statement appears normal until you reach the calculated property Groups.
What continues from the previous line is cycling through every group that an individual user is a memberof and get the friendly name of the group (MemberOf returns DistinguishedName's). At the end of every group add a ";" as to not interfere with the CSV that will be made later.
Append to a csv file.
For brevity I didnt include all the extra properties that you included in your Select-Object statement. You would obviously need to add those back as the need fits.
Since you have the use the Quest cmdlets you could just change member in your select statement to the following:
#{Name="Groups";Expression={$_.member | ForEach-Object{"$_;"}}}
I cannot test if this will work. It is based on the assumption that member contains a simple name as supposed to a distinguishedname

Referencing variables that are not strings

I want to reference properties selected from a cmdlet and then use them later on in my script as $mailboxarray.totalitemsize and $mailboxarray.totalitemsize
This is breaking later on in my script as I assume it doesn't like the type of object it is. How can I make anything I pull into the references a string? At the moment I am getting "No mapping exists from object type System.Management.Automation.PsObject to a known managed provider type". My code at the moment: the first command works fine but I can't use expandproperty when there are multiple entries like line two?
$recipienttype = Get-mailbox -identity $recordset.PrimarySmtpAddress | Select -expandproperty RecipientTypeDetails
$mailboxarray = Get-Mailbox -identity $recordset.PrimarySmtpAddress | Get-MailboxStatistics | Select-object totalitemsize, lastlogontime