Powershell script to pull remote pc serial number then match against an xlsx file then match against another and output only needed info - excel

hey im trying to build a powershell script that will pull a serial number from a remote pc and then match that against an xlsx file which would then match a column against another xlsx file i have gotten to the point where i can pull the remote sn and have everything put in to a csv output but i am having issues matching the data then filtering based on the match and then outputting only what i need im new to scripting so im pretty sure its more my lack of experiance than anything else this is my code so far
$computers = Get-Content c:\script\computerlist.txt
Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber| Format-Table |out-file C:\script\computerinfo.txt
$computerinfo = Import-Excel C:\script\compDB.xlsx
$userinfo = Import-Excel C:\script\userDB.xlsx
$Computerinfo[2].SERIAL -eq
$Computerinfo[2].DATE_ADDED
$Computerinfo[2].OS
$Computerinfo[2].MODEL
$Computerinfo[2].USER
$userinfo[2].NAME_FIRST
$userinfo[2].NAME_LAST
$userinfo[2].NT_USERID
''
'Computer Info'
'----------'
$computerinfo ,$userinfo | Format-Table - | Out-File c:\script\computerinfo.csv

First you need to save the wmi information to a variable:
$WMIinfo = Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber
Then you would need to loop through the spreadsheet and compare to data in Computer spreadsheet. If it matches loop through user spreadsheet for match:
foreach ($CompEntry in $Computerinfo) {
if ($WMIinfo.serial -eq $CompEntry.serial) {
foreach ($UserEntry in $userinfo) {
if ($UserEntry.NT_USERID -eq $CompEntry.USER) {
#output information you want here
}
}
}

I'll try to help you get there.
I created an Excel file called Serial.xslx. Here's what it looks like
SerialNumber DeployedTo
212 Ham
4M24N32 Stephen
I then import this as $list.
$list = import-excel C:\temp\serial.xlsx
Next,to get the Win32_Bios info, so I can grab the SerialNumber property.
$bios = get-WmiObject Win32_Bios
Finally, I'll filter through the $list (which contains the Excel file), and find a row which has a SerialNumber that matches this computers serial number. If I find a matching one, then I grab the .DeployedTo value for that record.
$user = $list | Where SerialNumber -eq $bios.SerialNumber | Select -ExpandProperty DeployedTo
All that remains is to demonstrate that it works.
"the computer with serial $($bios.SerialNumber) is deployed to $user"
>the computer with serial 4M24N32 is deployed to Stephen
Now, you've got two separate excel files, so I would either manually join them into one, or repeat this same basic approach.

Related

how to compare two excel sheet using powershell

I have last month excel sheet with following
Current month excel sheet with following
Now i would like find what is new server Name added in current month then list them out as shown below
So far i got following code. any idea would be appreciated ? i will be scheduling this with windows scheduler task .This should be powershell since i will be adding more code later how to pick right excel sheet from SMB share.
i am trying this
$oldbk = Import-Excel -Path '\\hcohesity05\cohesity_reports\2022\7\07-29\Cohesity_FETB_Report-2022-07-29-14-26-48.xlsx'
$newbk = Import-Excel -Path '\\hcohesity05\cohesity_reports\2022\8\08-26\Cohesity_FETB_Report-2022-08-26-14-26-48.xlsx'
$Compare = Compare-Object $oldbk $newbk -Property "Server Name" -includeDifferent -PassThru
$Compare | Export-Excel -Path '.\diff.xlsx'
but getting message
A parameter cannot be found that matches parameter name 'includeDifferent'.
By looking at your code I'm assuming you're only interested in finding the servers not present in the old Excel document, if that's the case you only need Where-Object for filtering:
$oldbk = Import-Excel -Path 'path\to\oldfile.xlsx'
Import-Excel -Path 'path\to\newfile.xlsx' | Where-Object {
$_."Server Name" -notin $oldbk."Server Name"
} | Export-Excel -Path 'path\to\diff.xlsx'
As for the error message, Compare-Object does not have a -IncludeDifferent parameter and shows differences between two objects by default.
$Compare = Compare-Object $oldbk $newbk -Property "Server Name" -PassThru

Powershell Separate csv data into separate rows

I have the following script and it gets me the info I need.
$Monitors = Get-WmiObject WmiMonitorID -Namespace root\wmi
$LogFile = "d:\monitors.csv"
"Manufacturer,Name,Serial" | Out-File $LogFile
ForEach ($Monitor in $Monitors)
{
$Manufacturer = ($Monitor.ManufacturerName|where {$_ -ne 0}|ForEach{[char]$_}) -join ""
$Name = ($Monitor.UserFriendlyName |where {$_ -ne 0}| ForEach{[char]$_}) -join ""
$Serial = ($Monitor.SerialNumberID |where {$_ -ne 0}| ForEach{[char]$_}) -join ""
"$Manufacturer,$Name,$Serial" | Out-File $LogFile -append
}
My problem is the data is exported to the excel spreadsheet like this..
Manufacturer,Name,Serial.
ACI,VE248,K8LMQS048382
HWP,HP P232,6CM8122DXL
HWP,HP P232,6CM7241DRB
I need it to be:
Manufacturer Name Serial
in the spreadsheet, and when I do the next pc, it adds to the next line and so on.
I have looked online and the examples just don't match.
Does anyone have any advice?
As others already commented, use Export-Csv to write out the wanted data in csv format, rather than constructing it manually.
That means your ForEach-Object loop should emit objects instead of lines of concatenated strings.
Also, nowadays, I would use the newer Get-CimInstance instead of Get-WmiObject (What's the difference)
Try
$LogFile = "d:\monitors.csv"
Get-CimInstance -ClassName WmiMonitorID -Namespace root\wmi | ForEach-Object {
[PsCustomObject]#{
Manufacturer = [string]::new($_.ManufacturerName, 0, $_.ManufacturerName.Length).Trim("`0")
Name = [string]::new($_.UserFriendlyName, 0, $_.UserFriendlyName.Length).Trim("`0")
Serial = [string]::new($_.SerialNumberID, 0, $_.SerialNumberID.Length).Trim("`0")
}
} | Export-Csv -Path $LogFile -NoTypeInformation -UseCulture
The -UseCulture switch makes sure the output csv file uses the same delimiter characters your locally installed Excel would expect, so you can simply double-click the file to open it in Excel

Comparing all properties of PSCustomObjects (Excel sheet data)

I am working on a script for PowerShell to import data from 2 separate Excel sheets, compare all properties of these sheets and export a new Excel worksheet with this output.
The purpose of this script is to compare an updated excel sheet with a previous version and spot what has changed, what has been added and possibly even what has been removed.
I have been using the Import-Excel module to handle the first part, and Compare-Object for the data comparison.
As far as I can tell Import-Excel imports the Excel data into a System.Object which is a hashtable of PSCustomObjects. Each PSCustomObject corresponds to a row in the Excel sheet.
I am running the following code:
$global:InputdataA = Import-Excel -Path $InputA -WorkSheetname $InputSheetA
$global:InputdataB = Import-Excel -Path $InputB -WorkSheetname $InputSheetB
$global:ReferenceObject = $InputdataA
$global:DifferenceObject = $InputdataB
$global:InputdataHeadersA = $InputdataA[0].psobject.properties.name
$global:InputdataHeadersB = $InputdataB[0].psobject.properties.name
$props = $InputdataHeadersA
$props += $InputdataHeadersB
$props = $props | Select -Unique
$compareResult = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $props -PassThru -CaseSensitive
I am using 2 excel files for testing:
Personnel_16_12_2018 - small2.xlsx (previous version)
Personnel_28_11_2018 - small2.xlsx (new version with changes and additions)
The files can be downloaded here:
https://ufile.io/bmstu
https://ufile.io/3z62x
The output I would like to see would be only the 7 entries that have been changed/added, with data from difference object (the new version of the excel sheet) This would represent the latest and "correct" data.
Currently I get an output from the compare-object, containing the 7 entries AND the 6 entries that have been changed from the reference object including side-indicator.
Is it possible to make the compare-object return only the changes or do I have to process the output afterwards?
Based on your additional information and the sample files, you could try something like this:
$oldFile = Import-Excel ".\personnel_28_11_2018---small2.xlsx"
$newFile = Import-Excel ".\personnel_16_12_2018---small2.xlsx"
$properties = "TRIAL_PK", "TRIALCOUNTRY_PK", "TRIALSSITE_PK", "ASSIGNMENT_LVL", "ROLE", "INT_EXT", "START_DATA", "END_DATE", "PERSONNELL_PK", "TITLE", "LAST_NAME", "FIRST_NAME", "ORGANIZATION_NAME"
$result = Compare-Object -ReferenceObject $oldFile -DifferenceObject $newFile -Property $properties -PassThru -CaseSensitive | Where-Object {$_.SideIndicator -eq "=>"}
$result | Select-Object $properties | Export-Excel ".\changed.xlsx"

Removing text in a string between two characters using Powershell

I have a powershell script that runs and collects information and puts it in a .csv file. A sample of the information looks like what is listed below, with each line starting with a unique server name followed by a random unique identifier in contained a pair of ( ).
"GDR01W01SQ004 (e785754f-eeb1)","1","4","63","NY-TER-PLN-P-5N"
"GDR01L02D001 (4b889a4d-d281)","4","12","129","CO-FDP-STE-NP-5N"
I have a second powershell script that runs and takes this .csv file and its information and formats it into a report with a header and proper spacing.
Can someone please assist me with removing the text in between the ( ) as well as the ( )?
I would like the entries for each line to look like the following:
"GDR01W01SQ004","1","4","63","NY-TER-PLN-P-5N"
Thank you very much in advance!
Here is the script I have been using.
####################PowerCLI Check####################
# Verify whether the PowerCLI module is loaded, if not load it.
if ( (Get-PSSnapin -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin VMware.VimAutomation.Core -ErrorAction Stop
}
################### Run Time Section ####################
#This script should be run from a server that has DNS records for all entries in vcenters.txt
$file = get-Content c:\reports\vcenter\vcenters.txt
foreach ( $server in $file) {
Connect-VIserver -Server $server
Get-VM | select Name, NumCpu, MemoryGB, ProvisionedSpaceGB, Notes | Out-Null
}
# Command for Custom Annotations.
Get-VM | select Name, NumCpu, MemoryGB, ProvisionedSpaceGB, Notes -expandproperty customfields | Export-Csv -path “c:\reports\vcenter\vcenall.csv” -NoTypeInformation
# Takes vcenall.csv and sorts only the Name and Notes columns and selects all but the custom fields. Capacity Reporting script caprep.ps1 runs against this csv.
Import-csv c:\reports\vcenter\vcenall.csv | Sort-Object Notes, Name | Select-Object Name, NumCpu, MemoryGB, ProvisionedSpaceGB, Notes |Export-csv capacity.csv -NoTypeInformation
#Used to remove domain from server name
(Get-Content capacity.csv) | ForEach-Object { $_ -replace ".domain.local", "" } | Set-Content capacity.csv
# Takes vcenall.csv and sorts only the Notes column and selects only the Name and Notes columns. Nimsoft comparison script nimcomp.ps1 runs against this csv.
Import-csv c:\reports\vcenter\vcenall.csv | Sort-Object Notes | Select-Object Name, Notes | Export-csv nimsoft.csv -NoTypeInformation
# Takes vcenall.csv and sorts only the Name columns and exports all fields. Backup/Restore comparison script bure.ps1 runs against this csv.
Import-csv c:\reports\vcenter\vcenall.csv | Sort-Object Name | Export-csv bure.csv -NoTypeInformation
I think you need to add more information but just using what you have let try this one approach
Import-Csv C:\temp\test.csv -Header server,1,2,3,4 | ForEach-Object{
$_.server = (($_.server).split("(")[0]).Trim()
$_
}
We import the csv data and assign a header. If you already have one then this parameter can be omitted.
Then we examine each row of data as an object. Change the server data by splitting it up by its spaces. If this data is for server names then it is safe to assume that that everything before the first space is the server name. This approach is dependent on the space being there. We could also use the same logic with the ( but this would be easier if the space was a guarantee.
So we update the server and then send the data back down the pipe with $_.
Sample Output
server 1 2 3 4
------ - - - -
GDR01W01SQ004 1 4 63 NY-TER-PLN-P-5N
GDR01L02D001 4 12 129 CO-FDP-STE-NP-5N
Edit based on comments
Since it is a server display name I changed the logic to split based on the "(". Also using the Split() method instead of the -split operator.

Outputting PowerShell data to a string

This is really PowerShell 101, I realise, but I'm stuck.
I'm trying to iterate through a folder tree, getting each subfolder name and a count of files. No problems there.
The new requirement is to get the ACLs on each subfolder as well. All of this data needs to be output as a CSV file, with a line consisting of each folder name, the file count, and the ACLs in a single string in one field of the CSV (I was going to delimit them with semicolons).
I am open to exporting to XML if the data can be viewed in Excel.
The part where I'm stuck is getting the ACL information into a single string for the CSV.
Get-ACL on each directory shows the data as follows (I'm doing a Select to just get the IdentityReference and FileSystemRights, which is all we're interested in):
IdentityReference FileSystemRights
----------------- ----------------
BUILTIN\Users ReadAndExecute, Synchronize
BUILTIN\Users AppendData
BUILTIN\Users CreateFiles
I would like the output file formatted with one line per subdirectory, similar to
#filecount,folder,perms
51,C:\temp,BUILTIN\Users:ReadAndExecute,Synchronize;BUILTIN\Users:AppendData...
I however can't get any kind of join working to have it presented in this way. I don't care about what combination of delimiters are used (again, must be readable in Excel).
The script, such as it is, is as follows. The output file has its line of data appended with each directory it traverses. I'm sure this isn't very efficient, but I don't want the process consuming all the server memory either. The bits I can't figure out are prepended with ###.
(Get-ChildItem C:\temp -recurse | Where-Object {$_.PSIsContainer -eq $True}) | foreach {
$a = ($_.GetFiles().Count)
$f = $_.FullName
$p = (get-acl $_.FullName).Access | select-object identityreference,filesystemrights
### do something with $p?
Out-File -FilePath c:\outfile.csv -Append -InputObject $a`,$f`,###$p?
}
Since you want all ACEs of a folder mangled into a single line you need something like this:
Get-ChildItem 'C:\temp' -Recurse | ? { $_.PSIsContainer } | % {
# build a list of "trustee:permissions" pairs
$perms = (Get-Acl $_.FullName).Access | % {
"{0}:{1}" -f $_.IdentityReference, $_.FileSystemRights
}
New-Object -Type PSObject -Property #{
'Filecount' = $_.GetFiles().Count
'Folder' = $_.FullName
'Permissions' = $perms -join ';' # join the list to a single string
}
} | Export-Csv 'c:\outfile.csv' -NoType
Repeated appending inside a loop usually guarantees poor performance, so it should be avoided whenever possible. The outer loop creates a list of custom objects, which can then be exported via Export-Csv in a single go.

Resources