Reputation: 1241
I have a Windows Service that monitors a folder for new files and runs a process. However, the service crashes every time I drop files into the monitored folder. Here is the Exception I am receiving:
Application: Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.IO.IOException Stack: at System.IO._Error.WinIOError(Int32, System.String) at System.IO._Error.WinIOError() at System.IO.File.Move(System.String, System.String) at Service.Service.Process(System.String, System.String) at Service.Service.OnChanged(System.Object, System.IO.FileSystemEventArgs) at System.IO.FileSystemWatcher.OnCreated(System.IO.FileSystemEventArgs)
at System.IO.FileSystemWatcher.NotifyFileSystemEventArgs(Int32, System.String) at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32, UInt32, System.Threading.NativeOverlapped*) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
Everything was working fine and then all of the sudden, it crashes every time I use it. I don't remember changing anything that would cause this. Here is my code:
public Service()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher(ConfigurationManager.AppSettings["UploadPath"]);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
public static void OnChanged(object source, FileSystemEventArgs e)
{
Process(e.Name, e.FullPath);
}
public static void Process(string fileName, string path)
{
string newPath = Path.Combine(ConfigurationManager.AppSettings["NewPath"], fileName);
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.FileName = @"C:\Program Files\Microsoft Security Client\Antimalware\mpcmdrun";
process.StartInfo.Arguments = " -scan -scantype 3 -file L:\\Test\\";
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
if (process.ExitCode == 0)
{
File.Move(path, cleanPath);
}
else
{
TextWriter tw = new StreamWriter(ConfigurationManager.AppSettings["FailedPath"] + fileName + ".txt");
tw.WriteLine(output);
tw.Close();
File.Delete(path);
}
}
protected override void OnStop()
{
}
Upvotes: 3
Views: 4105
Reputation: 7128
Two tricks that seem to be needed when working with MpCmdRun:
Include -DisableRemediation
to your list of parameters when you call MpCmdRun
. This causes the process to run very quickly and report the results back via StandardOutput
.
Ignore the returned exit code. Instead, look in the returned StandardOutput string for "found no threats"
to know if the file is clean. If that is not there, look for a line that starts with "Threat"
and read it to see what virus was found.
Upvotes: 0
Reputation: 151674
Could it be that another process, say another instance of the scanner you're manually starting, still holds a lock to the file at the moment you try to move it?
You should use Process Monitor to see which processes are accessing the file.
Anyway, you don't scan the new file, you always scan the whole folder L:\Test. Is that your intention?
Upvotes: 1
Reputation: 1241
I added Thread.Sleep(5000) before the creation of the process. This works well but it does at 5 seconds to the scanning of each file. And, as people have stated people, it feels kind of hackish.
Upvotes: 0
Reputation: 1456
Why dont you do following checks just after making sure the process existed with 0, like this,
if (process.ExitCode == 0)
{
process.Close();
process.Dispose();
if (File.Exists(path+filename) && !IsFileLocked(fileInfo) && Directory.Exists(cleanPath))
File.Move(path, cleanPath);
}
I doubt if the scan process is still quarantining the file while you are trying to move.
reference: know how to check a file is locked?
And ofcourse, you should handle the else conditions appropriately...
Upvotes: 0
Reputation: 31630
I suspect the process still has a lock on the file in some cases. Just wondering, why aren't you calling:
process.Close(); // Frees all the resources that are associated with this component
after WaitForExit().
Upvotes: 1