I wrote a C# app which takes screenshot every 5 mins a saves it to server. It is timer, 2 threads, few methods(ping srv, check folder, take screenshot etc.).
As process (exe) it runs great, but I need to install it as service. I am installing it trough installutil (Framework service installer).
My problem is, that when it is installed as service, it doesn't take screenshots. Pull out some, when stopping the service. Not the right resolution and black.
I assume, that the executive code is misplaced (see main). I don't know where to put it, since I cannot have more than one main method. Please help.
Code of main application:
I've deleted some not important code.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
//using System.Timers;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.ComponentModel;
using System.Configuration.Install;
namespace LogWriterService
{
static class Program
{
public static int TimeO = 5; // zpoždění časovače v minutách
private static bool Online;
private static bool active = false;
public static String GetIP()
{
// ...
// returns IP like xxx.xxx.xxx.xxx
// ...
}
// Test dostupnosti serveru
public static bool PingTest()
{
// ...
// return true if server is reachable
// ...
}
/*
* Z Windows.Forms _ screenů získá obrazová data, která uloží na
* server jako ../[IP]/[současný_systémový_čas].jpg
*/
public static void ScreenShot() //Bitmap
{
Int64 CurrTime = Int64.Parse(DateTime.Now.ToString("yyyyMMddhhmmss")); //yyyyMMddhhmmss
Rectangle bounds = Rectangle.Empty;
foreach (Screen s in Screen.AllScreens)
bounds = Rectangle.Union(bounds, s.Bounds);
Bitmap screenShotBMP = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); // PixelFormat.Format32bppArgb
Graphics screenShotGraphics = Graphics.FromImage(screenShotBMP);
screenShotGraphics.CopyFromScreen(bounds.X, bounds.Y,
0, 0, bounds.Size, CopyPixelOperation.SourceCopy);
string path = null; //"D:/TEMP/" + CurrTime + ".jpg"; // GetIP()
// Ukládání obrázků do dočasné složky a přesun, pokud se připojí
if (PingTest() == true)
{
path = "//10.0.0.10/Upload/screen/test/" + GetIP() + "/" + CurrTime + ".jpg";
string path2 = "//10.0.0.10/Upload/screen/test/" + GetIP() + "/";
Online = true;
if (Directory.Exists(path2))
{
MoveCached();
}
else
{
Console.WriteLine("Online slozka neni dostupna.");
}
} else {
Console.WriteLine("Caching .. ");
path = "C:/TEMP/" + CurrTime + ".jpg"; // "C:/TEMP/" + GetIP() + "/" + CurrTime + ".jpg"
string LPath = #"c:\TEMP";
if (!Directory.Exists(LPath))
{
DirectoryInfo di = Directory.CreateDirectory(LPath);
di.Attributes = FileAttributes.Directory | FileAttributes.Hidden;
Console.WriteLine("Lokalni slozka neexistuje. Vytvarim ..");
}
Online = false;
}
screenShotBMP.Save(path, ImageFormat.Jpeg); // C:\\test\\test.jpg
screenShotGraphics.Dispose();
screenShotBMP.Dispose();
return; //screenShotBMP;
}
/*
* Přesune cache soubory (za dobu offline) na server
*/
public static void MoveCached()
{
// ...
// after conect, move localy saved screenshots to server
// ...
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
// Vytvoří událost signalizující hranici odpočtu ve
// zpětném volání časovače
AutoResetEvent autoEvent = new AutoResetEvent(false);
// Počet průchodů timeru
StatusChecker statusChecker = new StatusChecker(Timeout.Infinite); // 1440
// Vytvoří odvozeného delegáta, který vyvolá metody pro časovač
TimerCallback tcb = statusChecker.CheckStatus;
// Create a timer that signals the delegate to invoke
// CheckStatus after one second, and every 1/4 second
// thereafter.
System.Threading.Timer stateTimer = new System.Threading.Timer(tcb, autoEvent, 1000, TimeO * 1000); // TimeO * 1000 * 60 * 12 * 5, 250
// When autoEvent signals, change the period to every
// 1/2 second.
autoEvent.WaitOne(15000, false);
stateTimer.Change(0, TimeO * 1000 * 60); // TimeO * 1000 * 60
Console.WriteLine("menim poprve..");
// When autoEvent signals the second time, dispose of
// the timer.
autoEvent.WaitOne(Timeout.Infinite, false);
stateTimer.Change(0, TimeO * 1000 * 60); // TimeO * 1000 * 60
Console.WriteLine("menim podruhe..");
//stateTimer.Dispose();
// Garbage collector
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}
class StatusChecker
{
private int invokeCount;
private int maxCount;
Int64 CurrTime = Int64.Parse(DateTime.Now.ToString("hh")); // screeny od 6:00 do 16:00
public StatusChecker(int count)
{
invokeCount = 0;
maxCount = count;
}
// Tato metoda je volána delegátem časovače
public void CheckStatus(Object stateInfo)
{
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
//if ((CurrTime > 6) & (CurrTime < 16)) // 16
//{
LogWriterService.Program.ScreenShot();
Console.WriteLine("ScreenShot ..");
//}
Console.WriteLine("{0} Kontroluji stav {1,2}.",
DateTime.Now.ToString("h:mm:ss.fff"),
(++invokeCount).ToString());
if (invokeCount == maxCount)
{
// Resetuje čítač a signál Main.
invokeCount = 0;
autoEvent.Set();
}
// Garbage collector
GC.Collect();
Console.WriteLine("Paměť uvolněna .. \n");
}
}
Code of service:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
namespace LogWriterService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Sluzba screenshot se spustila.");
}
protected override void OnStop()
{
EventLog.WriteEntry("Sluzba screenshot se zastavila.");
}
}
}
I thing the problem may be here:
public static void CreateProcessAsUser()
{
IntPtr hToken = WindowsIdentity.GetCurrent().Token;
IntPtr hDupedToken = IntPtr.Zero;
ProcessUtility.PROCESS_INFORMATION pi = new ProcessUtility.PROCESS_INFORMATION();
try
{
ProcessUtility.SECURITY_ATTRIBUTES sa = new ProcessUtility.SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
bool result = ProcessUtility.DuplicateTokenEx(
hToken,
ProcessUtility.GENERIC_ALL_ACCESS,
ref sa,
(int)ProcessUtility.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)ProcessUtility.TOKEN_TYPE.TokenPrimary,
ref hDupedToken
);
if (!result)
{
throw new ApplicationException("DuplicateTokenEx failed");
}
ProcessUtility.STARTUPINFO si = new ProcessUtility.STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = String.Empty;
string folder = "D:\\test"; //Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string path = folder + "\\LogWriter\\LogWriter.exe"; // "C:/TEMP/" + GetIP() + "/" + CurrTime + ".jpg"
result = ProcessUtility.CreateProcessAsUser(
hDupedToken,
#path, // C:\Users\ToXiC\AppData\Roaming\LogWriter\LogWriter.exe
String.Empty,
ref sa, ref sa,
false, 0, IntPtr.Zero,
#"D:\\test", ref si, ref pi
);
if (!result)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
throw new ApplicationException(message);
}
}
finally
{
if (pi.hProcess != IntPtr.Zero)
ProcessUtility.CloseHandle(pi.hProcess);
if (pi.hThread != IntPtr.Zero)
ProcessUtility.CloseHandle(pi.hThread);
if (hDupedToken != IntPtr.Zero)
ProcessUtility.CloseHandle(hDupedToken);
}
}
}
The screenshots are all black I think. This happens because a windows service runs in Session 0 Isolation
One solution is to start a console application (with UI hidden) from the service after every 5 mins. The console application can take the screenshot and exit.
Some code to start a console app from windows service:
string applicationPath = ...;
private ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(applicationPath);
//set working directiory
Directory.SetCurrentDirectory(Path.GetDirectoryName(applicationPath));
psi.WorkingDirectory = Path.GetDirectoryName(applicationPath);
//psi.CreateNoWindow = false;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
//psi.UseShellExecute = false;
prcs = System.Diagnostics.Process.Start(psi);
Edit: The console application will be started in session 0. Workaround is to use the WIN API CreateProcessAsUser pinvoke call and start the console application in a user session.
Some links with code samples on how to achieve this:
http://odetocode.com/blogs/scott/archive/2004/10/28/createprocessasuser.aspx
http://blogs.msdn.com/b/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx
http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/31bfa13d-982b-4b1a-bff3-2761ade5214f/
Problem was with token. I found working solution here
how-can-windows-service-execute-gui
Thank you all for helping me out of it. I understand now much more how windows service works.
Related
I want to write a window service for keep capturing the network traffic and save the packets info into a log file, but I can't start it.
"Error 1064: An exception occurred in the service when handling the control request."
References:
Capturing And Parsing Packets
Save Output to Log
Create Window Service
Here's the code for Windows Service(failed):
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 CapturingAndParsingPackets;
using PacketDotNet;
using SharpPcap;
namespace CaptureService
{
public partial class Service1 : ServiceBase
{
private static bool _stopCapturing;
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);//Get the desktop path
string filename = DateTime.Now.ToString("yyyy-MM-dd--HH-mm-ss");//Use date to name the file
public Service1()
{
InitializeComponent();
var devices = CaptureDeviceList.Instance; //Get the local devices
if (devices.Count < 1)
{
OnStop();
return;
}
}
protected override void OnStart(string[] args)
{
var devices = CaptureDeviceList.Instance; //Get the local devices
//set output type
var defaultOutputType = StringOutputType.Normal;
var outputTypeValues = Enum.GetValues(typeof(StringOutputType));
StringOutputType selectedOutputType = defaultOutputType;
int userSelectedOutputType;
userSelectedOutputType = 3;
selectedOutputType = (StringOutputType)userSelectedOutputType;
//read local device
var device = devices[3];
//read packets
var readTimeoutMilliseconds = 1000;
device.Open(DeviceModes.Promiscuous, readTimeoutMilliseconds);
//set filter
string filter = "host 192.168.0.212";
device.Filter = filter;
PacketCapture e;
var status = device.GetNextPacket(out e);
var rawCapture = e.GetPacket();
// use PacketDotNet to parse this packet and print out
// its high level information
var p = Packet.ParsePacket(rawCapture.GetLinkLayers(), rawCapture.Data);
// Create a log file to desktop and write the log into the log file
using (StreamWriter w = File.AppendText(path + "\\" + filename + ".log"))
{
Log(p.ToString(selectedOutputType) + p.PrintHex(), w);
}
device.Close();
}
public static void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
txtWriter.WriteLine();
txtWriter.WriteLine(logMessage);
txtWriter.WriteLine("============================================================================================================");
}
catch (Exception)
{
}
}
protected override void OnStop()
{
using (StreamWriter w = File.AppendText(path + "\\" + filename + ".log"))
{
Log("Service is stopped at " + DateTime.Now, w);
}
}
}
}
And Here is the script for just running it in VS(works fine):
using System;
using PacketDotNet;
using SharpPcap;
using System.IO;
using System.Reflection;
using log4net;
using log4net.Config;
namespace CapturingAndParsingPackets
{
class MainClass
{
// used to stop the capture loop
private static bool _stopCapturing;
public static void Main(string[] args)
{
// Print SharpPcap version
var ver = SharpPcap.Pcap.SharpPcapVersion;
Console.WriteLine("PacketDotNet example using SharpPcap {0}", ver);
// Retrieve the device list
var devices = CaptureDeviceList.Instance;
// If no devices were found print an error
if (devices.Count < 1)
{
Console.WriteLine("No devices were found on this machine");
return;
}
Console.WriteLine();
Console.WriteLine("The following devices are available on this machine:");
Console.WriteLine("----------------------------------------------------");
Console.WriteLine();
var i = 0;
// Print out the devices
foreach (var dev in devices)
{
/* Description */
Console.WriteLine("{0}) {1} {2}", i, dev.Name, dev.Description);
i++;
}
Console.WriteLine();
Console.Write("-- Please choose a device to capture: ");
Console.WriteLine();
Console.WriteLine("Output Verbosity Options");
Console.WriteLine("----------------------------------------------------");
Console.WriteLine();
var defaultOutputType = StringOutputType.Normal;
var outputTypeValues = Enum.GetValues(typeof(StringOutputType));
foreach (StringOutputType outputType in outputTypeValues)
{
Console.Write("{0} - {1}", (int)outputType, outputType);
if (outputType == defaultOutputType)
{
Console.Write(" (default)");
}
Console.WriteLine("");
}
Console.WriteLine();
Console.Write("-- Please choose a verbosity (or press enter for the default): ");
StringOutputType selectedOutputType = defaultOutputType;
int userSelectedOutputType;
//Fixed
userSelectedOutputType = 3;
selectedOutputType = (StringOutputType)userSelectedOutputType;
// Register a cancel handler that lets us break out of our capture loop
Console.CancelKeyPress += HandleCancelKeyPress;
//Fixed
var device = devices[3];
// Open the device for capturing
var readTimeoutMilliseconds = 1000;
device.Open(DeviceModes.Promiscuous, readTimeoutMilliseconds);
//filter host 192.168.0.212
//or you can set it to "filter = 'ip'; " for default
string filter = "host 192.168.0.212";
device.Filter = filter;
Console.WriteLine();
Console.WriteLine("-- Listening on {0}, hit 'ctrl-c' to stop...",
device.Name);
while (_stopCapturing == false)
{
PacketCapture e;
var status = device.GetNextPacket(out e);
// null packets can be returned in the case where
// the GetNextRawPacket() timed out, we should just attempt
// to retrieve another packet by looping the while() again
if (status != GetPacketStatus.PacketRead)
{
// go back to the start of the while()
continue;
}
var rawCapture = e.GetPacket();
// use PacketDotNet to parse this packet and print out
// its high level information
var p = Packet.ParsePacket(rawCapture.GetLinkLayers(), rawCapture.Data);
Console.WriteLine(p.ToString(selectedOutputType) + p.PrintHex());
Console.WriteLine("============================================================================================================");
using (StreamWriter w = File.AppendText("networkTraffic.log"))
{
Log(p.ToString(selectedOutputType), w);
Log(p.PrintHex(), w);
}
}
Console.WriteLine("-- Capture stopped");
// Print out the device statistics
Console.WriteLine(device.Statistics.ToString());
// Close the pcap device
device.Close();
}
static void Log(string logMessage, TextWriter txtWriter)
{
try
{
txtWriter.Write("\r\nLog Entry : ");
txtWriter.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
txtWriter.WriteLine();
txtWriter.WriteLine(logMessage);
txtWriter.WriteLine("============================================================================================================");
}
catch (Exception)
{
}
}
static void HandleCancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Console.WriteLine("-- Stopping capture");
_stopCapturing = true;
// tell the handler that we are taking care of shutting down, don't
// shut us down after we return because we need to do just a little
// bit more processing to close the open capture device etc
e.Cancel = true;
}
}
}
The error that shows in Event Viewer(1064):
Application: CaptureTrafficService.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
at CaptureTrafficService.Service1.OnStart(System.String[])
at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(System.Object)
at System.ServiceProcess.ServiceBase.Run(System.ServiceProcess.ServiceBase[])
at CaptureTrafficService.Program.Main()
Service cannot be started. System.IO.FileNotFoundException: Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b1xxxxxxxxxxx' or one of its dependencies. The system cannot find the file specified.
File name: 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b1xxxxxxxxxxx'
at CaptureTrafficService.Service1.OnStart(String[] args)
at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)
After I remove the while loop in OnStart method, It shows up another error(1053):
Application: CaptureTrafficService.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
Exception Info: System.IO.FileNotFoundException
at CaptureService.Service1..ctor()
at CaptureService.Program.Main()
The answer by #Sam1916 might lessen the frustration of FileNotFoundException.
The "System.IO.FileNotFoundException" caught my attention - but missing info on what files.
As Windows services run in "their own context" the files referenced (Through "using") might not exists in a readable directory, hench "FileNotFoundException"
Is the logfile placed in a directory where your service credentials are allowed to write?
There are too many unnecessary references that may affect each other in the solution so that it will return a lot of errors & warnings when building it. Just add them one by one if it is necessary, rebuild it when you added a new reference(for checking the compatibility) and not just copying all of them to the solution.
Too many unnecessary references(Before)
Just add the references you need(After)
Here's the code that works with windows service:
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 SharpPcap;
using PacketDotNet;
namespace Capture
{
public partial class Capture : ServiceBase
{
Timer timer = new Timer();
public Capture()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Log("Service started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
//timer.Interval = 5000;
timer.Enabled = true;
}
protected override void OnStop()
{
Log("Service is stopped at " + DateTime.Now);
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
var devices = CaptureDeviceList.Instance;
//set output type
var defaultOutputType = StringOutputType.Normal;
StringOutputType selectedOutputType = defaultOutputType;
int userSelectedOutputType;
userSelectedOutputType = ? ;//? = 0-3
selectedOutputType = (StringOutputType)userSelectedOutputType;
//read local device
var device = devices[?];//? is mean num 0-4 or more(depends on your device)
//read packets
var readTimeoutMilliseconds = 1000;
device.Open(DeviceModes.Promiscuous, readTimeoutMilliseconds);
PacketCapture d;
var status = device.GetNextPacket(out d);
var rawCapture = d.GetPacket();
var p = Packet.ParsePacket(rawCapture.LinkLayerType, rawCapture.Data);
Log(p.ToString(selectedOutputType) +p.PrintHex());//write to log file
device.Close();
}
public static void Log(string logMessage)
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);+ "\\Logs" ;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath =Environment.GetFolderPath(Environment.SpecialFolder.Desktop); + "\\Logs\\ServiceLog_" +
DateTime.Now.Date.ToShortDateString().Replace('/','_') + ".log";
using (StreamWriter sw = File.AppendText(filepath))
{
sw.WriteLine(logMessage);
sw.WriteLine("============================================================================================================");
}
}
}
}
In my project I need receive a video through UDP. Source have a IP 224.0.0.21, Sink have a IP 169.254.170.141. I receive video through a port 3956 (This is a valid information from Wireshark). I use SharpPcap for receive UDP traffic, but it have not methods for join to multicast. I try this code from MSDN, but it dont work.
IPAddress multicastaddress = IPAddress.Parse("224.0.0.21");
IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 3956);
m_ClientTarget.JoinMulticastGroup(multicastaddress, localAddr);
In my PC I have some network adapters, but I use the IP address from device, that connected to source video. Source and sink connected directly. When I start monitor traffic in the wireshark my programm also receive packet, but without the wireshack it cant do it.
My code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SharpPcap;
using SharpPcap.LibPcap;
using SharpPcap.AirPcap;
using SharpPcap.WinPcap;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Threading;
namespace GVSPCapture
{
public partial class Form1 : Form
{
static int frameCounter = 0;
static byte[] pixels = new byte[1920 * 1080 * 3];
static IPAddress fpgaAddr = IPAddress.Parse("224.0.0.21");
static IPAddress localAddr = IPAddress.Parse("169.254.170.141");
static MulticastOption mcastOption = new MulticastOption(fpgaAddr, localAddr);
private static UdpClient m_ClientTarget = new UdpClient(3956);
private static IPAddress m_GrpAddr;
const int GroupPort = 3956;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
findDevices();
}
public void findDevices()
{
string ver = SharpPcap.Version.VersionString;
var devices = CaptureDeviceList.Instance;
foreach (var dev in devices)
{
lbxDevices.Items.Add(dev.Name + dev.Description);
}
}
private void JoinVideoMulticast()
{
IPAddress multicastaddress = IPAddress.Parse("224.0.0.21");
IPEndPoint remoteep = new IPEndPoint(IPAddress.Any, 3956);
m_ClientTarget.JoinMulticastGroup(multicastaddress, IPAddress.Parse("169.254.170.141"));
while (true)
{ }
}
private void startCapture(ICaptureDevice dev)
{
if (!dev.Started)
{
dev.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival);
int readTimeoutMilliseconds = 1000;
if (dev is AirPcapDevice)
{
// NOTE: AirPcap devices cannot disable local capture
var airPcap = dev as AirPcapDevice;
airPcap.Open(SharpPcap.WinPcap.OpenFlags.DataTransferUdp, readTimeoutMilliseconds);
}
else if (dev is WinPcapDevice)
{
var winPcap = dev as WinPcapDevice;
winPcap.Open(SharpPcap.WinPcap.OpenFlags.DataTransferUdp | SharpPcap.WinPcap.OpenFlags.NoCaptureLocal, readTimeoutMilliseconds);
}
else if (dev is LibPcapLiveDevice)
{
var livePcapDevice = dev as LibPcapLiveDevice;
livePcapDevice.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
}
else
{
throw new System.InvalidOperationException("unknown device type of " + dev.GetType().ToString());
}
dev.StartCapture();
Thread recvThread = new Thread(JoinVideoMulticast);
recvThread.Start();
}
}
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.tbxCnt.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.tbxCnt.Text = text;
}
}
private void device_OnPacketArrival(object sender, CaptureEventArgs e)
{
var time = e.Packet.Timeval.Date;
var len = e.Packet.Data.Length;
if (len == 572)
{
var tmp = e.Packet.Data;
int packet_id = tmp[47] << 16 | tmp[48] << 8 | tmp[49];
int startPos = (packet_id - 1) * 522;
for (int i = 50; i < tmp.Length; i+=3)
{
pixels[startPos + i + 0 - 50] = tmp[i];
pixels[startPos + i + 1 - 50] = tmp[i];
pixels[startPos + i + 2 - 50] = tmp[i];
}
}
if (len == 60)
{
var im = CopyDataToBitmap(pixels);
pictbFrame.Image = im;
frameCounter += 1;
SetText(frameCounter.ToString());
}
}
public Bitmap CopyDataToBitmap(byte[] data)
{
GCHandle pinned = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr ptr = pinned.AddrOfPinnedObject();
BitmapData dt = new BitmapData();
dt.Scan0 = ptr;
dt.Stride = 5760;
dt.Width = 1920;
dt.Height = 1080;
dt.PixelFormat = PixelFormat.Format24bppRgb;
Bitmap btm = new Bitmap(1920, 1080, 5760, PixelFormat.Format24bppRgb, dt.Scan0);
return btm;
}
private void btnStart_Click(object sender, EventArgs e)
{
int devNum = lbxDevices.SelectedIndex;
if (devNum > 0)
{
var device = CaptureDeviceList.Instance[devNum];
startCapture(device);
}
}
private void btnStop_Click(object sender, EventArgs e)
{
int devNum = lbxDevices.SelectedIndex;
if (devNum > 0)
{
var device = CaptureDeviceList.Instance[devNum];
if (device.Started)
{
device.StopCapture();
device.Close();
}
}
m_ClientTarget.DropMulticastGroup(fpgaAddr);
}
}
}
Without seeing your code (I´m assuming that there´s more than the snippet you show) it´s difficult to help you.
A basic setup for a client receiving multicast datagrams would be something like this untested snippet:
UdpClient mClient = new UdpClient(3956, AddressFamily.InterNetwork);
IPAdress groupAddress = IPAddress.Parse("224.0.0.21);
mClient.JoinMulticastGroup(groupAddress);
After that you the receiving using mClient.Receive()...
Maybe this helps? Or the documentation on MSDN (https://msdn.microsoft.com/en-us/library/ekd1t784(v=vs.110).aspx).
C.
I tested the code with ffmpeg
ffmpeg.exe -i aa.mp4 -f mpeg udp://224.0.0.21:3956
int PORT = 3956;
string MULTICAST_IP = "224.0.0.21";
UdpClient udpClient = new UdpClient(PORT);
udpClient.JoinMulticastGroup(IPAddress.Parse(MULTICAST_IP));
var from = new IPEndPoint(0, 0);
var recvBuffer = udpClient.Receive(ref from);
I have made an application to log all websites visited by current PC user. This is not for a malicious use. I am making this feature for my employee monitoring software which will be licensed under proper laws.
Coming on main point, Whenever I am fetching URL from any browser such as IE. I am only getting its URL for all opened tabs. I am unable to get any tab handle for IE7+ , because of which I am unable to maintain a list of tabs for which I have already logged URL's for same tab.
Below is my code (Take a Look on Commented Code First):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WebsiteLoggerConsole
{
public class WebLogger
{
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow);
System.Threading.Timer log;
public void StartLoggin()
{
try
{
TimerCallback logcallback = new TimerCallback(LogTick);
log = new System.Threading.Timer(logcallback, null, 0, 2000);
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
}
}
public void StopLogging()
{
try
{
log.Dispose();
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
}
}
public void LogTick(Object stateInfo)
{
CreateLog();
}
void CreateLog()
{
try
{
SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
string filename;
foreach (SHDocVw.InternetExplorer ie in shellWindows)
{
filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
if (filename.Equals("iexplore"))
{
int val = ie.HWND;
IntPtr hwnd = new IntPtr(val);
IntPtr uihwnd = GetDirectUIHWND(hwnd);
string ddd = (ie.LocationURL) + " :::: " + (uihwnd.ToString());
Console.WriteLine(ddd);
}
}
//SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindows();
//string filename;
//foreach (SHDocVw.InternetExplorer ie in shellWindows)
//{
// filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower();
// if (filename.Equals("iexplore"))
// {
// int val = ie.HWND;
// IntPtr hwnd = new IntPtr(val);
// IntPtr uihwnd = GetDirectUIHWND(hwnd);
// IntPtr tabhwnd = GetDirectUIHWND(uihwnd);
// string ddd = (ie.LocationURL) + " :::: " + (tabhwnd.ToString());
// Console.WriteLine(ddd);
// }
//}
//Process[] processlist = Process.GetProcesses();
//foreach (Process theprocess in processlist)
//{
// if (theprocess.ProcessName == "iexplore")
// {
// Console.WriteLine("Process: {0}, ID: {1}, Handle: {3}, Window name: {2}",
// theprocess.ProcessName, theprocess.Id, theprocess.MainWindowTitle, theprocess.SessionId.ToString()
// );
// }
//}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
}
}
private static IntPtr GetDirectUIHWND(IntPtr ieFrame)
{
// try IE 9 first:
IntPtr intptr = FindWindowEx(ieFrame, IntPtr.Zero, "WorkerW", null);
if (intptr == IntPtr.Zero)
{
// IE8 and IE7
intptr = FindWindowEx(ieFrame, IntPtr.Zero, "CommandBarClass", null);
}
intptr = FindWindowEx(intptr, IntPtr.Zero, "ReBarWindow32", null);
//intptr = FindWindowEx(intptr, IntPtr.Zero, "TabBandClass", null);
//intptr = FindWindowEx(intptr, IntPtr.Zero, "DirectUIHWND", null);
return intptr;
}
}
}
I provided a solution on this topic: How to write a standalone URL logger for Windows?
There I used Java, but you can do the same by using C#. I am almost sure there is a lot of good libpcap wrappers for C#.
There is a project called pcapDotNet and you can use it.
Adjusting one example:
using System;
using System.Collections.Generic;
using PcapDotNet.Core;
using PcapDotNet.Packets;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
namespace InterpretingThePackets
{
class Program
{
static void Main(string[] args)
{
// Retrieve the device list from the local machine
IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;
if (allDevices.Count == 0)
{
Console.WriteLine("No interfaces found! Make sure WinPcap is installed.");
return;
}
// Print the list
for (int i = 0; i != allDevices.Count; ++i)
{
LivePacketDevice device = allDevices[i];
Console.Write((i + 1) + ". " + device.Name);
if (device.Description != null)
Console.WriteLine(" (" + device.Description + ")");
else
Console.WriteLine(" (No description available)");
}
int deviceIndex = 0;
do
{
Console.WriteLine("Enter the interface number (1-" + allDevices.Count + "):");
string deviceIndexString = Console.ReadLine();
if (!int.TryParse(deviceIndexString, out deviceIndex) ||
deviceIndex < 1 || deviceIndex > allDevices.Count)
{
deviceIndex = 0;
}
} while (deviceIndex == 0);
// Take the selected adapter
PacketDevice selectedDevice = allDevices[deviceIndex - 1];
// Open the device
using (PacketCommunicator communicator =
selectedDevice.Open(65536, // portion of the packet to capture
// 65536 guarantees that the whole packet will be captured on all the link layers
PacketDeviceOpenAttributes.Promiscuous, // promiscuous mode
1000)) // read timeout
{
// Check the link layer. We support only Ethernet for simplicity.
if (communicator.DataLink.Kind != DataLinkKind.Ethernet)
{
Console.WriteLine("This program works only on Ethernet networks.");
return;
}
// Compile the filter
using (BerkeleyPacketFilter filter = communicator.CreateFilter("ip and tcp"))
{
// Set the filter
communicator.SetFilter(filter);
}
Console.WriteLine("Listening on " + selectedDevice.Description + "...");
// start the capture
communicator.ReceivePackets(0, PacketHandler);
}
}
// Callback function invoked by libpcap for every incoming packet
private static void PacketHandler(Packet packet)
{
// print timestamp and length of the packet
Console.WriteLine(packet.Timestamp.ToString("yyyy-MM-dd hh:mm:ss.fff") + " length:" + packet.Length);
IpV4Datagram ip = packet.Ethernet.IpV4;
//Do your magic here using HttpRequestDatagram
}
}
}
I want to get my network interface's Name, Speed, and MAC Address.
var searcher = new ManagementObjectSearcher { Scope = GetConnectedScope(target, "cimv2") };
try
{
searcher.Query = new ObjectQuery("SELECT MACAddress, Speed, Name FROM Win32_NetworkAdapter");
var nicList = new List<NetworkInterfaceModel>();
foreach (var item in searcher.Get())
{
nicList.Add(new NetworkInterfaceModel
{
NetworkInterfaceName = (string)item["Name"],
NetworkInterfaceSpeed = (double)(item["Speed"] != null ? (ulong) item["Speed"] : 0)/1000/1000,
MacAddress = (string)item["MACAddress"]
});
}
For Windows 7 and Vista it work just fine, but for XP and Windows Server 2003 it didn't collect the speed. How can I get the speed for XP and Server 2003?
You can get networks name using windows cmd:
Process p = new Process();
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = "wlan show interfaces";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string s = p.StandardOutput.ReadToEnd();
string s1 = s.Substring(s.IndexOf("SSID"));
s1 = s1.Substring(s1.IndexOf(":"));
s1 = s1.Substring(2, s1.IndexOf("\n")).Trim();
p.WaitForExit();
namelabel.Text = s1;
for MAC Address:
IPAddress IP = IPAddress.Parse("192.168.1.1");
byte[] macAddr = new byte[6];
uint macAddrLen = (uint)macAddr.Length;
UInt32 nRet = 0;
uint nAddress = BitConverter.ToUInt32(IP.GetAddressBytes(), 0);
nRet = SendARP(nAddress, 0, macAddr, ref macAddrLen);
if (nRet == 0)
{
string[] sMacAddress = new string[(int)macAddrLen];
for (int i = 0; i < macAddrLen; i++)
{
sMacAddress[i] = macAddr[i].ToString("x2");
string macAddress += sMacAddress[i] + (i < macAddrLen - 1 ? ":" : "");
}
}
and about speed you can use the following code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.NetworkInformation;
Start with adding a timerInteval(How fast you want to change to the new value) a NetworkInteface and a timer:
private const double timerUpdate = 1000;
private NetworkInterface[] nicArr;
private Timer timer;
Then Continue using the folowing componets on start up:
public Form1()
{
InitializeComponent();
InitializeNetworkInterface();
InitializeTimer();
}
Componets:
private void InitializeNetworkInterface()
{
// Grab all local interfaces to this computer
nicArr = NetworkInterface.GetAllNetworkInterfaces();
// Add each interface name to the combo box
for (int i = 0; i < nicArr.Length; i++)
comboBox1.Items.Add(nicArr[i].Name); //you add here the interface types in a combobox and select from here WiFi, ethernet etc...
// Change the initial selection to the first interface
comboBox1.SelectedIndex = 0;
}
private void InitializeTimer()
{
timer = new Timer();
timer.Interval = (int)timerUpdate;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
Timer's tick
void timer_Tick(object sender, EventArgs e)
{
UpdateNetworkInterface();
}
With this void you update the ping:
public void UpdatePing()
{
try
{
Ping myPing = new Ping();
PingReply reply = myPing.Send(textBox1.Text, 1000);
if (reply != null)
{
label17.Text = reply.Status.ToString();
label18.Text = reply.RoundtripTime.ToString();
}
}
catch
{
label17.Text = "ERROR: You have Some TIMEOUT issue";
label18.Text = "ERROR: You have Some TIMEOUT issue";
}
}
and finally use this to show the speed in network form:
private void UpdateNetworkInterface()
{
// Grab NetworkInterface object that describes the current interface
NetworkInterface nic = nicArr[comboBox1.SelectedIndex];
// Grab the stats for that interface
IPv4InterfaceStatistics interfaceStats = nic.GetIPv4Statistics();
// Calculate the speed of bytes going in and out
// NOTE: we could use something faster and more reliable than Windows Forms Tiemr
// such as HighPerformanceTimer http://www.m0interactive.com/archives/2006/12/21/high_resolution_timer_in_net_2_0.html
// Update the labels
speedlbl.Text = nic.Speed.ToString();
interfaceTypelbl.Text = nic.NetworkInterfaceType.ToString();
bytesReceivedlbl.Text = interfaceStats.BytesReceived.ToString();
bytesSentlbl.Text = interfaceStats.BytesSent.ToString();
int bytesSentSpeed = (int)(interfaceStats.BytesSent - double.Parse(label10.Text)) / 1024;
int bytesReceivedSpeed = (int)(interfaceStats.BytesReceived - double.Parse(label11.Text)) / 1024;
bytescomelbl.Text = bytesSentSpeed.ToString() + " KB/s";
bytessentlbl.Text = bytesReceivedSpeed.ToString() + " KB/s";
}
Win32_NetworkAdapter doesn't support the speed property under XP, As per http://msdn.microsoft.com/en-us/library/windows/desktop/aa394216(v=vs.85).aspx :
Windows Server 2003, Windows XP, Windows 2000, and Windows NT 4.0: This property has not been implemented yet. It returns a NULL value by default.
Instead, use the CIM_NetworkAdapter class with the same property.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa387931(v=vs.85).aspx
using System.Net;
foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) {
Debug.WriteLine(netInterface.Name); // Name
Debug.WriteLine(netInterface.Speed); // Speed
Debug.WriteLine(netInterface.GetPhysicalAddress().ToString()); // MAC
}
OK, I am working on a program that will automatically download an update if the versions don't match.
The problem now is that it loads the info from an XML file, but it doesn't download the files specified.
Any suggestions to improve the code are welcome as well!
Here is the complete source code:
http://www.mediafire.com/?44d9mcuhde9fv3e
http://www.virustotal.com/file-scan/report.html?id=178ab584fd87fd84b6fd77f872d9fd08795f5e3957aa8fe7eee03e1fa9440e74-1309401561
Thanks in advance for the help!
EDIT
The File to download, specified in Program.cs does not download and the program gets stuck at
currentFile = string.Empty;
label1.Text = "Preparing to download file(s)...";
Thread t = new Thread(new ThreadStart(DownloadFiles)); // Making a new thread because I prefer downloading 1 file at a time
t.Start();
and it start the "Thread t".
Code that seems to be making problems:
UpdateForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.NetworkInformation;
using System.Net;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Xml;
using System.Xml.Linq;
using System.Runtime.InteropServices;
namespace LauncherBeta1
{
public partial class UpdateForm : Form
{
const int MF_BYPOSITION = 0x400;
[DllImport("User32")]
private static extern int RemoveMenu(IntPtr hMenu, int nPosition, int wFlags);
[DllImport("User32")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("User32")]
private static extern int GetMenuItemCount(IntPtr hWnd);
private static WebClient webClient = new WebClient();
internal static List<Uri> uriFiles = new List<Uri>();
internal static Uri uriChangelog = null;
private static long fileSize = 0, fileBytesDownloaded = 0;
private static Stopwatch fileDownloadElapsed = new Stopwatch();
bool updateComplete = false, fileComplete = false;
string currentFile = string.Empty, labelText = string.Empty;
int progbarValue = 0, KBps = 0;
public UpdateForm()
{
IntPtr hMenu = GetSystemMenu(this.Handle, false);
int menuItemCount = GetMenuItemCount(hMenu);
RemoveMenu(hMenu, menuItemCount - 1, MF_BYPOSITION);
InitializeComponent();
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://raiderz.daregamer.com/updates/app_version.xml");
XmlNode xNodeVer = xdoc.DocumentElement.SelectSingleNode("Version");
FileVersionInfo fileVer = FileVersionInfo.GetVersionInfo(AppDomain.CurrentDomain.BaseDirectory + "lua5.1.dll");
int ver_app = Convert.ToInt32(fileVer.FileVersion.ToString());
int ver_xml = Convert.ToInt32(xNodeVer);
if (ver_xml == ver_app)
{
Application.Run(new Form1());
Environment.Exit(0);
}
else
{
if (ver_xml < ver_app || ver_xml > ver_app)
{
if (uriChangelog != null)
{
label1.Text = "Status: Downloading changelog...";
try
{
string log = webClient.DownloadString(uriChangelog);
log = log.Replace("\n", Environment.NewLine);
txtboxChangelog.Text = log;
}
catch (WebException ex) { }
}
foreach (Uri uri in uriFiles)
{
string uriPath = uri.OriginalString;
currentFile = uriPath.Substring(uriPath.LastIndexOf('/') + 1);
if (File.Exists(currentFile))
{
label1.Text = "Status: Deleting " + currentFile;
File.Delete(currentFile);
}
}
currentFile = string.Empty;
label1.Text = "Preparing to download file(s)...";
Thread t = new Thread(new ThreadStart(DownloadFiles)); // Making a new thread because I prefer downloading 1 file at a time
t.Start();
}
else
{
//MessageBox.Show("Client is up to date!");
Application.Run(new Form1());
Environment.Exit(0);
}
}
}
private void DownloadFiles()
{
foreach (Uri uri in uriFiles)
{
try
{
fileComplete = false;
fileDownloadElapsed.Reset();
fileDownloadElapsed.Start();
string uriPath = uri.OriginalString;
currentFile = uriPath.Substring(uriPath.LastIndexOf('/') + 1);
webClient.DownloadFileAsync(uri, currentFile);
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressChanged);
while (!fileComplete) { Thread.Sleep(1000); }
}
catch { continue; }
}
currentFile = string.Empty;
updateComplete = true;
}
void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progbarValue = e.ProgressPercentage;
fileSize = e.TotalBytesToReceive / 1024;
fileBytesDownloaded = e.BytesReceived / 1024;
if (fileBytesDownloaded > 0 && fileDownloadElapsed.ElapsedMilliseconds > 1000)
{
KBps = (int)(fileBytesDownloaded / (fileDownloadElapsed.ElapsedMilliseconds / 1000));
}
labelText = "Status: Downloading " + currentFile +
"\n" + fileBytesDownloaded + " KB / " + fileSize + " KB - " + KBps + " KB/s";
}
void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
progbarValue = 0;
fileComplete = true;
}
/// <summary>
/// Returns file size (Kb) of a Uri
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
private long GetFileSize(Uri uri)
{
try
{
WebRequest webRequest = HttpWebRequest.Create(uri);
using (WebResponse response = webRequest.GetResponse())
{
long size = response.ContentLength;
return size / 1024;
}
}
catch { return 1; }
}
private void timerMultiPurpose_Tick(object sender, EventArgs e)
{
if (updateComplete == true)
{
updateComplete = false;
label1.Text = "Status: Complete";
progressBar1.Value = 0;
MessageBox.Show("Update complete!!");
Application.Run(new Form1());
Environment.Exit(0);
}
else
{
progressBar1.Value = progbarValue;
label1.Text = labelText;
}
}
private void UI_FormClosing(object sender, FormClosingEventArgs e)
{
Environment.Exit(0);
}
}
}
Relevant code from Program.cs:
System.Threading.Thread.Sleep(1000); // Give the calling application time to exit
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://raiderz.daregamer.com/updates/app_version.xml");
XmlNode xNodeVer = xdoc.DocumentElement.SelectSingleNode("Loc");
string ver_xml = Convert.ToString(xNodeVer);
args = new string[2];
args[0] = "Changelog=http://raiderz.daregamer.com/updates/changelog.txt";
args[1] = "URIs=" + ver_xml;
if (args.Length == 0)
{
MessageBox.Show("Can not run program without parameters", "Error");
return;
}
try
{
foreach (string arg in args)
{
if (arg.StartsWith("URIs="))
{
string[] uris = arg.Substring(arg.IndexOf('=') + 1).Split(';');
foreach (string uri in uris)
{
if (uri.Length > 0)
{
UpdateForm.uriFiles.Add(new Uri(uri));
}
}
}
else if (arg.StartsWith("Changelog="))
{
UpdateForm.uriChangelog = new Uri(arg.Substring(arg.IndexOf('=') + 1));
}
}
}
catch { MessageBox.Show("Missing or faulty parameter(s)", "Error"); }
I've not downloaded or reviewed your code, but if this is all C# based and on the v2.0 framework or higher you may want to check in to using ClickOnce. It will handle much of the auto updating for you and even allow users to continue using the program if they are offline and unable to connect to your update server.