Modding a PowerShell Script Found on Stack Overflow - powershell

I found this script Get-ProcessPlus by PMental here on Stack Overflow. With the help of zett42
and several others I manged to get it to run (very new to PS). Thanks guys, It had everything I was really looking for.
I opted too see if I could have the script add one more feature. I wanted it too return the commandline value of the process. I got it to partially work. With my modifications it still runs as default, and by Id, but no longer by name. I have done quite a bit of reading but still can not get it to work properly. Here is the code and my mods. Any help would be appreciated.
*$Command = Get-WmiObject Win32_Process | select name, CommandLine*
function Get-ProcessPlus {
[CmdletBinding(DefaultParameterSetName = 'Default')]
param (
[Parameter(ParameterSetName='ProcessName',Position = 0)]
[string[]]
$Name,
*[Parameter(ParameterSetName='CommandLine',Position = 0)]
[string[]]
$Command,*
[Parameter(ParameterSetName='PID',Position = 0)]
[int[]]
$Id
)
# Check which parameter set is in use and get our processes
switch ($PSCmdlet.ParameterSetName) {
'ProcessName' {
$AllProcesses = Get-Process -Name $Name
break
}
*'CommandLine' {
$AllProcesses = Get-Process -Name $Command
break
}*
'PID' {
$AllProcesses = Get-Process -Id $Id
break
}
default { $AllProcesses = Get-Process }
}
foreach ($Process in $AllProcesses) {
# Retrieve TCP and UDP Connection information for the current process (if any)
$UDPConnections = Get-NetUDPEndpoint -OwningProcess $Process.Id -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPConnections = Get-NetTCPConnection -OwningProcess $Process.Id -State Listen -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPPorts = $TCPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$UDPPorts = $UDPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$TCPAddresses = $TCPConnections.LocalAddress | Select-Object -Unique
$UDPAddresses = $UDPConnections.LocalAddress | Select-Object -Unique
# Collect and output all information about the current process
[PSCustomObject] #{
'ProcessName' = $Process.ProcessName
'Id' = $Process.Id
'Description' = $Process.Description
'Path' = $Process.Path
*'CommandLine' = $Process.Command*
'CPU usage (s)' = $Process.CPU
'TCP Addresses' = $TCPAddresses
'TCP Ports' = $TCPPorts
'UDP Addresses' = $UDPAddresses
'UDP Ports' = $UDPPorts
}
}
}

You need to match the Get-WMIObject output to the Get-Process Output. In your case, just replace this line:
'CommandLine' = $Process.Command
With this:
# Query WMI for process command line
'CommandLine' = Get-WmiObject -Query "
SELECT CommandLine from Win32_Process WHERE ProcessID = $($Process.ID)" |
# Select only the commandline property so we can display it
Select -ExpandProperty CommandLine
My output looks like so:
Get-ProcessPlus -Name notepad
ProcessName : notepad
Id : 10568
Description : Notepad
Path : C:\WINDOWS\system32\notepad.exe
CommandLine : "C:\WINDOWS\system32\notepad.exe" C:\temp\test.txt
CPU usage (s) : 0.390625

Related

PowerShell Invoke Command, Script not returning some values from remote PC's

