C++/WinRT의 새로운 기능What's new in C++/WinRT

이후 버전의 C++/WinRT가 출시됨에 따라 이 항목에서 새롭거나 변경된 기능에 대해 설명합니다.As subsequent versions of C++/WinRT are released, this topic describes what's new, and what's changed.

C++/WinRT 2.0의 새로운 기능 및 변경 내용News, and changes, in C++/WinRT 2.0

C++/WinRT Visual Studio 확장(VSIX), Microsoft.Windows.CppWinRT NuGet 패키지cppwinrt.exe 도구(다운로드 및 설치 방법 포함)에 대한 자세한 내용은 C++/WinRT, XAML, VSIX 확장 및 NuGet 패키지에 대한 Visual Studio 지원을 참조하세요.For more info about the C++/WinRT Visual Studio Extension (VSIX), the Microsoft.Windows.CppWinRT NuGet package, and the the cppwinrt.exe tool—including how to acquire and install them—see Visual Studio support for C++/WinRT, XAML, the VSIX extension, and the NuGet package.

버전 2.0용 C++/WinRT Visual Studio 확장(VSIX)의 변경 내용Changes to the C++/WinRT Visual Studio Extension (VSIX) for version 2.0

  • 이제 디버그 시각화 도우미는 Visual Studio 2019를 지원하며 Visual Studio 2017을 계속 지원합니다.The debug visualizer now supports Visual Studio 2019; as well as continuing to support Visual Studio 2017.
  • 수많은 버그가 수정되었습니다.Numerous bug fixes have been made.

버전 2.0용 Microsoft.Windows.CppWinRT NuGet 패키지의 변경 내용Changes to the Microsoft.Windows.CppWinRT NuGet package for version 2.0

  • 이제 cppwinrt.exe 도구는 Microsoft.Windows.CppWinRT NuGet 패키지에 포함되며 요청 시 각 프로젝트에 대한 플랫폼 프로젝션 헤더를 생성합니다.The cppwinrt.exe tool is now included in the Microsoft.Windows.CppWinRT NuGet package, and the tool generates platfom projection headers for each project on demand. 따라서 cppwinrt.exe 도구는 더 이상 Windows SDK를 사용하지 않지만, 호환성을 위해 계속해서 SDK와 함께 제공됩니다.Consequently, the cppwinrt.exe tool no longer depends on the Windows SDK (although, the tool still ships with the SDK for compatibility reasons).
  • 이제 cppwinrt.exe는 각 플랫폼/ 구성 특정 중간 폴더($IntDir) 아래에 프로젝션 헤더를 생성하여 병렬 빌드를 사용하도록 설정합니다.cppwinrt.exe now generates projection headers under each platform/configuration-specific intermediate folder ($IntDir) to enable parallel builds.
  • 이제 프로젝트 파일을 수동으로 사용자 지정하려는 경우 C++/WinRT 빌드 지원(속성/대상)이 완벽하게 문서화되어 있습니다.The C++/WinRT build support (props/targets) is now fully documented, in case you want to manually customize your project files. Microsoft.Windows.CppWinRT NuGet 패키지 추가 정보를 참조하세요.See the Microsoft.Windows.CppWinRT NuGet package readme.
  • 수많은 버그가 수정되었습니다.Numerous bug fixes have been made.

버전 2.0용 C++/WinRT의 변경 내용Changes to C++/WinRT for version 2.0

오픈 소스Open source

cppwinrt.exe 도구는 Windows 런타임 메타데이터(.winmd) 파일을 사용하며, 메타데이터에 설명된 API를 ‘프로젝션’하는 헤더 파일 기반 표준 C++ 라이브러리를 이 파일에서 생성합니다. The cppwinrt.exe tool takes a Windows Runtime metadata (.winmd) file, and generates from it a header-file-based standard C++ library that projects the APIs described in the metadata. 이 방법으로 C++/WinRT 코드에서 해당 API를 사용할 수 있습니다.That way, you can consume those APIs from your C++/WinRT code.

이제 이 도구는 GitHub에서 제공되는 완전한 오픈 소스 프로젝트입니다.This tool is now an entirely open source project, available on GitHub. Microsoft/xlang을 방문하여 src > tool > cppwinrt를 클릭합니다.Visit Microsoft/xlang, and then click in to src > tool > cppwinrt.

xlang 라이브러리xlang libraries

앞으로 모든 Windows 런타임 및 xlang 도구는 Windows 런타임에서 사용하는 ECMA-335 메타데이터 형식을 구문 분석하기 위해 완전히 이식 가능한 헤더 전용 라이브러리를 기반으로 합니다.A completely portable header-only library (for parsing the ECMA-335 metadata format used by the Windows Runtime) forms the basis of all the Windows Runtime and xlang tooling going forward. 특히 xlang 라이브러리를 사용하여 처음부터 cppwinrt.exe 도구를 다시 작성했습니다.Notably, we also rewrote the cppwinrt.exe tool from the ground up using the xlang libraries. 이 도구는 더 정확한 메타데이터 쿼리를 제공하므로 C++/WinRT 언어 프로젝션에 관련된 몇 가지 오래된 문제가 해결됩니다.This provides far more accurate metadata queries, solving a few long-standing issues with the C++/WinRT language projection.

종속성 감소Fewer dependencies

xlang 메타데이터 판독기로 인해 cppwinrt.exe 도구 자체의 종속성이 감소합니다.Due to the xlang metadata reader, the cppwinrt.exe tool itself has fewer dependencies. 이 덕분에 도구는 유연성이 훨씬 더 높아지며 특히 제한된 빌드 환경과 같은 더 많은 시나리오에서 사용할 수 있습니다.This makes it far more flexible, as well as being usable in more scenarios—especially in constrained build environments. 특히 이 도구는 더 이상 RoMetadata.dll을 사용하지 않습니다.Notably, it no longer relies on RoMetadata.dll.   이 종속성은 cppwinrt.exe 2.0에 해당합니다.These are the dependencies for cppwinrt.exe 2.0.  

  • ADVAPI32.dllADVAPI32.dll
  • KERNEL32.dllKERNEL32.dll
  • SHLWAPI.dllSHLWAPI.dll
  • XmlLite.dllXmlLite.dll

이러한 DLL은 모두 Windows 10뿐만 아니라 Windows 7, 심지어 Windows Vista에서도 사용할 수 있습니다.All of those DLLs are available not only on Windows 10, but all the way down to Windows 7, and even Windows Vista. 이렇게 하려면 Windows 7을 실행하는 이전 빌드 서버에서 이제 cppwinrt.exe를 실행하여 프로젝트에 대한 C++ 헤더를 생성할 수 있습니다.If you want it to, your old build server running Windows 7 can now run cppwinrt.exe to generate C++ headers for your project. 관심이 있는 경우 약간의 작업을 통해 Windows 7에서 C++/WinRT를 실행할 수도 있습니다.With a bit of work, you can even run C++/WinRT on Windows 7, if that interests you.

