Reputation: 11
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()
Upvotes: 0
Views: 234
Reputation: 11
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("============================================================================================================");
}
}
}
}
Upvotes: 0
Reputation: 41
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?
Upvotes: 0