views:

721

answers:

5

Ok so here's the problem, i use a connection with using(connection.... blah blah) and then after my using block is over I want to start the excel aplication like this: System.Diagnostics.Process.Start(excelFile);

This works... sometimes, other times my computer runs too quick and before the file is fully close, or the connection is fully terminated, or something like that, the above statement is exicuted and excel opens and says it cannot access the file.

This happens on and off, if i pause it, it work more often, but i need a way to check to see if i am going to be able to access the file before I access it.

This does not throw an exception, so catching the exception is not an option

i have tried: connection.Close(); connection.Dispose(); GC.Collect(); of which none have worked.

I know that any check will most likley have the possability of returning that the file is available and then before the open statment can be exicued the file being used by someone, thats fine. Just need a way to check.

Ok I tried this:

Microsoft.Office.Interop.Excel.Application _app = new Microsoft.Office.Interop.Excel.Application();

        try
        {
            Workbook wbook = _app.Workbooks.Open(excelFile,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        }
        catch (COMException ex)
        {
            //The file can't be opened in Excel
        }
        finally
        {
            //close the workbook and release the resources (GC.Collect() et al as usual)
            _app.Workbooks.Close();
            GC.Collect();

        }
        System.Diagnostics.Process.Start(excelFile);

and i goes through catches the exception and then proceeded to the start command where excel tells me it "cannot access 'fileName'"

A: 

I'm assuming, as you're writing to the file, you can get its file size fairly easy. Have you tried comparing the two?

while (fileSize != new FileInfo(excelFile).Length) {
    Thread.Sleep(1000);
}
System.Diagnostics.Process.Start(excelFile);

You may want to put in a counter so you don't sleep forever if the file doesn't write properly. Not sure if this'll work, but I guess it's worth a shot.

Samir Talwar
i guess i'm not sure what that would do. Are you trying to say that when the files are the same size it would be finished with the file? i'm not sure thats ture, even if it is i'm not sure that this would check that. how do u know what the file size should be?
This was kinda under the assumption that that data would be easy to get. I'm not sure how you're creating the file. If it's not, you can disregard this.
Samir Talwar
A: 

An option to see if the file is valid to open in Excel is to use the Primary Interop Assemblies:

Microsoft.Office.Interop.Excel.Application _app = 
                              new Microsoft.Office.Interop.Excel.Application();

try {
    Workbook wbook = _app.Workbooks.Open(excelFile,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing);
} catch (COMException ex) {
    //The file can't be opened in Excel
} finally {
    //close the workbook and release the resources (GC.Collect() et al as usual)
}

//The file can be opened in Excel if there wasn't a caught exception.
//You can wrap the above in a loop to test more than once as per the other answer

But anyway, it's still better to find a nice way to synchronize your writing to your reading. Maybe if you share the code with the writing part you can get better suggestions.

Vinko Vrsalovic
GREAT! sounds good, so where would I exicute System.Diagnostics.Process.Start(excelFile);?in the finally block?
You should release all the resources used via the Interop Assembly in the finally block, closing the _app and the workbook and passing a round of the GC. Then, on outside of the finally you can start the new process.
Vinko Vrsalovic
i closed the app and the gc.collect and then tried to start the file. as shown above, this did not work
You need to provide more information... did it catch an exception?
Vinko Vrsalovic
yes it caught the exception
If an exception is caught, then the file CANNOT BE READ, so of course it'll fail afterwards. What you can do is post what is the exception you get to see why it cannot be read, or loop in the try/catch/finally block until no exception is thrown.
Vinko Vrsalovic
A: 

Solution 1: You could just try

File.Move(sourceFilename, destinationFilename)

for the file you want to open. If there is no exception, just move the file back to the original source.

A drawback of this solution would be that it also throws an exception if the file is read by any other process.

Solution 2:

    FileStream stream = File.OpenWrite("yourfilename");
    stream.Close();

This should only check if the file is writeable.

With these solutions you don't have to add an dependency to Excel and it works for every filetype.

batzen
A: 

Try this function to check whether the file is still open :

public bool IsFileOpen(string path)
{
    FileStream fs = null;
    try
    {
        fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
        return false;
    }
    catch(IOException ex)
    {
        return true;
    }
    finally
    {
        if (fs != null)
            fs.Close();
    }
}
Thomas Levesque
A: 

You may use FileSystemWatcher class to subscribe for file system events, including file changing.

When Changed event has fired I suppose it's safe to open the file. Though, additional checking if the file has been shortly locked again by some other process is still worth doing.

Dmitry Tashkinov