开发者

Force Visual Studio 2008 debugger to release executable file

I find myself in the annoying situation where the visual studio debugger does not cleanly release itself once the debugging session is finished. Hence, devenv.exe retains a lock on the executable file and I cannot rebuild the project due to the dreaded error:

Error 1 Unable to copy file "obj\Debug\program.exe" to "bin\Debug\program.exe". The process cannot access the file 'bin\Debug\program.exe' because it is being used by another开发者_StackOverflow中文版 process.

This can be fixed by restarting visual studio but restarting my entire IDE after every run cycle is not exactly conducive to a great coding environment. Build -> Clean does not help.

I've googled this error and while the symptom seems to be fairly common the underlying cause is varied. Primarily I would like to know, in order of importance:

  1. Is there any speedy way to get the file to be unlocked without restarting visual studio?
  2. Barring that, what defensive programming techniques should I be employing to prevent this?
  3. What exactly is going on behind the scenes in the below example which is causing the debugger to not release?

An example of code that will produce this symptom is here.

class Program
{
    static void Main(string[] args)
    {
        var f1 = new Form1();
        f1.Dir = "asdf";
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private FileSystemWatcher fsw;

    public string Dir
    {
        get { return fsw.Path;}
        set
        {
            fsw = new FileSystemWatcher(value);
            fsw.EnableRaisingEvents = true;
            throw new Exception("asdf");
        }
    }

    ~Form1()
    {
        if (fsw != null)
            fsw.Dispose();
    }
}

To reproduce:

  1. Run Program.Main using the Visual Studio 2008 debugger.
  2. Stop debugging when the exception is thrown.
  3. Change the source code and attempt to rebuild.

Edit: a solution of sorts:

public Form1()
{
    InitializeComponent();
    this.Closing += (sender, args) =>
    {
        if (watcher != null)
            watcher.Dispose();
    };
}

I am still interested in why this works and while placing it in the destructor does not.


One way to attack this problem and one you should have in your toolbelt as a developer is to use Process Explorer from MS/Sys Internals. One of its features allows you to search ll the open handles in a system and when found, to kill the handle. It is a very handy and free app. Now, this does not solve your core issue but it will help along.


I used to have this problem too.

Running a .bat with:

taskkill /F /IM program.exe
taskkill /F /IM program.vshost.exe

usually fix my problems...


Aren't you disposing in a finalizer ? Finalizers are managed by the machine, while developers are responsible for disposing. Finalzers are non-deterministic, while disposing are deterministic.

Maybe you could try the disposing in the "Disposed" event of the form.


Don't use a destructor ~. Don't call Dipose() in the destructor.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