programing

빌드의 일부로 Xml 직렬화 어셈블리 생성

javamemo 2023. 11. 6. 21:35
반응형

빌드의 일부로 Xml 직렬화 어셈블리 생성

이 코드는 FileNotFoundException을 생성하지만 최종적으로는 문제없이 실행됩니다.

void ReadXml()
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    //...
}

여기 예외가 있습니다.


'System' 유형의 첫 번째 기회 예외입니다.mscorlib.dll에서 'IO.FileNotFoundException'이(가) 발생했습니다.

추가 정보:'MyAssembly' 파일 또는 어셈블리를 로드할 수 없습니다.Xml Serializer, 버전=1.4.3190.15950, Culture=neutral, PublicKeyToken= null' 또는 해당 종속성 중 하나입니다.지정한 파일을 찾을 수 없습니다.


프레임워크가 발견되지 않으면 자동으로 직렬화 어셈블리를 생성하는 것으로 보입니다.sgen.exe를 사용하여 수동으로 생성할 수 있어 예외를 완화합니다.

시각 스튜디오에서 XML Serialization 어셈블리를 자동으로 생성하려면 어떻게 해야 합니까?


업데이트: 직렬화 어셈블리 생성:설정에서 아무 것도 하지 않는 것 같습니다.

마틴이 답변에서 설명한 것처럼 프로젝트 속성을 통해 직렬화 어셈블리의 생성을 켜는 것은 SGen 작업이 추가되고 있기 때문에 충분하지 않습니다./proxytypessgen으로 전환합니다.exe 명령행입니다.

Microsoft는 문서화된 MSBuild 속성을 가지고 있으며 이 속성을 사용하지 않도록 설정할 수 있습니다./proxytypesswitch를 실행하면 어셈블리에 프록시 유형이 없더라도 SGen Task에서 직렬화 어셈블리를 생성합니다.

SGenUse프록시 유형

SGen.exe에서 프록시 유형을 생성해야 하는지 여부를 나타내는 부울 값입니다.SGen 대상은 이 속성을 사용하여 UseProxyTypes 플래그를 설정합니다.이 속성은 true로 기본 설정되며 이를 변경할 UI가 없습니다.웹 서비스가 아닌 유형에 대한 직렬화 어셈블리를 생성하려면 이 속성을 프로젝트 파일에 추가하고 Microsoft를 가져오기 전에 false로 설정합니다.흔한.대상 또는 C#/VB.대상

문서에서 알 수 있듯이 프로젝트 파일을 수작업으로 수정해야 하지만 추가할 수 있습니다.SGenUseProxyTypes생성이 가능하도록 구성에 속성을 지정합니다.프로젝트 파일 구성은 결국 다음과 같은 모양을(를)

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <!-- Snip... -->
    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>
    <SGenUseProxyTypes>false</SGenUseProxyTypes>
  </PropertyGroup>

이것이 제가 제 안에 있는 MSBUILD 스크립트를 수정해서 할 수 있었던 방법입니다.CSPROJ 파일:

먼저, 당신의 것을 엽니다.프로젝트가 아닌 파일로 CSPROJ 파일.프로젝트 태그가 닫히기 직전에 주석이 달린 코드를 찾을 때까지 파일 맨 아래로 스크롤합니다.

<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->

이제 AfterBuild 대상을 삽입하여 기존 XmlSerializer를 삭제하고 SGen을 우리 고유의 것으로 삭제합니다.

<Target Name="AfterBuild" DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource" Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)" Outputs="$(OutputPath)$(_SGenDllName)">
   <!-- Delete the file because I can't figure out how to force the SGen task. -->
   <Delete
     Files="$(TargetDir)$(TargetName).XmlSerializers.dll"
     ContinueOnError="true" />
   <SGen
     BuildAssemblyName="$(TargetFileName)"
     BuildAssemblyPath="$(OutputPath)"
     References="@(ReferencePath)"
     ShouldGenerateSerializer="true"
     UseProxyTypes="false"
     KeyContainer="$(KeyContainerName)"
     KeyFile="$(KeyOriginatorFile)"
     DelaySign="$(DelaySign)"
     ToolPath="$(TargetFrameworkSDKToolsDirectory)"
     Platform="$(Platform)">
      <Output
       TaskParameter="SerializationAssembly"
       ItemName="SerializationAssembly" />
   </SGen>
</Target>

저는 그것이 좋습니다.

이 질문에 대한 다른 답변에서는 프로젝트 속성->빌드->직렬화 어셈블리 생성 설정에 대해 이미 언급했지만, 기본적으로 프로젝트에 "XML 웹 서비스 프록시 유형"이 있는 경우에만 어셈블리를 생성합니다.

