Mono bug? CS0219 warning when variable is actually used - c#

MonoDevelop (2.10.8) is reporting:
JPGCorruptForm.cs(20,20): Warning CS0219: The variable `myStream' is assigned but its value is never used (CS0219) (JPGCorrupt)
For this function:
private void toolStripButtonChooseText_Click(object sender, EventArgs e)
{
Stream myStream = null;
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = ".";
openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = false;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
Stop();
try
{
if ((myStream = openFileDialog.OpenFile()) != null)
{
_settings.TextFile = openFileDialog.FileName;
CurrentTextFile = _settings.TextFile;
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
}
This is my frist mono test project and I'm not sure if this kind of thing is normal. It certainly is not fatal, but could get annoying.

Well you're assigning a value to the variable, but you're never actually reading from it. In other words, you could easily remove it, just changing the middle expression to:
if (openFileDialog.OpenFile() != null)
Note that your existing code doesn't actually read from the variable even though you might think it does in the comparison to null. It's more like this:
Stream tmp = openFileDialog.OpenFile();
myStream = tmp;
if (tmp != null)
It sounds like you probably should be using it, to close the stream if nothing else... although I'd then declare it as late as possible, like this:
using (Stream myStream = openFileDialog.OpenFile())
{
if (myStream != null)
{
_settings.TextFile = openFileDialog.FileName;
CurrentTextFile = _settings.TextFile;
}
}
Here's a simpler example of the same problem, but the way:
using System;
class Test
{
static void Main()
{
string x;
if ((x = "Hello") != null)
{
Console.WriteLine("Yes");
}
}
}
Note that with warning level 4 (and possibly lower ones), the Microsoft C# 4 compiler picks up on it too:
Test.cs(7,16): warning CS0219: The variable 'x' is assigned but its value is
never used

Related

How to throw file extension exception in the File Dialog window?

I writing code to upload pdf file onto the third party server. I have done some path validation checks. I am checking if the file exists or not. Now for this validation the c# automatically throws an exception message box, without closing file dialog(browser window). I want to implement same validation for file extension. I tried checking for extension and then throwing the exception in message box, but the file dialog closes. I am attaching a screen shot so that this becomes clearer.
This type of validation I want and the background window should remain open
This validation I want to implement for file extension. As far as I know there are not exceptions for validating file extensions.
public System.Windows.Forms.OpenFileDialog cmndBrowseOpen;
public System.Windows.Forms.SaveFileDialog cmndBrowseSave;
public System.Windows.Forms.DialogResult cmdBrowseResult
public void cmdBrowse_Click()
{
const string sFilter = "PDFs (*.pdf)|*.pdf";
string sMsg = String.Empty;
string sTitle = String.Empty;
FileInfo oFile = null;
try
{
if (moFrmIntComplaint != null)
{
moFrmIntComplaint.cmndBrowseOpen.Filter = sFilter;
moFrmIntComplaint.cmndBrowseOpen.Title = ResourceHandler.Resources.GetString("BrowseFile:Title");
moFrmIntComplaint.cmdBrowseResult = moFrmIntComplaint.cmndBrowseOpen.ShowDialog();
string fileExtension = Path.GetExtension(moFrmIntComplaint.cmndBrowseOpen.FileName);
moFrmIntComplaint.cmndBrowseOpen.DefaultExt = ".pdf";
if (fileExtension != ".pdf")
{
moFrmIntComplaint.cmndBrowseOpen.FileOk += delegate(object s, System.ComponentModel.CancelEventArgs ev)
{
ev.Cancel = true;
};
}
if (String.IsNullOrEmpty(moFrmIntComplaint.cmndBrowseOpen.FileName) == false)
{
oFile = new FileInfo(moFrmIntComplaint.cmndBrowseOpen.FileName);
if ((oFile != null) && (File.Exists(moFrmIntComplaint.cmndBrowseOpen.FileName) && (fileExtension == ".pdf")))
{
if (Convert.ToDouble(oFile.Length) > dMaxFileSize)
{
sTitle = ResourceHandler.Resources.GetString("BrowseFile:FilSizTitle");
sMsg = ResourceHandler.Resources.GetString("BrowseFile:FileSize");
Cerner.Foundations.Measurement.TimedMessageBox.Show(sMsg, sTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
moFrmIntComplaint.lblFileName.Text = System.String.Empty;
moFrmIntComplaint.lblFilePath.Text = System.String.Empty;
moFrmIntComplaint.cmdRemove.Visible = false;
}
else
{
moFrmIntComplaint.lblFileName.Text = Path.GetFileName(moFrmIntComplaint.cmndBrowseOpen.FileName);
moFrmIntComplaint.lblFilePath.Text = moFrmIntComplaint.cmndBrowseOpen.FileName;
moFrmIntComplaint.cmdRemove.Left = moFrmIntComplaint.lblFileName.Left + moFrmIntComplaint.lblFileName.Width + 5;
moFrmIntComplaint.cmdRemove.Visible = true;
}
}
}
}
return;
}
The top three statements are in a different class called moFrmIntComplaint. As these variables are used in the browse_click method, this why I have mentioned these variables here. I have tried using delegate because of this question.
Even this doesn't help.

Background Worker Locking Main Thread - Windows Forms C#

I have a background worker that I use to create files in the background.
I had it working so that the files were created and the UI was still responsive.
I made some changes and now I can't figure out why the background worker is locking my main thread.
Here are my background worker methods. I don't have a progress changed event.
private void filecreator_bgw_DoWork(object sender, DoWorkEventArgs e)
{
if (filecreator_bgw.CancellationPending == true)
{
e.Cancel = true;
}
else
{
myManager.createFiles((SelectedFileTypes) e.Argument);
}
}
private void filecreator_bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
//status_label.Text = "Canceled!";
}
else if (e.Error != null)
{
//status_label.Text = "Error: " + e.Error.Message;
}
else
{
// Check the file manager object to see if the files were created successfully
status_label.Text = "COMPLETE";
file_statusLabel.Text = "Files Created: " + DateTime.Now.ToShortTimeString();
System.Threading.Thread.Sleep(5000);
status_label.Text = "Click Create Files to Begin";
createfiles_button.Enabled = true;
}
}
Here is the method to create the files.
public void createFiles(SelectedFileTypes x)
{
if (string.IsNullOrEmpty(Filename) || (x.isCSV == false && x.isTAB == false && x.isXML == false))
{
filesCreated = false;
return;
}
// Declare the streams and xml objects used to write to the output files
XDocument xmlFile;
StreamWriter swCSV;
StreamWriter swTAB;
CSVFilename = Path.GetDirectoryName(Filename) + Path.DirectorySeparatorChar.ToString() +
Path.GetFileNameWithoutExtension(Filename) + "CSV_TEST.csv";
swCSV = new StreamWriter(CSVFilename);
TABFilename = Path.GetDirectoryName(Filename) + Path.DirectorySeparatorChar.ToString() +
Path.GetFileNameWithoutExtension(Filename) + "TAB_TEST.csv";
swTAB = new StreamWriter(TABFilename);
XMLFilename = Path.GetDirectoryName(Filename) + Path.DirectorySeparatorChar.ToString() +
Path.GetFileNameWithoutExtension(Filename) + "XML_TEST.csv";
xmlFile = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XComment("Crosswalk"));
xmlFile.Add(new XElement("ACCOUNTS"));
// String array for use when creating xml nodes
string[] splits;
// String used to read in a line from the input file
string line = "";
// Use a try and catch block, if any errors are caught, return false
try
{
// Read each line in the file and write to the output files
using (StreamReader sr = new StreamReader(Filename))
{
int i = 0;
while ((line = sr.ReadLine()) != null)
{
if (x.isCSV)
{
swCSV.WriteLine(line.Replace(delim, ","));
}
if (x.isTAB)
{
swTAB.WriteLine(line.Replace(delim, "\t"));
}
if (x.isXML)
{
if (i <= 0)
{
i++;
continue;
}
splits = line.Split(new string[] { delim }, StringSplitOptions.RemoveEmptyEntries);
xmlFile.Root.Add(
new XElement("ACCOUNTS",
from s in header
select new XElement(s, splits[Array.IndexOf(header, header.Where(z => z.Equals(s, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault())])
)
);
}
}
// Dispose of all objects
swCSV.Close();
swCSV.Dispose();
swTAB.Close();
swTAB.Dispose();
if (x.isXML)
{
//xmlFile.Save(Path.GetFullPath(Filename) + Path.GetFileNameWithoutExtension(Filename) + "_TEST.xml");
xmlFile.Save(XMLFilename);
}
}
}
catch (Exception)
{
filesCreated = false;
return;
}
// Return true if file creation was successfull
filesCreated = true;
}
In the do work method, I build a simple struct to determine what output file types should be made and then I pass it to the method. If I comment out that call to create the files, the UI still does not respond.
In the create files method, I build out the files based on the input file that I am transforming. I do use a LINQ statement to help build out XML tags, but the arrays holding the tags values are small, 3-5 elements depending on the file chosen.
Is there a simple solution, or should I re-design the method. If I have to re-design, what are things I should keep in mind to avoid locking the main thread.
Thanks
Here is how I call the runworkerasync method:
private void createfiles_button_Click(object sender, EventArgs e)
{
SelectedFileTypes selVal = new SelectedFileTypes();
foreach (var structVal in outputformats_checkedListBox.CheckedItems)
{
if (structVal.ToString().Equals("CSV", StringComparison.InvariantCultureIgnoreCase))
selVal.isCSV = true;
if (structVal.ToString().Equals("TAB", StringComparison.InvariantCultureIgnoreCase))
selVal.isTAB = true;
if (structVal.ToString().Equals("XML", StringComparison.InvariantCultureIgnoreCase))
selVal.isXML = true;
}
// Call the FileManager object's create files method
createfiles_button.Enabled = false;
filecreator_bgw.RunWorkerAsync(selVal);
}
UPDATE:
I updated the call to start the worker and then the call to create the files using the argument passed into the worker.
You cannot interact with most UI controls directly from a BackgroundWorker. You need to access outputformats_checkedListBox.CheckedItems from the UI thread and pass the resulting SelectedFileTypes object into the BackgroundWorker as a parameter.
Also, pleas enote that your cancellation logic really didn't do much. In order for it to work well, you need to check CancellationPending throughout the process, not just when starting.
Here is a rough example of how you should start the worker:
private void StartWorker()
{
SelectedFileTypes selVal = new SelectedFileTypes();
foreach (var structVal in outputformats_checkedListBox.CheckedItems)
{
if (structVal.ToString().Equals("CSV", StringComparison.InvariantCultureIgnoreCase))
selVal.isCSV = true;
if (structVal.ToString().Equals("TAB", StringComparison.InvariantCultureIgnoreCase))
selVal.isTAB = true;
if (structVal.ToString().Equals("XML", StringComparison.InvariantCultureIgnoreCase))
selVal.isXML = true;
}
filecreator_bgw.RunWorkerAsync(selVal);
}
private void filecreator_bgw_DoWork(object sender, DoWorkEventArgs e)
{
SelectedFileTypes selVal = (SelectedFileTypes)e.Argument;
myManager.createFiles(selVal);
}

How do I make it so that when the user clicks cancel, it cancels the dialog?

I have the following code:
Open File Code
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Open File";
ofd.FileName = "";
ofd.Filter = "Rich Text Files (*.rtf)|*.rtf|Text Document (*.txt)|*.txt|Microsoft Word Document (*.doc)|*.doc|Hypertext Markup Language Document (*.html)|*.html"; StreamReader sr = null;
if (ofd.ShowDialog() != DialogResult.Yes) return;
{
NewFile();
}
try
{
sr = new StreamReader(ofd.FileName);
this.Text = string.Format("{0} - Basic Word Processor", Path.GetFileName(ofd.FileName));
richTextBoxPrintCtrl1.Text = ofd.FileName;
richTextBoxPrintCtrl1.Text = sr.ReadToEnd();
filepath = ofd.FileName;
richTextBoxPrintCtrl1.LoadFile(fileName, RichTextBoxStreamType.RichText);
}
catch
{
}
finally
{
if (sr != null) sr.Close();
}
New File Code
if (richTextBoxPrintCtrl1.Modified)
{
DialogResult r = MessageBox.Show(this, "Save Current Document?", "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (r == DialogResult.Yes) SaveFile();
if (r == DialogResult.Cancel) return;
}
this.Text = string.Format("Untitled - Basic Word Processor");
richTextBoxPrintCtrl1.Text = "";
filepath = null;
}
}
SaveFileAs Code
SaveFileDialog sfdSaveFile = new SaveFileDialog();
sfdSaveFile.Title = "Save File";
sfdSaveFile.FileName = "Untitled";
sfdSaveFile.Filter = "Rich Text Files (*.rtf)|*.rtf|Text Document (*.txt)|*.txt|Microsoft Word Document (*.doc)|*.doc|Hypertext Markup Language Document (*.html)|*.html";
if (sfdSaveFile.ShowDialog() == DialogResult.OK)
try
{
filepath = sfdSaveFile.FileName;
SaveFile();
this.Text = string.Format("{0} - Basic Word Processor", Path.GetFileName(sfdSaveFile.FileName));
}
catch (Exception exc)
{
}
SaveFile Code
if (filepath == null)
{
SaveFileAs();
return;
}
StreamWriter sw = new StreamWriter(filepath);
//StreamWriter stwrite = null;
try
{
sw.WriteLine(richTextBoxPrintCtrl1.Text);
richTextBoxPrintCtrl1.Modified = false;
sw.Close();
}
catch (Exception e)
{
MessageBox.Show("Failed to save file. \n" + e.Message);
}
finally
{
if (sw != null) sw.Close();
}
Currently, the program skips the NewFile event (even if the text has been modified). How can I make it so that when I click "Open", it asks me if I would like to save (if the text is modified). Then if I click cancel, it returns me to the form?
Sorry. I'm really new to programming so this is all a learning curve.
Okay, I think I see what's going on here. First off I don't believe return; works the way you think it does.
if (ofd.ShowDialog() != DialogResult.Yes) return;
{
NewFile();
}
You have a return; call that happens if the show dialog is not yes. The { newFile() } code doesn't need braces around it. So those lines are really:
if (ofd.ShowDialog() != DialogResult.Yes) return;
NewFile();
Now, given your requirement, NewFile is called WAY too late in the game anyway. You want that to happen before you ask them what to open; just like most other windows programs work.
But, there's another issue. Your return statement in the NewFile method is simply returning from NewFile. It's not telling the previous method to bail out.
So the NewFile method needs a return type to indicate whether to allow the calling method to go forward or not.
And, looking at your save file you have a return method there too. What's with all of the return; calls?
Which brings us back to how do we fix this?
Answer: rewrite the whole thing. Starting with the following method:
private Boolean CanClear() {
Boolean result = false;
if (richTextBoxPrintCtrl1.Modified)
{
DialogResult r = MessageBox.Show(this, "Save Current Document?", "Save?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (r == DialogResult.Yes) {
SaveFile();
result = true;
}
} else {
result = true;
}
return result;
}
Now, in your Open and New file methods do the following (assuming these are the method headers)
protected void OpenFile(...) {
if (!CanClear()) return;
.... now execute the code to load the open dialog and the selected file.
}
protected void NewFile(...) {
if (!CanClear()) return;
this.Text = string.Format("Untitled - Basic Word Processor");
richTextBoxPrintCtrl1.Text = "";
filepath = null;
}
The problem is here:
if (ofd.ShowDialog() != DialogResult.Yes) return;
{
NewFile();
}
remove that return. But, as #Chris says, you should ask whether to save the current file or not before the user selects the new file to open.

Update ui thread

I have a ListBox which I put some files, if the file is not AVI I automatically converts it but I want when the files converting message will write on a label that the files are now converted to another format, i know i need use Dispatcher in order to update the UI thread but i use now Winform instead of WPF, and i need help with this.
BTW i cannot use Task because i am using .Net 3.5
private void btnAdd_Click(object sender, EventArgs e)
{
System.IO.Stream myStream;
OpenFileDialog thisDialog = new OpenFileDialog();
thisDialog.InitialDirectory = "c:\\";
thisDialog.Filter = "All files (*.*)|*.*";
thisDialog.FilterIndex = 1;
thisDialog.RestoreDirectory = false;
thisDialog.Multiselect = true; // Allow the user to select multiple files
thisDialog.Title = "Please Select Source File";
thisDialog.FileName = lastPath;
List<string> list = new List<string>();
if (thisDialog.ShowDialog() == DialogResult.OK)
{
foreach (String file in thisDialog.FileNames)
{
try
{
if ((myStream = thisDialog.OpenFile()) != null)
{
using (myStream)
{
listBoxFiles.Items.Add(file);
lastPath = file;
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
for (int i = 0; i < listBoxFiles.Items.Count; i++)
{
string path = (string)listBoxFiles.Items[i];
FileInfo fileInfo = new FileInfo(path);
if (fileInfo.Extension != ".AVI")
{
listToRemove.Add(path);
}
}
(new System.Threading.Thread(sendFilesToConvertToPcap)).Start();
foreach (string file in listToRemove) //remove all non .AVI files from listbox
{
listBoxFiles.Items.Remove(file);
}
}
}
this function need to change the Label:
public void sendFilesToConvertToPcap()
{
if (listToRemove.Count == 0) // nothing to do
{
return;
}
lblStatus2.Content = "Convert file to .AVI...";
foreach (String file in listToRemove)
{
FileInfo fileInfo = new FileInfo(file);
myClass = new (class who convert the files)(fileInfo);
String newFileName = myClass.mNewFileName;
listBoxFiles.Items.Add(myClass._newFileName);
}
lblStatus2.Content = "Finished...";
}
From your question, it seems that you'd like to convert several files. You may want to consider using the BackgroundWorker class and overwrite the DoWork and ProgressChanged events as described in this article. You can update the label and other controls in the ProgressChanged event.
public void sendFilesToConvertToPcap()
{
.....
....
this.Invoke((MethodInvoker)delegate {
lblStatus2.Text = "Convert file to .AVI..."; });
....
}
This is a very common requirement for long-running processes. If you don't explicitly call methods on a separate thread, they will automatically run on the main (see: UI) thread and cause your UI to hand (as I suspect you already know).
http://www.dotnetperls.com/backgroundworker
Here is an old, but excellent link with an example on how to use the background worker to handle the threadpool for you.
This way, you can just create a worker to manage running your conversion process on a separate thread, and I believe there is even an example for creating a process bar.

c# Unable to open file for reading

I'm writing a program that uses FileSystemWatcher to monitor changes to a given directory, and when it receives OnCreated or OnChanged event, it copies those created/changed files to a specified directories. At first I had problems with the fact that OnChanged/OnCreated events can be sent twice (not acceptable in case it needed to process 500MB file) but I made a way around this and with what I'm REALLY BLOCKED with is getting the following IOException:
The process cannot access the file 'C:\Where are Photos\bookmarks (11).html' because it is being used by another process.
Thus, preventing the program from copying all the files it should.
So as I mentioned, when user uses this program he/she specifes monitored directory, when user copies/creates/changes file in that directory, program should get OnCreated/OnChanged event and then copy that file to few other directories.
Above error happens in all cases, if user copies few files that needs to overwrite other ones in folder being monitored or when copying bulk of several files or even sometimes when copying one file in a monitored directory.
Whole program is quite big so I'm sending the most important parts.
OnCreated:
private void OnCreated(object source, FileSystemEventArgs e) {
AddLogEntry(e.FullPath, "created", "");
// Update last access data if it's file so the same file doesn't
// get processed twice because of sending another event.
if (fileType(e.FullPath) == 2) {
lastPath = e.FullPath;
lastTime = DateTime.Now;
}
// serves no purpose now, it will be remove soon
string fileName = GetFileName(e.FullPath);
// copies file from source to few other directories
Copy(e.FullPath, fileName);
Console.WriteLine("OnCreated: " + e.FullPath);
}
OnChanged:
private void OnChanged(object source, FileSystemEventArgs e) {
// is it directory
if (fileType(e.FullPath) == 1)
return; // don't mind directory changes itself
// Only if enough time has passed or if it's some other file
// because two events can be generated
int timeDiff = ((TimeSpan)(DateTime.Now - lastTime)).Seconds;
if ((timeDiff < minSecsDiff) && (e.FullPath.Equals(lastPath))) {
Console.WriteLine("-- skipped -- {0}, timediff: {1}", e.FullPath, timeDiff);
return;
}
// Update last access data for above to work
lastPath = e.FullPath;
lastTime = DateTime.Now;
// Only if size is changed, the rest will handle other handlers
if (e.ChangeType == WatcherChangeTypes.Changed) {
AddLogEntry(e.FullPath, "changed", "");
string fileName = GetFileName(e.FullPath);
Copy(e.FullPath, fileName);
Console.WriteLine("OnChanged: " + e.FullPath);
}
}
fileType:
private int fileType(string path) {
if (Directory.Exists(path))
return 1; // directory
else if (File.Exists(path))
return 2; // file
else
return 0;
}
Copy:
private void Copy(string srcPath, string fileName) {
foreach (string dstDirectoy in paths) {
string eventType = "copied";
string error = "noerror";
string path = "";
string dirPortion = "";
// in case directory needs to be made
if (srcPath.Length > fsw.Path.Length) {
path = srcPath.Substring(fsw.Path.Length,
srcPath.Length - fsw.Path.Length);
int pos = path.LastIndexOf('\\');
if (pos != -1)
dirPortion = path.Substring(0, pos);
}
if (fileType(srcPath) == 1) {
try {
Directory.CreateDirectory(dstDirectoy + path);
//Directory.CreateDirectory(dstDirectoy + fileName);
eventType = "created";
} catch (IOException e) {
eventType = "error";
error = e.Message;
}
} else {
try {
if (!overwriteFile && File.Exists(dstDirectoy + path))
continue;
// create new dir anyway even if it exists just to be sure
Directory.CreateDirectory(dstDirectoy + dirPortion);
// copy file from where event occured to all specified directories
using (FileStream fsin = new FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
using (FileStream fsout = new FileStream(dstDirectoy + path, FileMode.Create, FileAccess.Write)) {
byte[] buffer = new byte[32768];
int bytesRead = -1;
while ((bytesRead = fsin.Read(buffer, 0, buffer.Length)) > 0)
fsout.Write(buffer, 0, bytesRead);
}
}
} catch (Exception e) {
if ((e is IOException) && (overwriteFile == false)) {
eventType = "skipped";
} else {
eventType = "error";
error = e.Message;
// attempt to find and kill the process locking the file.
// failed, miserably
System.Diagnostics.Process tool = new System.Diagnostics.Process();
tool.StartInfo.FileName = "handle.exe";
tool.StartInfo.Arguments = "\"" + srcPath + "\"";
tool.StartInfo.UseShellExecute = false;
tool.StartInfo.RedirectStandardOutput = true;
tool.Start();
tool.WaitForExit();
string outputTool = tool.StandardOutput.ReadToEnd();
string matchPattern = #"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";
foreach (Match match in Regex.Matches(outputTool, matchPattern)) {
System.Diagnostics.Process.GetProcessById(int.Parse(match.Value)).Kill();
}
Console.WriteLine("ERROR: {0}: [ {1} ]", e.Message, srcPath);
}
}
}
AddLogEntry(dstDirectoy + path, eventType, error);
}
}
I checked everywhere in my program and whenever I use some file I use it in using block so even writing event to log (class for what I omitted since there is probably too much code already in post) wont lock the file, that is it shouldn't since all operations are using using statement block.
I simply have no clue who's locking the file if not my program "copy" process from user through Windows or something else.
Right now I have two possible "solutions" (I can't say they are clean solutions since they are hacks and as such not desirable). Since probably the problem is with fileType method (what else could lock the file?) I tried changing it to this, to simulate "blocking-until-ready-to-open" operation:
fileType:
private int fileType(string path) {
FileStream fs = null;
int ret = 0;
bool run = true;
if (Directory.Exists(path))
ret = 1;
else {
while (run) {
try {
fs = new FileStream(path, FileMode.Open);
ret = 2;
run = false;
} catch (IOException) {
} finally {
if (fs != null) {
fs.Close();
fs.Dispose();
}
}
}
}
return ret;
}
This is working as much as I could tell (test), but... it's hack, not to mention other deficients.
The other "solution" I could try (I didn't test it yet) is using GC.Collect() somewhere at the end of fileType() method. Maybe even worse "solution" than previous one.
Can someone pleas tell me, what on earth is locking the file, preventing it from opening and how can I fix that? What am I missing to see?
Thanks in advance.
The problem is most likely that the file is still being copied while you already try to access it. This can happen especially on large files.
You can try to check whether the file can be opened with write permissions before you actually start your processing. For details how to do that check here.
If you can influence the process creating the file there might be a better solution. First copy the file with a temporary extension, and then, after the copying is completed, rename it so that the FileSystemWatcher event will be triggered.
You can try with Volume Shadow Copies.
See www.codeproject.com/KB/dotnet/makeshadowcopy.aspx for more details.
FileSystemWatcher events trigger when the file begins the copy, not at the end, so it's common to run into this kind of errors.
Your first approach will work, however, I would recommend spinning the I/O intensive code on another thread, and using an incremental Sleep() instead of the busy waiting you do.
However, if you have access to the software that actually creates the files, the extension changing is a slightly less complicated solution. Just beware, that a xls filter on the FileSystemwatcher will match a file called myfile1.xls.temp, as I found that out the hard way :)

Categories