위의 목록을 다음과 같은 cppwinrt.exe 1.0의 종속성과 대조합니다.Contrast the list above with these dependencies, which cppwinrt.exe 1.0 has.

  • ADVAPI32.dllADVAPI32.dll
  • SHELL32.dllSHELL32.dll
  • api-ms-win-core-file-l1-1-0.dllapi-ms-win-core-file-l1-1-0.dll
  • XmlLite.dllXmlLite.dll
  • api-ms-win-core-libraryloader-l1-2-0.dllapi-ms-win-core-libraryloader-l1-2-0.dll
  • api-ms-win-core-processenvironment-l1-1-0.dllapi-ms-win-core-processenvironment-l1-1-0.dll
  • RoMetadata.dllRoMetadata.dll
  • SHLWAPI.dllSHLWAPI.dll
  • KERNEL32.dllKERNEL32.dll
  • api-ms-win-core-rtlsupport-l1-1-0.dllapi-ms-win-core-rtlsupport-l1-1-0.dll
  • api-ms-win-core-heap-l1-1-0.dllapi-ms-win-core-heap-l1-1-0.dll
  • api-ms-win-core-timezone-l1-1-0.dllapi-ms-win-core-timezone-l1-1-0.dll
  • api-ms-win-core-console-l1-1-0.dllapi-ms-win-core-console-l1-1-0.dll
  • api-ms-win-core-localization-l1-2-0.dllapi-ms-win-core-localization-l1-2-0.dll
  • OLEAUT32.dllOLEAUT32.dll
  • api-ms-win-core-winrt-error-l1-1-0.dllapi-ms-win-core-winrt-error-l1-1-0.dll
  • api-ms-win-core-winrt-error-l1-1-1.dllapi-ms-win-core-winrt-error-l1-1-1.dll
  • api-ms-win-core-winrt-l1-1-0.dllapi-ms-win-core-winrt-l1-1-0.dll
  • api-ms-win-core-winrt-string-l1-1-0.dllapi-ms-win-core-winrt-string-l1-1-0.dll
  • api-ms-win-core-synch-l1-1-0.dllapi-ms-win-core-synch-l1-1-0.dll
  • api-ms-win-core-threadpool-l1-2-0.dllapi-ms-win-core-threadpool-l1-2-0.dll
  • api-ms-win-core-com-l1-1-0.dllapi-ms-win-core-com-l1-1-0.dll
  • api-ms-win-core-com-l1-1-1.dllapi-ms-win-core-com-l1-1-1.dll
  • api-ms-win-core-synch-l1-2-0.dllapi-ms-win-core-synch-l1-2-0.dll 

Windows 런타임 noexcept 특성The Windows Runtime noexcept attribute

Windows 런타임에는 MIDL 3.0에서 메서드와 속성을 데코레이트하는 데 사용할 수 있는 새로운 [noexcept] 특성이 있습니다.The Windows Runtime has a new [noexcept] attribute, which you may use to decorate your methods and properties in MIDL 3.0. 이 특성이 있다는 것은 지원하는 도구의 경우 구현이 예외를 throw하지 않고 실패한 HRESULT도 반환하지 않음을 나타냅니다.The presence of the attribute indicates to supporting tools that your implementation doesn't throw an exception (nor return a failing HRESULT). 이 특성을 사용하면 실패할 가능성이 있는 ABI(Application Binary Interface) 호출을 지원하는 데 필요한 예외 처리 오버헤드를 방지하여 언어 프로젝션으로 코드 생성을 최적화할 수 있습니다.This allows language projections to optimize code-generation by avoiding the exception-handling overhead that's required to support application binary interface (ABI) calls that can potentially fail.

C++/WinRT는 사용 및 제작 코드의 C++ noexcept 구현을 둘 다 생성하여 이 특성을 활용합니다.C++/WinRT takes advantage of this by producing C++ noexcept implementations of both the consuming and authoring code. API 메서드 또는 속성에 오류가 없고 코드 크기가 걱정된다면 이 특성을 살펴볼 수 있습니다.If you have API methods or properties that are fail-free, and you're concerned about code size, then you can investigate this attribute.

최적화된 코드 생성Optimized code-generation

이제 C++/WinRT는 백그라운드에서 훨씬 더 효율적인 C++ 원본 코드를 생성하므로 C++ 컴파일러는 최대한 가장 작고 가장 효율적인 이진 코드를 생성할 수 있습니다.C++/WinRT now generates even more efficient C++ source code (behind the scenes) so that the C++ compiler can produce the smallest and most efficient binary code possible. 불필요한 해제 정보를 방지하여 예외 처리 비용을 줄이기 위해 많은 개선 사항이 제공됩니다.Many of the improvements are geared toward reducing the cost of exception-handling by avoiding unnecessary unwind information. 대용량 C++/WinRT 코드를 사용하는 이진 파일은 4% 정도의 코드 크기 감소를 보입니다.Binaries that use large amounts of C++/WinRT code will see roughly a 4% reduction in code size. 명령 수 감소로 인해 코드도 더 효율적입니다(더 빠르게 실행됨).The code is also more efficient (it runs faster) due to the reduced instruction count.

이 개선 사항에는 사용자에게 제공되는 새로운 interop 기능도 사용됩니다.These improvements rely on a new interop feature that's available to you, as well. 이제 리소스 소유자인 모든 C++/WinRT 형식에는 소유권을 직접 가져오는 생성자가 포함되므로 이전 2단계 접근법을 피할 수 있습니다.All of the C++/WinRT types that are resource owners now include a constructor for taking ownership directly, avoiding the previous two-step approach.

ABI::Windows::Foundation::IStringable* raw = ...

IStringable projected(raw, take_ownership_from_abi);

printf("%ls\n", projected.ToString().c_str());

최적화된 EH(예외 처리) 코드 생성Optimized exception-handling (EH) code-generation

이 변경 내용은 Microsoft C++ 최적화 프로그램 팀이 예외 처리 비용을 줄이기 위해 수행한 작업을 보완합니다.This change complements work that has been done by the Microsoft C++ optimizer team to reduce the cost of exception-handling. 코드에서 COM과 같은 ABI(Application Binary Interface)를 많이 사용하는 경우 이 패턴을 따르는 많은 코드가 관찰됩니다.If you use application binary interfaces (ABIs) (such as COM) heavily in your code, then you'll observe a lot of code following this pattern.