I'm new to scripting so please excuse me if my script is messy. This script pretty much does what I want it to do but for 2 fields it doesn't return the values.
If I run the commands without Invoke I get all the values I want but when I run this with the Invoke command on remote computers the OsHotFixes and CsProcessors return weird values of "Microsoft.PowerShell.Commands.HotFix" for each hotfix and "Microsoft.PowerShell.Commands.Processor" for the CsProcessors value. All other properties gave me the values I am looking for. I'm not sure why those 2 aren't returning correct values. If someone could point me in the right direction that would be awesome.
$c = Get-Content "myfilepath"
$e = "myfilepath"
$ScriptBlock = {
$ComputerInfo = Get-ComputerInfo -Property WindowsVersion, OsBuildNumber, OsHotFixes, CsModel, BiosSMBIOSBIOSVersion, WindowsProductName, CsProcessor, OsInstallDate, OsArchitecture, CsProcessors
$GPU = Get-WmiObject win32_VideoController | Select-Object "Name", "DeviceID", "DriverVersion"
$RAM = Get-CimInstance -ClassName CIM_PhysicalMemory | Select-Object "Manufacturer", "PartNumber", #{'Name'='Capacity (GB)'; 'Expression'={[math]::Truncate($_.capacity / 1GB)}}, "Speed"
$Storage = Get-WmiObject Win32_LogicalDisk | Where caption -eq "C:" | Foreach-object {write " $($_.caption) $('{0:N2}' -f ($_.Size/1gb)) GB total, $('{0:N2}' -f ($_.FreeSpace/1gb)) GB Free"}
$MyArray = #($ComputerInfo, $GPU, $RAM, $Storage)
$Properties =
#(
'WindowsVersion'
'OsBuildNumber'
'OsHotFixes'
'CsModel'
'BiosSMBIOSBIOSVersion'
'WindowsProductName'
'OsInstallDate'
'OsArchitecture'
'CsProcessors'
'Name'
'DeviceID'
'DriverVersion'
'Manufacturer'
'PartNumber'
'Capacity'
'Speed'
'Disk'
)
$MyArray | ForEach-Object {
:Inner ForEach( $Property in $Properties )
{
If($_.$Property)
{
[PSCustomObject][Ordered]#{
hostname = $env:COMPUTERNAME
WindowsVersion = $_.WindowsVersion
Build = $_.OsBuildNumber
Patches = $_.OsHotFixes
Motherboard = $_.CsModel
BiosVersion = $_.BiosSMBIOSBIOSVersion
WindowsProductName = $_.WindowsProductName
OsInstallDate = $_.OsInstallDate
OsArchitecture = $_.OsArchitecture
Processor = $_.CsProcessors
GPUName = $_.Name
DeviceID = $_.DeviceID
DriverVersion = $_.DriverVersion
RamManufacturer = $_.Manufacturer
PartNumber = $_.PartNumber
Capacity = $_.Capacity
Speed = $_.Speed
Disk = $Storage
}
Break Inner
}
}
}
}
Invoke-Command -ComputerName $c -ScriptBlock $ScriptBlock | Sort hostname | Export-Csv -append $e -NoTypeInformation
I've tried running just the lines from 4 - 8 locally and then Outputting the Array. This will show all correct values. However when this script runs with the PSCustomObject and Invoke command I don't get CsProcessors or OsHotFixes values.

Powershell - Process List with arguments

I am trying to find a way to list processes with;
PID
Process Name
CPU Usage
Execution Path
Port Number (TCP and UDP)
Description
and export it in a csv file.
Is it possible? If not, can this list be configured to search the process name as "like process_name" ?
For example, list multiple process names (as I specify) with other arguments.
So far, I've found this one but it doesn't include the port numbers;
Get-Process | select id, processname,cpu,path,description | where {$_.path -like "*postgre*"} | Export-Csv -Path C:\temp\process.csv -Delimiter ',' -NoTypeInformation
Thanks.
Here's a new function I whipped together called Get-ProcessPlus. It supports calling with process name(s) or process id(s) or without any parameters (will return all processes).
Example of output:
ProcessName : NVIDIA Web Helper
Id : 10184
Description : NVIDIA Web Helper Service
Path : C:\Program Files (x86)\NVIDIA Corporation\NvNode\NVIDIA Web Helper.exe
CPU usage (s) : 0,59375
TCP Addresses : 127.0.0.1
TCP Ports : 13549
UDP Addresses : 127.0.0.1
UDP Ports : 10010
Either run this code in ISE or VSCode, save it and dot source it (eg. . c:\path\to\Get-ProcessPlus.ps1 or maybe add it to your profile.
Then just call it with Get-ProcessPlus. Using a parameter name is optional, just providing one or more process ids or names will work, eg. Get-ProcessPlus chrome,firefox or Get-ProcessPlus 1044,894,432.
Finally, here's the code:
function Get-ProcessPlus {
[CmdletBinding(DefaultParameterSetName = 'Default')]
param (
[Parameter(ParameterSetName='ProcessName',Position = 0)]
[string[]]
$Name,
[Parameter(ParameterSetName='PID',Position = 0)]
[int[]]
$Id
)
# Check which parameter set is in use and get our processes
switch ($PSCmdlet.ParameterSetName) {
'ProcessName' {
$AllProcesses = Get-Process -Name $Name
break
}
'PID' {
$AllProcesses = Get-Process -Id $Id
break
}
default { $AllProcesses = Get-Process }
}
foreach ($Process in $AllProcesses) {
# Retrieve TCP and UDP Connection information for the current process (if any)
$UDPConnections = Get-NetUDPEndpoint -OwningProcess $Process.Id -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPConnections = Get-NetTCPConnection -OwningProcess $Process.Id -State Listen -ErrorAction Ignore |
Select-Object LocalAddress,LocalPort
$TCPPorts = $TCPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$UDPPorts = $UDPConnections.LocalPort | Where-Object { $null -ne $_} | Select-Object -Unique
$TCPAddresses = $TCPConnections.LocalAddress | Select-Object -Unique
$UDPAddresses = $UDPConnections.LocalAddress | Select-Object -Unique
# Collect and output all information about the current process
[PSCustomObject] #{
'ProcessName' = $Process.ProcessName
'Id' = $Process.Id
'Description' = $Process.Description
'Path' = $Process.Path
'CPU usage (s)' = $Process.CPU
'TCP Addresses' = $TCPAddresses
'TCP Ports' = $TCPPorts
'UDP Addresses' = $UDPAddresses
'UDP Ports' = $UDPPorts
}
}
}

