Programmatically move files after virus scan - antivirus

Is it possible to move files programmatically based on virus scan status?
What I want to do is have a set of folders:
Incoming
Scanned
Scanned/Clean
Scanned/Infected
Not Scanned
Files would be dropped into the Incoming folder. At that point, I would like to kick off the antivirus and scan the files in the Incoming folder. Once complete, the files would then need to be moved to the appropriate folder, either Clean or Infected. If, for whatever reason, the file could not be scanned or had trouble scanning, it would be moved to the Not Scanned folder.
I was hoping there would be a way to script this out. Has anyone ever done anything like this before?

public void Scan()
{
string[] uploadPath = Directory.GetFiles(ConfigurationManager.AppSettings["UploadPath"]);
foreach(string filePath in uploadPath)
{
string fileName = Path.GetFileName(filePath);
string cleanPath = Path.Combine(ConfigurationManager.AppSettings["CleanPath"], fileName);
try
{
Process AV = new Process();
AV.StartInfo.UseShellExecute = false;
AV.StartInfo.RedirectStandardOutput = true;
AV.StartInfo.FileName = ConfigurationManager.AppSettings["VSApp"];
AV.StartInfo.Arguments = " -Scan -ScanType 3 -file " + ConfigurationManager.AppSettings["UploadPath"] + " -DisableRemediation";
AV.Start();
string output = AV.StandardOutput.ReadToEnd();
AV.WaitForExit();
if (AV.ExitCode == 0)
{
File.Move(filePath, cleanPath);
}
else if (AV.ExitCode == 2)
{
using (TextWriter tw = new StreamWriter(ConfigurationManager.AppSettings["FailedPath"] + fileName + ".txt"))
{
tw.WriteLine("2");
tw.Close();
}
using (TextWriter tw1 = new StreamWriter(ConfigurationManager.AppSettings["FailedFiles"] + fileName + ".txt"))
{
tw1.WriteLine(AV.StandardOutput);
tw1.Close();
}
File.Delete(filePath);
}
AV.Close();
}
catch (Exception ex)
{
if (ex.ToString().Contains("Could not find file"))
{
string failedFile = ConfigurationManager.AppSettings["FailedPath"] + fileName + ".txt";
string failedFileDesc = ConfigurationManager.AppSettings["FailedPath"] + fileName + "_ErrorDesc" + ".txt";
using (TextWriter tw = new StreamWriter(failedFile))
{
tw.WriteLine("2");
tw.Close();
}
using (TextWriter tw1 = new StreamWriter(failedFileDesc))
{
tw1.WriteLine(ex.ToString());
tw1.Close();
}
}
else
{
Thread.Sleep(2000);
if (runCounter == 0)
{
Scan();
}
runCounter++;
string errorFile = ConfigurationManager.AppSettings["ProcessErrorPath"] + fileName + ".txt";
using (TextWriter tw = new StreamWriter(errorFile))
{
tw.WriteLine(ex.ToString());
tw.Close();
}
}
}
}
}
I created this as a Windows Service. My OnStart method creates my FileSystemWatcher to watch the Upload Path. For On Created, I have a method that runs my Scan method and creates my counter and sets it to 0. My On Error event just logs. I had an issue where the FileSystemWatcher was trying to open the file before it had been uploaded, hence why I added the sleep.
Finally, I am using Microsoft Forefront's command line scanner. File path: C:\Program Files\Microsoft Security Client\mpcmdrun.exe.
Let me know if any questions.

Related

How to set the path of the file writer to location of the jar using it?

