Project 1 - AppDomain (Console Application)
Program.cs
This project has no reference to Project 3 (FileLockFail). FileLockFail will not appear in the list of assemblies.
Unloading the created appDomain will release the file lock.
using System;
using System.Reflection;
using Interfaces;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
private const string targetDllName = "FileLockFail.dll";
static void Main(string[] args)
{
string testFileFullPath = CreateTestFile();
#if(DEBUG)
//Copy the DDL that will be loaded into the AppDomain into the working directory.
DirectoryInfo dllDir = new DirectoryInfo(Environment.CurrentDirectory);
string source = Path.Combine(dllDir.Parent.Parent.Parent.FullName, @"FileLockFail\bin\Debug\" + targetDllName);
string destination = Path.Combine(dllDir.FullName, targetDllName);
File.Copy(source, destination, true);
#endif
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationName = "appDomain";
domainSetup.ApplicationBase = Environment.CurrentDirectory;
AppDomain appDomain = AppDomain.CreateDomain("appDomain", null, domainSetup);
ITestMethod otherDomainTestClass = (ITestMethod)appDomain.CreateInstanceAndUnwrap(
targetDllName.Replace(".dll", ""),
"FileLockFail.FailToCloseFileStream");
otherDomainTestClass.TestMethod(testFileFullPath);
try
{
//This should fail due to the file lock still being open.
System.IO.File.Delete(testFileFullPath);
System.Diagnostics.Debug.Fail("Exception expected");
}
catch (IOException)
{
AppDomain.Unload(appDomain);
}
System.IO.File.Delete(testFileFullPath);
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Console.WriteLine("Assembly: {0}", AppDomain.CurrentDomain.FriendlyName);
foreach (Assembly assembly in assemblies)
{
Console.WriteLine("Loaded: {0}.", assembly.ManifestModule.Name);
}
Console.WriteLine("Press enter");
Console.ReadLine();
}
private static string CreateTestFile()
{
string filePath = Path.Combine(Environment.CurrentDirectory, "TestFile.txt");
using (FileStream fileStream = File.Create(filePath))
{
using (System.IO.StreamWriter fileWriter = new StreamWriter(fileStream))
{
fileWriter.Write("Hello World " + DateTime.Now);
}
}
return filePath;
}
}
}
Project 2 - Interfaces (Class Library)
ITestMethod.cs
Shared interface between both DLL's.
namespace Interfaces
{
public interface ITestMethod
{
void TestMethod(string message);
}
}
Project 3 - FileLockFail (Class Library)
FailToCloseFileStream.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace FileLockFail
{
[Serializable]
public class FailToCloseFileStream : MarshalByRefObject, Interfaces.ITestMethod
{
private static System.IO.FileStream _fileStream = null;
public void TestMethod(string message)
{
Console.WriteLine("Host domain: {0} Message: {1}", AppDomain.CurrentDomain.FriendlyName, message);
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
Console.WriteLine("Assembly: {0}", AppDomain.CurrentDomain.FriendlyName);
foreach (Assembly assembly in assemblies)
{
Console.WriteLine("Loaded: {0}.", assembly.ManifestModule.Name);
}
_fileStream = System.IO.File.OpenWrite(message);
//Don't close the file stream
}
}
}
See Also:
- Specify the path to a config file for the AppDomain MSDN: AppDomainSetup.ConfigurationFile
- Prevent the AppDomain locking the DLL using shadow copy - AppDomain and Shadow Copy