Powershell : import-csv with if condition

I have a csv as below :
Server OS HotFixID
Comp1 Win12 KB452
Comp1 Win12 KB453
svrname3 Win8 KB134
I have written below script for checking OS and if its matched then it should check if the server is having the same HotfixID or not.
$file = Import-Csv .\Desktop\hotfix.csv
if($Win12 = $file | where {$_.os -eq "Win12"} | select Source, HotFixID)
{
Get-HotFix -ComputerName ($Win12.Source) -Id ($Win12.HotFixID)
}
else
{
$Win8 = $file | where {$_.os -eq "Win8"} | select Source, HotFixID
Get-HotFix -ComputerName ($Win8.Source) -Id ($Win8.HotFixID)
}
problem is with output.. I have 2 Win12 server in csv, but I am getting 4 output 2 as duplicate.. I am able to understand that here one nested loop is running but unable to rectify it. Please!! let me know how can we fix this issue.
Assumed I understood your task correct you should iterate over all elements in your CSV file and check each item indivually.
$CSVList = Import-Csv .\Desktop\hotfix.csv
foreach ($CSVItem in $CSVList) {
if ($CSVItem.os -eq 'Win12' -or $CSVItem.os -eq 'Win8') {
if (Test-Connection -ComputerName $CSVItem.Source) {
Get-HotFix -ComputerName $CSVItem.Source -Id $CSVItem.HotFixID
}
}
}
You have multiple entries with Win12 so $Win12 is an array of PSCustomObject. When you use ($Win12.Source) it will output an array of all sources. (Comp1,Comp1). Get-Hotfix accepts this array and tests $Win12.HotFixID (which is an array, too) with each of the sources. Thats the reason you get each Item the Number of times they apear in the CSV. To avoid this, process each line in the CSV on their own. If you want to keep your structure, your code would look like this:
if($Win12 = $file | where {$_.os -eq "Win12"} | select Source, HotFixID)
{
$Win12 | foreach {
Get-HotFix -ComputerName ($_.Source) -Id ($_.HotFixID)
}
}
else
{
$Win8 = $file | where {$_.os -eq "Win8"} | select Source, HotFixID
$Win8 | foreach {
Get-HotFix -ComputerName ($_.Source) -Id ($_.HotFixID)
}
}
However the Code of Olaf is cleaner and does the same.

Resolve-DNSName for Windows 2008

