visual-studio - 탐색기 - 프로젝트 를 빌드 한 후 다시 시도 하거나




솔루션에서 프로젝트 종속성을 사용하는 경우 MSBuild가 참조(DLL 파일)를 복사하지 않습니다. (12)

내 Visual Studio 솔루션 (모든 3.5 .NET을 대상으로하는)에서 네 개의 프로젝트가 있습니다. 내 문제에 대해서만이 두 가지가 중요합니다.

  1. MyBaseProject <-이 클래스 라이브러리는 타사 DLL 파일 (elmah.dll)을 참조합니다.
  2. MyWebProject1 <-이 웹 응용 프로그램 프로젝트에는 MyBaseProject에 대한 참조가 있습니다.

"Add reference ..."→ "Browse"탭 → "elmah.dll"을 클릭하여 Visual Studio 2008의 MyBaseProject 에 elmah.dll 참조를 추가했습니다.

Elmah Reference의 속성은 다음과 같습니다.

  • 별칭 - 글로벌
  • 로컬 복사 - true
  • 문화 -
  • 설명 - ASP.NET 용 로깅 모듈 및 처리기 (ELMAH) 오류
  • 파일 형식 - 어셈블리
  • 경로 - D : \ webs \ otherfolder \ _myPath \ __ tools \ elmah \ Elmah.dll
  • 해결됨 - 참
  • 런타임 버전 - v2.0.50727
  • 지정된 버전 - 거짓
  • 강력한 이름 - 거짓
  • 버전 - 1.0.11211.0

MyWebProject1에서 "참조 추가 ..."→ "프로젝트"탭 → "MyBaseProject"를 선택하여 MyBaseProject 프로젝트에 대한 참조를 추가했습니다. 이 참조의 속성은 다음 멤버를 제외하고 동일합니다.

  • 설명 -
  • 경로 - D : \ webs \ CMS \ MyBaseProject \ bin \ Debug \ MyBaseProject.dll
  • 버전 - 1.0.0.0

Visual Studio 에서 빌드를 실행하면 elmah.dll 파일이 MyBaseProject.dll과 함께 MyWebProject1의 bin 디렉토리에 복사됩니다!

그러나 정리하고 솔루션 (D : \ webs \ CMS> C : \ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe / t : ReBuild / p : Configuration = Debug MyProject.sln을 통해 MSBuild 를 실행하는 경우) ) elmah.dll은 MyWebProject1의 bin 디렉토리에 없지만 빌드 자체에는 경고 나 오류가 없습니다!

나는 이미 MyBaseProject의 .csproj에 값 "true"(Visual Studio의 " copy local "에 대한 별칭이어야 함)가있는 private 요소가 포함되어 있는지 확인했습니다.

<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
    **<Private>true</Private>**
</Reference>

Visual Studio에서 "로컬 복사"라고 말했지만 기본적으로 .csproj의 xml에는 private 태그가 표시되지 않았습니다. "로컬 복사"를 false로 저장 - 저장하고 다시 true로 설정 - 저장하십시오!)

MSBuild의 문제점은 무엇입니까? MyWebProject1의 bin에 복사 된 (elmah.dll) 참조를 얻으려면 어떻게해야합니까?

모든 프로젝트의 postbuild 명령에 postbuild 복사 작업을 추가하고 싶지 않습니다! (MyBaseProject에 의존하는 많은 프로젝트가 있다고 상상해보십시오!)


Alex Burtsev가 XAML 리소스 사전이나 제 경우에만 사용되는 주석에 언급 한 것처럼, XAML에서만 사용되고 코드 뒤에는 사용되지 않는 것이 MSBuild에서 '사용 중'으로 간주되지 않습니다.

따라서 일부 코드 숨김에서 어셈블리의 클래스 / 구성 요소에 대한 더미 참조를 새로 작성하는 것만으로도 어셈블리가 실제로 사용되었다는 것을 MSBuild에서 납득시킬 수있었습니다.


Visual Studio와 MsBuild를 빌드 할 때 왜 다른지 확실하지 않지만 MsBuild와 Visual Studio에서이 문제가 발생했을 때 무엇을 발견 했습니까?

설명

샘플 시나리오의 경우 프로젝트 X, 어셈블리 A 및 어셈블리 B가 있다고 가정 해 봅시다. 어셈블리 A는 어셈블리 B를 참조하므로 프로젝트 X는 A와 B 모두에 대한 참조를 포함합니다. 또한 프로젝트 X는 어셈블리 A를 참조하는 코드를 포함합니다 (예 : A. SomeFunction ()). 이제 프로젝트 X를 참조하는 새 프로젝트 Y를 만듭니다.

따라서 종속성 체인은 다음과 같습니다. Y => X => A => B

Visual Studio / MSBuild는 현명하고 프로젝트 X가 필요로하는 것으로 발견 한 프로젝트 Y에만 참조를 가져옵니다. 프로젝트 Y가 어셈블리 B (예 : B.SomeFunction ())를 명시 적으로 사용하는 코드를 실제로 포함하지 않기 때문에 VS / MSBuild가 B가 필요하다는 것을 감지하지 못하기 때문에 문제가 발생합니다 X로 복사하여 프로젝트 Y의 bin 디렉토리에 복사하지 않습니다. X 및 A 어셈블리 만 복사합니다.

해결책

이 문제를 해결할 수있는 두 가지 옵션이 있습니다. 둘 다 어셈블리 B가 프로젝트 Y의 bin 디렉토리에 복사됩니다.

  1. 프로젝트 Y의 어셈블리 B에 대한 참조를 추가합니다.
  2. 어셈블리 B를 사용하는 프로젝트 X의 파일에 더미 코드 추가

