Identifying 32/64bit Version via Powershell Script - arrays

I need to identify if the installed software (several times per host) is an 32bit or 64bit version. To do this I want to check the Execution Folder of the Service via powershell.
This is my first powershell script and I'm a bit lost. I would like to store the information of Get-WmiObject win32_service to a multidimensional array.
If I run the command selecting PathName, State and DisplayName the PathName will be shortened, for that I run this command several times. But don't know how to get is in the right fields of the array or get the right fields in my foreach
Here is what I got so far:
`$ServiceArray = #()
$ServiceArray[] = Get-WmiObject win32_service | ?{$_.Name -like 'foo_*'} |
Select PathName
$ServiceArray[][] = Get-WmiObject win32_service | ?{$_.Name -like 'foo_*'} |
Select State
$ServiceArray[][][] = Get-WmiObject win32_service | ?{$_.Name -like 'foo_*'}
| Select DisplayName
foreach($array in $ServiceArray[])
{
if ($array.Contains(\bin\test\win64\test.exe)
{
$ServiceArray[][][][] = "win64"
}
else
{
$ServiceArray[][][][] = "win32"
} `
I know that it does not work this way, but I don't know how it works correct, either.

You can select multiple properties in the same statement with Select-Object:
$ServiceArray = Get-WmiObject Win32_Service |
Where-Object {$_.Name -like 'foo_*'} |
Select PathName,State,DisplayName
You can also use Select-Object with a calculated property to add the bitness based on the PathName argument if needed:
$ServiceArray = Get-WmiObject Win32_Service |
Where-Object {$_.Name -like 'foo_*'} |
Select PathName,State,DisplayName,#{Name='Bitness';Expression={if($_.PathName -like "*Win64*"){"Win64"}else{"Win32"}}}

You can select multiple properties. You were almost there. Edited your code a little.
$ServiceArray = #()
$ServiceArray = Get-WmiObject win32_service | ?{$_.Name -like 'foo_*'} | Select PathName,State,DisplayName,Architecture
foreach($Element in $ServiceArray)
{
if ($Element.PathName.Contains('\bin\test\win64\test.exe'))
{
$Element.Architecture = 'win64'
}
else
{
$Element.Architecture = 'win32'
}
$Element
}

Related

PowerShell: Add New Value to Array

Using PowerShell I retrieve information from multiple ActiveDirectory groups and output it to a single CSV file. To each row I want to add the name of the group, in addition to the information retrieved. How can I achieve this?
Desired Result:
"CN","Department","co","Company","Group"
"ABCDEF","Media","UK","Global Entertainment","XXX"
Current Result:
"CN","Department","co","Company"
"ABCDEF","Media","UK","Global Entertainment"
My PowerShell code:
#Roles to check membership for
$Roles= #(
'XXX'
'YYY'
)
$FolderName = "C:\"
$OutputAD = #()
foreach ($role in $Roles) {
$GroupMembers = Get-ADGroupMember -identity $role | select name
$GroupMembersArray = $GroupMembers | Foreach {"$($_.Name)"}
$GroupMembersArray | ForEach-Object {
$UserLookup = Get-ADUser -Filter "Name -eq '$_'" -Properties CN,Department,co,Company | Select-Object CN,Department,co,Company
$OutputAD += $UserLookup
}
}
$OutputAD | Export-Csv "$FolderName\Membership $(get-date -Format yyyy-MMM-dd-HH-mm-ss).csv" -NoTypeInformation
Found the solution. In Select-Object you can add a calculated property.
Example: Select-Object CN,Department,co,Company,#{n='Role';e={$role}}

How do i compare every PC name from a multiobject array to a single object array

