2012-04-04 5 views
0

메서드를 노출하는 WCF 서비스가 있습니다. 클라이언트가이 메소드를 호출하면 다음이 발생합니다 :이 방법은 일부 처리는 위의 DLL이없는 경우는 이미 WCF 응용 프로그램에서 호출 할 때 CompileAssemblyFromSource 문제가 발생했습니다.

  • , 그것은 C 번호가 생성하는 경우 어셈블리를로드하려고
  • 을 수행

    1. 을 코드에서는 CSharpCodeProvider의 CompileAssemblyFromSource의 API를 그런 다음 지금 방금 생성 된 어셈블리를

    에게 문제를로드

  • 를 사용하여 컴파일합니다. 메서드를 처음 호출 할 때 3 번 지점에서 어셈블리를 생성하고 CompilerResults.CompiledAssembly를 통해 어셈블리 참조를 반환하려고하면 예외를 찾을 수없는 파일을 throw합니다. 그러나 명확하게 어셈블리가 지정된 위치에서 생성 된 것을 볼 수 있으며 다른 응용 프로그램에서도 어셈블리를 열 수 있습니다.

    클라이언트를 통해 다시 메서드를 호출하면 어셈블리를로드 할 수 있습니다 (이전 호출의 결과로 성공적으로 생성되었습니다). 나머지 작업 집합을 계속 수행합니다. 어셈블리가 거기에 있지 않을 때만 그것을 생성하고 즉시로드하기 위해 진행됩니다. 어떤 아이디어? 나는 web.config를 가지고 놀아 보았고, 가장을 true/false로 변경했다. 나는이 웹 응용 프로그램을 실행하는 별도의 응용 프로그램 풀을 가지고 로컬 시스템에서 로컬 시스템으로 응용 프로그램 풀의 ID를 변경하려고 시도했지만 관리 권한이 있지만 운이없는 Windows 로그온 자격 증명을 제공했습니다.

    도움을 주시면 감사하겠습니다.

  • 답변

    0

    감사합니다 귀하의 입력 user1796307 :

    는에 쓸 적당한 폴더를 찾을 수 있습니다. 이 문제는 해결했지만 업데이트하는 것을 잊었습니다. 모든 사람의 이익을 위해 그것을 나눠줍니다. 그것은 .NET Fusion이었습니다. 어셈블리로드 경로를 캐시하고 동일한 위치에서 이전로드가 실패한 경우 어셈블리로드를 시도하지 않습니다. 즉 :

    if (Assembly.Load("C:\xyz.dll") == null) 
    { 
        Compile("C:\xyz.dll"); // Now the dll exists 
        Assembly.Load("C:\xyz.dll"); // this will still fail 
    } 
    
    
    The solution is to change it as: 
    
        if (!File.Exists("C:\xyz.dll") 
    { 
        Compile("C:\xyz.dll"); // Now the dll exists 
        Assembly.Load("C:\xyz.dll"); // this will now work 
    
    } 
    
    1

    어셈블리를 생성 하시겠습니까? 나는 생성 된 .dll을 찾을 수 없다는 것을 제외하면 같은 문제가있다. 처음에는 폴더에 쓸 수 없다고 의심되어 이제 CreateDirectory을 호출하고 폴더가 쓰기 가능하다는 것을 보여주는 텍스트 파일을 삭제합니다.

    어쨌든, 동일한 문제, 성공하지 못했습니다. 아무도이 문제를 안고있는 건가요? 나는 마이크로 소프트의 PDB의 단계별로 할 수있는 경우 서버 & 볼 원격 디버깅거야

    ...

    - 편집 -

    마이크로 소프트의 코드를 단계별 필요가 없습니다. 나는 CompilerResults의 Errors 콜렉션을 살펴 보았는데 거기에 1 개의 아이템이있다 : "메타 데이터 파일 'c : \ Windows \ System32 \ aaclient.dll'을 열 수 없다 - '다음과 같은 프로그램을로드하려고 시도했다. 잘못된 형식 ' "

    나는 ... 그것은 윈도우 System32 디렉터리를 usign의 다른 DLL을 데리러 Directory.GetCurrentDirectory()를 얻을 때

    -.

    추가하여이 문제를 해결 - 편집 실행중인 어셈블리 폴더의 참조 :

    CompilerParameters compilerParameters = new CompilerParameters 
        { 
         OutputAssembly = Path.Combine(GeneratedAssembliesFolder, string.Format("{0}.Generated.dll", typeName)) 
        }; 
    string executingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
    string[] dllFiles = Directory.GetFiles(executingDirectory, "*.dll"); 
    compilerParameters.ReferencedAssemblies.AddRange(dllFiles.Select(f => Path.Combine(executingDirectory, f)).ToArray()); 
    IEnumerable<string> exeFiles =Directory.GetFiles(executingDirectory, "*.exe").Where(f => !f.Contains(".vshost.")); 
    compilerParameters.ReferencedAssemblies.AddRange(exeFiles.Select(f => Path.Combine(executingDirectory, f)).ToArray()); 
    

    더 강력하려면 하나의 유효한 관리 코드 어셈블리 인 바이너리에 대한 검사를 추가해야합니다. 이 코드 도 두 GetFiles 호출 사이에 Linq. 유니온을 사용하여 단축 될 수 있습니다.

    private static string generatedAssembliesFolder; 
    
    private static string GeneratedAssembliesFolder 
    { 
        get 
        { 
         if (generatedAssembliesFolder == null) 
         { 
          string[] candidateFolders = new[] 
           { 
            Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.Process), 
            Environment.GetEnvironmentVariable("TMP", EnvironmentVariableTarget.Process), 
            Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.User), 
            Environment.GetEnvironmentVariable("TMP", EnvironmentVariableTarget.User), 
            Environment.GetEnvironmentVariable("TEMP", EnvironmentVariableTarget.Machine), 
            Environment.GetEnvironmentVariable("TMP", EnvironmentVariableTarget.Machine), 
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), 
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 
           }; 
          foreach (string candidateFolder in candidateFolders) 
          { 
           try 
           { 
            if (!Directory.Exists(candidateFolder)) Directory.CreateDirectory(candidateFolder); 
            string testFileName = Path.Combine(candidateFolder, Path.GetRandomFileName()); 
            File.WriteAllBytes(testFileName, new byte[0]); 
            File.Delete(testFileName); 
           } 
           catch (Exception ex) 
           { 
            continue; 
           } 
           generatedAssembliesFolder = candidateFolder; 
    
           break; 
          } 
         } 
         return generatedAssembliesFolder; 
        } 
    } 
    
    관련 문제