Visual Studio의 정확한 동작을 이해하는 가장 좋은 방법은 C:\ 내에서 Generate Serialization Assembly 대상을 조사하는 것입니다.WINDOWS\Microsoft.NET\Framework\v2.0.50727**Microsoft.Common.targets** 파일입니다.

Visual Studio Output 창에서 이 빌드 작업의 결과를 확인하고 Show output from: 드롭다운 상자에서 Build를 선택할 수 있습니다.당신은 뭔가를 볼 수 있을 겁니다.

C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin\sgen.exe/assembly:D:\Temp\LibraryA\obj\Debug\LibraryA.dll /proxytypes /reference:../compiler:/delaysign - 라이브러리 A -> D:\Temp\LibraryA\bin\Debug\Library A.dll

여기서 핵심은 /proxytype 스위치입니다.XML Serializer Generator Tool(Sgen.exe)의 다양한 스위치에 대해 읽을 수 있습니다.

MSBuild에 익숙한 경우 GenerateSerializationAssemblys 대상을 사용자 지정하여 SGen 작업이 참이 아닌 UseProxyTypes="false" 속성을 갖도록 할 수 있지만 Visual Studio/MSBuild 시스템 사용자 지정과 관련된 모든 책임을 져야 합니다.또는 빌드 프로세스를 확장하여 /proxytype 스위치 없이 수동으로 SGen을 호출할 수도 있습니다.

SGen에 대한 설명서를 읽어보면 Microsoft가 이 기능의 사용을 제한하고자 했다는 것을 알 수 있습니다.이 주제에 대한 잡음의 양을 고려할 때, Microsoft가 비주얼 스튜디오 경험을 문서화하는 데 큰 역할을 하지 못했다는 것은 분명합니다.이 문제에 대한 피드백 연결 항목도 있는데 반응이 좋지 않습니다.

새 sgen 작업 정의를 생성하면 파리가 깨집니다.필요한 변수를 설정하여 작업이 의도한 대로 작동되도록 합니다.어쨌든 마이크로소프트 문서에는 중요한 정보가 몇 가지 부족합니다.

직렬화 어셈블리를 생성하기 위한 단계

(http://msdn.microsoft.com/en-us/library/ff798449.aspx) 의 일부와 함께)

  1. Visual Studio 2010의 솔루션 탐색기에서 직렬화 어셈블리를 생성할 프로젝트를 마우스 오른쪽 버튼으로 누른 다음 프로젝트 언로드를 누르십시오.
  2. 솔루션 탐색기에서 직렬화 어셈블리를 생성할 프로젝트를 마우스 오른쪽 버튼으로 누른 다음 편집 .csproj를 누르십시오.
  3. .csproj 파일에서, 그 직후에<TargetFrameworkVersion>v?.?</TargetFrameworkVersion>element, 다음 element를 추가합니다.

    <SGenUseProxyTypes>false</SGenUseProxyTypes> <SGenPlatformTarget>$(Platform)</SGenPlatformTarget>

  4. .csproj 파일에서, 각 플랫폼 구성에서

    예.<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">

    다음 행을 추가합니다.

    <GenerateSerializationAssemblies>On</GenerateSerializationAssemblies>

  5. .csproj 파일을 저장하고 닫습니다.

  6. 솔루션 탐색기에서 방금 편집한 프로젝트를 마우스 오른쪽 단추로 클릭한 다음 프로젝트 다시 로드를 클릭합니다.

이 절차에서는 출력 폴더에 .xmlSerializers.dll이라는 이름의 어셈블리를 추가로 생성합니다.솔루션과 함께 이 어셈블리를 배포해야 합니다.


설명.

프록시 유형에 대한 SGen은 기본적으로 "모든 CPU"에 대해 생성됩니다.프로젝트 파일에 해당 변수를 설정하지 않으면 이 문제가 발생합니다.

SGenPlatformTarget은 PlatformTarget과 일치해야 합니다.저는 이것이 프로젝트 템플릿의 버그라고 생각하는 경향이 있습니다.sgen target 플랫폼이 프로젝트 플랫폼과 다른 이유는 무엇입니까?그러면 런타임 예외가 발생합니다.

0x80131040:위치한 어셈블리의 매니페스트 정의가 어셈블리 참조와 일치하지 않습니다.

프로젝트 파일을 분석하여 msbuild 작업 정의를 찾을 수 있습니다.

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

여기서 MSBuildToolsPath는 사용자의<TargetFrameworkVersion> http://msdn.microsoft.com/en-us/library/bb397428.aspx

TargetFrameworkVersion 4.0에 대한 SGen 작업 정의 내부를 확인합니다.

Windows 설치 경로\Microsoft.NET\Framework\v4.0.30319\Microsoft.CS샤프타겟

프로젝트 파일에서 자유롭게 설정할 수 있는 $(SGenPlatformTarget)과 같은 문서화되지 않은 변수를 보려면

<Target
    Name="GenerateSerializationAssemblies"
    Condition="'$(_SGenGenerateSerializationAssembliesConfig)' == 'On' or ('@(WebReferenceUrl)'!='' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto')"
    DependsOnTargets="AssignTargetPaths;Compile;ResolveKeySource"
    Inputs="$(MSBuildAllProjects);@(IntermediateAssembly)"
    Outputs="$(IntermediateOutputPath)$(_SGenDllName)">

    <SGen
        BuildAssemblyName="$(TargetFileName)"
        BuildAssemblyPath="$(IntermediateOutputPath)"
        References="@(ReferencePath)"
        ShouldGenerateSerializer="$(SGenShouldGenerateSerializer)"
        UseProxyTypes="$(SGenUseProxyTypes)"
        KeyContainer="$(KeyContainerName)"
        KeyFile="$(KeyOriginatorFile)"
        DelaySign="$(DelaySign)"
        ToolPath="$(SGenToolPath)"
        SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
        EnvironmentVariables="$(SGenEnvironment)"
        SerializationAssembly="$(IntermediateOutputPath)$(_SGenDllName)"
        Platform="$(SGenPlatformTarget)"
        Types="$(SGenSerializationTypes)">
            <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly"/>
    </SGen>
</Target>

이전에 모든 것이 정상적으로 작동한 후에 다른 사람이 갑자기 이 문제에 직면한 경우:제 경우에는 옵션 메뉴(옵션 -> 디버깅)에서 "Enable Just My Code (Managed Only)" 확인란을 선택 해제하는 것과 관련이 있었습니다(설치 후 자동으로 꺼짐).NET Reflector).