Hi Powershell newbie alert,
I am trying to compare the computer name of my $getADComp function (CN) with the output of $WSUSArr.
I want to know which PC's are in the WSUS but not and the AD and vice versa. I want the PC names to go in 2 diffrent result arrays so i can use these again later
Eventually i want something like this
$separator = "."
$GetWSUSComp = Get-wsuscomputer -UpdateServer $wsus
$GetADComp = Get-ADComputer -Filter * -Property CN, CanonicalName, Description | Select-Object CN, CanonicalName, Description
$WSUSArr = #()
for ($i = 0; $i -lt $GetWSUSComp.Count; $i++){
$WSUSArr += $GetWSUSComp[$i].FullDomainName.split($separator)[0].ToUpper()
}
Compare-Object -ReferenceObject $WSUSArr -DifferenceObject $GetADComp
If there is a more efficient way to do this feel free to make use of another method (hash table, etc.)
I have another array which is called $WSUSArr which contains the names of all the computer that are connected to the WSUS server i will have to compare those two lists with eachother.
Why not go for an array of objects ?
$GetADComp = Get-ADComputer -Filter * -Property CN, DistinguishedName, Description |
Select-Object CN, DistinguishedName, Description
This way you avoid gathering all properties with -Property * where you only want three.
Every property of items in the array can be accessed by using
$GetADComp[$index].CN
$GetADComp[$index].DistinguishedName
$GetADComp[$index].Description
and compared with an array of CN's like
$GetADComp | Where-Object { $_.CN -eq $WSUSArr[$index] }
In order to compare the computer CN's with the objects returned from the Get-ADComputer cmdlet:
1.
Get the computers that are both in AD and in the WSUS array.
If you want this to be a simple string array of just the CN's, do this:
$ADcomputersInWsus = $GetADComp | Where-Object { $WSUSArr -contains $_.CN } | Select-Object -ExpandProperty CN
Without the Select-Object, this will get you an array of objects with three
properties: CN, DistinguishedName, Description.
$ADcomputersInWsus = $GetADComp | Where-Object { $WSUSArr -contains $_.CN }
# An object array like this is perfect for saving as CSV:
# $ADcomputersInWsus | Export-Csv -Path 'X:\ADcomputersInWsus.csv' -NoTypeInformation
2.
Get a list of computers that are in WSUS, but not in AD:
# ($GetADComp).CN returns an string array with just the CN's, just like the $WSUSArr
$WsusComputersNotInAD = $WSUSArr | Where-Object { ($GetADComp).CN -notcontains $_ }
3.
Get a list of AD computers that are not in WSUS:
$ADcomputersNotInWsus = $GetADComp | Where-Object { $WSUSArr -notcontains $_.CN } | Select-Object -ExpandProperty CN
Note, the $WsusComputersNotInAD is derived from the $WSUSArr string array and is therefore also an array of strings, not objects.
To save that to file, either use:
$WsusComputersNotInAD | Out-File -FilePath "C:\XXX\XXX\WSUSCompNotInAD.txt" -Force
Or convert to an object array and use Export-Csv like the other results:
$WsusComputersNotInAD | ForEach-Object { [PsCustomObject]#{'ComputerName' = $_}} |
Export-Csv -Path "C:\XXX\XXX\WSUSCompNotInAD.csv" -NoTypeInformation

Can I combine these two arrays

I have some simple Exchange Powershell I have written. I would like to list the UPN, Displayname, Item Count, and Item Size into a single CSV. However I have only been able to successfully push the data to two arrays and then manually combine them. Here is my code.
$MailBoxs = Get-Mailbox * | Select UserPrincipalName -ExpandProperty UserPrincipalName | Sort-Object UserPrincipalName
$Mailboxs2 = $MailBoxs.Where({ $_ -ne $null })
ForEach($MailBox2 in $MailBoxs2) { Get-MailboxStatistics $Mailbox2 | Sort-Object TotalItemSize –Descending | Select #{label=”User”;expression={$_.DisplayName}},#{label=”Total Size (MB)”;expression={$_.TotalItemSize.Value.ToMB()}},#{label=”Items”;expression={$_.ItemCount}} | Export-CSV "C:\T2\MailBoxSize.csv" -Append -NoTypeInformation }
ForEach($MailBox2 in $MailBoxs2) { $Mailbox2 | Export-CSV "C:\T2\MailBoxSize2.csv" -Append -NoTypeInformation }
Basically the second CSV gives me two fields for some reason the SMTP address and some random Length field, It also gives me a leading whitespace. If anyone has any ideas on how to clean this up I would love to hear them. Thanks for your time.
The multiple select statements were unnecessary. Here's a bit simplified way:
$mailboxes = #(Get-Mailbox *).
Where({$_.UserPrincipalName}) |
Sort-Object -Property UserPrincipalName
foreach ($box in $mailboxes) {
Get-MailboxStatistics $box.UserPrincipalName |
Sort-Object -Property TotalItemSize -Descending |
Select-Object -Property #(
#{L='UPN';E={$box.UserPrincipalName}}
#{L='User';E={$_.DisplayName}}
#{L='Total Size (MB)';E={$_.TotalItemSize.Value.ToMB()}}
#{L='Items';E={$_.ItemCount}}
) |
Export-Csv -Path 'C:\T2\MailBoxSize.csv' -NoTypeInformation -Append
}

Calling an Array in PowerShell

I have a string array $Exclude which I want to put into a filter in a Get-WMIObject cmdlet. I have added it at the end but it does not work.
How can I filter out the services that are listed in that array?
$ServicesToExclude = "RemoteRegistry,CpqNicMgmt"
$Exclude = $ServicesToExclude.split(",")
$Services = Get-WmiObject -Class Win32_Service -Filter {State != 'Running' and StartMode = 'Auto' and Name -ne $Exclude}
$Result = foreach ($Service in $Services.Name)
{
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$Service" |
Where-Object {$_.Start -eq 2 -and $_.DelayedAutoStart -ne 1}|
Select-Object -Property #{label='ServiceName';expression={$_.PSChildName}} |
get-Service
}
If ($Result.count -gt 0){
$Displayname = $Result.displayname
[string] $Line = "`n-----------------------------------------"
$Api.LogScriptEvent( 'Stopped_Auto_Services.ps1',1234,4,"`nStopped Automatic Services$Line `n$($Displayname)")
Filtering an array out of a list is not done on the WMI side. Instead, you should use Where-Object to filter out those services which name is contained in $Exclude.
$Services = Get-WmiObject -Class Win32_Service -Filter {State != 'Running' and StartMode = 'Auto'} |
Where-Object {$Exclude -notcontains $_.Name}
WMI queries do not work well with arrays and need to be done a different way. If you want to keep the filtering on the server side, you can do some work prior to running the command by creating a filter string as shown here:
$Exclude = "RemoteRegistry","CpqNicMgmt"
$StringBuilder = New-Object System.Text.StringBuilder
[void]$StringBuilder.Append("State != 'Running' AND StartMode = 'Auto' AND ")
[void]$StringBuilder.Append("($(($Exclude -replace '^(.*)$','Name != "$1"') -join ' AND '))")
$Query = $StringBuilder.ToString()
$Services = Get-WmiObject -Class Win32_Service -Filter $Query
There may be better ways to accomplish this, but this was the first thing that I could think of to accomplish the goal of your question.

PowerShell kill multiple processes

I am trying to accomplish the following via PS and having an issue getting what I need. I have tried many different formats for writing this script and this is the closest I have gotten I think.
I run the following and no error, but no result either.
$softwarelist = 'chrome|firefox|iexplore|opera'
get-process |
Where-Object {$_.ProcessName -eq $softwarelist} |
stop-process -force
Here is another example that I was trying, but this one wasn't terminating all the process I was providing (IE in W8.1).
1..50 | % {notepad;calc}
$null = Get-WmiObject win32_process -Filter "name = 'notepad.exe' OR name = 'calc.exe'" |
% { $_.Terminate() }
Thanks for any help!
Your $softwarelist variable looks like a regular expression, but in your Where-Object condition, you're using the -eq operator. I think you want the -match operator:
$softwarelist = 'chrome|firefox|iexplore|opera'
get-process |
Where-Object {$_.ProcessName -match $softwarelist} |
stop-process -force
You can also pass multiple processes to Get-Process, e.g.
Get-Process -Name 'chrome','firefox','iexplore','opera' | Stop-Process -Force
# First, create an array of strings.
$array = #("chrome","firefox","iexplore","opera")
# Next, loop through each item in your array, and stop the process.
foreach ($process in $array)
{
Stop-Process -Name $process
}

Resources