3

I have a method in my windows service as follows:

System.IO.File.Copy(path, ConfigurationManager.AppSettings["BulkInsertGiftRegisterCreatorDirectory"] + System.IO.Path.GetFileName(path));

Loyalty.Entity.Base.FileInfo file = new Loyalty.Entity.Base.FileInfo();
file.FileName = path;
request.Object = file;

ResponseBase response = new ResponseBase(request);
RequestConnection connection = new RequestConnection("cn");
FileManager fileManager = new FileManager(request, connection);
response = fileManager.OfflineGiftRegisterBulkInsert();

System.IO.File.Delete(ConfigurationManager.AppSettings["BulkInsertGiftRegisterCreatorDirectory"] + System.IO.Path.GetFileName(path));

// here is the part of stored procedure that uses file
SELECT @SCRIPT= 'BULK INSERT GIFT_CARD.GIFT_TEMP'
                            +' FROM '''
                            + @FILE_PATH
                            +''' WITH ('
                                 +'FIELDTERMINATOR = '','','
                                 + 'KEEPNULLS'
                            +');'

I can delete the file from file system by hand, but this code says me "Ooops! System.IO.IOException: The process cannot access the file 'filename' because it is being used by another process."

I've searched the similar questions on stackoverflow and else where. But I could not find anything to help me. Copy or Delete methods return void and I have no stream in my code to dispose.

How can I fix it?

Thanks in advance.

xkcd
  • 2,538
  • 11
  • 59
  • 96
  • 2
    What is the "do something else" part doing? I assume it is doing *something* with the file being copied/deleted. And I have the feeling that this something is important here. – Dirk Vollmar Nov 08 '10 at 21:29
  • Does your Window's service run under the same identity as you? If not, maybe the Window's service doesn't have permission to delete the file. – ChrisNel52 Nov 08 '10 at 21:35
  • I call a stored procedure that uses the path of the file to bulk insert the rows contained by the file. – xkcd Nov 08 '10 at 21:35
  • @anilca: That means that the file is opened (probably by the method executing the stored procedure, or by the stored procedure). Make sure it is properly closed. If you show your code we can help you find the problem. – Dirk Vollmar Nov 08 '10 at 21:37
  • @ChrisNel52 I'm logging in as the same user that windows service uses. – xkcd Nov 08 '10 at 21:37
  • @0xA3 I added the service call lines – xkcd Nov 08 '10 at 21:44
  • Make sure that the request, connection and fileManager objects are properly disposed if they implement `IDisposable`. You can do so best by wrapping your code in `using` blocks. – Dirk Vollmar Nov 08 '10 at 21:55
  • How are you triggering the method? FileWatcher? timer? – Conrad Frix Nov 08 '10 at 22:02
  • And what if they do not implement IDisposable? – xkcd Nov 08 '10 at 22:02
  • So, was my answer helpful or not? – Vercas Nov 17 '10 at 14:18

3 Answers3

5

Here is a method for you to check if a file is in use:

public static System.Boolean FileInUse(System.String file)
{
    try
    {
        if (!System.IO.File.Exists(file)) // The path might also be invalid.
        {
            return false;
        }

        using (System.IO.FileStream stream = new System.IO.FileStream(file, System.IO.FileMode.Open))
        {
            return false;
        }
    }
    catch
    {
        return true;
    }
}

Also, to wait for a file I have made:

public static void WaitForFile(System.String file)
{
    // While the file is in use...
    while (FileInUse(file)) ; // Do nothing.
}

I hope this helps!

Vercas
  • 8,931
  • 15
  • 66
  • 106
4

Before you go looking through the code you might want to use process explorer to Identify what process has the handle. This might rule out some issue you haven't thought of

update

Since you are using a timer you must make sure that your method is reentrant and you don't have any race conditions.. E.g. the timer ticks faster than you can process the event.

See this question And this answer

Community
  • 1
  • 1
Conrad Frix
  • 51,984
  • 12
  • 96
  • 155
1

Even better solution, is to add this two lines of code before using the function FileInUse that Vercas showed:

GC.Collect();
GC.WaitForPendingFinalizers();
  • Please explain why this is a better solution. Also, generally speaking, answers should be able to stand on their own. Right now, this looks more like a comment or reply than an answer. – p.s.w.g May 27 '14 at 15:02
  • I say it's a better solution because I tested it. I was having the same problem, a File.Copy followed by a File.Delete would give me the error. First I tested only with "FileInUse", and it worked. But the system was taking like 10 to 15 seconds to delete the file. Then I tested with the lines I shared here, and it worked in some situations and others don't. So I combined both solutions: First I called the two lines I shared here, then tested the file with the function "FileInUse", and finally called "File.Delete". It works like a charm, and the file gets deleted almost instantly. – user2501815 May 27 '14 at 17:15