How do I detect when the internet is idle (no download/upload) using C#, and initiate a download when it is?
If you are waiting for a moment where there are no connections... you have to know that there are a lot of connections even when you think you are not using Internet.
Try giving a look at WireShark and Prcomon (from sysitnerals) to have an idea.
Notwork traffic
Note: if you are using .NET on Mac or Linux via Mono, you should know that this APIs don't port well to other operating systems. So, what I describe here is only for Windows.
If what you want is to have an idea of the traffic, you can try using System.Net.NetworkInformation.IPGlobalStatistics.
You can do so, like this:
var properties = IPGlobalProperties.GetIPGlobalProperties();
// IPGlobalStatistics for IPv4
var ipv4stat = properties.GetIPv4GlobalStatistics();
// IPGlobalStatistics for IPv6
var ipv6stat = properties.GetIPv6GlobalStatistics();
From the example at MSDN:
Console.WriteLine(" Forwarding enabled ...................... : {0}",
ipstat.ForwardingEnabled);
Console.WriteLine(" Interfaces .............................. : {0}",
ipstat.NumberOfInterfaces);
Console.WriteLine(" IP addresses ............................ : {0}",
ipstat.NumberOfIPAddresses);
Console.WriteLine(" Routes .................................. : {0}",
ipstat.NumberOfRoutes);
Console.WriteLine(" Default TTL ............................. : {0}",
ipstat.DefaultTtl);
Console.WriteLine("");
Console.WriteLine(" Inbound Packet Data:");
Console.WriteLine(" Received ............................ : {0}",
ipstat.ReceivedPackets);
Console.WriteLine(" Forwarded ........................... : {0}",
ipstat.ReceivedPacketsForwarded);
Console.WriteLine(" Delivered ........................... : {0}",
ipstat.ReceivedPacketsDelivered);
Console.WriteLine(" Discarded ........................... : {0}",
ipstat.ReceivedPacketsDiscarded);
Console.WriteLine(" Header Errors ....................... : {0}",
ipstat.ReceivedPacketsWithHeadersErrors);
Console.WriteLine(" Address Errors ...................... : {0}",
ipstat.ReceivedPacketsWithAddressErrors);
Console.WriteLine(" Unknown Protocol Errors ............. : {0}",
ipstat.ReceivedPacketsWithUnknownProtocol);
Console.WriteLine("");
Console.WriteLine(" Outbound Packet Data:");
Console.WriteLine(" Requested ........................... : {0}",
ipstat.OutputPacketRequests);
Console.WriteLine(" Discarded ........................... : {0}",
ipstat.OutputPacketsDiscarded);
Console.WriteLine(" No Routing Discards ................. : {0}",
ipstat.OutputPacketsWithNoRoute);
Console.WriteLine(" Routing Entry Discards .............. : {0}",
ipstat.OutputPacketRoutingDiscards);
Console.WriteLine("");
Console.WriteLine(" Reassembly Data:");
Console.WriteLine(" Reassembly Timeout .................. : {0}",
ipstat.PacketReassemblyTimeout);
Console.WriteLine(" Reassemblies Required ............... : {0}",
ipstat.PacketReassembliesRequired);
Console.WriteLine(" Packets Reassembled ................. : {0}",
ipstat.PacketsReassembled);
Console.WriteLine(" Packets Fragmented .................. : {0}",
ipstat.PacketsFragmented);
Console.WriteLine(" Fragment Failures ................... : {0}",
ipstat.PacketFragmentFailures);
Console.WriteLine("");
Is Internet Available?
If you need to get a notification when the Internet is avaliable, you can subscribe to System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged. That way you will get a notification event if the Internet is connected or disconnected (Don't forget to unsubscribe).
Example:
var handler = new NetworkAddressChangedEventHandler
(
(sender, args) =>
{
//handle notification
}
);
System.Net.NetworkInformation.NetworkChange += handler;
// Unsubscribe:
System.Net.NetworkInformation.NetworkChange -= handler;
You may be interested in knowing what Network adapters are Up or Down and how much traffic each one has... for that see below.
Idle & Idle time
Let's define "Idle". I would say "Idle" means that the Internet is available (check above), and if it hasn't been used for a given ammount of time.
So, the other thing you got to do is is calling NetworkInterface.GetAllNetworkInterfaces that will give you an array of System.Net.NetworkInformation.NetworkInterface on which you can call the method GetIPStatistics to get an IPStatistics object for that particular netowork interface. You can also read the OperationalStatus property to know if the particular interface is Up or not
Example:
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (var adapter in adapters)
{
// Is Up, Down, something else?
Console.WriteLine(" {0} is {1}", adapter.Name, dapter.OperationalStatus);
var stats = adapter.GetIPStatistics();
// Read some properties
Console.WriteLine(" Bytes Recieved: {0}", stats.BytesReceived);
Console.WriteLine(" Bytes Sent: {0}", stats.BytesSent);
}
What you will need to do is store this information in a way you can query it, to check if it has changed:
// Fields
Dictionary<string, Tuple<long, long>> data
= new Dictionary<string, Tuple<long, long>>();
bool IsInternetIdle()
{
bool idle = true;
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
foreach (var adapter in adapters)
{
var stats = adapter.GetIPStatistics();
Tuple<long, long> info;
if (!data.TryGetValue(adapter.Name, out info))
{
//New Adapter
info = new Tuple<long, long>
(
stats .BytesReceived,
stats .BytesSent
);
data.Add(adapter.Name, info);
}
else
{
if
(
info.Item1 != stats .BytesReceived
|| info.Item2 != stats .BytesSent
)
{
idle = false;
break;
}
}
}
//Console.WriteLine("Is Idle: {0}", idle.ToString());
return idle;
}
And add some logic to handle idle time:
// Fields
Stopwatch watch = new Stopwatch();
static TimeSpan? GetInternetIdleTime()
{
if (IsInternetIdle())
{
if (!watch.IsRunning)
{
watch.Start();
}
//Console.WriteLine("Idle Time: {0}", XmlConvert.ToString(watch.Elapsed));
return watch.Elapsed;
}
else
{
watch.Stop();
watch.Reset();
return null;
}
}
Example usage:
GetInternetIdleTime(); //preemptive call
Thread.Sleep(1000);
var result = GetInternetIdleTime();
if (result.HasValue)
{
Console.WriteLine("Idle time: {0}", result.Value);
}
else
{
Console.WriteLine("Not Idle");
}
Console.ReadKey();
Words of caution
Remember to unsubscribe your event handler.
This is intended to work on Windows only.
Remember that the first run of IsInternetIdle (described above) all the network adapters are new. You may want to do a preemptive call to GetInternetIdleTime (described above) before stating using them.
The methods IsInternetIdle and GetInternetIdleTime are intended to be used only when Internet is available. You could add checks to see if the individual network adapters are Up.
The result of GetInternetIdleTime described above is not the total time that the connections has been inactive, but the time since it was discovered that the connections are inactive. You may want to call GetInternetIdleTime in a timer (of if your application has a main loop - say, it's a game - you can call it with a given frequency).
If a netwokr adaptes is Active, it doesn't mean that it is using Internet. Maybe it is connected to some Intranet. There is no way to tell if "Internet" is reachable. You should check for conectivity with individual servers yourself. Don't know what to check? It can be problematic because DNS can be overrrided locally... but you can try example.or, InterNIC.net or even ntp.ord.
Alternative
Since this is for Windows anyway, you can try using WMI to the network adapters information, for that I'll refer you to Find only physical network adapters with WMI Win32_NetworkAdapter class by Mladen Prajdic.
Digging deeper
You can emulate what WireShark does by using PCapDotNet, you will find examples at CodeProject.com. Let me DuckDuckGo that for you.
Related
How can I get a list of long running services on my current machine?
I can list all processes but how can I add to filter long running ones?
private void ListProcesses()
{
Process[] processCollection = Process.GetProcesses();
foreach (Process p in processCollection)
{
Console.WriteLine(p.ProcessName);
}
}
The Process class has a datetime property Process.StartTime that gets the time that the associated process was started.
You could use it to figure out which ones that run for longer.
I can list all processes but how can I add to filter long running ones?
Something like (assuming you are asking for wall time):
foreach (var p in processCollection.Where(n => (DateTime.Now - p.StartTime) > someThresholdInterval))
{
//...long running
}
There are other properties you could also use like TotalProcessorTime which would give you the total amount of time that the process has actually been using the processor (versus sleeping) which might be more interesting in some cases.
If you actually want services, rather than processes, then there is a different method to get those. To get services use ServiceController.GetServices however, I don't think there's a way to get when they started.
for running services only, we must use ServiceController and ManagementObject . here is my code for "long" running services :
static public void Main()
{
TimeSpan Interval = new TimeSpan(5,0,10); // as exemple
var scServices= ServiceController.GetServices();
foreach (ServiceController scTemp in scServices)
{
if (scTemp.Status == ServiceControllerStatus.Running)
{
ManagementObject wmiService;
wmiService = new ManagementObject("Win32_Service.Name='" + scTemp.ServiceName + "'");
wmiService.Get();
var id = Convert.ToInt32(wmiService.Properties["ProcessId"].Value);
Process p = Process.GetProcessById(id);
if ((DateTime.Now.Subtract(p.StartTime)) > Interval)
{
Console.WriteLine(" Service : {0}", scTemp.ServiceName);
Console.WriteLine(" Display name: {0}", scTemp.DisplayName);
Console.WriteLine(" StartTime: {0}", p.StartTime);
}
}
}
Console.ReadLine();
}
This code works fine, however I would like to know if it's possible to get the information on who initiated each connection? Like in which endpoint initiated the connection. Is that possible?
using System.Net.NetworkInformation;
public static void ShowActiveTcpConnections()
{
Console.WriteLine("Active TCP Connections");
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] connections = properties.GetActiveTcpConnections();
foreach (TcpConnectionInformation c in connections)
{
Console.WriteLine("{0} <==> {1}",
c.LocalEndPoint.ToString(),
c.RemoteEndPoint.ToString());
}
}
TCP Connections are received on listing ports. Connections made inbound would be returned from GetActiveTcpListeners(), and could be deducted from GetActiveTcpConnections() to get the connections made outbound.
https://msdn.microsoft.com/en-us/library/system.net.networkinformation.ipglobalproperties.getactivetcplisteners(v=vs.110).aspx
You might take a look at http://www.timvw.be/2007/09/09/build-your-own-netstatexe-with-c/
This will tell you how to get the process:
Console.WriteLine(" {0}", processModule.FileName);
Is there any way to query a list of valid domains from ASP.NET C#, similar to the list shown when logging into widows? I would like to provide this to the client users so they can select the appropriate domain with which to login to an intranet web application. I've tried using Forest.GetCurrentForest but I always seem to only get one domain back, when I definitely know there are others.
UPDATE: (CODE)
using System;
using System.Configuration;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.ActiveDirectory;
namespace Domains {
class Program {
static void Main(string[] args) {
try {
using (Forest forest = Forest.GetCurrentForest()) {
Console.WriteLine("FOREST");
Console.WriteLine(" {0}", forest.Name);
Console.WriteLine("-------------------------------------------------------------------------------");
Console.WriteLine(" DOMAINS");
foreach (Domain domain in forest.Domains) {
Console.WriteLine(String.Format(" {0}", domain.Name));
Console.WriteLine(" TRUSTS");
TrustRelationshipInformationCollection domainTrusts = domain.GetAllTrustRelationships();
if (domainTrusts.Count == 0) {
Console.WriteLine(" N/A");
} else {
foreach (TrustRelationshipInformation trust in domainTrusts) {
DirectoryContext x = new DirectoryContext(DirectoryContextType.Domain, trust.TargetName);
Console.WriteLine(String.Format(" {0} -> {1}", trust.SourceName, trust.TargetName));
}
}
domain.Dispose();
}
Console.WriteLine("-------------------------------------------------------------------------------");
Console.WriteLine(" TRUSTS");
TrustRelationshipInformationCollection forestTrusts = forest.GetAllTrustRelationships();
if (forestTrusts.Count == 0) {
Console.WriteLine(" N/A");
} else {
foreach (TrustRelationshipInformation trust in forestTrusts) {
Console.WriteLine(String.Format(" {0} -> {1}", trust.SourceName, trust.TargetName));
}
}
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
Console.WriteLine("\nPress ESC to exit...");
do {
while (!Console.KeyAvailable) {
// Do something
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
}
Now when I go to log into the machine directly (remote desktop, etc.) I get a list of 6 domains I can log into, but when the above code runs on the same machine (currently just a console app for testing, not ASP.NET enabled yet), I get one domain, the current domain I'm logged into on the machine.
EDIT:
I think maybe I'm getting confused, perhaps what I am really looking for is the NetBios domain names. Because I just realized the domain + all the trusts equal the count of domains I'm looking for, but these are the full names, not short names I expected.
UPDATE:
So I was able to acquire the netbiosname of the main domains using an LDAP query, but I'm not sure how to go about getting the netbiosname for the trusted domains...
If you are looking for all domains in teh forest use:
Forest.Domains
property. returns a DomainCollection.
GetCurrentForest returns only Forest for the current user context.
Forest.GetCurrentForest().Domains
Should return all domains.
I am currently facing a problem related to SMSlib for .NET library (you can download it at http://www.smslib.org/)
btw I used SendMessage example (you can find it in ...\Examples\SendMessage) found in the library, and tried to compile and run it using VS2012...it worked fine , but it never succeeded when I tried to restart the services again after adding a little bit code to restart the services into it...
Do you know how to make the services restart properly?
btw part of the code is as follows :
try
{
Console.WriteLine("Example: Read messages from a serial gsm modem.");
Console.WriteLine(Library.getLibraryDescription());
Console.WriteLine("Version: " + Library.getLibraryVersion());
// Start the COM listening thread.
new Thread(new ThreadStart(com1.Run)).Start();
// Lets set some callbacks.
srv.setInboundMessageNotification(new InboundNotification());
srv.setCallNotification(new CallNotification());
srv.setGatewayStatusNotification(new GatewayStatusNotification());
// Create the Gateway representing the serial GSM modem.
// Due to the Comm2IP bridge, in SMSLib for .NET all modems are considered IP modems.
IPModemGateway gateway = new IPModemGateway("modem.com14", "127.0.0.1", 12000, "Huawei","E173");
gateway.setIpProtocol(ModemGateway.IPProtocols.BINARY);
// Set the modem protocol to PDU (alternative is TEXT). PDU is the default, anyway...
gateway.setProtocol(AGateway.Protocols.PDU);
// Do we want the Gateway to be used for Inbound messages?
gateway.setInbound(true);
// Do we want the Gateway to be used for Outbound messages?
gateway.setOutbound(true);
// Add the Gateway to the Service object.
srv.addGateway(gateway);
// Similarly, you may define as many Gateway objects, representing
// various GSM modems, add them in the Service object and control all of them.
// Start! (i.e. connect to all defined Gateways)
srv.startService();
// Printout some general information about the modem.
Console.WriteLine();
Console.WriteLine("Modem Information:");
Console.WriteLine(" Manufacturer: " + gateway.getManufacturer());
Console.WriteLine(" Model: " + gateway.getModel());
Console.WriteLine(" Serial No: " + gateway.getSerialNo());
Console.WriteLine(" SIM IMSI: " + gateway.getImsi());
Console.WriteLine(" Signal Level: " + gateway.getSignalLevel() + "dBm");
Console.WriteLine(" Battery Level: " + gateway.getBatteryLevel() + "%");
Console.WriteLine();
// Send one message.
// Remember to change the recipient!
OutboundMessage msg = new OutboundMessage("0952998989", "Hello from SMSLib for .NET");
srv.sendMessage(msg);
Console.WriteLine(msg);
Console.WriteLine("Press <ENTER> to terminate...");
Console.In.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
finally
{
com1.Stop();
srv.stopService();
// Start! (i.e. connect to all defined Gateways)
srv.startService();
new Thread(new ThreadStart(com1.Run)).Start();
}
You should not call com1.Stop(); until you're completely done with starting/stopping the service. Just leave the listener active.
E.g.
finally
{
srv.stopService();
srv.startService();
srv.stopService();
srv.startService();
srv.stopService();
srv.startService();
srv.stopService();
srv.startService();
srv.stopService();
// ... and finally ...
com1.Stop();
}
From C# console application i had open the command prompt and checked the ping utility.
string aptracommand;
aptracommand = "/C ping 10.38.2.73";
Process.Start(#"cmd",aptracommand);
Now , i need to apply a conditional statement if ping request time out then it should say "Not able to connect" and if its able to ping then need to show "Server is up"
You can use Ping class for this purpose. As stated below:
using System.Net.NetworkInformation;
var ping = new Ping();
var reply = ping.Send("10.38.2.73", 60 * 1000); // 1 minute time out (in ms)
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Server is up");
}
else
{
Console.WriteLine("Server is down");
}
You can reduce the time out value to quickly check if server is up or down.
use this instead
Ping pingSender = new Ping ();
byte[] data = Encoding.ASCII.GetBytes ("test");
int timeout = 100;
PingReply reply = pingSender.Send("127.0.0.1", timeout, data);
if (reply.Status == IPStatus.Success)
{
Console.WriteLine("Address: {0}", reply.Address.ToString());
Console.WriteLine("RoundTrip time: {0}", reply.RoundtripTime);
Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
}
I think you will need to capture the output, check for the existence of time out string and then take the decision based on that.
Capturing the Output