Hello All I'm new to C# and .NET programming. I am trying to take a powershell script and make an agent that performs the similar function. The agent compiles and installs correctly and logs the output of the powershell commands to a log file. The problem is that I am not accessing the values but rather the log prints the object out? How can I access the values? Thanks in advance and be gentle with my rudimentary attempt.
My reference to the documentation I have been using: https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.powershell?view=powershellsdk-7.4.0
Log file output: Execution Time: 10/2/2024 3:49:45 PM Launched Bandwidth Trap...System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Management.Automation;
namespace SBC_Agent
{
public partial class Service1 : ServiceBase
{
Timer timer = new Timer(); // name space(using System.Timers;)
private Timer _audittimer;
private string auditFilePath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\Audit";
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WriteToFile("Service is started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 5000; //number in milliseconds
timer.Enabled = true;
_audittimer = new Timer();
_audittimer.Interval = 60000;
_audittimer.Elapsed += new ElapsedEventHandler(OnElapsedAuditTime);
_audittimer.Enabled = true;
Directory.CreateDirectory(Path.GetDirectoryName(auditFilePath));
}
private void OnElapsedAuditTime(object source, ElapsedEventArgs e)
{
RunPowerShellCommands();
}
private void BandwidthTrap()
{
try
{
using (System.Management.Automation.PowerShell psInstance = System.Management.Automation.PowerShell.Create())
{
//psInstance.AddScript("Get-WmiObject -Class win32_ip4routetable | where {$_.destination -eq \"0.0.0.0\"} | select -ExpandProperty InterfaceIndex | select -First 1");
psInstance.AddScript("Get-WmiObject -Class win32_ip4routetable");
var int_index = psInstance.Invoke();
//var ifIndex = "InterfaceIndex=" + int_index;
using (StreamWriter writer = new StreamWriter(auditFilePath, true))
{
writer.WriteLine("Execution Time: " + DateTime.Now.ToString() + " Launched Bandwidth Trap..." + int_ndex);
}
}
}
catch (Exception ex)
{
EventLog.WriteEntry("Powershell Service Error: " + ex.Message, EventLogEntryType.Error);
using (StreamWriter writer = new StreamWriter(auditFilePath, true))
{
writer.WriteLine("Error: " + ex.Message);
writer.WriteLine("StackTrace: " + ex.StackTrace);
}
}
}
private void RunPowerShellCommands()
{
try
{
BandwidthTrap();
/*
using (System.Management.Automation.PowerShell psInstance = System.Management.Automation.PowerShell.Create())
{
psInstance.AddScript("Get-Process");
var results = psInstance.Invoke();
using (StreamWriter writer = new StreamWriter(auditFilePath, true))
{
writer.WriteLine("Execution Time: " + DateTime.Now.ToString());
foreach (var result in results)
{
writer.WriteLine(result.ToString());
}
writer.WriteLine();
}
}
*/
}
catch (Exception ex)
{
EventLog.WriteEntry("Powershell Service Error: " + ex.Message, EventLogEntryType.Error);
using (StreamWriter writer = new StreamWriter(auditFilePath, true))
{
writer.WriteLine("Error: " + ex.Message);
writer.WriteLine("StackTrace: " + ex.StackTrace);
}
}
}
protected override void OnStop()
{
WriteToFile("Service is stopped at " + DateTime.Now);
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
WriteToFile("Service is recall at " + DateTime.Now);
}
public void WriteToFile(string Message)
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\ServiceLog_" + DateTime.Now.Date.ToShortDateString().Replace('/', '_') + ".txt";
if (!File.Exists(filepath))
{
//Create a file to write to
using (StreamWriter sw = File.CreateText(filepath))
{
sw.WriteLine(Message);
}
}
}
}
}
Original script:
$HOSTNAME=hostname
$RXKEY="bandwidth_rx_trap"
$TXKEY="bandwidth_tx_trap"
$ifIndex = Get-WmiObject -Class win32_ip4routetable | where {$_.destination -eq "0.0.0.0"} | select -ExpandProperty InterfaceIndex | select -First 1
$ifIndex = "InterfaceIndex=" + $ifIndex
$nic_name = Get-WmiObject -Class win32_networkadapterconfiguration -Filter $ifIndex | select -ExpandProperty Description
$nic = [System.Net.NetworkInformation.Networkinterface]::GetAllNetworkInterfaces() | where {($_.description -eq $nic_name) -and ($_.operationalstatus -eq "up")}
for ($i=1; $i -le 5; $i++){
$bytesSent = 0
$bytesReceived = 0
$stats = $nic.GetIPv4Statistics()
$bytesSent = $stats.BytesSent
$bytesReceived = $stats.BytesReceived
$bytesSentSum = $bytesSentSum + $bytesSent
$bytesReceivedSum = $bytesReceivedSum + $bytesReceived
Start-Sleep 1
}
$TXAVG=[math]::round($bytesSentSum/5/1024,0)
$RXAVG=[math]::round($bytesReceivedSum/5/1024,0)
If you want to extract the first InterfaceIndex
from win32_ip4routetable
it's easier to use the Invoke<T>()
method, then the method outputs a Collection<T>
instead of a Collection<PSObject>
, then from there you can FirstOrDefault()
it pretty easily.
In summary:
using (PowerShell psInstance = PowerShell.Create())
{
int int_index = psInstance
.AddScript(@"
Get-CimInstance -Class win32_ip4routetable |
Where-Object { $_.Destination -eq '0.0.0.0' } |
Select-Object -ExpandProperty InterfaceIndex -First 1")
.Invoke<int>()
.FirstOrDefault();
using (StreamWriter writer = new StreamWriter(auditFilePath, true))
{
writer.WriteLine(
$"Execution Time: {DateTime.Now} Launched Bandwidth Trap...{int_index}");
}
}
You could also use ManagementObjectSearcher
class directly, no PowerShell instance needed:
string query = @"
SELECT InterfaceIndex FROM Win32_IP4RouteTable
WHERE Destination='0.0.0.0'";
ManagementObject? result = new ManagementObjectSearcher(query)
.Get()
.OfType<ManagementObject>()
.FirstOrDefault();
using (StreamWriter writer = new StreamWriter(auditFilePath, true))
{
writer.WriteLine(
$"Execution Time: {DateTime.Now} Launched Bandwidth Trap...{result?["InterfaceIndex"]}");
}