0

In C#, my code is indirectly accessing a file. The file stays open long after what accessed it goes out of scope. I can't directly close the file, since I don't have a filestream for it.

Query: How do I either: Get a file handle my code has open indirectly so that I can close it? Tell my code it's time to close the file. (Similar to file.dispose() or file.close(), but I don't have the file object to start with.)

This isn't a "my code isn't working" question. It isn't about a bitmap specifically. Read the question. I want to know the general answer to do either of the options I asked for above. Stop projecting your interpretation onto the question and focus on what's actually in question.

JKreft
  • 113
  • 7
  • Have you tried GC.Collect()? The [finalizer](https://learn.microsoft.com/en-us/dotnet/api/system.io.filestream.finalize?view=netframework-4.7.2) will free up any resources, assuming the file is truly no longer in use.. – John Wu Jan 13 '19 at 11:54
  • Looks like a solution: https://stackoverflow.com/questions/177146/how-do-i-get-the-list-of-open-file-handles-by-process-in-c – opewix Jan 13 '19 at 11:57
  • Because, as the question said, other objects are indirectly opening the file. I don't have the file handle, I want to get it. So I'm trying to find a *general* answer, not an answer specific to one object as MJWIlls seems to have successfully hijacked my question into. – JKreft Jan 13 '19 at 12:26
  • @JKreft I see, you are saying some other process or code is opening the file which you've no control of? and you want some way to close the file indirectly? – Aman B Jan 13 '19 at 12:32
  • Code that I can't rewrite/control is doing it, yes, but in "my" process space. In other words, as far as C# is concerned, it's part of my app, but I have no way to rewrite the code that is indirectly opening the file. I pass it the name, it does some stuff, and I need away to close the file by name. Since my app has it open, there shouldn't be an access control issue. – JKreft Jan 13 '19 at 12:34
  • https://hintdesk.com/2010/05/25/c-get-all-files-being-accessed-by-a-process-in-64-bits/ may be of assistance. – mjwills Jan 13 '19 at 12:47
  • Was that link helpful @JKreft? If so, I can vote to re-open the question if you'd like. – mjwills Jan 13 '19 at 22:00
  • I'd delete the question if it would let me. It got derailed into uselessness. – JKreft Jan 14 '19 at 20:08
  • The "general solution" is "read the documentation for the object/library that is opening the file and follow its rules". The "The file remains locked until the Image is disposed." rule that Aman found for you is a specific instance of "read the documentation". **You cannot ignore the details of the specific object because they are important** (some libraries may use ordinary synchronous I/O, others asynchronous I/O, others will memory-map the file). Doing what you said (forcibly closing the file that another library opened) is a sure-fire way to crash your process. – Ben Voigt Jan 19 '19 at 18:39
  • It won't, because the underlying object doesn't use the file any more. In fact, the underlying object isn't being used anymore, but disposing of it didn't close the file until the program ended, which resulted in tons of stack being eaten. – JKreft Jan 21 '19 at 15:49

1 Answers1

1

Why not simply use a using statement? Inside that you can assign the loaded file to a variable and the Dispose method (which is called automatically) will unload the original file and thus unlock it... For example if you still want to load a Bitmap file as in the previous question:

private Bitmap LoadBitmap(string fileName)
{
    using (var bitmap = new Bitmap(fileName))
    {
        return new Bitmap(bitmap);
    }
}

What this does is temporarily lock the file, load in into memory, return in as a Bitmap and then unlock the file again. Of course you still need to do some null-checking, but you get the idea.

Saeverix
  • 397
  • 5
  • 18
  • 1
    `Garbage Collector will automatically unload the original file and unlock it` Technically, the GC is **not** doing that when you use `using`, so it may be worth removing that part of your answer. The unlocking is caused by the call to `Dispose`, not by the GC. – mjwills Jan 13 '19 at 12:25
  • That's a specific answer to a different question, not an answer to my question. I am looking for a general solution. – JKreft Jan 13 '19 at 12:27
  • @mjwills have you actually tried the code? Because when `return new Bitmap(bitmap);` is executed the original image is being unloaded/unlocked and a copy of the image is send back. So it's working as explained. @JKreft I hope you have enough skills to edit this answer to make it more general and make it load all kinds of files instead of just Bitmaps... – Saeverix Jan 13 '19 at 13:07
  • I am not saying the code doesn't work. I am saying part of the explanation is wrong. In your code example, the GC is completely uninvolved in the unlocking of the file. So I'd recommend perhaps changing `Inside that you can assign the loaded file to a variable and the Garbage Collector will automatically unload the original file and unlock it.` to `The use of 'using' will ensure that 'bitmap' gets Disposed, and thus the file will be unlocked` (or something to that effect) to make it clear that the GC is not involved. – mjwills Jan 13 '19 at 13:09
  • @mjwills I agree and I was already ahead of you and changed the answer. Thanks for the heads up! – Saeverix Jan 13 '19 at 13:16
  • 1
    Yes, you did change the answer - 8 minutes after writing your comment (and after writing mine). Which makes your comment even more odd in hindsight... – mjwills Jan 13 '19 at 21:59