I have a folder. When a file copied to that folder I need to rename it. Hence I have used a System.IO.FileSystemWatcher to do that. And I have implemented a service to do it.
My code as follows.
private System.IO.FileSystemWatcher FSWatcherTest;
FSWatcherTest.Created += new FileSystemEventHandler(FSWatcherTest_Created);
--------
private void FSWatcherTest_Created(object sender, System.IO.FileSystemEventArgs e)
{
//Some code
File.Move(oldfilepath, newfilepath);
//some code
}
When I copy a text file from my local machine it is working finely. But when I copy I large file from the network this is not working. Error is when it is copping this will fired. So the file is not accessible to this method. But I’m wondering why this is fired while it’s copping.
I’m using VS 2008 and C# for this application.
Thanks in advance.
Hacky solution:
If there is no way to know when the file has been fully copied, you could keep trying to do it until it works.
Something like this:
private void FSWatcherTest_Created(object sender, System.IO.FileSystemEventArgs e)
{
FileMover(object sender, System.IO.FileSystemEventArgs e);
}
private void FileMover(object sender, System.IO.FileSystemEventArgs e)
{
try{
//Some code
File.Move(oldfilepath, newfilepath);
//some code
}
catch
{
//Call an asynchronous method that will wait 1 second then call FileMover again
//with the same arguments,
//a BackGroundWorker would be perfect for that job.
}
}
Just found this snippit
Dim F As Short = FreeFile()
FileOpen(F, sFile, OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.LockReadWrite)
FileClose(F)
Would it be possible to wrap it in a 'WHILE' loop so it waits until the copy process is free?
Related
I'm C# with Compact Framework and I realized something weird today. I'm calling a method by an event that applies a set to an object and when I debug, it passes by this, but just performs after the last close bracket of the method. My example:
public string Loading
{
set { lblLoading.Text = value; }
}
private void btnAuth_Click(object sender, EventArgs e)
{
Loading = "Loading...";
_presenter.PerformAuth();
}
When I debug, it passes by my first statement, applies it, but doesn't change anything on the screen... Oh, until it do PerformAuth(). After it, so, then the label value is changed. Oh, the problem isn't just by it be synchronous. The same occurs when I try to do an asynchronous task:
private void btnAuth_Click(object sender, EventArgs e)
{
ASyncResult res = BeginInvoke(new Action(() =>Loading = "Loading..."));
EndInvoke(res);
_presenter.PerformAuth();
}
I think it might be a bug in thread and in C# design implementation. And also with direct set it is stubborn to me. As you can see in the image below:
I just want to set a text in a label, call a method and unset it in an event. Why does C# get it so complicated?
I am using the below code to find the base address of a running process. It's within a timer control for other purposes. If the target process is not running I want to display "Process is not running" in the label text, but keep checking for the running process and when/if found continue with the next code block. I have tried a few ways I thought would work, such as a 'try' with exception handling, but the form I am using to hold the label just freezes, I am quit new to c#. Here is the code,
private void timer1_Tick(object sender, EventArgs e)
{
#region BaseAddress
Process[] test = Process.GetProcessesByName("process");
int Base = test[0].MainModule.BaseAddress.ToInt32();
#endregion
//Other code
}
The exception when run is: "IndexOutOfRange exception was unhandled" - Index was outside the bounds of the array. Hopefully someone can help. Thanks.
private void timer1_Tick(object sender, EventArgs e)
{
#region BaseAddress
Process[] test = Process.GetProcessesByName("process");
if (test.Length > 0)
{
int Base = test[0].MainModule.BaseAddress.ToInt32();
}
else
{
myLabel.Text = "Process is not running";
}
#endregion
//Other code
}
Rather than use a try–catch block to handle the error, you should check whether the process was found before trying to access it:
private void timer1_Tick(object sender, EventArgs e)
{
#region BaseAddress
Process[] test = Process.GetProcessesByName("process");
if (test.Any())
{
// Process is running.
int Base = test[0].MainModule.BaseAddress.ToInt32();
// Perform any processing you require on the "Base" address here.
}
else
{
// Process is not running.
// Display "Process is not running" in the label text.
}
#endregion
//Other code
}
I think that the Process with the name "process" does not exist. You need to give a real processname. So the array does not contain any elements. Try debugging to see if the array contains any elements and add error handling or a verification that the array length is higher than 0 before doing the second line of your code.
Problem is that application closes without any error, VS stays opened.
I have multiple dynamically created FileSystemWatchers, all of them have eventhandler on "Created" event. So this eventhandler method looks like this :
void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
FileInfo f1 = new FileInfo(e.FullPath);
filesDataGrid.Rows.Add(f1.Name);
foreach (TLPclass table in parameterForm.getParameters)
{
//uses some funcion form another class
}
}
Line which causes program to close is the one where I'm adding File name to DataGridView - filesDataGrid.Rows.Add(f1.Name);
Also runs OK without that line.
Weird thing is that application runs normally, when launched from .exe file in projects folder. I can't see error in my code, but I guess theres something awfully wrong with it, if it doesn't even show error message.
And - what are the most common reasons why program could just shut down with no warnings?
The FileSystemWatcher will trigger the events in a separate thread. The logic inside the event handlers will need to take that fact in consideration and perform any synchronization needed. So you'll need something like this:
private void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
if (filesDataGrid.InvokeRequired)
{
filesDataGrid.Invoke((MethodInvoker)delegate { watcher_FileCreated(sender, e); });
}
else
{
FileInfo f1 = new FileInfo(e.FullPath);
filesDataGrid.Rows.Add(f1.Name);
foreach (TLPclass table in parameterForm.getParameters)
{
//uses some funcion form another class
}
}
}
Wrap your function with a Try{}catch (Exception ex) { } block.
i Would think it is because DataGridRow needs to be created with the variables from the FileSystemWatcher first.
e.g
DataGridViewRow row = filesDataGrid.NewRow();
row["columnname"] = f1.name;
filesDataGrid.Rows.Add(row);
I have an autocompleate textbox that looks into a data base. Some times while I'm typing I received the following error.
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Here is the code
private void tBSearchName_TextChanged(object sender, EventArgs e)
{
try
{
//test length
if (tBSearchName.Text.Length > 3)
{
//prevent db lookups
if (!tBSearchName.Text.ToLower().Contains(oldName) || oldName == String.Empty)
{
//test for a name + first letter of last name
if (Regex.IsMatch(tBSearchName.Text, #"(\w)+\s(\w)+(\.)*"))
{
tBSearchName.AutoCompleteCustomSource = AccessDB.serachByNemberName(tBSearchName.Text);
tBSearchName.AutoCompleteMode = AutoCompleteMode.Suggest;
//prevent db lookups
oldName = tBSearchName.Text.ToLower();
}
}
}
}
catch
{
}
}
My insight is that I should frezz typing into the application while search is done, can some suggest how to do this. Or any other insight on what is happening
It is a bug in Windows Forms's wrapper of autocomplete APIs. Windows Forms does not protect the AutoCompleteCustomSource object from being replaced while it is being enumerated by a background thread created by autocomplete.
Instead of replacing the data store, you can try replace the autocomplete object or use the IAutoCompleteDropDown interface to reset the enumerator.
You can use lock:
private void tBSearchName_TextChanged(object sender, EventArgs e)
{
lock(this) { /* do magic */
}
Do note that it's bad practice to perform long tasks in the event handlers. If the search takes more then 30ms, better use a worker thread.
If I'm reading a text file in shared access mode and another process truncates it, what is the easiest way to detect that? (I'm excluding the obvious choice of refreshing a FileInfo object periodically to check its size) Is there some convenient way to capture an event? (Filewatcher?)
There is, It's called FileSystemWatcher.
If you are developing a windows forms application, you can drag-and-drop it from the toolbox.
Here's some usage example:
private void myForm_Load(object sender, EventArgs e)
{
var fileWatcher = new System.IO.FileSystemWatcher();
// Monitor changes to PNG files in C:\temp and subdirectories
fileWatcher.Path = #"C:\temp";
fileWatcher.IncludeSubdirectories = true;
fileWatcher.Filter = #"*.png";
// Attach event handlers to handle each file system events
fileWatcher.Changed += fileChanged;
fileWatcher.Created += fileCreated;
fileWatcher.Renamed += fileRenamed;
// Start monitoring!
fileWatcher.EnableRaisingEvents = true;
}
void fileRenamed(object sender, System.IO.FileSystemEventArgs e)
{
// a file has been renamed!
}
void fileCreated(object sender, System.IO.FileSystemEventArgs e)
{
// a file has been created!
}
void fileChanged(object sender, System.IO.FileSystemEventArgs e)
{
// a file is modified!
}
It's in System.IO and System.dll so you should be able to use it in most type of projects.
FSW cannot work reliably, it is asynchronous. Assuming you don't get an exception, StreamReader.ReadLine() will return null when the file got truncated. Then check if the size changed. Beware of the unavoidable race condition, you'll need to verify assumptions about timing.
Just something to chew on; it may not apply to your situation:
chakrit's solution is correct for what you asked for, but I have to ask -- why are you reading a file while another process truncates it?
In particular, if you don't have some synchronization, reading/writing files concurrently is not particularly safe, and you may find you have other mysterious problems.