개인적으로 나는 두 가지 이유로 옵션 2를 선호합니다.

  1. 나중에 프로젝트 X를 참조하는 다른 프로젝트를 추가하는 경우 옵션 1과 마찬가지로 어셈블리 B에 대한 참조도 포함해야 함을 기억할 필요가 없습니다.
  2. 더미 코드가 왜 필요하고 그것을 제거하지 않아야하는지에 대해 명시 적으로 설명 할 수 있습니다. 따라서 누군가 실수로 코드를 삭제하면 (예 : 사용하지 않는 코드를 찾는 리팩터링 도구로 말하면) 코드가 필요하다는 것을 소스 컨트롤에서 쉽게보고 복원 할 수 있습니다. 옵션 1을 사용하고 누군가 리팩토링 도구를 사용하여 사용하지 않는 참조를 정리하면 주석이 없습니다. .csproj 파일에서 참조가 제거 된 것을 볼 수 있습니다.

다음은이 상황이 발생할 때 일반적으로 추가하는 "더미 코드"의 샘플입니다.

    // DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
    private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
    {
        // Assembly A is used by this file, and that assembly depends on assembly B,
        // but this project does not have any code that explicitly references assembly B. Therefore, when another project references
        // this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
        // assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
        // gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
        var dummyType = typeof(B.SomeClass);
        Console.WriteLine(dummyType.FullName);
    }

나는 같은 문제가 있었고 dll은 동적으로로드 된 참조였습니다. 이 문제를 해결하기 위해 dll의 네임 스페이스에 "using"을 추가했습니다. 이제 dll은 출력 폴더에 복사됩니다.


나는 똑같은 문제가 있었다.

프로젝트의 프레임 워크 버전이 참조 할 때 사용한 DLL의 프레임 워크 버전과 같은지 확인하십시오.

필자의 경우 클라이언트는 "Framework 4 Client"를 사용하여 컴파일되었고 DLL은 "Framework 4"에있었습니다.


나는 이걸 그냥 처리해. 참조 속성으로 이동하여 다음을 수행하십시오.

Set "Copy local = false"
Save
Set "Copy local = true"
Save

그리고 그게 다야.

Visual Studio 2010은 처음에 참조 태그에 <private>True</private> 를 넣지 않고 "copy local"을 false로 설정하면 태그가 만들어집니다. 이후에는 그에 따라 true와 false로 설정됩니다.


내가 직면 한 문제는 도서관 프로젝트에 의존하는 프로젝트가 있다는 것입니다. 빌드하려면 다음 단계를 수행했습니다.

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package

물론 나는 빈에있는 라이브러리의 dll 파일을 잃어 버렸고 가장 중요한 것은 패키지 zip 파일에 없다는 것을 의미했습니다. 나는 이것이 완벽하게 작동한다는 것을 발견했다.

msbuild.exe myproject.vbproj /T:Rebuild;Package

나는 왜이 작품이 왜 처음에는 없었는지 전혀 모른다. 그러나 도움이되는 희망.


또 다른 시나리오는 Visual Studio에서 이전 "웹 사이트"프로젝트 유형을 사용하는 경우입니다. 해당 프로젝트 유형의 경우 자체 디렉토리 구조 (현재 폴더 및 아래쪽) 외부에있는 .dll을 참조 할 수 없습니다. 따라서 위의 대답에서 디렉토리 구조가 다음과 같다고 가정 해 보겠습니다.

ProjectX와 ProjectY는 부모 / 자식 디렉터리이고 ProjectX는 B.dll을 참조하는 A.dll을 참조하며 B.dll은 루트 (패키지)의 Nuget 패키지, A와 같은 디렉터리 구조 외부에 있습니다. dll은 포함되지만 B.dll은 포함되지 않습니다.


방금 비슷한 문제가 발생했습니다. Visual Studio 2010을 사용하여 컴파일 할 때 DLL 파일이 bin 폴더에 포함되었습니다. 그러나 MSBuild를 사용하여 컴파일 할 때 타사 DLL 파일은 포함되지 않았습니다.

매우 실망합니다. 내가 해결 한 방법은 직접 웹 프로젝트에 패키지를 사용하지 않더라도 NuGet 참조를 패키지에 포함시키는 것입니다.


보세요:

이 MSBuild 포럼 스레드가 시작했습니다.

내 임시 솔루션 / 해결 방법을 찾을 수 있습니다!

(MyBaseProject는 MyWebProject1의 bin으로 복사되는 elmah.dll에 대한 elmah.dll의 클래스를 참조하는 코드가 필요합니다!)


빌드 중에 사용되지 않는 어셈블리를 참조하는 것은 올바른 방법이 아닙니다. 빌드 파일을 보강하여 추가 파일을 복사해야합니다. 사후 빌드 이벤트를 사용하거나 속성 그룹을 업데이트하십시오.

일부 사례는 다른 게시물에서 찾을 수 있습니다.


이를 위해서는 .targets 파일을 프로젝트에 추가하고 프로젝트의 includes 섹션에 포함되도록 설정해야합니다.

절차에 대한 내 대답을 참조하십시오.


코드에서 직접 어셈블리를 사용하지 않는다면 Visual Studio는 유용하지 않은 것을 감지하여 사용되지 않고 출력에 포함시키지 않습니다. Visual Studio와 MSBuild간에 다른 동작이 나타나는 이유가 확실하지 않습니다. 두 가지 모두에 대해 빌드 출력을 진단으로 설정하고 결과가 다른 곳을 비교해 볼 수 있습니다.

elmah.dll 참조에 관해서는 코드에서 직접 참조하지 않는다면 프로젝트에 항목으로 추가하고 Build Action을 Content 설정하고 Output Directory에 Copy를 Always 설정할 수 있습니다.





project