I am having an issue with exporting results to a txt in Powershell.
I have 2 commands I need to run and when they are done, I am hoping to get something like this:
Name Version
---- -------
Mitel Connect 214.100.1252.0
Cylance Unified Agent 2.4.1070.1
Instead of this:
Name Version
---- -------
Mitel Connect 214.100.1252.0
Name Version
---- -------
Cylance Unified Agent 2.4.1070.1
Here is the code:
get-package 'Microsoft Edge','Mitel Connect', '*7-Zip*','*Cylance*','*Office Profession*','*Dameware*','Cisco AnyConnect Secure Mobility Client' | select name,version | Out-File "C:\temp\export.txt" -Append
Get-WmiObject -Class Win32_Product | where Name -eq "Manageengine AssetExplorer Agent" | select Name, Version | Out-File "C:\temp\export.txt" -Append
I have tried piping the code, google and nothing works,
Does anyone have any idea who to get the output?
If the output file only needs to record the output from these two commands:
Call (& ) them in sequence via a script block ({ ... })...
... pipe the output to a single Select-Object call ...
... which you can then pipe to a single Out-File call.
& {
Get-Package 'Microsoft Edge','Mitel Connect', '*7-Zip*','*Cylance*','*Office Profession*','*Dameware*','Cisco AnyConnect Secure Mobility Client'
Get-CimInstance -Class Win32_Product | Where-Object Name -eq "Manageengine AssetExplorer Agent"
} |
Select-Object Name, Version |
Out-File "C:\temp\export.txt"
That way, the output objects are formatted together, as a single table, by the single Out-File call.
(By contrast, if you call Out-File multiple times, you'll get a separate table in the file for each call, which is what you saw.)
Note, however, that the resulting file format is only meant for display purposes, as it uses the same rich formatting you'd see in the console (terminal) by default, which is meant for the human observer rather than programmatic processing.
For programmatic processing, consider a structured text format, such as CSV (Export-Csv), which also allows you to append to the file iteratively later.
Since you only get the name and version of these objects, pushing them into an array and then exporting the array would work as you intend it to. However, in case you try to add more properties in each select, this will not work. The objects in the array will preserve the structure of the 1st element added to it.
This is the code that managed to create the desired result.
$arr = #()
get-package 'Microsoft Edge' | select name, version | % { $arr += $_ }
Get-WmiObject -Class Win32_Product | where Name -eq "Go Programming Language amd64 go1.18" | select Name, Version | % { $arr += $_ }
$arr | Out-File "C:\temp\export.txt" -Append
The following 2 snippets show the undesired effect if you try to add properties in the select that don't exist in both structures.
$arr = #()
Get-WmiObject -Class Win32_Product | where Name -eq "Go Programming Language amd64 go1.18" | select Name, Vendor, Version | % { $arr += $_ }
get-package 'Microsoft Edge' | select name,version | % { $arr += $_ }
$arr | Out-File "C:\temp\export.txt" -Append
This will have an empty Vendor prop for the "get-package" objects
$arr = #()
get-package 'Microsoft Edge' | select name,version | % { $arr += $_ }
Get-WmiObject -Class Win32_Product | where Name -eq "Go Programming Language amd64 go1.18" | select Name, Vendor, Version | % { $arr += $_ }
$arr | Out-File "C:\temp\export.txt" -Append
This will disregard the "Vendor" property for all data from "Get-WmiObject" Command
Related
I'm collecting information using a WMI query. I want to send this information to a CSV file including the machine name. I can send the information but I'm not able to include machine name with it.
$PasswordState = Get-WmiObject -Class Lenovo_BiosPasswordSettings -Namespace root\wmi |
Select -Expand PasswordState |
Select-Object -Last 1 |
Out-File -FilePath '\\server\share\Bios_Password_Status.csv' -Append -Encoding Unicode
I need this to create a CSV file with two items:
Data returned from WMI query
Machine name
Does this give you what you want, it will store the result in an array called $Output. You can then use $Output | Out-File -Append to add it to a file or something.
$Result = Get-WmiObject -Class Lenovo_BiosPasswordSettings -Namespace root\wmi | Select -Property PSComputerName,PasswordState
$Output += $Result | Format-Table -HideTableHeaders
I want to monitor python scripts in powershell. For that I am using Get-ProcessByName. I want to monitor individual python and JAVA scripts running and store its processId in a csv file according to individual script running. Get-ProcessByName lists all the the python or JAVA processes in the same row. How do I separate all the script names in different rows. What I am currently doing is-
$process = [System.Diagnostics.Process]
$outputTime = $process::GetProcessesByName($processName.ProcessName)[0].TotalProcessorTime.TotalMilliseconds
$name = ($process::GetProcessesByName($processName.ProcessName)[0]) | Select-Object -ExpandProperty ProcessName
$extra = Get-WmiObject -Class Win32_Process -Filter "name = '$name.exe'" | Select-Object -ExpandProperty CommandLine
Here in $extra I am getting names of all the python scripts.How do I seperate all the scripts
From my understanding Win32_Process already has all the information you need. You can use Select-Object and Calculated Properties to modify if required.
Get-WmiObject -Class Win32_Process |
Where-Object {$_.Name -eq 'python.exe'} |
Select-Object -Property Name,
#{Name = 'Script'
Expression = {$_.CommandLine -replace
'(.*)\\(?<py>.*\.py)|(.*)\ (?<py>.*\.py.*)',
'${py}'}
},
#{
Name = 'CpuTime'
Expression = {($_.KernalModeTime + $_.UserModeTime) / 10000000}
} |
Sort-Object -Property CpuTime -Descending
This would output something like
Name Script CpuTime
---- ------ -------
python.exe completion.py preview 1,65625
python.exe Untitled-1.py 0,015625
Of course this would work for java.exe or other, even multiple processes, as well. If you dont want to output the full CommandLine replace the first Calculated Property with CommandLine.
I would use this
Get-Process | where ProcessName -Match python
I need help with manipulating data that I export to a CSV. Right now I actually learned how to merge columns together so that once it is put into a CSV the hostname shows on only 1 line and the other two columns I merge together so that each line will only have one hostname. I however need to take it a step further.
Below is my progression:
Phase 1:
This was only good because the script retrieved the data, but as you can see below Hostname1 shows up on every line for each caption and version, which would lead to several repeats of a machine name for several lines making the CSV file extremely longer than it necessarily should be.
Script:
GWMI -Class Win32_Product -Comp (GC D:\McAfeeHost.txt) |
Where {$_.Vendor -like "mcafee*" -or $_.Vendor -like "usaf*"} |
Select PSComputerName, Caption, Version |
Export-Csv -NoTypeInformation d:\Get-HBSSModules-Test.csv
Output in CSV:
PSComputerName caption version
Hostname1 McAfee Host Intrusion Prevention 8.00.0801
Hostname1 McAfee Policy Auditor Agent 6.2.0
Hostname1 McAfee DLP Endpoint 10.0.260.42
Hostname1 McAfee VirusScan Enterprise 8.8.08000
Hostname1 ACCM 3.0.4.1
Hostname1 McAfee Agent 5.00.4006
Phase 2:
I have progressed by merging the caption and version together, so that each hostname that is fetched from -Comp (GC D:\McAfeeHost.txt) shows up only once per line. While this is more of what I am looking for, it isn't the best option for formatting as shown below the in the output of the CSV.
Script:
GWMI -Class Win32_Product -Comp (GC D:\McAfeeHost.txt) |
Where {$_.Vendor -like "mcafee*" -or $_.Vendor -like "usaf*"} |
Select PSComputername, Caption, Version |
Sort-Object Caption |
Export-Csv -NoTypeInformation d:\Get-HBSSModules-Test.csv
$a = Import-Csv d:\Get-HBSSModules-Test.csv
$a | Group-Object PSComputerName |
Select-Object #{name="PSComputerName";expression={$_.Name}},
#{name="caption, version";expression={($_.Group | % { $_.Caption, $_.Version }) -join ';'}} |
Export-Csv d:\Get-HBSSModules-Test.csv -NoTypeInformation
Output to CSV:
Phase 3:
If at all possible I would like to take each caption along with its version and put them together like phase 2, but separated by columns and still only having one hostname per line as shown below:
I do not have multiple computers available, nor have I any McAffee product installed. However, here is a possible solution to your problem. You would have to adjust Vendor to PSComputerName, the -match RegEx, and add the -ComputerName or -CimSession parameter to Get-CimInstance. But the basic concept should work.
$Product = Get-CimInstance -ClassName Win32_Product | Where-Object {$_.Vendor -match '(microsoft|intel)'}
$Group = $Product | Group-Object -Property Vendor
$result = foreach ($Vendor in $Group) {
$Products = foreach ($item in $Vendor.Group) {
"$($item.Caption);$($item.Version)"
}
$Products = $Products -join ','
"$($Vendor.Name),$Products"
}
$HeaderLength = ($result | ForEach-Object {($_ -split ',').Count} | Sort-Object -Descending)[0]-1
$Header = "Vendor,"
$x = 1
$Header += do {
$x++
"Caption;Version,"
} until ($x -eq $HeaderLength)
$Header | Out-File -FilePath $env:TEMP\strange.csv
$result | Out-File -FilePath $env:TEMP\strange.csv -Append
If you open $env:TEMP\strange.csv in Excel and use the Text to columns function with , as the delimiter, you get the result es requested in your Phase 3 Output.
It's not beautiful and also it doesn*t make any sense to me, but that's what you requested for. :p
Using Group-Object and Flatten-Object:
Given:
$CSV = ConvertFrom-CSV #"
PSComputerName,caption,version
Hostname1,McAfee Host Intrusion Prevention,8.00.0801
Hostname1,McAfee Policy Auditor Agent,6.2.0
Hostname1,McAfee DLP Endpoint,10.0.260.42
Hostname1,McAfee VirusScan Enterprise,8.8.08000
Hostname1,ACCM,3.0.4.1
Hostname1,McAfee Agent,5.00.4006
Hostname2,McAfee Agent,5.00.4006
Hostname2,McAfee DLP Endpoint,10.0.260.42
Hostname2,McAfee DLP Endpoint,10.0.260.42
Hostname3,McAfee Policy Auditor Agent,6.2.0
Hostname3,McAfee DLP Endpoint,10.0.260.42
"#
Command:
$CSV | Group PSComputerName | Flatten | Format-Table
Result:
Values.1 Count Group.1.PSComputerName Group.1.caption Group.1.version Group.2.PSComputerName Group.2.caption
-------- ----- ---------------------- --------------- --------------- ---------------------- ---------------
Hostname1 6 Hostname1 McAfee Host Intrusion Prevention 8.00.0801 Hostname1 McAfee Policy A...
Hostname2 3 Hostname2 McAfee Agent 5.00.4006 Hostname2 McAfee DLP Endp...
Hostname3 2 Hostname3 McAfee Policy Auditor Agent 6.2.0 Hostname3 McAfee DLP Endp...
I currently have the following script that works well for gathering a list of installed programs from a list of remote computers.
$PCListOld = Get-Content F:\PCList-Old.txt
ForEach ($PC in $PCListOld)
{
$AppList = Get-WmiObject -Computer $PC Win32_Product | Sort-Object Name
$AppList | Export-CSV C:\~Scripts\AppLists\$PC.csv
}
However, I really only need the Name property in $AppList, but if I simply pipe $AppList.Name to Export-CSV, I don't get the same output in the csv as I would have on the screen. Can someone give me some advice on how I should edit this so I can just get the Name value exported to the csv file?
Thanks in advance for the help.
Restrict the result properties to just Name via Select-Object:
foreach ($PC in $PCListOld) {
Get-WmiObject -Computer $PC Win32_Product |
Sort-Object Name |
Select-Object Name |
Export-Csv C:\~Scripts\AppLists\$PC.csv
}
I want to be able to output data from PowerShell without any column headings. I know I can hide the column heading using Format-Table -HideTableHeaders, but that leaves a blank line at the top.
Here is my example:
get-qadgroupmember 'Domain Admins' | Select Name | ft -hide | out-file Admins.txt
How do I eliminate the column heading and the blank line?
I could add another line and do this:
Get-Content Admins.txt | Where {$_ -ne ""} | out-file Admins1.txt
But can I do this on one line?
In your case, when you just select a single property, the easiest way is probably to bypass any formatting altogether:
get-qadgroupmember 'Domain Admins' | foreach { $_.Name }
This will get you a simple string[] without column headings or empty lines. The Format-* cmdlets are mainly for human consumption and thus their output is not designed to be easily machine-readable or -parseable.
For multiple properties I'd probably go with the -f format operator. Something along the lines of
alias | %{ "{0,-10}{1,-10}{2,-60}" -f $_.COmmandType,$_.Name,$_.Definition }
which isn't pretty but gives you easy and complete control over the output formatting. And no empty lines :-)
A better answer is to leave your script as it was. When doing the Select name, follow it by -ExpandProperty Name like so:
Get-ADGroupMember 'Domain Admins' | Select Name -ExpandProperty Name | out-file Admins.txt
If you use "format-table" you can use -hidetableheaders
add the parameter -expandproperty after the select-object, it will return only data without header.
The -expandproperty does not work with more than 1 object. You can use this one :
Select-Object Name | ForEach-Object {$_.Name}
If there is more than one value then :
Select-Object Name, Country | ForEach-Object {$_.Name + " " + $Country}
Joey mentioned that Format-* is for human consumption. If you're writing to a file for machine consumption, maybe you want to use Export-*? Some good ones are
Export-Csv - Comma separated value. Great for when you know what the columns are going to be
Export-Clixml - You can export whole objects and collections. This is great for serialization.
If you want to read back in, you can use Import-Csv and Import-Clixml. I find that I like this better than inventing my own data formats (also it's pretty easy to whip up an Import-Ini if that's your preference).
First we grab the command output, then wrap it and select one of its properties. There is only one and its "Name" which is what we want. So we select the groups property with ".name" then output it.
to text file
(Get-ADGroupMember 'Domain Admins' |Select name).name | out-file Admins1.txt
to csv
(Get-ADGroupMember 'Domain Admins' |Select name).name | export-csv -notypeinformation "Admins1.csv"
$server = ('*')+(Read-Host -prompt "What Server Context?")+'*'
$Report = (Get-adcomputer -SearchBase "OU=serverou,DC=domain,DC=com" -filter {name -like $server} -SearchScope Subtree|select Name |Sort -Unique Name)
$report.Name | Out-File .\output\out.txt -Encoding ascii -Force
$Report
start notepad .\output\out.txt
Put your server SearchBase in above.
If you are not sure what your server OU is try this function below...
#Function Get-OSCComputerOU($Computername)
{
$Filter = "(&(objectCategory=Computer)(Name=$ComputerName))"
$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$DirectorySearcher.Filter = $Filter
$SearcherPath = $DirectorySearcher.FindOne()
$DistinguishedName = $SearcherPath.GetDirectoryEntry().DistinguishedName
$OUName = ($DistinguishedName.Split(","))[1]
$OUMainName = $OUName.SubString($OUName.IndexOf("=")+1)
# $Obj = New-Object -TypeName PSObject -Property #{"ComputerName" = $ComputerName
# "BelongsToOU" = $OUMainName
# "Full" = $DistinguishedName}
$Obj = New-Object -TypeName PSObject -Property #{"Full" = $DistinguishedName}
$Obj
}
Makes sure to run the Get-OSCComputerOU Servername with a select -expandproperty Full filter.
Then just plug in the response to the Searchbase...
All thanks to http://www.jaapbrasser.com