Performance monitor on Vpn - c#

I am using the windows performance monitor classes in my C# project to measure bytes sents etc via the network card and all seems fine. I am using the network index number to determine the network interface to use to record performance data. I can see the network index numbers via the command prompt (netsh int ipv4 show int)
However, I have connected to the vpn and changed the network index number to refer to the vpn and when I try to read the performance monitor "nextValue()" I get an exception.
So my question is, can I use the "System.Diagnostic.PerformanceCounters" to get packets sent etc from the VPN or is there another way to do this?

Try to use the powershell performance counters, they have a lot of power...
The way guide to the power shell commands (import-counter) can be found here..
http://ss64.com/ps/
I have added some example code below for you to see how they are called:
private static void LoadBLG(string CounterPath)
{
PowerShell ps = PowerShell.Create();
ps.AddCommand("import-counter");
ps.AddArgument(CounterPath);
Console.WriteLine(CounterPath);
Console.WriteLine("------------------------");
foreach (PSObject result in ps.Invoke())
{
if (result.ImmediateBaseObject is PerformanceCounterSampleSet)
{
PerformanceCounterSampleSet Counters = result.ImmediateBaseObject as PerformanceCounterSampleSet;
foreach (PerformanceCounterSample sample in Counters.CounterSamples)
Console.WriteLine("{0,-20}{1}",
sample.Path, sample.RawValue);
}
} // End foreach.
Good luck
Matthew

Related

determining the current link speed of WiFi in C#

I am writing a program that does one thing, it finds out the current link speed of the wifi connection and reports it to the user in real time. the problem I am having is that it does not seem to be able to find out the current link speed, only the max link speed of the device (300 Mbps). the reason I am writing this is that I have a problem where, periodically the link speed will drop drastically (down to 1-2 Mbps) and I want to be able to see when that happens. with this code it will simply give me the maximum speed that the adapter supports, not the current link speed of the connection.
private void update(object state)
{
System.Net.NetworkInformation.NetworkInterface[] nics = null;
nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
long speed = 0;
string adapter = "";
foreach (System.Net.NetworkInformation.NetworkInterface net in nics)
{
if (net.Name.Contains("Wireless") || net.Name.Contains("WiFi") || net.Name.Contains("802.11") || net.Name.Contains("Wi-Fi"))
{
speed = net.Speed;
adapter = net.Name;
break;
}
}
string temp;
if (speed == 0)
{
temp = "There is currently no Wi-Fi connection";
}
else
{
temp = "Current Wi-Fi Speed: " + (speed / 1000000) + "Mbps on " + adapter;
}
if (label1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(update);
label1.Invoke(d, new object[] { temp });
}
else
{
label1.Text = temp;
}
}
this run by calling
System.Threading.Timer ticker = new System.Threading.Timer(update, label1, 0, 1000);
in the main method.
Considering that it literally took me the whole entire day to find what the solution to this was, I figured I'd at least show StackOverflow for future reference what I came across and what did and did not work for this question.
tl;dr: Scroll to the The Code section
What I found
Good ol' control panel
If you are looking for the really easy way to do this you can simply go and open Contol Panel. Depending on what version of Windows you are on (in my case I'm on Windows 8), the path to the page is Control Panel >> Network and Internet >> Network and Sharing Center and then you can click on the link next to "Connections: " which will give you a window that looks like what is below.
The current link speed is highlighted in red which in my case is 36.0 Mbps. Though, of course, this might not satisfy your original question if you were intending to integrate some code with the actual value.
WMI
With a mix of Googling and whatnot, I thought I might have found something in Windows Management Instrumentation.
Long story short, AFAIK, WMI does not have what we're looking for.
WMI, in short, is a giant object database (that
can also be queried through SQL) that allows you to query information about a
Windows machine such as process, disks, etc. In WMI, everything is
represented by a class with a series of instances each with a set of
properties.
Anyhow, WMI Explorer allows you to view all of this on your machine.
I (supposedly) found two classes on MSDN that might have the info on link speed but from WMI Explorer, there was nothing useful.
The first class, MSFT_NetAdapter, did not even show up in WMI Explorer on my machine.
The second class, Win32_NetworkAdapter, showed up in WMI Explorer, but the Speed property was still incorrect. The same network adapter was showing a value of 168000000 or 168 Mbps which is not right. Though I find this strange because there was already a MaxSpeed but it was blank.
Scratch WMI off the list.
Win32 P/Invoke
Yes, of course, the solution to everything is always calling unmanaged Win32 APIs using P/Invoke magic.
This is the route used to solve the problem.
Luckily, the IP_ADAPTER_ADDRESSES structure solves the problem. If you look at the MSDN page, it's a fairly large structure but what is important here is TransmitLinkSpeed which actually works.
Calling the GetAdaptersAddresses() function will return the actual structure.
Now, the actual C# P/Invoke code. Luckily, pinvoke.net already had interop for this function which I've added. This is all that was necessary.
The Code
Finally, here is your code patched up with the new P/Invoke black magic. I've made it work as a console application for demo purposes:
Using Statements:
using System;
using System.Threading;
Code:
class Program
{
private static void Main(string[] args)
{
Timer ticker = new Timer(Update, null, 0, 1000);
// Keep the main thread from dying
while (true)
{
Thread.Sleep(1000);
}
}
private static void Update(object state)
{
ulong speed = 0;
string adapter = "";
string[] nameSearches = { "Wireless", "WiFi", "802.11", "Wi-Fi" };
// The enum value of `AF_INET` will select only IPv4 adapters.
// You can change this to `AF_INET6` for IPv6 likewise
// And `AF_UNSPEC` for either one
foreach (IPIntertop.IP_ADAPTER_ADDRESSES net in IPIntertop.GetIPAdapters(IPIntertop.FAMILY.AF_INET))
{
bool containsName = false;
foreach (string name in nameSearches)
{
if (net.FriendlyName.Contains(name))
{
containsName = true;
}
}
if (!containsName) continue;
speed = net.TrasmitLinkSpeed;
adapter = net.FriendlyName;
break;
}
string temp;
if (speed == 0)
{
temp = "There is currently no Wi-Fi connection";
}
else
{
temp = string.Format("Current Wi-Fi Speed: {0} Mbps on {1}", (speed / 1000000.0), adapter);
}
Console.WriteLine(temp);
}
}
You are then going to be looking for the actual IPIntertop class that I updated. Since it's pretty big you can find it updated at pinvoke.net or on this PasteBin in case something goes down.
Bottom Line
Windows has a lot of APIs which are somewhat broken (WMI), can have a few "leaky abstractions" (.Net), or can be a pain to work with (Win32).
Sigh, that is a lot and I hope it helps.
I come accross the same issue, and need to get windows wifi link speed which is current negotiated.
and thanks to #Jaxrtech's WMI approach, that really works.
the correct class is CIM_NetworkAdapter(i'm using windows7), and query the speed column to get the current speed.
while wifi current negotiated speed is changing, this speed is changing too. i tested it, this matched ok.
select Description , DeviceID, Speed from CIM_NetworkAdapter
get:
D-Link DWA-140 RangeBooster N USB Adapter 17 285000000
Since no-one here mentioned it yet: why not use https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface.speed?view=net-5.0#System_Net_NetworkInformation_NetworkInterface_Speed
This is, if the table on this site is correct included since .NET Framework 2.0 and seem to included in all other versions of .net including .net core.

Communication via GPIB and RS-232/COM using SCPI

I am currently looking for different possibilities to communicate with SCPI-compatible devices via C#. I've written my first code in LabWindows/CVI (language: C) via a COM interface and did it quite "manually" as I would say:
ComOpen(ComId, "Com1",....);
ComWrite("SYST:...\r");
ComRead(&value)`
Something like this. The problem was for me that I don't like pure C and the lack of OOP was just stupid since I have real objects that want to communicate. Dear National Instruments, why not use OOP to control objects?
Now somebody gave me the hint, that I should look into the global SCPI-documentation since there is more information than in the manual of the device. And I've found a .NET-compatible set of commands. For example,
IIviDCPwr Ivi.DCPwr.Create(String resourceName,
Boolean idQuery,
Boolean reset,
LockType lockType,
String accessKey,
String options);
to build up an object-oriented communication with SCPI-devices. Since I really like C# I want to try this in the next weeks.
But I really can not see the connection settings since resourceName only seems to be a name to free the regarded device afterwards and the other settings were used when the connection is already set. How can an instance of IIviDCPwr know which connection (TCP/IP, COM or GPIB) should be used?
I've only seen solutions for TCP/IP by using sockets. But I think this is not applicable to COM and GPIB?
Another solution would be to use the National Instruments VISA-package. But I don't like the idea of using a proprietary package provided by NI (I think after using CVI I feel a newly developed repulsion towards NI).
Can you provide code snippets or documentations to handle this problem? Have you made any experiences by using VISA? Can I use sockets for COM/GPIB-communication?
BTW: How to create new lines in code snippets? Neither enter nor Shift + Enter, \r, \n, \ works for me...
You can use the .NET SerialPort and Socket (without using VISA) to communicate with your devices, by using their read/write methods. About GPIB, your hardware should have a .NET driver, with similar methods.
Some example of how to communicate with device using SerialPort (with some pseudo-SCPI)
SerialPort port = new SerialPort("COM1", 9600);
port.Open();
port.WriteLine(":DEVICE:OUT 1"); //turn on
port.WriteLine(":DEVICE:MEAS:VOLT?"); //measure voltage
float v = float.Parse(port.ReadLine()); //reading from device
Console.WriteLine("The measured voltage is " + v );
Now you can create classes of your devices, where every instance would have his own protocol (SerialPort, Socket, GPIB), and methods
public class SomeDevice
{
private SerialPort _port;
public SomeDevice(string serialPortName)
{
// do the connection work...
}
public void SetVoltage(float voltage)
{
port.WriteLine(":VOLT " + voltage.ToSring("N2"));
}
public float GetVoltage()
{
port.WriteLine(":DEVICE:MEAS:VOLT?");
return float.Parse(port.ReadLine()); //reading from device
}
}
You can even improve your classes to have the ability to use any kind of connection (SerialPort, Socket, GPIB...) by creating an interface (lets say - GenConnection) of general connection (with the common read/write methods), and then create child of your connection types implementing this interface - then each of your devices would have only GenConnection instance without "knowing" which kind of connection it realy is (just overload the constructor for each kind of connection)
Few points to keep in mind:
The programming manual help avoiding common errors
Connection configuration (baud, parity ...)
End of line character, you should keep in mind to send and separate readings
with the device end of line - usually <CR> or <CR><LF> ("\r" or "\r\n" in C#).
The SerialPort's ReadLine & WriteLine is doing it for you using the specified SerialPort's NewLine property
You can play with your port and socket using TeraTerm to see everything as expected

Determine which network adapter a process is using

I've seen several similar questions on Google, but nothing exactly matches what I'm trying to do. I'm making a lag-reducing program (for a game) that basically lowers the user's MTU when a certain process is open, and restores it when the process is closed. However, MTU is a network-adapter specific setting, and some users have multiple connected network adapters. To this end, I thought it'd be nice to have the program also detect which adapter is being used by the game, and only change the MTU on that adapter.
The game will only use one adapter at a time.
I can't hardcode in end-server-IP addresses because they change fairly frequently. It seems to be there must be a way to determine which adapter the other process is using without knowing the end IP address, but I can't seem to find it.
EDIT:
Thanks to Cicada and Remco, I've solved the problem.
I used the ManagedIPHelper class that Remco linked to (ManagedIpHelper) and Cicada's comments led me to this article (Identifying active network interface)
Combining those with some (Nasty, horribly unoptimized) LINQ, I got this code snippet, which takes the process name and returns the Network Interface it's using, or null if it can't find one.
private NetworkInterface getAdapterUsedByProcess(string pName)
{
Process[] candidates = Process.GetProcessesByName(pName);
if (candidates.Length == 0)
throw new Exception("Cannot find any running processes with the name " + pName + ".exe");
IPAddress localAddr = null;
using (Process p = candidates[0])
{
TcpTable table = ManagedIpHelper.GetExtendedTcpTable(true);
foreach (TcpRow r in table)
if (r.ProcessId == p.Id)
{
localAddr = r.LocalEndPoint.Address;
break;
}
}
if (localAddr == null)
throw new Exception("No routing information for " + pName + ".exe found.");
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
IPInterfaceProperties ipProps = nic.GetIPProperties();
if (ipProps.UnicastAddresses.Any(new Func<UnicastIPAddressInformation, bool>((u) => { return u.Address.ToString() == localAddr.ToString(); })))
return nic;
}
return null;
}
Testing confirms this works perfectly! Many thanks, guys!
Side notes to anyone using this snippet:
You'll need the ManagedIpHelper classes.
Your app may need to request elevation, depending on the situation.
Multiple running processes (think Chrome) will return an undefined result. If you're going to use this code with a multpile-process-candiate situation, I highly recommend you change using (Process p = candidates[0]) to a more specific filter, ie based on PID.
You may also want to impliment new exception types, so you can, for example, catch "No routing info" more cleanly, the reason being that this error is often fixed by simply waiting a bit (to let the target process open a connection) and then retrying.
in addition to Cicada, this must help you:
It is a C# wrapper around some c/c++ code, which gets you the list of all open connections with associated PID ( Process Id ).
http://www.timvw.be/2007/09/09/build-your-own-netstatexe-with-c/
I do believe this is the only way to go, determine the process(id) based on executable path/name and try to find the current connection of that process.

network sessions and sending files

Background
Hi.
I write a program that analyzes the packets for specific words contained therein. I need to analyze outgoing email, jabber, ICQ. If the words are found, the packet is blocked.I did it, but I have a problem with the files and sending email through the web.
Problems
Simple code:
while (Ndisapi.ReadPacket(hNdisapi, ref Request))
{
// some work
switch (protocol)
{
//....
case "HTTP":
// parse packet(byte[])
HTTP.HttpField field = HTTP.ParseHttp(ret);
if (field != null && field.Method == HTTP.HttpMethod.POST)
{
// analyze packet and drop if needed
DoWork();
}
}
The problem is the following. For example, I attach to email the file of 500 KB. The file will be split approximately in 340 packets. In the code above, DoWork() only for first packet will be executed.
Ok, then I need to restore session completely and pass whole session to DoWork(). I did it. But I can't wait while session is finished, because other packet( http, arp, all packets) will be suspended (And after a couple of minutes the Internet is disconnected).
Therefore, the first question:
How to solve this problem (may be advice for design program)?
Now the email, suppose this code:
switch (protocol)
{
//....
case "HTTP":
// parse packet(byte[])
var httpMimeMessage = Mime.Parse(ret);
// analyze packet and drop if needed
DoSomeWork();
break;
}
For example, we are looking for word "Finance". Then, if we open any website and there will be a word finance then packet is blocked.
Second question: How do I determine that this is the e-mail?
Thanks and sorry for my English.
To be able to analyze more than one packet/stream at the same time, you'll need to refactor your solution to use threading or some other form of multitasking and since your task appears to be both compute and io-intensive, you'll probably want to take a hard look at how to leverage event-handling at the operating system level (select, epoll, or the equivalent for your target platform).
And to answer your second question regarding email, you'll need to be able to identify and track the tcp session used to deliver email messages from client to server, assuming the session hasn't been encrypted.
As I'm sure you already know, the problem you're trying to solve is a very complicated one, requiring very specialized skills like realtime programming, deep knowledge of networking protocols, etc.
Of course, there are several "deep packet inspection" solutions out there already that do all of this for you, (typically used by public companies to fulfill regulatory requirements like Sarbanes-Oxley), but they are quite expensive.

How to simulate network failure for test purposes (in C#)?

I'm building what could be called the DAL for a new app. Unfortunately, network connectivity to the database is a real problem.
I'd like to be able to temporarily block network access within the scope of my test so that I can ensure my DAL behaves as expected under those circumstances.
UPDATE: There are many manual ways to disable the network, but it sure would be nice if I could enable/disable within the test itself.
For the time being, I'm just "disabling" the network by setting a bogus static IP as follows:
using System.Management;
class NetworkController
{
public static void Disable()
{
SetIP("192.168.0.4", "255.255.255.0");
}
public static void Enable()
{
SetDHCP();
}
private static void SetIP(string ip_address, string subnet_mask)
{
ManagementClass objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection objMOC = objMC.GetInstances();
foreach (ManagementObject objMO in objMOC) {
if ((bool)objMO("IPEnabled")) {
try {
ManagementBaseObject setIP = default(ManagementBaseObject);
ManagementBaseObject newIP = objMO.GetMethodParameters("EnableStatic");
newIP("IPAddress") = new string[] { ip_address };
newIP("SubnetMask") = new string[] { subnet_mask };
setIP = objMO.InvokeMethod("EnableStatic", newIP, null);
}
catch (Exception generatedExceptionName) {
throw;
}
}
}
}
private static void SetDHCP()
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc) {
// Make sure this is a IP enabled device. Not something like memory card or VM Ware
if ((bool)mo("IPEnabled")) {
ManagementBaseObject newDNS = mo.GetMethodParameters("SetDNSServerSearchOrder");
newDNS("DNSServerSearchOrder") = null;
ManagementBaseObject enableDHCP = mo.InvokeMethod("EnableDHCP", null, null);
ManagementBaseObject setDNS = mo.InvokeMethod("SetDNSServerSearchOrder", newDNS, null);
}
}
}
}
Write a wrapper to the network class connectivity class you're using (e.g. WebClient) with an on-off switch :)
Either that, or block your application in the firewall.
Try blocking the connection with a firewall midway through the session maybe?
I like the wrapper idea as well, but thats kind of abstracting the problem and you prolly might not get exact real world behavior. Also, inserting the wrapper layer and then removing it may be more trouble than its worth.
Edit: Run a script that turns the Network adapter on/off randomly or at set intervals?
If you are trying a complete network outage for your application unplugging the network cable will work. Sometimes you might have a data access layer with multiple data sources (on different machines) in which case you can simulate an exception in your tests with a Mock Framework like Rhino Mocks. Here is some pseudo-code that you may have in your test
void TestUserDBFailure()
{
// ***** THIS IS PSEUDO-CODE *******
//setting up the stage - retrieval of the user info create an exception
Expect.Call(_userRepository.GetUser(null))
.IgnoreArguments()
.Return(new Exception());
// Call that uses the getuser function, see how it reacts
User selectedUser = _dataLoader.GetUserData("testuser", "password");
}
Probably not helpful for simulating "real" network issues, but you could just point your DB connection string to a non-existent machine while within the scope of your test.
Depends on what particular network problem you wish to simulate. For most folks, it's as simple as "server unreachable", in which case you'd just try to connect to a non existent server. Be careful, though, because you want something that is routable but does not answer. Trying to connect to dkjdsjk.com will fail immediately (DNS lookup), but trying to connect to www.google.com:1433 will (probably) time out due to a firewall - which is how your app will behave when your DB server is down.
Try Toxiproxi, it can simulate network outage.
They have REST API and even .NET Client API to change the network simulation programatically (from your test code)
https://github.com/shopify/toxiproxy
Look for a WAN simulator that will allow you to restrict bandwidth (and cut it off completely) I always find it interesting to see how the user experience changes when my apps are run in a bandwidth restricted environment. Look here for some information.
There is a tool you can use for simulating High Latency and Low Bandwidth in Testing of Database Applications as explained in this blog entry.
Just found an alternative that allows to directly close TCP connections:
http://lamahashim.blogspot.ch/2010/03/disabling-network-using-c.html
It is based on Windows IP Helper API (uses DllImport):
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366073(v=vs.85).aspx
Use mock objects to create configurable, destructible versions of the real thing--in this case, the database.

Categories

Resources