int32_t Function() noexcept
{
    try
    {
        // code here constitutes unique value.
    }
    catch (...)
    {
        // code here is always duplicated.
    }
}

C++/WinRT 자체는 구현된 모든 API에 대해 이 패턴을 생성합니다.C++/WinRT itself generates this pattern for every API that's implemented. 수천 개의 API 함수를 사용하는 경우 최적화가 중요할 수 있습니다.With thousands of API functions, any optimization here can be significant. 과거에 최적화 프로그램은 이 catch 블록이 모두 동일하다는 사실을 감지하지 않았으므로, 각 ABI에 관련된 많은 코드가 복제되고 있었으며 이는 시스템 코드에서 예외를 사용하면 큰 이진 파일이 생성된다고 생각하는 원인이 되었습니다.In the past, the optimizer wouldn't detect that those catch blocks are all identical, so it was duplicating a lot of code around each ABI (which in turn contributed to the belief that using exceptions in system code produces large binaries). 그러나 Visual Studio 2019부터 C++ 컴파일러는 해당 catch funclet를 모두 접으며 고유한 funclet만 저장합니다.However, from Visual Studio 2019 on, the C++ compiler folds all of those catch funclets, and only stores those that are unique. 결과적으로 이 패턴을 많이 사용하는 이진 파일의 코드 크기가 전체적으로 18% 더 감소합니다.The result is a further and overall 18% reduction in code size for binaries that rely heavily on this pattern. 이제 EH 코드는 반환 코드를 사용하는 것보다 더 효율적일 뿐 아니라 더 큰 이진 파일에 대한 걱정은 과거의 일입니다.Not only is EH code now more efficient than using return codes, but also the concern about larger binaries is now a thing of the past.

증분 빌드 개선 사항Incremental build improvements

이제 cppwinrt.exe 도구는 생성된 헤더/원본 파일의 출력을 디스크에 있는 기존 파일의 콘텐츠에 비교하며 파일이 실제로 변경된 경우에만 파일을 작성합니다.The cppwinrt.exe tool now compares the output of a generated header/source file against the contents of any existing file on disk, and it only writes out the file if the file has in fact changed. 이 덕분에 상당한 디스크 I/O 시간이 절약되며 파일은 C++ 컴파일러에서 “더티”로 간주되지 않습니다.This saves considerable time with disk I/O, and it ensures that the files are not considered "dirty" by the C++ compiler. 결과적으로 대부분의 경우 다시 컴파일이 방지되거나 감소합니다.The result is that recompilation is avoided, or reduced, in many cases.

이제 제네릭 인터페이스가 모두 생성됩니다.Generic interfaces are now all generated

xlang 메타데이터 판독기로 인해 C++/WinRT는 이제 메타데이터에서 매개 변수가 있는 인터페이스나 제네릭 인터페이스를 생성합니다.Due to the xlang metadata reader, C++/WinRT now generates all parameterized, or generic, interfaces from metadata. Windows::Foundation::Collections::IVector<T> 같은 인터페이스는 이제 winrt/base.h에서 직접 작성되는 대신 메타데이터에서 생성됩니다.Interfaces such as Windows::Foundation::Collections::IVector<T> are now generated from metadata rather than hand-written in winrt/base.h. 결과적으로 winrt/base.h 크기는 절반으로 감소했으며 코드에 바로 최적화가 생성됩니다(수동으로 최적화하기에는 어려움).The result is that the size of winrt/base.h has been cut in half, and that optimizations are generated right into the code (which was tricky to do with the hand-rolled approach).

중요

이제 제공된 예제와 같은 인터페이스는 winrt/base.h가 아닌 각 네임스페이스 헤더에 나타납니다.Interfaces such as the example given now appear in their respective namespace headers, rather than in winrt/base.h. 따라서 인터페이스를 사용하려면 적절한 네임스페이스 헤더를 포함해야 합니다(아직 포함하지 않은 경우).So, if you have not already done so, you'll have to include the appropriate namespace header in order to use the interface.

구성 요소 최적화Component optimizations

이 업데이트는 아래 섹션에서 설명하는 C++/WinRT에 대한 여러 추가 옵트인 최적화 지원을 추가합니다.This update adds support for several additional opt-in optimizations for C++/WinRT, described in the sections below. 이 최적화는 새로운 변경 내용(지원을 위해 약간 변경해야 할 수 있음)이므로 명시적으로 켜야 합니다.Because these optimizations are breaking changes (which you may need to make minor changes to support), you'll need to turn them on explicitly. Visual Studio에서 프로젝트 속성 공용 속성 > C++/WinRT > 최적화됨로 설정합니다.In Visual Studio, set project property Common Properties > C++/WinRT > Optimized to Yes. 이렇게 하면 <CppWinRTOptimized>true</CppWinRTOptimized>를 프로젝트 파일에 추가하는 효과가 있습니다.That has the effect of adding <CppWinRTOptimized>true</CppWinRTOptimized> to your project file. 또한 명령줄에서 cppwinrt.exe를 호출할 때 -opt[imize] 스위치를 추가하는 것과 동일한 효과입니다.And it has the same effect as adding the -opt[imize] switch when invoking cppwinrt.exe from the command line.

프로젝트 템플릿 기반 새 프로젝트는 기본적으로 -opt를 사용합니다.A new project (from a project template) will use -opt by default.

균일한 생성 및 직접 구현 액세스Uniform construction, and direct implementation access

이 두 가지 최적화에서는 프로젝션된 형식만 사용하는 경우에도 고유한 구현 형식에 대한 구성 요소 직접 액세스를 허용합니다.These two optimizations allow your component direct access to its own implementation types, even when it's only using the projected types. 공용 API 표면을 사용하려는 경우에는 make, make_selfget_self를 사용할 필요가 없습니다.There's no need to use make, make_self, nor get_self if you simply want to use the public API surface. 호출은 호출을 구현으로 이동하도록 컴파일되며 완전히 인라인될 수도 있습니다.Your calls will compile down to direct calls into the implementation, and those might even be entirely inlined.

자세한 내용과 및 코드 예제는 균일한 생성 및 직접 구현 액세스 옵트인을 참조하세요.For more info, and code examples, see Opt in to uniform construction, and direct implementation access.

형식이 지워진 팩터리Type-erased factories

이 최적화는 module.g.cpp에서 #include 종속성을 피하므로 단일 구현 클래스가 변경될 때마다 다시 컴파일할 필요가 없습니다.This optimization avoids the #include dependencies in module.g.cpp so that it need not be recompiled every time any single implementation class happens to change. 이에 따라 빌드 성능이 향상됩니다.The result is improved build performance.

