2016-10-20 6 views
1

MEF를 사용하여 어셈블리를로드하는 WinForms 프로그램을 작성하고 있습니다. 이러한 어셈블리는 실행 파일과 같은 폴더에 있지 않습니다. 파일 유지 관리를 수행해야하므로 실제 WinForm을로드하기 전에 Program.cs 파일에 일부 코드를 구현하여 파일 (어셈블리 인 경우에도)이 프로그램에서로드되지 않도록해야합니다. .파일 조작으로 파일 블록 처리

내가이 작업을 수행하고 있습니다 : - 타 하나 개 한 위치에서 폴더를 이동 - 아카이브에서 파일 인 경우 폴더에서 dll 파일을 아카이브에서 압축 풀기 파일 덮어 쓰기 이동 (것보다 새로운 이동)

폴더를 이동 한 후에 파일이 잠겨 덮어 쓸 수 없다는 것이 문제입니다. 또한 이동이 끝나면 파일을 하나씩 이동하여 파일을 이동하려고했습니다.

는 누군가가 파일이 차단 된 이유를 나에게 설명 할 수 나는

감사

private static void InitializePluginsFolder() 
    { 
     if (!Directory.Exists(Paths.PluginsPath)) 
     { 
      Directory.CreateDirectory(Paths.PluginsPath); 
     } 

     // Find archive that contains plugins to deploy 
     var assembly = Assembly.GetExecutingAssembly(); 
     if (assembly.Location == null) 
     { 
      throw new NullReferenceException("Executing assembly is null!"); 
     } 

     var currentDirectory = new FileInfo(assembly.Location).DirectoryName; 
     if (currentDirectory == null) 
     { 
      throw new NullReferenceException("Current folder is null!"); 
     } 

     // Check if previous installation contains a "Plugins" folder 
     var currentPluginsPath = Path.Combine(currentDirectory, "Plugins"); 
     if (Directory.Exists(currentPluginsPath)) 
     { 
      foreach (FileInfo fi in new DirectoryInfo(currentPluginsPath).GetFiles()) 
      { 
       using (FileStream sourceStream = new FileStream(fi.FullName, FileMode.Open)) 
       { 
        using (FileStream destStream = new FileStream(Path.Combine(Paths.PluginsPath, fi.Name), FileMode.Create)) 
        { 
         destStream.Lock(0, sourceStream.Length); 
         sourceStream.CopyTo(destStream); 
        } 
       } 
      } 

      Directory.Delete(currentPluginsPath, true); 
     } 

     // Then updates plugins with latest version of plugins (zipped) 
     var pluginsZipFilePath = Path.Combine(currentDirectory, "Plugins.zip"); 

     // Extract content of plugins archive to a temporary folder 
     var tempPath = string.Format("{0}_Temp", Paths.PluginsPath); 

     if (Directory.Exists(tempPath)) 
     { 
      Directory.Delete(tempPath, true); 
     } 

     ZipFile.ExtractToDirectory(pluginsZipFilePath, tempPath); 

     // Moves all plugins to appropriate folder if version is greater 
     // to the version in place 
     foreach (var fi in new DirectoryInfo(tempPath).GetFiles()) 
     { 
      if (fi.Extension.ToLower() != ".dll") 
      { 
       continue; 
      } 

      var targetFile = Path.Combine(Paths.PluginsPath, fi.Name); 
      if (File.Exists(targetFile)) 
      { 
       if (fi.GetAssemblyVersion() > new FileInfo(targetFile).GetAssemblyVersion()) 
       { 
        // If version to deploy is newer than current version 
        // Delete current version and copy the new one 

        // FAILS HERE 

        File.Copy(fi.FullName, targetFile, true); 
       } 
      } 
      else 
      { 
       File.Move(fi.FullName, targetFile); 
      } 
     } 

     // Delete temporary folder 
     Directory.Delete(tempPath, true); 
    } 
+2

코드를 공유하십시오. –

+0

슬프게도 우리는 실제로 그것으로부터 추측 할 수 없습니다. – BugFinder

+0

죄송합니다. 많은 코드를 넣고 싶지는 않지만 확실히 도움이 될 것 같습니다. 이 메서드는 Main 메서드에서 호출 된 첫 번째 메서드입니다. –

답변

3

체크 코드의 일부를 사용 GetAssemblyVersion() 방법의 구현 :

if (File.Exists(targetFile)) 
{ 
    if (fi.GetAssemblyVersion() > new FileInfo(targetFile).GetAssemblyVersion()) 
    { 
    // If version to deploy is newer than current version 
    // Delete current version and copy the new one 

    // FAILS HERE 

    File.Copy(fi.FullName, targetFile, true); 
    } 
} 