So i recently switch from starting the jar file from a service rather than a script that first goes to the relevant directory. Is there a way to make sure that the path to the jar file is used instead of wherever the service started it? Inside the application i use the code below to get the correct path.
try {
Path p = Path.of(getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
workPath = p.getParent().toString();
if( workPath.matches(".*[lib]")) { // Meaning used as a lib
workPath = Path.of(workPath).getParent().toString();
}
settingsFile = Path.of(workPath, "settings.xml");
} catch (URISyntaxException e) {
Logger.error(e);
}
Store your work path as system property:
try {
Path p = Path.of(getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
workPath = p.getParent().toString();
if(workPath.matches(".*[lib]")) { // Meaning used as a lib
workPath = Path.of(workPath).getParent().toString();
}
System.setProperty("tinylog.directory", workPath); // Set work path as system property
settingsFile = Path.of(workPath, "settings.xml");
} catch (URISyntaxException e) {
Logger.error(e);
}
Use the system property in tinylog.properties:
writer = file
writer.file = #{tinylog.directory}/log.txt
writer.format = {date: HH:mm:ss.SSS} {level}: {message}

Take all text files in a folder and combine then into 1

I'm trying to merge all my text files into one file.
The problem I am having is that the file names are based on data previously captured in my app. I don't know how to define my path to where the text files are, maybe. I keep getting a error, but the path to the files are correct.
What am I missing?
string filesread = System.AppDomain.CurrentDomain.BaseDirectory + #"\data\Customers\" + CustComboB.SelectedItem + #"\";
Directory.GetFiles(filesread);
using (var output = File.Create("allfiles.txt"))
{
foreach (var file in new[] { filesread })
{
using (var input = File.OpenRead(file))
{
input.CopyTo(output);
}
}
}
System.Diagnostics.Process.Start("allfiles.txt");
my error:
System.IO.DirectoryNotFoundException
HResult=0x80070003
Message=Could not find a part of the path 'C:\Users\simeo\source\repos\UpMarker\UpMarker\bin\Debug\data\Customers\13Dec2018\'.
I cant post a pic, but let me try and give some more details on my form.
I select a combobox item, this item is a directory. then I have a listbox that displays the files in my directory. I then have a button that executes my desires of combining the files. thanks
I finally got it working.
string path = #"data\Customers\" + CustComboB.SelectedItem;
string topath = #"data\Customers\";
string files = "*.txt";
string[] txtFiles;
txtFiles = Directory.GetFiles(path, files);
using (StreamWriter writer = new StreamWriter(topath + #"\allfiles.txt"))
{
for (int i = 0; i < txtFiles.Length; i++)
{
using (StreamReader reader = File.OpenText(txtFiles[i]))
{
writer.Write(reader.ReadToEnd());
}
}
System.Diagnostics.Process.Start(topath + #"\allfiles.txt");
}

Download files from Sharepoint 365 using SSIS

I have a document library (Sharepoint 365) named "S & P" which contains many folders & sub-folders. My requirement is to download all the files exists in these folders/sub-folders to my local/server folder by using SSIS package. This can be done by either using a script task (C# or VB code) or execute process task(Powershell or Batch script) but I am not able to pull any file. So far I have tried to use powershell - failed & C# code - failed. All the code used was copied from internet (don't know much of C# & Powershell).
Any solution to retrieve these files from sharepoint to my local folder would be accepted (can't use 3rd party or unauthorized tools)
SharePoint URL structure is like below- https://xyzcompany.sharepoint.com/sites/dm/S%20%20P/Forms/AllItems.aspx
Note: All folders & subfolder are in S & P document library
Please help!
About downloading all the files from SharePoint Document library via C# code, here is a demo for your reference and i have tested successfully.
/// <summary>
/// download all files from Document Library
/// </summary>
/// <param name="context"></param>
/// <param name="docLibName">MyDocumentLibrary</param>
/// <param name="path">C:\\folder\\</param>
public static void DownloadAllFilesFromDocLib(ClientContext context, string docLibName, string path)
{
if (!path.EndsWith("\\"))
{
path = path + "\\";
}
Web web = context.Site.RootWeb;
List doclib = web.Lists.GetByTitle(docLibName);
context.Load(doclib);
context.Load(web);
context.ExecuteQuery();
FileCollection filesInRootFolder = doclib.RootFolder.Files;
FolderCollection subfolders = doclib.RootFolder.Folders;
context.Load(filesInRootFolder);
context.Load(subfolders);
context.ExecuteQuery();
//download files from root folders
foreach (Microsoft.SharePoint.Client.File file in filesInRootFolder)
{
FileInformation fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, file.ServerRelativeUrl);
System.IO.Stream fileOutputStream = fileInfo.Stream;
System.IO.Stream fileInputputStream = new FileStream(path + file.Name,FileMode.OpenOrCreate, FileAccess.ReadWrite);
byte[] bufferByte = new byte[1024 * 100];
int len = 0;
while ((len = fileOutputStream.Read(bufferByte, 0, bufferByte.Length)) > 0)
{
fileInputputStream.Write(bufferByte, 0, len);
fileInputputStream.Flush();
}
fileInputputStream.Close();
fileOutputStream.Close();
}
//download files from sub folders
foreach (Microsoft.SharePoint.Client.Folder folder in subfolders)
{
//Remove the default folder "Forms"
if (folder.Name == "Forms")
{
continue;
}
//create folder in local disk
Directory.CreateDirectory(path+folder.Name);
context.Load(folder.Files);
context.ExecuteQuery();
foreach (Microsoft.SharePoint.Client.File file in folder.Files)
{
FileInformation fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(context, file.ServerRelativeUrl);
System.IO.Stream fileOutputStream = fileInfo.Stream;
System.IO.Stream fileInputputStream = new FileStream(path+folder.Name + "\\" + file.Name, FileMode.OpenOrCreate, FileAccess.ReadWrite);
byte[] bufferByte = new byte[1024 * 100];
int len = 0;
while ((len = fileOutputStream.Read(bufferByte, 0, bufferByte.Length)) > 0)
{
fileInputputStream.Write(bufferByte, 0, len);
fileInputputStream.Flush();
}
fileInputputStream.Close();
fileOutputStream.Close();
}
}
}
Screenshots of my test result:

Saving jTextPane text not working properly

I'm trying to save a "history" I'm building after you sent a command from a line, so every time you press Enter the commands goes to the jTextPane with a line separator... However when I save the file it doesn't seem to get the line separator. Example, my jTextPane has something like:
Create database user
use database user
show tables from database
Instead of saving the workspace just like that, it gives me this:
Create database useruse database usershow tables from database
What should I do? Here's my code
String ar;
String TEXTO = jTextPane1.getText() + System.lineSeparator();
FileFilter ft = new FileNameExtensionFilter("Text Files", ".txt");
FC.setFileFilter(ft);
int returnVal = FC.showSaveDialog(this);
if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
java.io.File saved_file = FC.getSelectedFile();
String file_name = saved_file.toString();
File archivo;
ar = "" + file_name + ".txt";
archivo = new File(ar);
try {
if (saved_file != null) {
try (FileWriter GUARDADO = new FileWriter(ar)) {
GUARDADO.write(TEXTO);
}
}
} catch (IOException exp) {
System.out.println(exp);
}
}
You need to use :
jTextPane1.getDocument().getText(0,jTextPane1.getDocument().getLength());
The issue is that you need to use /n instead of System.lineSeparator. The JTextPane behavior doesn't depends on the System.

Mercurial - log the command executed

We've been using mercurial for a while now and everything is working fine.
The only problem we encounter is when someone runs a "bad command".
An example would be, merging an unstable branch in the stable trunk or pulling a similarly named branch over something completely unrelated overwriting a bunch of stuff...
You've got hg log but you always get people that won't believe the output saying "I didn't do that"...now in the interest of public shaming :) and giving rightful priviledges to the "You broke the built hat", I'm wondering, is there a way to have Mercurial log every command its given to a text file that would give us something like:
hg pull -b something
hg merge TotallyWrongBranch
hg ci -m "I didn't do it!" -u bsimpson
Ok, I had a few minutes on my hand so I wrote an exe and named it hg.exe and renamed Mercurial's original exe to real_hg...
An ugly hack don't mind the code quality please IT WORKS!
public static StreamWriter sw;
static void Main(string[] args)
{
sw = new StreamWriter("hgCommandLog.txt", true);
StringBuilder sbArguments = new StringBuilder();
if (args.Length > 0)
{
for (int i = 0; i < args.Length; i++)
{
sbArguments.Append(args[i]);
sbArguments.Append(" ");
}
}
//Console.WriteLine("arg:" + sbArguments.ToString());
//Console.WriteLine("Session ID = " + System.Diagnostics.Process.GetCurrentProcess().SessionId.ToString());
//Console.WriteLine("hello ->"+Environment.GetEnvironmentVariable("CLIENTNAME"));
string sessionID = System.Diagnostics.Process.GetCurrentProcess().SessionId.ToString();
string clientName = Environment.GetEnvironmentVariable("CLIENTNAME");
//log the command to sw
sw.WriteLine(DateTime.Now.ToString() + "\t" + clientName + "("+sessionID+")\t" + "hg " + sbArguments.ToString());
sw.Flush();
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "real_hg";
p.StartInfo.Arguments = sbArguments.ToString();
p.StartInfo.CreateNoWindow = true;
p.ErrorDataReceived += outputReceived;
p.OutputDataReceived += outputReceived;
p.EnableRaisingEvents = true;
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
p.BeginOutputReadLine();
//p.BeginErrorReadLine();
p.WaitForExit();
sw.Close();
}
static void outputReceived(object sender, DataReceivedEventArgs e)
{
sw.WriteLine("\t"+e.Data);
Console.WriteLine(e.Data);
}