편집: 물론 이 예외는 이전에도 발생했지만 "내 코드만 활성화"가 해제되면 디버깅 어시스턴트(활성화된 경우)가 이 시점에서 중지됩니다.

파티에 좀 늦었지만, 이전 답변은 같이 하기가 어려웠습니다.특히 비주얼 스튜디오는 프로젝트의 속성을 보려고 할 때마다 충돌합니다.이것은 csproj 파일을 읽는 방법을 더 이상 이해하지 못했기 때문이라고 생각합니다.그럼요...

빌드 후 이벤트 명령줄에 다음을 추가합니다.

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe" "$(TargetPath)" /force

이렇게 하면 디버그 또는 릴리스용 프로젝트를 빌드할 때마다 sgen.exe를 직접 사용하여 Xml Serialization 어셈블리를 재구성할 수 있습니다.

용액의 속성을 조사합니다.하단의 빌드 탭에는 "직렬화 어셈블리 생성"이라는 드롭다운이 있습니다.

Brain backup에서 제공하는 솔루션과 약간 다른 솔루션은 플랫폼을 사용해야 하는 위치를 직접 지정하는 것입니다.

<!-- Check the platform target value and if present use that for a correct *.XmlSerializer.dll platform setup (default is MSIL)-->
<PropertyGroup Condition=" '$(PlatformTarget)'=='' ">
  <SGenPlatform>$(Platform)</SGenPlatform>
</PropertyGroup>
<PropertyGroup Condition=" '$(PlatformTarget)'!='' ">
  <SGenPlatform>$(PlatformTarget)</SGenPlatform>
</PropertyGroup>

<!-- Delete the file because I can't figure out how to force the SGen task. -->
<Delete Files="$(TargetDir)$(TargetName).XmlSerializers.dll" ContinueOnError="true" />
<SGen
  BuildAssemblyName="$(TargetFileName)"
  BuildAssemblyPath="$(OutputPath)"
  References="@(ReferencePath)"
  ShouldGenerateSerializer="true"
  UseProxyTypes="false"
  KeyContainer="$(KeyContainerName)"
  KeyFile="$(KeyOriginatorFile)"
  DelaySign="$(DelaySign)"
  ToolPath="$(SGenToolPath)"
  SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)"
  EnvironmentVariables="$(SGenEnvironment)"
  Platform="$(SGenPlatform)">
  <Output TaskParameter="SerializationAssembly" ItemName="SerializationAssembly" />
</SGen>

누구든지 그렇게 하는 것에 관심이 있습니다.NET Core - MS 문서 https://learn.microsoft.com/en-us/dotnet/core/additional-tools/xml-serializer-generator 을 참조하십시오.

기본적으로, 당신의 프로젝트에 nuget 패키지 하나만 추가하면 됩니다.

언급URL : https://stackoverflow.com/questions/134224/generating-an-xml-serialization-assembly-as-part-of-my-build

반응형