여러 라이브러리가 포함된 큰 프로젝트에 더 스마트하고 더 효율적인 module.g.cppSmarter and more efficient module.g.cpp for large projects with multiple libs

이제 module.g.cpp 파일에는 winrt_can_unload_nowwinrt_get_activation_factory로 명명된 두 가지 구성 가능한 도우미도 추가로 포함됩니다.The module.g.cpp file now also contains two additional composable helpers, named winrt_can_unload_now, and winrt_get_activation_factory. 이 도우미는 각각 고유한 런타임 클래스를 포함하는 많은 라이브러리로 DLL이 구성된 더 큰 프로젝트용으로 디자인되었습니다.These have been designed for larger projects where a DLL is composed of a number of libs, each with its own runtime classes. 이 경우 수동으로 DLL의 DllGetActivationFactoryDllCanUnloadNow를 함께 연결해야 합니다.In that situation, you need to manually stitch together the DLL's DllGetActivationFactory and DllCanUnloadNow. 이 도우미를 사용하면 출처 위조 오류가 방지되어 이 작업을 훨씬 더 쉽게 수행할 수 있습니다.These helpers make it much easier for you to do that, by avoiding spurious origination errors. 또한 cppwinrt.exe 도구의 -lib 플래그는 개별 라이브러리에 고유한 개별적으로 프리앰블(winrt_xxx가 아님)을 제공하는 데 사용되므로 각 라이브러리의 함수는 개별적으로 이름이 지정되어 명시적으로 결합될 수 있습니다.The cppwinrt.exe tool's -lib flag may also be used to give each individual lib its own preamble (rather than winrt_xxx) so that each lib's functions may be individually named, and thus combined unambiguously.

코루틴 지원Coroutine support

코루틴 지원은 자동으로 포함됩니다.Coroutine support is included automatically. 이전에는 지원이 분산되어 있어 너무 제한적이라고 생각했습니다.Previously, the support resided in multiple places, which we felt was too limiting. 또한 v2.0의 경우 일시적으로 winrt/coroutine.h 헤더 파일이 필요했지만 더 이상 필요하지 않습니다.And then temporarily for v2.0, a winrt/coroutine.h header file was necessary, but that's no longer needed. 이제 Windows 런타임 비동기 인터페이스가 생성되었으므로 수동으로 작성하지 않아도 이제 winrt/Windows.Foundation.h에 코루틴이 있습니다.Since the Windows Runtime async interfaces are now generated, rather than hand-written, they now reside in winrt/Windows.Foundation.h. 더 효율적으로 유지 및 지원할 수 있다는 것 외에도, resume_foreground와 같은 코루틴 도우미를 더 이상 특정 네임스페이스 헤더의 끝까지 추적할 필요가 없습니다.Apart from being more maintainable and supportable, it means that coroutine helpers such as resume_foreground no longer have to be tacked on to the end of a specific namespace header. 오히려 더 자연스럽게 종속성을 포함할 수 있습니다.Instead, they can more naturally include their dependencies. 또한 이를 통해 resume_foreground는 지정된 Windows::UI::Core::CoreDispatcher 다시 시작을 지원할 뿐 아니라 지정된 Windows::System::DispatcherQueue 다시 시작도 지원할 수 있습니다.This further allows resume_foreground to support not only resuming on a given Windows::UI::Core::CoreDispatcher, but it can now also support resuming on a given Windows::System::DispatcherQueue. 이전에는 하나의 네임스페이스에만 정의가 포함될 수 있었기 때문에 두 개 중 하나만 지원할 수 있었습니다.Previously, only one could be supported; but not both, since the definition could only reside in one namespace.

다음은 DispatcherQueue 지원 예제입니다.Here's an example of the DispatcherQueue support.

...
#include <winrt/Windows.System.h>
using namespace Windows::System;
...
fire_and_forget Async(DispatcherQueueController controller)
{
    bool queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(queued);

    // This is just to simulate queue failure...
    co_await controller.ShutdownQueueAsync();

    queued = co_await resume_foreground(controller.DispatcherQueue());
    assert(!queued);
}