fi 변수 FileInfo 입력 갖는다는 GetAssemblyVersion() 내선 방법처럼 보인다. 파일에서 어셈블리 버전을 검색하는 방법을 확인해야합니다. 이 메서드가 어셈블리를로드하면 파일을 언로드하여 언로드해야합니다.

별도의 AppDomain은 어셈블리를로드해야하고 작업을 수행 한 후 언로드해야하는 경우 유용합니다. 여기 GetAssemblyVersion 방법의 구현 :

public static Version GetAssemblyVersion(this FileInfo fi) 
{ 
    AppDomain checkFileDomain = AppDomain.CreateDomain("DomainToCheckFileVersion"); 
    Assembly assembly = checkFileDomain.Load(new AssemblyName {CodeBase = fi.FullName}); 
    Version fileVersion = assembly.GetName().Version; 
    AppDomain.Unload(checkFileDomain); 
    return fileVersion; 
} 

당신의 AppDomain에로드 어셈블리없이 어셈블리 버전을 검색 할 수있는 GetAssemblyVersion() 다음과 같은 구현입니다. Thnx @usterdev 힌트.

public static Version GetAssemblyVersion(this FileInfo fi) 
{ 
    return AssemblyName.GetAssemblyName(fi.FullName).Version; 
} 
0

아래 문은 파일

destStream.Lock(0, sourceStream.Length); 

를 잠그는 것을 피할 수있는 방법 그러나 그 후 당신은 잠금 해제를 havent 파일. 아마도 그것은 당신의 문제의 원인입니다.

+0

감사하지만 유감 스럽지만 이는 원인이 아닙니다. 복사 후에 잠금을 제거하거나 잠금 해제를 추가해도 문제가 해결되지 않습니다. –

0

프로그램을 실제로로드했는지 확인하기 시작할 것입니다.

이 개 제안 :

1 - AssemblyLoad 이벤트에 등록, 홈페이지의 첫 번째 줄에서 이벤트 처리기에서로드 어셈블리를 덤프 -

static void DumpLoadedAssemblies() 
{ 
    var ads = AppDomain.CurrentDomain.GetAssemblies(); 
    Console.WriteLine(ads.Length); 
    foreach (var ad in ads) 
    { 
     Console.WriteLine(ad.FullName); 
     // maybe this can be helpful as well 
     foreach (var f in ad.GetFiles()) 
      Console.WriteLine(f.Name); 
     Console.WriteLine("*******"); 
    } 
} 

이 당신의 InitializePluginsFolder 호출하기 전에이 같은 메서드를 호출

public static void Main() 
{ 
    AppDomain.CurrentDomain.AssemblyLoad += OnAssemlyLoad; 
    ... 
} 
static void OnAssemlyLoad(object sender, AssemblyLoadEventArgs args) 
{ 
    Console.WriteLine("Assembly Loaded: " + args.LoadedAssembly.FullName); 
} 
1

당신은, 당신은 그것에서 버전을 얻으려면 도메인에 Assembly로드되지 않도록해야 그렇지 않으면 파일이 잠긴다.AssemblyName.GetAssemblyName() 정적 메소드 (see MSDN)를 사용하여

는 어셈블리 파일은로드 버전은 읽기 다음 를 언로드하지만 도메인에 추가되지 않습니다. 여기

FileInfo에 대한 확장이 그렇게 :

public static Version GetAssemblyVersion(this FileInfo fi) 
{ 
    AssemblyName an = AssemblyName.GetAssemblyName(fi.FullName); 
    return an.Version; 
} 
0

당신은 확실히 AssemblyName.GetAssemblyName를 사용하여 어셈블리를로드, 불행하게도 .NET로드 어셈블리없이 조립 메타 데이터를 확인하는 더 전통적인 방법이 없습니다. 이를 방지하려면 다음을 수행 할 수 있습니다 니키타 제안으로 분리 된 응용 프로그램 도메인에서

  1. 로드 어셈블리, 내가 추가 할 수 있습니다 ReflectionOnlyLoad
  2. 으로로드 또는 반사경 그냥 완전성에 대한
  3. 을처럼 Mono.Cecil 라이브러리를 사용하여 어셈블리 버전을 얻을 : 실제로 어셈블리 파일을 두 단계로 잠그지 않고 동일한 AppDomain에 어셈블리를로드 할 수 있습니다. 파일 내용을 byte []로 읽고 Assembly.Load (byte [] rawAssembly)를 사용하지만이 방법은 심각한 "로드 컨텍스트"문제를 가지고 있으며 몇 가지 로드 된 어셈블리 :