2013-03-05 7 views
7

이 문제는 며칠 동안 두통을 불러 일으켰으며 그 이유를 찾을 수 없습니다. 나는 이것이 나의 기계에 특별한 환경 문제이지만, 여전히 시험 문제를 일으키는 것이 확실하다.64 비트 유형 라이브러리와 32 비트 유형의 라이브러리가 동기화되지 않음

Visual Studio 2010 Professional을 사용하여 C#으로 DLL을 만들고 있습니다. 버전 1은 아래에 있습니다.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace TestCOM 
{ 
    [ClassInterface(ClassInterfaceType.AutoDual)] 
    [System.Runtime.InteropServices.ComVisible(true)] 
    [System.Runtime.InteropServices.ProgId("TestCOM.Class1")] 
    [System.Runtime.InteropServices.Guid("803A1B2F-1CDA-4571-9084-87500388693B")] 
    public class Class1 
    { 
     public void showMessage() 
     { 
      MessageBox.Show("Hello from TextCom"); 
     } 

    } 
} 

이 어셈블리는 잘 컴파일되고 모든 것이 좋습니다. 다음 스크립트를 COM 객체로 등록하기 위해 실행합니다 (처음에는 32 비트, 64 비트).

C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe TestCOM.dll /codebase /nologo /tlb:TestCOM32.tlb 
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe TestCOM.dll /codebase /nologo /tlb:TestCOM64.tlb 

그리고 나서 다음 스크립트를 사용하여 테스트하십시오.

dim tc 
set tc = CreateObject("TestCOM.Class1") 
tc.showMessage() 

I는 스크립트를 테스트 csript를 사용하므로, I는 사용되는 비트 깊이를 제어 할 수있다 - I은 64 비트와 32 비트 번에 한번 테스트. 지금까지 모든 것이 좋습니다. 내가 수정하기 전에

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace TestCOM 
{ 
    [ClassInterface(ClassInterfaceType.AutoDual)] 
    [System.Runtime.InteropServices.ComVisible(true)] 
    [System.Runtime.InteropServices.ProgId("TestCOM.Class1")] 
    [System.Runtime.InteropServices.Guid("803A1B2F-1CDA-4571-9084-87500388693B")] 
    public class Class1 
    { 
     public void showMessage() 
     { 
      MessageBox.Show("Hello from TextCom"); 
     } 

     public void HelloWorld() 
     { 
      MessageBox.Show("Hello World!!"); 
     } 

    } 
} 

을 다음과 같이 함수를 추가하려면 원본 어셈블리를 수정 이제

는, 나는 "RegAsm을/등록 취소"를 사용하여 라이브러리를 등록 해제하며 등록 성공적으로 모든 유형을보고했다.

라이브러리를 등록하면 변경 사항이 적용되므로 원래 테스트 스크립트가 완벽하게 작동합니다. 새로운 HelloWorld 함수를 호출하도록 테스트 스크립트를 확장한다면;

32 비트 스크립트에서 완벽하게 작동합니다. 64 비트 스크립트에서 TestCOM.Class1 개체에 대한 함수가 없다는 메시지가 표시됩니다.

가능한 모든 방법을 시도했지만 32 비트에서 새 기능을 사용할 수있는 이유를 확인할 수 없습니다. 발신자는 아니지만 64 비트 호출은 아닙니다.

내가 뭘 잘못하고 있니? 64 비트 항목에 대해 어딘가에 캐시가 있습니까, 아니면 레지스트리 설정이 변경 될 필요가 있습니까?

맑음; 2. 등록 스크립트를 사용하여 64 3. 시험에 대해 한 번 32 번, RegAsm을을 사용하여 1. 빌드 어셈블리 - 모든 2 단계 7에 따라 6. 등록을 재 구축 5. 수정합니다 4. 등록 취소 라이브러리 작동 테스트는 32 비트에서 작동하지만 64에서는 작동하지 않습니다. Wtf?

답변

2

분명히 당신은 DLL 지옥으로 고통 받고 있습니다. 항상 COM으로 인해 DLL의 이전 버전이로드되고 있습니다. 귀하의 GAC는 초기 실험에 의해 오염되었을 수 있었으며, 항상 GACed 버전을 먼저 발견 할 것입니다. [Guid]를 지정하여 악화 시키므로 새로운 클래스가 이전 클래스와 동일하게 보이도록 만듭니다 (동일하지 않더라도). COM이 새 버전의 클래스를 찾을 수 없다는 것을 COM에서 방지합니다.

가장 안정적이지만 시끄 럽지만 DLL의 출처를 확인하는 방법은 SysInterals의 ProcMon 유틸리티를 사용하는 것입니다. 레지스트리 키를 읽고 DLL을로드하는 것을 보게 될 것입니다. 어떤 디렉토리에서 왔는지 확인할 수 있습니다. GAC가 아닌지 확인하고 gacutil/u를 사용하여 제거한 다음 파일의 타임 스탬프를 확인하여 재구성했는지 확인하십시오.

+0

당신은 절대 전설입니다. 어떤 이유에서든 dll의 초기 빌드 복사본이 c : \ windows \ system32에 있었던 것 같습니다. 해당 복사본을 삭제하면 문제가 즉시 해결되고 다시 등록 할 필요가 없습니다. 감사합니다. procmon을 사용하여 어떤 일이 발생했는지 결코 알지 못했습니다. 최종 질문 중 하나는 내가 GUID를 지정해서는 안된다는 말씀입니까? 항상 네가해야한다고 들었어? – DFriend