이제 코루틴 도우미는 [[nodiscard]]로 데코레이트되기도 하므로 사용 편의성이 향상됩니다.The coroutine helpers are now also decorated with [[nodiscard]], thereby improving their usability. 그러나 코루틴 도우미 작동에 필요한 코루틴 도우미 co_await를 수행하는 것을 잊거나 감지하지 못하는 실수를 하면 [[nodiscard]]로 인해 컴파일러 경고가 생성됩니다.If you forget to (or don't realize you have to) co_await them for them to work then, due to [[nodiscard]], such mistakes now produce a compiler warning.

직접(스택) 할당 진단 지원Help with diagnosing direct (stack) allocations

프로젝션 및 구현 클래스 이름은 기본적으로 동일하고 네임스페이스로만 구별되므로 두 클래스를 혼동할 수 있고 도우미의 make 패밀리를 사용하는 대신 실수로 스택에서 구현을 만들 수도 있습니다.Since the projected and implementation class names are (by default) the same, and only differ by namespace, it's possible to mistake the one for the other, and to accidentally create an implementation on the stack, rather than using the make family of helpers. 해결되지 않은 참조가 진행되는 동안 개체가 소멸될 수 있으므로 경우에 따라 이 문제를 진단하기가 어려울 수 있습니다.This can be hard to diagnose in some cases, because the object may be destroyed while outstanding references are still in flight. 이제 어설션은 디버그 빌드를 위해 이 문제를 발견합니다.An assertion now picks this up, for debug builds. 어설션은 코루틴 내부에서 스택 할당을 감지하지 않지만 대부분의 해당 실수를 발견하는 데 유용합니다.While the assertion doesn't detect stack allocation inside a coroutine, it's nevertheless helpful in catching most such mistakes.

자세한 내용은 직접 할당 진단을 참조하세요.For more info, see Diagnosing direct allocations.

향상된 캡처 도우미 및 variadic 대리자Improved capture helpers, and variadic delegates

이 업데이트는 프로젝션된 형식을 지원하여 캡처 도우미의 제한 사항을 수정합니다.This update fixes the limitation with the capture helpers by supporting projected types as well. 이 업데이트는 지금부터 프로젝션된 형식을 반환할 때 Windows 런타임 interop API와 함께 제공됩니다.This comes up now and then with the Windows Runtime interop APIs, when they return a projected type.

또한 variadic(Windows 이외 런타임) 대리자를 만들 때 get_strongget_weak 지원을 추가합니다.This update also adds support for get_strong and get_weak when creating a variadic (non-Windows Runtime) delegate.

소멸 중에 지연된 삭제 및 안전한 QI 지원Support for deferred destruction and safe QI during destruction

참조 수를 일시적으로 증가시키는 메서드를 호출하는 것은 런타임 클래스 개체의 소멸자에서 종종 일어나는 일입니다.It's not uncommon in the destructor of a runtime class object to call a method that temporarily bumps the reference count. 참조 수가 0으로 반환되면 개체가 다시 소멸됩니다.When the reference count returns to zero, the object destructs a second time. XAML 애플리케이션에서는 계층 구조에서 위아래로 일부 정리 구현을 호출하기 위해 소멸자의 QueryInterface(QI)를 수행해야 할 수 있습니다.In a XAML application, you might need to perform a QueryInterface (QI) in a destructor, in order to call some cleanup implementation up or down the hierarchy. 하지만 개체의 참조 수가 이미 0에 도달했으므로 QI는 참조 수 바운스 역시 구성합니다.But the object's reference count has already reached zero, so that QI constitutes a reference count bounce, too.

이 업데이트는 참조 수를 디바운스하는 지원을 추가하여 일단 0에 도달하면 다시 나타나지 않도록 하지만, 소멸 중에 필요한 QI는 일시적으로 허용합니다.This update adds support for debouncing the reference count, ensuring that once it reaches zero it can never be resurrected; while still allowing you to QI for any temporary that you require during destruction. 특정 XAML 애플리케이션/컨트롤에서는 이 프로시저를 피할 수 없으며 이제 C++/WinRT가 이 프로시저에 탄력적으로 대처합니다.This procedure is unavoidable in certain XAML applications/controls, and C++/WinRT is now resilient to it.

구현 형식에서 정적 final_release 함수를 제공하면 소멸을 연기할 수 있습니다.You can defer destruction by providing a static final_release function on your implementation type. std::unique_ptr 형식으로 개체에 대해 마지막 남은 포인터가 final_release로 전달됩니다.The last remaining pointer to the object, in the form of a std::unique_ptr, is passed to your final_release. 그러면 해당 포인터의 소유권을 다른 컨텍스트로 이동하도록 선택할 수 있습니다.You can then opt to move ownership of that pointer to some other context. 이중 소멸을 트리거하지 않고 포인터에 대해 QI를 수행하는 것이 안전합니다.It's safe for you to QI the pointer without triggering a double-destruction. 하지만 참조 수에 대한 실제 변경 값은 개체 소멸 지점에서 0이어야 합니다.But the net change to the reference count must be zero at the point you destruct the object.

final_release의 반환 값은 void가 될 수 있으며, 이 값은 IAsyncAction 또는 winrt::fire_and_forget 등과 같은 비동기 작업 개체입니다.The return value of final_release can be void, an asynchronous operation object such as IAsyncAction, or winrt::fire_and_forget.

struct Sample : implements<Sample, IStringable>
{
    hstring ToString()
    {
        return L"Sample";
    }

    ~Sample()
    {
        // Called when the unique_ptr below is reset.
    }

    static void final_release(std::unique_ptr<Sample> self) noexcept
    {
        // Move 'self' as needed to delay destruction.
    }
};

아래 예제에서 MainPage가 마지막으로 릴리스되면 final_release가 호출됩니다.In the example below, once the MainPage is released (for the final time), final_release is called. 이 함수는 5초 동안 스레드 풀에서 대기한 후 QI/AddRef/Release 작동에 필요한 페이지 Dispatcher를 사용하여 다시 시작합니다.That function spends five seconds waiting (on the thread pool), and then it resumes using the page's Dispatcher (which requires QI/AddRef/Release to work). 그 다음, 해당 UI 스레드에서 리소스를 정리합니다.It then cleans up a resource on that UI thread. 그리고 마지막으로 MainPage 소멸자를 실제로 호출하는 unique_ptr을 지웁니다.And finally it clears the unique_ptr, which causes the MainPage destructor to actually get called. 이 소멸자에서도 IFrameworkElement에 대한 QI가 필요한 DataContext는 호출됩니다.Even in that destructor, DataContext is called, which requires a QI for IFrameworkElement.

final_release를 코루틴으로 구현할 필요는 없습니다.You don't have to implement your final_release as a coroutine. 그러나 작업이 수행되면 이 예제에서처럼 소멸을 다른 스레드로 매우 쉽게 이동할 수 있습니다.But that does work, and it makes it very simple to move destruction to a different thread, which is what's happening in this example.

struct MainPage : PageT<MainPage>
{
    MainPage()
    {
    }

    ~MainPage()
    {
        DataContext(nullptr);
    }

    static IAsyncAction final_release(std::unique_ptr<MainPage> self)
    {
        co_await 5s;

        co_await resume_foreground(self->Dispatcher());
        co_await self->resource.CloseAsync();

        // The object is destructed normally at the end of final_release,
        // when the std::unique_ptr<MyClass> destructs. If you want to destruct
        // the object earlier than that, then you can set *self* to `nullptr`.
        self = nullptr;
    }
};

자세한 내용은 지연된 소멸을 참조하세요.For more info, see Deferred destruction.

COM 스타일 단일 인터페이스 상속에 대한 향상된 지원Improved support for COM-style single interface inheritance

또한 Windows 런타임 프로그래밍을 위해 C++/WinRT는 COM 전용 API를 작성하고 사용하는 데 사용됩니다.As well as for Windows Runtime programming, C++/WinRT is also used to author and consume COM-only APIs. 이 업데이트를 통해 인터페이스 계층 구조가 있는 COM 서버를 구현할 수 있습니다.This update makes it possible to implement a COM server where there exists an interface hierarchy. 이 서버는 Windows 런타임에 필요하지 않지만 일부 COM 구현에는 필요합니다.This isn't required for the Windows Runtime; but it is required for some COM implementations.

out 매개 변수의 올바른 처리Correct handling of out params

특히 Windows 런타임 배열과 같은 out 매개 변수는 사용하기 어려울 수 있습니다.It can be tricky to work with out params; particularly Windows Runtime arrays. 이 업데이트를 통해 C++/WinRT는 out 매개 변수 및 배열에 도달할 때 더 강력하고 탄력적으로 실수에 대처할 수 있으며, 해당 매개 변수가 언어 프로젝션을 통해 도착하는지 또는 원시 ABI를 사용하거나 실수로 변수를 일관성 있게 초기화하지 않는 COM 개발자로부터 도착하는지 여부는 상관이 없습니다.With this update, C++/WinRT is considerably more robust and resilient to mistakes when it comes to out params and arrays; whether those parameters arrive via a language projection, or from a COM developer who's using the raw ABI, and who's making the mistake of not initializing variables consistently. 두 경우 모두에서 C++/WinRT는 리소스의 릴리스를 기억하여 프로젝션된 형식을 ABI에 전달하게 될 때와 0에 도달하거나 ABI를 통해 도착하는 매개 변수를 정리할 때 올바른 작업을 수행합니다.In either case, C++/WinRT now does the right thing when it comes to handing off projected types to the ABI (by remembering to release any resources), and when it comes to zeroing out or clearing out parameters that arrive across the ABI.

이제 이벤트는 잘못된 토큰을 안정적으로 처리함Events now handle invalid tokens reliably

winrt::event 구현은 이제 remove 메서드가 잘못된 토큰 값(배열에 없는 값)으로 호출되는 경우를 적절하게 처리합니다.The winrt::event implementation now gracefully handles the case where its remove method is called with an invalid token value (a value that's not present in the array).

코루틴 로컬은 이제 코루틴이 반환하기 전에 소멸됩니다.Coroutine locals are now destroyed before the coroutine returns

코루틴 형식을 구현하는 기존 방법에서는 코루틴이 반환/완료된 ‘이후’(마지막 일시 중단 이전이 아님) 코루틴 내 로컬이 소멸되도록 허용합니다. The traditional way of implementing a coroutine type may allow locals within the coroutine to be destroyed after the coroutine returns/completes (rather than prior to final suspension). 이 문제를 피하고 다른 이점을 만들기 위해 대기자 다시 시작은 이제 마지막 일시 중단까지 지연됩니다.The resumption of any waiter is now deferred until final suspension, in order to avoid this problem and to accrue other benefits.

Windows SDK 버전 10.0.17763.0(Windows 10 버전 1809)의 새로운 기능 및 변경 내용News, and changes, in Windows SDK version 10.0.17763.0 (Windows 10, version 1809)

아래 표에는 Windows SDK 버전 10.0.17763.0(Windows 10 버전 1809)에서 C++/WinRT의 새로운 기능과 변경 내용이 포함됩니다.The table below contains news and changes for C++/WinRT in the Windows SDK version 10.0.17763.0 (Windows 10, version 1809).

새로운 기능 또는 변경된 기능New or changed feature 추가 정보More info
주요 변경 내용.Breaking change. C++/WinRT는 컴파일하기 위해 Windows SDK의 헤더를 사용하지 않습니다.For it to compile, C++/WinRT doesn't depend on headers from the Windows SDK. 아래 Windows SDK 헤더 파일에서 격리를 참조하세요.See Isolation from Windows SDK header files, below.
Visual Studio 프로젝트 시스템 형식이 변경되었습니다.The Visual Studio project system format has changed. 아래 C++/WinRT 프로젝트의 대상을 Windows SDK 최신 버전으로 다시 지정하는 방법을 참조하세요.See How to retarget your C++/WinRT project to a later version of the Windows SDK, below.
Windows 런타임 함수에 컬렉션 개체를 전달하는 데 도움이 되거나 자체 컬렉션 속성과 컬렉션 형식을 구현하는 새로운 함수와 기본 클래스가 있습니다.There are new functions and base classes to help you pass a collection object to a Windows Runtime function, or to implement your own collection properties and collection types. C++/WinRT로 작성된 컬렉션을 참조하세요.See Collections with C++/WinRT.
C++/WinRT 런타임 클래스와 함께 {바인딩} 태그 확장을 사용할 수 있습니다.You can use the {Binding} markup extension with your C++/WinRT runtime classes. 자세한 내용과 코드 예제는 데이터 바인딩 개요를 참조하세요.For more info, and code examples, see Data binding overview.
코루틴 취소 지원을 통해 취소 콜백을 등록할 수 있습니다.Support for canceling a coroutine allows you to register a cancellation callback. 자세한 내용과 코드 예제는 비동기 작업 취소 및 취소 콜백를 참조하세요.For more info, and code examples, see Canceling an asychronous operation, and cancellation callbacks.
멤버 함수를 가리키는 대리자를 만들 때 처리기가 등록된 지점에서 원시 this 포인터 대신에 현재 개체에 대한 강력하거나 약한 참조를 설정할 수 있습니다.When creating a delegate pointing to a member function, you can establish a strong or a weak reference to the current object (instead of a raw this pointer) at the point where the handler is registered. 자세한 내용과 코드 예제는 이벤트 처리 대리자를 사용하여 안전하게 this 포인터 액세스 섹션에서 멤버 함수를 대리자로 사용하는 경우 하위 섹션을 참조하세요.For more info, and code examples, see the If you use a member function as a delegate sub-section in the section Safely accessing the this pointer with an event-handling delegate.
Visual Studio의 C++ 표준 규칙이 향상되어 처리되지 않았던 버그가 수정되었습니다.Bugs are fixed that were uncovered by Visual Studio's improved conformance to the C++ standard. C++/WinRT의 표준 규칙의 유효성을 검사하기 위해 LLVM 및 Clang 도구 체인을 더 효율적으로 이용합니다.The LLVM and Clang toolchain is also better leveraged to validate C++/WinRT's standards conformance. 새 프로젝트가 컴파일되지 않는 이유는 무엇인가요? Visual Studio 2017(버전 15.8.0 이상) 및 SDK 버전 17134를 사용하고 있습니다.에 설명된 문제가 더 이상 발생하지 않습니다.You'll no longer encounter the issue described in Why won't my new project compile? I'm using Visual Studio 2017 (version 15.8.0 or higher), and SDK version 17134

기타 변경 내용은 아래와 같습니다.Other changes.

  • 주요 변경 내용.Breaking change. winrt::get_abi(winrt::hstring const&) 는 이제 HSTRING 대신 void*를 반환합니다.winrt::get_abi(winrt::hstring const&) now returns void* instead of HSTRING. static_cast<HSTRING>(get_abi(my_hstring));을 사용하여 HSTRING을 가져올 수 있습니다.You can use static_cast<HSTRING>(get_abi(my_hstring)); to get an HSTRING. ABI의 HSTRING과 상호 운용을 참조하세요.See Interoperating with the ABI's HSTRING.
  • 주요 변경 내용.Breaking change. winrt::put_abi(winrt::hstring&) 는 이제 HSTRING* 대신 void**를 반환합니다.winrt::put_abi(winrt::hstring&) now returns void** instead of HSTRING*. reinterpret_cast<HSTRING*>(put_abi(my_hstring));을 사용하여 HSTRING*를 가져올 수 있습니다.You can use reinterpret_cast<HSTRING*>(put_abi(my_hstring)); to get an HSTRING*. ABI의 HSTRING과 상호 운용을 참조하세요.See Interoperating with the ABI's HSTRING.
  • 주요 변경 내용.Breaking change. 이제 HRESULT는 winrt::hresult로 프로젝션됩니다.HRESULT is now projected as winrt::hresult. 형식 검사를 수행하거나 형식 특성을 지원하기 위해 HRESULT가 필요한 경우 ::hresultstatic_cast를 수행할 수 있습니다.If you need an HRESULT (to do type checking, or to support type traits), then you can static_cast a winrt::hresult. 그러지 않으면 C++/WinRT 헤더를 포함하기 전에 unknwn.h를 포함하는 한 winrt::hresult가 HRESULT로 변환됩니다.Otherwise, winrt::hresult converts to HRESULT, as long as you include unknwn.h before you include any C++/WinRT headers.
  • 주요 변경 내용.Breaking change. GUID는 이제 winrt::guid로 프로젝션됩니다.GUID is now projected as winrt::guid. 구현하는 API의 경우 GUID 매개 변수에 winrt::guid를 사용해야 합니다.For APIs that you implement, you must use winrt::guid for GUID parameters. 그러지 않으면 C++/WinRT 헤더를 포함하기 전에 unknwn.h를 포함하는 한 winrt::guid가 GUID로 변환됩니다.Otherwise, winrt::guid converts to GUID, as long as you include unknwn.h before you include any C++/WinRT headers. ABI의 GUID 구조체와 상호 운용을 참조하세요.See Interoperating with the ABI's GUID struct.
  • 주요 변경 내용.Breaking change. winrt::handle_type 생성자가 명시적으로 설정되어 강화되었습니다(이제 이 생성자로 잘못된 코드를 작성하기가 더 어려움).The winrt::handle_type constructor has been hardened by making it explicit (it's now harder to write incorrect code with it). 원시 핸들 값을 할당해야 하는 경우 handle_type::attach 함수를 대신 호출합니다.If you need to assign a raw handle value, call the handle_type::attach function instead.
  • 주요 변경 내용.Breaking change. WINRT_CanUnloadNowWINRT_GetActivationFactory의 서명이 변경되었습니다.The signatures of WINRT_CanUnloadNow and WINRT_GetActivationFactory have changed. 이 함수는 선언하면 안 됩니다.You mustn't declare these functions at all. 대신 C++/WinRT Windows 네임스페이스 헤더 파일을 포함하는 경우 자동으로 포함되는 winrt/base.h를 포함하여 이 함수의 선언을 포함합니다.Instead, include winrt/base.h (which is automatically included if you include any C++/WinRT Windows namespace header files) to include the declarations of these functions.
  • winrt::clock 구조체의 경우 from_FILETIME/to_FILETIME은 더 이상 사용되지 않고, 대신 from_file_time/to_file_time이 사용됩니다.For the winrt::clock struct, from_FILETIME/to_FILETIME are deprecated in favor of from_file_time/to_file_time.
  • IBuffer 매개 변수가 필요한 API가 간소화되었습니다.APIs that expect IBuffer parameters are simplified. 대부분의 API는 컬렉션 또는 배열을 선호하지만 C++에서 더 쉽게 사용할 필요가 있었던 많은 API는 IBuffer를 사용합니다.Although most APIs prefer collections or arrays, enough APIs rely on IBuffer that it needed to be easier to use such APIs from C++. 이 업데이트는 C++ 표준 라이브러리 컨테이너에서 사용하는 동일한 데이터 명명 규칙을 사용하여 IBuffer 구현 뒤에 있는 데이터에 대한 직접 액세스를 제공합니다.This update provides direct access to the data behind an IBuffer implementation, using the same data naming convention used by the C++ Standard Library containers. 또한 일반적으로 대문자로 시작하는 메타데이터 이름과 충돌하지 않도록 합니다.This also avoids colliding with metadata names that conventionally begin with an uppercase letter.
  • 코드 생성이 향상되었습니다. 코드 크기를 줄이고, 인라인을 개선하고, 팩터리 캐싱을 최적화하기 위한 다양한 개선 사항이 있습니다.Improved code generation: various improvements to reduce code size, improve inlining, and optimize factory caching.
  • 불필요한 재귀가 제거되었습니다.Removed unnecessary recursion. 명령줄이 특정 .winmd가 아닌 폴더를 참조하는 경우 cppwinrt.exe 도구는 더 이상 .winmd 파일을 재귀적으로 검색하지 않습니다.When the command-line refers to a folder, rather than to a specific .winmd, the cppwinrt.exe tool no longer searches recursively for .winmd files. 또한 cppwinrt.exe 도구는 이제 복제본을 더 적절하게 처리하므로 사용자 오류 및 형식이 잘못된 .winmd 파일에 더 탄력적으로 대처할 수 있습니다.The cppwinrt.exe tool also now handles duplicates more intelligently, making it more resilient to user error, and to poorly-formed .winmd files.
  • 스마트 포인터가 강화되었습니다.Hardened smart pointers. 이전에는 새 값을 이동 할당할 때 이벤트 취소자가 호출되지 않았습니다.Formerly, the event revokers failed to revoke when move-assigned a new value. 이를 통해 스마트 포인터가 루트가 winrt::com_ptr struct template인 자체 할당을 안정적으로 처리하지 않는 문제를 파악할 수 있었습니다.This helped uncover an issue where smart pointer classes weren't reliably handling self-assignment; rooted in the winrt::com_ptr struct template. winrt::com_ptr이 수정되었으며, 이벤트 취소자는 이동 의미 체계를 제대로 처리하여 할당 시 취소되도록 수정되었습니다.winrt::com_ptr has been fixed, and the event revokers fixed to handle move semantics correctly so that they revoke upon assignment.

중요

버전 1.0.181002.2 및 이후 버전 1.0.190128.4에서 모두 C++/WinRT Visual Studio 확장(VSIX)에 대한 주요 변경 내용이 있습니다.Important changes were made to the C++/WinRT Visual Studio Extension (VSIX), both in version 1.0.181002.2, and then later in version 1.0.190128.4. 이 변경 내용에 대한 자세한 내용과 이 변경 내용이 기존 프로젝트에 어떻게 영향을 미치는지 알아보려면 Visual Studio의 C++/WinRT 지원이전 버전의 VSIX 확장을 참조하세요.For details of these changes, and how they affect your existing projects, Visual Studio support for C++/WinRT and Earlier versions of the VSIX extension.

Windows SDK 헤더 파일에서 격리Isolation from Windows SDK header files

이는 코드의 주요 변경 내용이 될 수 있습니다.This is potentially a breaking change for your code.

C++/WinRT는 컴파일하기 위해 더 이상 Windows SDK의 헤더 파일을 사용하지 않습니다.For it to compile, C++/WinRT no longer depends on header files from the Windows SDK. CRT(C 런타임 라이브러리) 및 C++ STL(표준 템플릿 라이브러리)에 있는 헤더 파일에도 Windows SDK 헤더가 포함되지 않습니다.Header files in the C run-time library (CRT) and the C++ Standard Template Library (STL) also don't include any Windows SDK headers. 또한 이를 통해 표준을 좀 더 준수하고, 의도치 않은 종속성을 방지하고, 보호해야 하는 매크로 수를 크게 줄입니다.And that improves standards compliance, avoids inadvertent dependencies, and greatly reduces the number of macros that you have to guard against.

이 독립성은 C++/WinRT가 이제 좀 더 이식 가능하고 표준을 준수하며 컴파일러 간 라이브러리와 플랫폼 간 라이브러리가 될 가능성을 발전시킨다는 것을 의미합니다.This independence means that C++/WinRT is now more portable and standards compliant, and it furthers the possibility of it becoming a cross-compiler and cross-platform library. 또한 C++/WinRT 헤더가 매크로에 악영향을 주지 않음을 의미합니다.It also means that the C++/WinRT headers aren't adversely affected macros.

이전에 프로젝트에 Windows 헤더를 포함하기 위해 C++/WinRT에 헤더를 남겨 놓은 경우 이제는 직접 헤더를 포함해야 합니다.If you previously left it to C++/WinRT to include any Windows headers in your project, then you'll now need to include them yourself. 언제든지 사용하는 헤더를 명시적으로 포함하며 헤더를 포함하기 위해 다른 라이브러리에 헤더를 남겨 놓지 않는 것이 좋습니다.It is, in any case, always best practice to explicitly include the headers that you depend on, and not leave it to another library to include them for you.

현재 Windows SDK 헤더 파일 격리의 유일한 예외는 내장 함수와 숫자입니다.Currently, the only exceptions to Windows SDK header file isolation are for intrinsics, and numerics. 마지막으로 남은 이 종속성에는 알려진 문제가 없습니다.There are no known issues with these last remaining dependencies.

프로젝트에서 필요한 경우 Windows SDK 헤더를 통해 interop를 다시 사용하도록 설정할 수 있습니다.In your project, you can re-enable interop with the Windows SDK headers if you need to. 예를 들어 루트가 IUnknown인 COM 인터페이스를 구현하려고 할 수 있습니다.You might, for example, want to implement a COM interface (rooted in IUnknown). 이 예제의 경우 C++/WinRT 헤더를 포함하기 전에 unknwn.h를 포함합니다.For that example, include unknwn.h before you include any C++/WinRT headers. 이렇게 하면 C++/WinRT 기본 라이브러리가 다양한 후크를 통해 클래식 COM 인터페이스를 지원할 수 있습니다.Doing so causes the C++/WinRT base library to enable various hooks to support classic COM interfaces. 코드 예제는 C++/WinRT를 통한 COM 구성 요소 작성을 참조하세요.For a code example, see Author COM components with C++/WinRT. 마찬가지로, 호출하려는 형식 /또는 함수를 선언하는 다른 Windows SDK 헤더를 명시적으로 포함합니다.Similarly, explicitly include any other Windows SDK headers that declare types and/or functions that you want to call.

C++/WinRT 프로젝트의 대상을 Windows SDK 최신 버전으로 다시 지정하는 방법How to retarget your C++/WinRT project to a later version of the Windows SDK

컴파일러 및 링커 문제를 최소화할 수 있는 프로젝트의 대상을 다시 지정하는 방법에는 많은 작업이 필요합니다.The method for retargeting your project that's likely to result in the fewest compiler and linker issue is also the most labor-intensive. 이 방법에서는 선택한 Windows SDK 버전을 대상으로 하는 새 프로젝트를 만든 후 이전 프로젝트에서 새 프로젝트로 파일을 복사합니다.That method involves creating a new project (targeting the Windows SDK version of your choice), and then copying files over to your new project from your old. 추가하는 파일을 Visual Studio에 저장하기 위해 복사하기만 하면 되는 이전 .vcxproj.vcxproj.filters 파일의 섹션이 있습니다.There will be sections of your old .vcxproj and .vcxproj.filters files that you can just copy over to save you adding files in Visual Studio.

그러나 Visual Studio에서 프로젝트 대상을 다시 지정하는 두 가지 다른 방법이 있습니다.However, there are two other ways to retarget your project in Visual Studio.

  • 프로젝트 속성 일반 > Windows SDK 버전으로 이동한 다음, 모든 구성모든 플랫폼을 선택합니다.Go to project property General > Windows SDK Version, and select All Configurations and All Platforms. Windows SDK 버전을 대상으로 지정할 버전으로 설정합니다.Set Windows SDK Version to the version that you want to target.
  • 솔루션 탐색기에서 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고, 프로젝트 대상 다시 지정을 클릭하고, 대상으로 지정할 버전을 선택한 다음, 확인을 클릭합니다.In Solution Explorer, right-click the project node, click Retarget Projects, choose the version(s) you wish to target, and then click OK.

이 두 가지 방법 중 하나를 사용한 후 컴파일러 또는 링커 오류가 발생하면 다시 빌드하기 전에 솔루션을 정리할 수 있습니다(빌드 > 솔루션 정리 및/또는 수동으로 모든 임시 폴더와 파일 삭제).If you encounter any compiler or linker errors after using either of these two methods, then you can try cleaning the solution (Build > Clean Solution and/or manually delete all temporary folders and files) before trying to build again.

C++ 컴파일러에서 “오류 C2039: ‘IUnknown’: '`전역 네임스페이스''의 멤버가 아닙니다.”가 생성되면 C++/WinRT 헤더를 포함하기 전에 #include <unknwn.h>pch.h 파일의 맨 위에 추가합니다. If the C++ compiler produces "error C2039: 'IUnknown': is not a member of '`global namespace''", then add #include <unknwn.h> to the top of your pch.h file (before you include any C++/WinRT headers).

또한 그 뒤에 #include <hstring.h>을 추가해야 할 수 있습니다.You may also need to add #include <hstring.h> after that.

C++ 링커에서 “오류 LNK2019: 확인되지 않은 외부 기호 _WINRT_CanUnloadNow@0이 _VSDesignerCanUnloadNow@0 함수에서 참조되었습니다. ”가 생성되면 #define _VSDESIGNER_DONT_LOAD_AS_DLLpch.h 파일에 추가하여 이 오류를 해결할 수 있습니다.If the C++ linker produces "error LNK2019: unresolved external symbol _WINRT_CanUnloadNow@0 referenced in function _VSDesignerCanUnloadNow@0", then you can resolve that by adding #define _VSDESIGNER_DONT_LOAD_AS_DLL to your pch.h file.