I have a script working for Windows 2012 (PowerShell v4) but it has to work also for Windows 2008 (PowerShell v2), what is the equivalent of the cmdlet "Resolve-DNSName" for Windows 2008?
Resolve-DnsName -Name client01 -Server server01
I know it exists the same for nslookup and this is what I would like as a cmdlet (one-liner, with no input required from my part)
nslookup
server server01
client01
The following works for DNS resolution but is missing the -server parameter :
[Net.DNS]::GetHostEntry("MachineName")
Thanks
Unfortunately there isn't a way to do this natively in powershell prior to Version 4 in Windows 8.1 or Server 2012. There are .NET methods however:
https://stackoverflow.com/a/8227917/4292988
The simplest solution in powershell is to call nslookup, and cleanup the output
&nslookup.exe client01 server01
I removed select-string from the original sample, it left less to work with
The function you posted following mine doesnt work very well, and will never work in PowershellV2, [PSCustomObject] wasn't supported until v3. Furthermore if you send a dns query that would normally return a single address, it returns nothing. For queries with aliases, it returns the aliases where the ipaddress should be. Test Resolve-DnsName2008 -name www.stackoverflow.com -server 8.8.8.8.
The Following is a function that should do what your asking, at least for ipv4addresses:
function Resolve-DnsName2008
{
Param
(
[Parameter(Mandatory=$true)]
[string]$Name,
[string]$Server = '127.0.0.1'
)
Try
{
$nslookup = &nslookup.exe $Name $Server
$regexipv4 = "^(?:(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)$"
$name = #($nslookup | Where-Object { ( $_ -match "^(?:Name:*)") }).replace('Name:','').trim()
$deladdresstext = $nslookup -replace "^(?:^Address:|^Addresses:)",""
$Addresses = $deladdresstext.trim() | Where-Object { ( $_ -match "$regexipv4" ) }
$total = $Addresses.count
$AddressList = #()
for($i=1;$i -lt $total;$i++)
{
$AddressList += $Addresses[$i].trim()
}
$AddressList | %{
new-object -typename psobject -Property #{
Name = $name
IPAddress = $_
}
}
}
catch
{ }
}
I use this code to input FQDNs one per line and output respective IPs.
$Server = Get-Content servers.txt
$OutArray = #()
$output = foreach ($Server in $Server) {
$IP = [System.Net.Dns]::GetHostAddresses($Server)
$OutArray += $Server + " " + $IP.IPAddressToString
}
$OutArray | Out-File IPs.txt
The problem is that if I use :
&nslookup.exe client01 server01 | select-string "Name", "Addresses"
It will only display the first record, in my case I had 5 records found and only one displayed.
The solution I found works very well :
function Resolve-DNSName2008
{
Param
(
[string]$Name,
[string]$Server
)
$nslookup = &nslookup.exe $Name $Server
$name = [string]($nslookup | Select-String "Name")
$nameClean = ([regex]::match($name,'(?<=:)(.*\n?)').value).Trim()
$addresses = (([regex]::match($nslookup,'(?<=Addresses:)(.*\n?)').value).Trim()).Split(' ')
$addressesClean = $addresses.Split('',[System.StringSplitOptions]::RemoveEmptyEntries) | Sort-Object
$addressesClean | %{
[PSCustomObject]#{
Name = $nameClean
IPAddress = $_
}
}
}
Usage:
Resolve-DNSName2008 -Name server.domain.com -Server 10.0.0.0
Output:
Name IPAddress
---- ---------
server.domain.com 10.0.0.1
server.domain.com 10.0.0.2
server.domain.com 10.0.0.3
server.domain.com 10.0.0.4
server.domain.com 10.0.0.5

How to get server information from VMware

I have access to the VMWare GUI and I can easily export all the columns such as UPtime, IPAddress, Notes, DNS, GuestOs, State, Name and so on.
I want to right a script that can automatically get this information daily. So gar I was only able to get the server name, power state and VMhost. for some reason VMware is making it so hard to extract that information. I used the script below and I thought by adding the columns I mentioned above to this script, I should be able to retireve the data I need. But it doesn't work that way. Can someone please tell me how I can get this information?
Thanks,
Add-PSSnapin vmware.vimautomation.core
Connect-VIServer SERVERNAME
Get-VM|Select Name, VMHost, Id, PowerState
Exit 0
After digging into the system and many hours of research I found the solution. I just wish VMWare would make it easier to retrieve data or at least improve the manual.
The following code creates two files; one with the server information and another one with Uptime information.
Get-VM | select name,VMHost, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }}, #{ Name = "PowerState"; Expression = { $_.Guest.State }} , #{ Name = "GuestOS"; Expression = { $_.Guest }}, Notes | Export-Csv -Path "HQstat.csv"
Get-Stat -Entity * -Stat sys.uptime.latest -Realtime -MaxSamples 1| Export-Csv -Path "HQtime.csv"
Why not use the views? They have all the information that you need. Code below assumes you are connected to the vCenter.
$vmView = Get-View -ViewType VirtualMachine -Property Name,Config,Guest,Runtime
$hostView = Get-View -ViewType HostSystem -Property Name
$date = Get-Date
Foreach ($vm in $vmView)
{
If ($vm.Runtime.BootTime -ne $null)
{
$dateDiff = $date.Subtract($vmView.Runtime.BootTime)
}
Else
{
$dateDiff = $null
}
foreach ($h in $hostView)
{
If ($vm.Runtime.Host -eq $h.MoRef)
{
$tempHost = $($h.Name)
Break
}
}
$global:Export += #([PSCustomObject]#{
VMName = $($vm.Name)
ID = $($vm.Config.Uuid) #or use $($vm.MoRef)
Host = $tempHost
PowerState = $($vm.Guest.GuestState)
IPAddress = $($vm.Guest.IPAddress)
Notes = $($vm.Config.Annotations)
UptimeMinutes = $($dateDiff.TotalMinutes)
})
$dateDiff = $null
$tempHost = $null
}
$exportFileName = "C:\temp\VMInformation.csv"
$Export | Export-Csv $exportFileName -Force -NoTypeInformation