I'm building a form and I'm trying to use threading in order to get some results from a WMI query to display in a textbox without having the form freeze up on the user. However, when I use the code below and use Break-All when debugging, the code just sits on getPrinterThread.Join(). I know I must be missing something.
My aim is to get a thread to run the ObtainPrinterPort method to completion, then get a thread to run the InstallPrinterPort method to completion. I have the code below as inline code in another method. The code isn't in a separate class or anything and I don't have a background worker because all of the examples I've seen, up until now, have only confused me.
Here's my admittedly poor thread attempt:
Thread printThread = new Thread(ObtainPrinterPort);
printThread.Start();
while (!printThread.IsAlive) ;
Thread.Sleep(1);
printThread.Join(); // Form sits and does nothing; Break-all reveals this line as statement being executed.
Thread installThread = new Thread(InstallPrinterPort);
installThread.Start();
while (!installThread.IsAlive);
Thread.Sleep(1);
installThread.Join();
Is there a simple way I can get something to work that is safe and will allow me to display the results that occur in the methods as they happen to the user in the textbox? Hopefully there's a way to do this that will allow me to continue to use the instance variables/methods/code I've written in the form class...otherwise, I'll have to re-write a lot of code if I'm going to implement a "DoWork"-type example (where my methods are called from the DoWork method/constructor or the Worker class).
Please keep in mind that my methods need to return text from the thread to a textbox to display results to the user. I have code that I'm assuming will allow me to return the text from the thread if it works, but I just wanted to make sure that any suggestions/help kept this in mind. The code I'm using is below:
public void AppendTextBox(string value)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(AppendTextBox), new object[] { value });
return;
}
txtResults.Text += value;
}
For what it's worth, here's my ObtainPrinterPort method and the CreateNewConnection method that accompanies it...the InstallPrinterPort method is extremely similar, so posting it won't really reveal much:
private ManagementScope CreateNewConnection(string server, string userID, string password)
{
string serverString = #"\\" + server + #"\root\cimv2";
ManagementScope scope = new ManagementScope(serverString);
try
{
ConnectionOptions options = new ConnectionOptions
{
Username = userID,
Password = password,
Impersonation = ImpersonationLevel.Impersonate,
EnablePrivileges = true
};
scope.Options = options;
scope.Connect();
}
catch (ManagementException err)
{
MessageBox.Show("An error occurred while querying for WMI data: " +
err.Message);
}
catch (System.UnauthorizedAccessException unauthorizedErr)
{
MessageBox.Show("Connection error (user name or password might be incorrect): " + unauthorizedErr.Message);
}
return scope;
}
private void ObtainPrinterPort()
{
string computerName = "";
string userID = "";
string password = "";
string printerQuery = "SELECT * FROM Win32_Printer WHERE Name = ";
string portQuery = "SELECT * FROM Win32_TCPIPPrinterPort WHERE Name = ";
string search = "";
SelectQuery query;
foreach (var s in lstServer)
{
computerName = s.ServerName;
userID = s.UserID;
password = s.Password;
}
ManagementScope scope = CreateNewConnection(computerName, userID, password);
foreach (Printers p in lstPrinters)
{
AppendTextBox("Obtaining printer/port info for " + p.PrinterName + "\r\n");
search = printerQuery + "'" + p.PrinterName + "'";
query = new SelectQuery(search);
try
{
using (var searcher = new ManagementObjectSearcher(scope, query))
{
ManagementObjectCollection printers = searcher.Get();
if (printers.Count > 0)
{
AppendTextBox("\tStoring printer properties for " + p.PrinterName + "\r\n");
foreach (ManagementObject mo in printers)
{
StorePrinterProperties(p, mo);
}
}
else
{
lstPrinterExceptions.Add("Printer: " + p.PrinterName);
AppendTextBox("\t**Printer " + p.PrinterName + " not found**\r\n");
}
}
}
catch (Exception exception)
{
MessageBox.Show("Error: " + exception.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
if (!lstPrinterExceptions.Contains("Printer: " + p.PrinterName)
&& !lstPrinterExceptions.Contains("Port: " + p.PortName))
{
search = portQuery + "'" + p.PortName + "'";
query = new SelectQuery(search);
try
{
using (var searcher = new ManagementObjectSearcher(scope, query))
{
ManagementObjectCollection ports = searcher.Get();
if (ports.Count > 0)
{
AppendTextBox("\tStoring port properties for " + p.PortName + " (" + p.PrinterName + ")\r\n");
foreach (ManagementObject mo in ports)
{
StorePortProperties(p, mo);
}
}
else
{
lstPrinterExceptions.Add("Port: " + p.PortName);
AppendTextBox("\t**Port " + p.PortName + " for " + p.PrinterName + " not found**\r\n");
}
}
}
catch (Exception exception)
{
MessageBox.Show("Error: " + exception.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
AppendTextBox("\tSuccessfully obtained printer/port info for " + p.PrinterName + "\r\n");
}
}
}
Thanks.
Your problem is that the Invoke calls are blocking waiting for the main thread to DoEvents so they can be processed, but the main thread is blocking in Thread.Join. You have a deadlock.
This is how you run a thread without blocking the UI thread. Thread.Join blocks until the other thread finishes, so here I am blocking only for max 100ms, then calling DoEvents so the form can respond to messages (including processing your Invoke calls from the other thread), then looping until the background thread is complete.
Thread printThread = new Thread(ObtainPrinterPort);
printThread.Start();
while (printThread.IsAlive) {
Application.DoEvents();
printThread.Join(100);
}
Calling DoEvents in a loop like this is a bit hacky, but it will work.
You can also look into BackgroundWorker, which makes the whole thing a lot safer and easier.
A simple example:
var bw = new BackgroundWorker();
bw.DoWork += (worker, args) => {
ObtainPrinterPort();
};
bw.RunWorkerAsync();
Related
I'm using Mangement class to create a process, but That starts a UI console - I want to console to run in background.
public uint LaunchProcess(string sIPAddress, string sPort)
{
uint iPid = 0;
try
{
logger.AddLog("LaunchProcess : " + sIPAddress + " " + sPort);
object[] PlugInRunnerInfo = { StaticUtils.GetLocation(AgilentPluginCommonConstants.PlugInRunnerPath) + "\\" + "PlugInRunner.exe" + " " + sIPAddress + " " + sPort, null, null, 0 };
//ManagementClass is a part of Windows Management Intrumentation,namespaces. One of its use is to provides access to manage applications.
//Here this class is used to launch PlugInRunner as detached process.By setting the ManagementClass object's property 'CreateFlags' to value 0x00000008
//we can start the PlugInRunner as detached one.
using (var mgmtObject = new ManagementClass("Win32_Process"))
{
var processStartupInfo = new ManagementClass("Win32_ProcessStartup",null);
processStartupInfo.Properties["CreateFlags"].Value = 0x00000008;//DETACHED_PROCESS.
var result = mgmtObject.InvokeMethod("Create", PlugInRunnerInfo);
if (result != null)
{
logger.AddLog("Process id " + Convert.ToUInt32(PlugInRunnerInfo[3]));
iPid = Convert.ToUInt32(PlugInRunnerInfo[3]);
}
}
}
catch (Exception ex)
{
logger.AddLog("Exception " + ex.Message);
}
return iPid;
}
The above code what I have got. Please help me.
this is my first question in here.
So I have this app that connects to a remote database using Npgsql library.
I have a method that connects to the db, execute a query, and finally it closes the connection.
It work fine, but the problem is that if, while the program is running but not calling the method, I disconnect the WiFi to simulate the inability to connect to the server, and then run the method, the connection method still is able to open the connection. This causes the query to get stuck.
I can't seem to find a way to check if I can connect to server because, even if I disconnect the internet, the NpgsqlConnection.Open() method still opens it.
Sorry about my english
public static NpgsqlConnection ConnectRemote()
{
try
{
remoteConnection = new NpgsqlConnection("Server = " + remoteData.server + "; " +
"Port = " + remoteData.port + "; " +
"User Id = " + remoteData.user + "; " +
"Password = " + remoteData.password + "; " +
"Database = " + remoteData.dataBase + "; ");
remoteConnection.Open();
}
catch (NpgsqlException ex)
{
throw;
}
catch (Exception ex)
{
remoteConnection.Close();
remoteConnection = null;
}
return remoteConnection;
}
public static bool CheckRemote()
{
if (remoteConnection != null)
{
if (remoteConnection.FullState.Equals(ConnectionState.Open))
return true;
return false;
}
return false;
}
public bool AddNewProduct(Product product)
{
try
{
DBManager.ConnectLocal();
DBManager.ConnectRemote();
object[] parameters;
if (DBManager.CheckRemote())
{
if (!DBManager.isSyncronized)
{
DBManager.Syncronize();
}
parameters = new object[8];
parameters[0] = 1;
parameters[1] = product.id;
parameters[2] = product.description;
parameters[3] = (decimal)product.salePrice;
parameters[4] = (decimal)product.cost;
parameters[5] = product.minStock;
parameters[6] = product.providerName;
parameters[7] = product.category;
DBManager.RunFunction(DBManager.remoteConnection, DBProcedures.createProduct, parameters);
}
else
{
string sql = "select * from createproduct(1, " + product.id + ", '" + product.description + "', " + (decimal)product.salePrice + ", "
+ (decimal)product.cost + ", " + product.minStock + ", '" + product.providerName + "', '" + product.category + "'); ";
parameters = new object[1];
parameters[0] = sql;
DBManager.RunFunction(DBManager.localConnection, "addsync", parameters);
DBManager.isSyncronized = false;
}
parameters = new object[6];
parameters[0] = product.description;
parameters[1] = (decimal)product.salePrice;
parameters[2] = (decimal)product.cost;
parameters[3] = product.minStock;
parameters[4] = product.providerName;
parameters[5] = product.category;
DataTable result = DBManager.RunFunction(DBManager.localConnection, DBProcedures.createProduct, parameters);
DBManager.DisconnectLocal();
DBManager.DisconnectRemote();
return true;
}
catch (Npgsql.NpgsqlException ex)
{
return false;
}
}
A few things -- one unrelated, and two related. I am hopeful that some combination of these will help.
First, the unrelated comment. The NpgSqlStringBuilder class is a nice tool to help demystify the connection strings. I realize yours works, but as you have to make edits (as I will suggest in a minute), I find it much easier to use than navigating String.Format, just as Query Parameters are easier (on top of being more secure) than trying to string.Format your way through passing arguments to a query. Also, declare the ApplicationName in your connection string to help diagnose what exactly is happening on the server, like you will read in the next comment.
If you are using connection pooling, When a connection is closed, I don't think it's really closed -- not even on the database. If you open server admin, you will see what I mean -- it kind of dangles out there, waiting to be reused. Try setting pooled=false in your connection string to ensure that when you close a connection you really close it.
If this doesn't work, try a trivial query. The cost will be minimal in cases where you don't need it and will undoubtedly fix your use case when you do need it.
All three suggestions are reflected here:
public static NpgsqlConnection ConnectRemote()
{
NpgsqlConnectionStringBuilder sb = new NpgsqlConnectionStringBuilder();
sb.ApplicationName = "Connection Tester";
sb.Host = remoteData.server;
sb.Port = remoteData.port;
sb.Username = remoteData.user;
sb.Password = remoteData.password;
sb.Database = remoteData.database;
sb.Pooling = false;
remoteConnection = new NpgsqlConnection(sb.ToString());
try
{
remoteConnection.Open();
NpgSqlCommand test = new NpgSqlCommand("select 1", remoteConnection);
test.ExecuteScalar();
}
catch (NpgsqlException ex)
{
throw;
}
catch (Exception ex)
{
remoteConnection.Close();
remoteConnection = null;
}
return remoteConnection;
}
I've looked at Parallel.ForEach - System Out of Memory Exception regarding this issue but not much of a solution was given. I'm very new to using Parallel.ForEach, so I'm trying to figure out what's going on.
Diagnostic tools caps out at 1023 repeating (I understand this is an x86 to x64 arch restriction, but I wanted to offer the program in both formats.) I also don't feel like any program should ever meet that threshold. When I compile the program in x64, I sit around 1.1-1.4GB with MaxDegree . For sake of testing, I am running GC.Collection() at the end of each Parallel.ForEach iteration (I understand this isn't good practice, I'm just trying to troubleshoot at this point.)
Here's what I'm seeing:
Now if I try to use a Partitioner method, such as:
var checkforfinished = Parallel.ForEach<ListViewItem>(Partitioner.Create(0,lstBackupUsers.Items.Count), lstBackupUsers.Items.Cast<ListViewItem>(), opts, name =>
The I get an error of:
"No overload for method 'ForEach' takes 4 arguments"
That's fine, I modify my Parallel.ForEach statement so it looks like this:
var checkforfinished = Parallel.ForEach(Partitioner.Create(0,lstBackupUsers.Items.Count), lstBackupUsers.Items, opts, name => (I removed my casts)
and then my ForEach method won't accept the statement because it wants me to explicitly tell it that it's addressing a listviewbox.items method.
I am so confused on what to do.
Do I create a Partitioner, and if I do, how do I make my Parallel.ForEach method understand how to address a listviewbox?
update 1
I want to try to give as many details as possible because this is just rough. I'm sure it's easy, I'm just overcomplicationg it by an nth degree.
I have my Parallel.ForEach(//) running in a background worker function. My DoWork process is over 300 lines (I'm not an expert in C#, I'm just putting things together for a program at work.)
Here are bullet points of its basic structure
User clicks a "Start backup" button as seen in the screenshot
Button begins a separate function that checks to see which method the user selected to grab a list of usernames from (LDAP or flat text file)
That function then sends off a bgw_dowork() request
Inside the DoWork request, it looks like a summary of:
Check preliminary statements (bgw.cancellationpending for example)
Move on to grabbing some settings from the configurationmanager.appsettings
Begin the "complex" Parallel.ForEach command which Reads the listbox record rows and foreach row performs a very long list of commands to complete an operation for one user
The entire program, especially bgw_dowork heavily uses Google's v3 Drive API to login as a user, grab a file as recorded by other functions that prepare the user directory to be backed up (separate functions which login as a user, record their files (and fileIds) and their directories/subdirectories) and the bgw_dowork performs a chunk of the actual download functionality, which then calls off to the other functions to finish moving the files after they have been downloaded.
The actual "code" I use is (and I promise it's not pretty...)
private void bgW_DoWork(object sender, DoWorkEventArgs e)
{
{
try
{
txtFile.ReadOnly = true;
btnStart.Text = "Cancel Backup";
var appSettings = ConfigurationManager.AppSettings;
string checkreplace = ConfigurationManager.AppSettings["checkreplace"];
string userfile = txtFile.Text;
int counter = 0;
int arraycount = 0;
if (bgW.CancellationPending)
{
e.Cancel = true;
stripLabel.Text = "Operation was canceled!";
}
else
{
for (int z = 0; z >= counter; z++)
{
if (bgW.CancellationPending)
{
e.Cancel = true;
stripLabel.Text = "Operation was canceled!";
break;
}
else
{
double totalresource = int.Parse(ConfigurationManager.AppSettings["multithread"]);
totalresource = (totalresource / 100);
//var opts = new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * totalresource) * 1.0)) };
var opts = new ParallelOptions { MaxDegreeOfParallelism = 2 };
var part = Partitioner.Create(1, 100);
//foreach (ListViewItem name in lstBackupUsers.Items)
var checkforfinished = Parallel.ForEach(lstBackupUsers.Items.Cast<ListViewItem>(), name =>
{
try
{
string names = name.SubItems[0].Text;
lstBackupUsers.Items[arraycount].Selected = true;
lstBackupUsers.Items[arraycount].BackColor = Color.CornflowerBlue;
arraycount++;
stripLabel.Text = "";
Console.WriteLine("Selecting user: " + names.ToString());
txtLog.Text += "Selecting user: " + names.ToString() + Environment.NewLine;
txtCurrentUser.Text = names.ToString();
// Define parameters of request.
string user = names.ToString();
// Check if directory exists, create if not.
string savelocation = ConfigurationManager.AppSettings["savelocation"] + user + "\\";
if (File.Exists(savelocation + ".deltalog.tok"))
File.Delete(savelocation + ".deltalog.tok");
FileInfo testdir = new FileInfo(savelocation);
testdir.Directory.Create();
string savedStartPageToken = "";
var start = CreateService.BuildService(user).Changes.GetStartPageToken().Execute();
// This token is set by Google, it defines changes made and
// increments the token value automatically.
// The following reads the current token file (if it exists)
if (File.Exists(savelocation + ".currenttoken.tok"))
{
StreamReader curtokenfile = new StreamReader(savelocation + ".currenttoken.tok");
savedStartPageToken = curtokenfile.ReadLine().ToString();
curtokenfile.Dispose();
}
else
{
// Token record didn't exist. Create a generic file, start at "1st" token
// In reality, I have no idea what token to start at, but 1 seems to be safe.
Console.Write("Creating new token file.\n");
//txtLog.Text += ("Creating new token file.\n" + Environment.NewLine);
StreamWriter sw = new StreamWriter(savelocation + ".currenttoken.tok");
sw.Write(1);
sw.Dispose();
savedStartPageToken = "1";
}
string pageToken = savedStartPageToken;
int gtoken = int.Parse(start.StartPageTokenValue);
int mytoken = int.Parse(savedStartPageToken);
txtPrevToken.Text = pageToken.ToString();
txtCurrentToken.Text = gtoken.ToString();
if (gtoken <= 10)
{
Console.WriteLine("Nothing to save!\n");
//txtLog.Text += ("User has nothing to save!" + Environment.NewLine);
}
else
{
if (pageToken == start.StartPageTokenValue)
{
Console.WriteLine("No file changes found for " + user + "\n");
//txtLog.Text += ("No file changes found! Please wait while I tidy up." + Environment.NewLine);
}
else
{
// .deltalog.tok is where we will place our records for changed files
Console.WriteLine("Changes detected. Making notes while we go through these.");
lblProgresslbl.Text = "Scanning Drive directory.";
// Damnit Google, why did you change how the change fields work?
if (savedStartPageToken == "1")
{
statusStripLabel1.Text = "Recording folder list ...";
txtLog.Text = "Recording folder list ..." + Environment.NewLine;
exfunctions.RecordFolderList(savedStartPageToken, pageToken, user, savelocation);
statusStripLabel1.Text = "Recording new/changed files ... This may take a bit!";
txtLog.Text += Environment.NewLine + "Recording new/changed list for: " + user;
exfunctions.ChangesFileList(savedStartPageToken, pageToken, user, savelocation);
}
else
{
//proUserclass = proUser;
statusStripLabel1.Text = "Recording new/changed files ... This may take a bit!";
txtLog.Text += Environment.NewLine + "Recording new/changed list for: " + user + Environment.NewLine;
exfunctions.ChangesFileList(savedStartPageToken, pageToken, user, savelocation);
}
// Get all our files for the user. Max page size is 1k
// after that, we have to use Google's next page token
// to let us get more files.
StreamWriter logFile = new StreamWriter(savelocation + ".recent.log");
string[] deltafiles = File.ReadAllLines(savelocation + ".deltalog.tok");
int totalfiles = deltafiles.Count();
int cnttototal = 0;
Console.WriteLine("\nFiles to backup:\n");
if (deltafiles == null)
{
return;
}
else
{
double damn = ((gtoken - double.Parse(txtPrevToken.Text)));
damn = Math.Round((damn / totalfiles));
if (damn <= 0)
damn = 1;
foreach (var file in deltafiles)
{
try
{
if (bgW.CancellationPending)
{
stripLabel.Text = "Backup canceled!";
e.Cancel = true;
break;
}
DateTime dt = DateTime.Now;
string[] foldervalues = File.ReadAllLines(savelocation + "folderlog.txt");
cnttototal++;
bgW.ReportProgress(cnttototal);
proUser.Maximum = int.Parse(txtCurrentToken.Text);
stripLabel.Text = "File " + cnttototal + " of " + totalfiles;
double? mathisfun;
mathisfun = ((100 * cnttototal) / totalfiles);
if (mathisfun <= 0)
mathisfun = 1;
double mathToken = double.Parse(txtPrevToken.Text);
mathToken = Math.Round((damn + mathToken));
// Bring our token up to date for next run
txtPrevToken.Text = mathToken.ToString();
File.WriteAllText(savelocation + ".currenttoken.tok", mathToken.ToString());
int proval = int.Parse(txtPrevToken.Text);
int nowval = int.Parse(txtCurrentToken.Text);
if (proval >= nowval)
proval = nowval;
proUser.Value = (proval);
lblProgresslbl.Text = ("Current progress: " + mathisfun.ToString() + "% completed.");
// Our file is a CSV. Column 1 = file ID, Column 2 = File name
var values = file.Split(',');
string fileId = values[0];
string fileName = values[1];
string mimetype = values[2];
mimetype = mimetype.Replace(",", "_");
string folder = values[3];
string ext = null;
int folderfilelen = foldervalues.Count();
fileName = GetSafeFilename(fileName);
Console.WriteLine("Filename: " + values[1]);
logFile.WriteLine("ID: " + values[0] + " - Filename: " + values[1]);
logFile.Flush();
// Things get sloppy here. The reason we're checking MimeTypes
// is because we have to export the files from Google's format
// to a format that is readable by a desktop computer program
// So for example, the google-apps.spreadsheet will become an MS Excel file.
switch (mimetype)
{
(switch statement here removed due to body length issues for this post.)
}
if (ext.Contains(".doc") || ext.Contains(".xls"))
{
string whatami = null;
if (ext.Contains(".xls"))
{
whatami = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
else if (ext.Contains(".doc"))
{
whatami = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
else if (ext.Contains(".ppt"))
{
whatami = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
}
if (fileName.Contains(".mov") || ext == ".ggl" || fileName.Contains(".mp4"))
{
txtLog.Text += Environment.NewLine + "Skipping file.";
return;
}
var requestfileid = CreateService.BuildService(user).Files.Export(fileId, whatami);
statusStripLabel1.Text = (savelocation + fileName + ext);
txtCurrentUser.Text = user;
string dest1 = Path.Combine(savelocation, fileName + ext);
var stream1 = new System.IO.FileStream(dest1, FileMode.OpenOrCreate, FileAccess.ReadWrite);
scrolltobtm();
requestfileid.MediaDownloader.ProgressChanged +=
(IDownloadProgress progress) =>
{
switch (progress.Status)
{
case DownloadStatus.Downloading:
{
Console.WriteLine(progress.BytesDownloaded);
logFile.WriteLine("Downloading: " + progress.BytesDownloaded);
txtLog.Text += ("Downloading ... " + progress.BytesDownloaded + Environment.NewLine);
scrolltobtm();
logFile.Flush();
break;
}
case DownloadStatus.Completed:
{
Console.WriteLine("Download complete.");
logFile.WriteLine("[" + user + "] Download complete for: " + requestfileid.ToString());
txtLog.Text += ("[" + user + "] Download complete for: " + fileName + Environment.NewLine);
logFile.Flush();
break;
}
case DownloadStatus.Failed:
{
Console.WriteLine("Download failed.");
logFile.WriteLine("Download failed.");
logFile.Flush();
break;
}
}
};
scrolltobtm();
GC.Collect();
GC.WaitForPendingFinalizers();
requestfileid.Download(stream1);
stream1.Close();
stream1.Dispose();
}
else
{
scrolltobtm();
var requestfileid = CreateService.BuildService(user).Files.Get(fileId);
//Generate the name of the file, and create it as such on the local filesystem.
statusStripLabel1.Text = (savelocation + fileName + ext);
string dest1 = Path.Combine(savelocation, fileName + ext);
var stream1 = new System.IO.FileStream(dest1, FileMode.OpenOrCreate, FileAccess.ReadWrite);
requestfileid.MediaDownloader.ProgressChanged +=
(IDownloadProgress progress) =>
{
switch (progress.Status)
{
case DownloadStatus.Downloading:
{
Console.WriteLine(progress.BytesDownloaded);
logFile.WriteLine("Downloading: " + progress.BytesDownloaded);
txtLog.Text += ("Downloading ... " + progress.BytesDownloaded + Environment.NewLine);
scrolltobtm();
logFile.Flush();
break;
}
case DownloadStatus.Completed:
{
Console.WriteLine("Download complete.");
logFile.WriteLine("Download complete for: " + requestfileid.ToString());
txtLog.Text += (Environment.NewLine + "[" + user + "] Download complete for: " + fileName + Environment.NewLine);
logFile.Flush();
break;
}
case DownloadStatus.Failed:
{
Console.WriteLine("Download failed.");
logFile.WriteLine("Download failed.");
logFile.Flush();
break;
}
}
};
scrolltobtm();
GC.Collect();
GC.WaitForPendingFinalizers();
requestfileid.Download(stream1);
stream1.Close();
stream1.Dispose();
}
}
catch (Google.GoogleApiException ex)
{
Console.Write("\nInfo: ---> " + ex.Message.ToString() + "\n");
}
}
}
exfunctions.MoveFiles(savelocation);
Console.WriteLine("\n\n\tBackup completed for selected user!");
txtLog.Text += ("\n\nBackup completed for selected user.\n\n");
statusStripLabel1.Text = "";
//logFile.Close();
//logFile.Dispose();
}
}
}
catch (Google.GoogleApiException ex)
{
Console.WriteLine("Info: " + ex.Message.ToString());
}
}
);
if (checkforfinished.IsCompleted == true)
{
MessageBox.Show("Parallel.ForEach() Finished!");
Console.WriteLine("Parallel.ForEach() Finished!");
}
else
{
MessageBox.Show("Parallel.ForEach() not completed!");
Console.WriteLine("Parallel.ForEach() not completed!");
}
}
}
}
}
catch (Google.GoogleApiException ex)
{
Console.WriteLine("Info: " + ex.Message.ToString());
}
}
}
You can see where I initiate the Parallel.ForEach(...) and then see what it is in charge of doing. It's a lot, and I understand it's not pretty, so I appreciate constructive criticism.
I have made a tool that will copy files from a source to a destination. However during the copy, the software came across a virus that was flagged by the anti-virus software (Symantec).
The anti-virus then caused my software to close down, and quarantine the program as a "dropper".
Is there anyway I can gracefully handle this scenario, rather than shutting down my program completely?
I appreciate that the action was the result of the anti-virus, but is there anything I can do to help the situation? For example, Robocopy does not just terminate when it comes across a virus.
Here is my copy code;
void CopyFileExactly(CopyParameterBundle cpb, bool overwrite)
{
string CTP = "", CFP = "";
CFP = cpb.SourcePath;
if (cpb.RenameFile)
CTP = cpb.DestPath ;
else
CTP = cpb.DestPath;
//Check firstly if the file to copy exists
if (!File.Exists(CFP))
{
throw new FileNotFoundException();
}
//Check if destination file exists
//If it does, make it not read only so we can update MAC times
if (File.Exists(CTP))
{
var target = GetFile(CTP);//new FileInfo(CTP);
if (target.IsReadOnly)
target.IsReadOnly = false;
}
var origin = GetFile(CFP);//new FileInfo(CFP);
GetFile(CTP).Directory.Create();
//(new FileInfo(CTP)).Directory.Create();
origin.CopyTo(CTP, (overwrite ? true : false));
if (!File.Exists(CTP))
{
throw new FileNotFoundException("Destination file not found!");
}
var destination = GetFile(CTP);//new FileInfo(CTP);
if (destination.IsReadOnly)
{
destination.IsReadOnly = false;
destination.CreationTime = origin.CreationTime;
destination.LastWriteTime = origin.LastWriteTime;
destination.LastAccessTime = origin.LastAccessTime;
destination.IsReadOnly = true;
}
else
{
destination.CreationTime = origin.CreationTime;
destination.LastWriteTime = origin.LastWriteTime;
destination.LastAccessTime = origin.LastAccessTime;
}
if (performMD5Check)
{
var md5Check = compareFileMD5(CFP, CTP);
cpb.srcMD5Hash = md5Check.Item2;
cpb.dstMD5Hash = md5Check.Item3;
if (!md5Check.Item1)
throw new MD5MismatchException("MD5 Hashes do NOT match!");
}
}
The calling code;
void BeginCopy(int DegreeOfParallelism, int retryCount, int retryDelay)
{
object _lock;
//Setup cancellation token
po.CancellationToken = cts.Token;
//Set max number of threads
po.MaxDegreeOfParallelism = DegreeOfParallelism;
//Exceptio logging queue
var exceptions = new ConcurrentQueue<Exception>();
var completeItems = new ConcurrentQueue<CopyParameterBundle>();
var erroredItems = new ConcurrentQueue<CopyParameterBundle>();
//Logger logger = new Logger(sLogPath);
//logger.Write("Starting copy");
Task.Factory.StartNew(() =>
{
Parallel.ForEach(CopyParameters,
po,
(i, loopState, localSum) =>
{
localSum = retryCount;
do
{
try
{
//Go off and attempt to copy the file
DoWork(i);
//Incrememt total count by 1 if successfull
i.copyResults.TransferTime = DateTime.Now;
i.copyResults.TransferComplete = true;
completeItems.Enqueue(i);
//logger.Write("Copied file from: " + i.SourcePath + "\\" + i.SourceFile + " => " + i.DestPath + "\\" + i.SourceFile);
break;
}
catch (Exception ex)
{
//this.richTextBox1.AppendText("[-] Exception on: " + i.SourcePath + "\\" + i.SourceFile + " => " + ex.Message.ToString() + System.Environment.NewLine);
//Exception was thrown when attempting to copy file
if (localSum == 0)
{
//Given up attempting to copy. Log exception in exception queue
exceptions.Enqueue(ex);
this.SetErrorText(exceptions.Count());
//Write the error to the screen
this.Invoke((MethodInvoker)delegate
{
this.richTextBox1.AppendText("[-] Exception on: " + i.SourcePath + "\\" + i.SourceFile + " => " + ex.Message.ToString() + System.Environment.NewLine);
i.copyResults.TransferComplete = false;
i.copyResults.TransferTime = DateTime.Now;
i.copyResults.exceptionMsg = ex;
erroredItems.Enqueue(i);
//logger.Write("ERROR COPYING FILE FROM : " + i.SourcePath + "\\" + i.SourceFile + " => " + i.DestPath + "\\" + i.SourceFile + " => " + ex.Message.ToString() + " => " + ex.Source);
});
}
//Sleep for specified time before trying again
Thread.Sleep(retryDelay);
localSum--;
}
//Attempt to Repeat X times
} while (localSum >= 0);
//Check cancellation token
po.CancellationToken.ThrowIfCancellationRequested();
Interlocked.Increment(ref TotalProcessed);
this.SetProcessedText(TotalProcessed);
//Update Progress Bar
this.Invoke((MethodInvoker)delegate
{
this.progressBar1.Value = (TotalProcessed);
});
});
//aTimer.Stop();
this.Invoke((MethodInvoker)delegate
{
this.label9.Text = "Process: Writing Log";
});
WriteLog(sLogPath, completeItems, erroredItems);
this.Invoke((MethodInvoker)delegate
{
this.label9.Text = "Process: Done!";
});
if (exceptions.Count == 0)
MessageBox.Show("Done!");
else
MessageBox.Show("Done with errors!");
EnableDisableButton(this.button2, true);
EnableDisableButton(this.button4, false);
});
}
What happened is most likely that the antivirus was aware of the virus file, so when it detected that a change in the file system (moving the file) occurred, it terminated the program because by moving the virus to a different location in your computer, it could cause problems (since it's a virus). It was flagged as dropper, basically a type of program that is designed to install the virus.
Edit: i forgot to mention that to solve the problem you will most likely need to license your program.
How to display list process, when i run sql*loader in c#. I mean when i run sql*loader from cmd windows, i get list process how many row has been inserted. But when i run SQL*Loader from C#, i can't get process SQL*Loader.
This is my code:
string strCmd, strSQLLoader;
string strLoaderFile = "XLLOAD.CTL";
string strLogFile = "XLLOAD_LOG.LOG";
string strCSVPath = #"E:\APT\WorkingFolder\WorkingFolder\sqlloader\sqlloader\bin\Debug\8testskrip_HTTP.csv";
string options = "OPTIONS (SKIP=1, DIRECT=TRUE, ROWS=1000000,BINDSIZE=512000)";
string append = "APPEND INTO TABLE XL_XDR FIELDS TERMINATED BY ','";
string table = "OPTIONALLY ENCLOSED BY '\"' TRAILING NULLCOLS (xdr_id,xdr_type,session_start_time,session_end_time,session_last_update_time,session_flag,version,connection_row_count,error_code,method,host_len,host,url_len,url,connection_start_time,connection_last_update_time,connection_flag,connection_id,total_event_count,tunnel_pair_id,responsiveness_type,client_port,payload_type,virtual_type,vid_client,vid_server,client_addr,server_addr,client_tunnel_addr,server_tunnel_addr,error_code_2,ipid,c2s_pkts,c2s_octets,s2c_pkts,s2c_octets,num_succ_trans,connect_time,total_resp,timeouts,retries,rai,tcp_syns,tcp_syn_acks,tcp_syn_resets,tcp_syn_fins,event_type,flags,time_stamp,event_id,event_code)";
strCmd = "sqlldr xl/secreat#o11g control=" + strLoaderFile + " LOG=" + strLogFile;
System.IO.DirectoryInfo di;
try
{
System.Diagnostics.ProcessStartInfo cmdProcessInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe");
di = new DirectoryInfo(strCSVPath);
strSQLLoader = "";
strSQLLoader += "LOAD DATA INFILE '" + strCSVPath.ToString().Trim() + "' " + append + " " + table;
StreamWriter writer = new StreamWriter(strLoaderFile);
writer.WriteLine(strSQLLoader);
writer.Flush();
writer.Close();
// Redirect both streams so we can write/read them.
cmdProcessInfo.RedirectStandardInput = true;
cmdProcessInfo.RedirectStandardOutput = true;
cmdProcessInfo.UseShellExecute = false;
cmdProcessInfo.LoadUserProfile = true;
//System.Diagnostics.Process.Start("CMD.exe", strCmdLine);
// Start the procses.
System.Diagnostics.Process pro = System.Diagnostics.Process.Start(cmdProcessInfo);
// Issue the dir command.
pro.StandardInput.WriteLine(strCmd);
// Exit the application.
pro.StandardInput.WriteLine("exit");
//Process[] processlist = Process.GetProcesses();
//foreach(Process pro in processlist){
Console.WriteLine("Process: {0} ID: {1}", pro.ProcessName, pro.Id);
Console.WriteLine(pro.StandardOutput.ReadLine());
//}
// Read all the output generated from it.
string strOutput;
strOutput = pro.StandardOutput.ReadToEnd();
pro.Dispose();
}
catch (Exception ex)
{
return;
}
finally
{
}
Thanks
When you send
pro.StandardInput.WriteLine("exit");
to the process, this will close the console and exit the process.
So when you call
Console.WriteLine("Process: {0} ID: {1}", pro.ProcessName, pro.Id);
it raises a
"Process has exited, so the requested
information is not available."
exception. To fix this, move your exit call to after this line.
Never ignore exceptions!!! They tell you useful things that help you to fix your problems!!