Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for running the terminal core as a content process #12938

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
e168413
I think this merges `the-whole-thing` into this branch. The remote co…
zadjii-msft Aug 10, 2021
bb49d50
I believe this merges the buisness of `connection-factory`, though th…
zadjii-msft Aug 10, 2021
7731f59
Some comments because everything is hard
zadjii-msft Aug 10, 2021
996c71a
Add a signal that the content can use to tell the window it's ready
zadjii-msft Aug 12, 2021
2f23e1f
A close button, and more logging
zadjii-msft Aug 12, 2021
c3a9445
some short-circuits for these inits, to make them more stable
zadjii-msft Aug 12, 2021
7e792b2
You know, there's 0% chance that this is the right pattern for this, …
zadjii-msft Aug 12, 2021
5a07282
Add a kill button for manually killing the content
zadjii-msft Aug 12, 2021
3d15b09
This works to kill the content and have the app live
zadjii-msft Aug 12, 2021
ea9d3cb
a fix for a crash when closing
zadjii-msft Aug 16, 2021
4a8f0e9
The sample app has a hard time loading TermControl resources so we're…
zadjii-msft Aug 16, 2021
eeb01a1
this was the part where I realized I dun goofed
zadjii-msft Aug 16, 2021
dafb627
Revert "this was the part where I realized I dun goofed"
zadjii-msft Aug 16, 2021
1a78557
This too didn't work. Creating the XAML thing not on the XAML thing i…
zadjii-msft Aug 16, 2021
35ca313
Revert "This too didn't work. Creating the XAML thing not on the XAML…
zadjii-msft Aug 16, 2021
8ceb9ba
This doesn't immediately crash, but it does crash when you start aski…
zadjii-msft Aug 16, 2021
768d4c0
some cleanup
zadjii-msft Aug 24, 2021
651efe2
add a dialog internally to the bounds of the control, not outside of …
zadjii-msft Aug 24, 2021
738d191
Move the content process handling to a separate file in TermControl p…
zadjii-msft Aug 24, 2021
f818885
move the content process main to another file as well
zadjii-msft Aug 24, 2021
07ba33b
simplify the interface here a bit
zadjii-msft Aug 24, 2021
cf70797
BODGY, don't raise an event on destruction, that would be too...
zadjii-msft Aug 24, 2021
34601f7
more cleanup
zadjii-msft Aug 25, 2021
46e299d
Definitely needed those
zadjii-msft Apr 11, 2022
5429fca
The sample works again
zadjii-msft Apr 12, 2022
b253440
add a velocity flag for this
zadjii-msft Apr 12, 2022
b312919
derp
zadjii-msft Apr 12, 2022
857fb39
add localization back
zadjii-msft Apr 12, 2022
9141f04
tried to make these blindli fire_and_forgets. Didn't work
zadjii-msft Apr 12, 2022
76d8fa7
start thinking about moving the timers to being threadpooltimers in t…
zadjii-msft Apr 12, 2022
7b3ca83
this reconnects the new window to the existing content process
zadjii-msft Apr 13, 2022
33b1ab9
own the handle
zadjii-msft Apr 13, 2022
2a9eefc
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft Apr 15, 2022
99308b4
This actually works for not loading the resources
zadjii-msft Apr 15, 2022
bf0f516
For this commit, I went with what was in #11501. That seems to have b…
zadjii-msft Apr 15, 2022
358edd5
Revert "For this commit, I went with what was in #11501. That seems t…
zadjii-msft Apr 15, 2022
b1ee82a
Revert "start thinking about moving the timers to being threadpooltim…
zadjii-msft Apr 18, 2022
ce8f8fb
Make the window smaller because the default is HUUEG
zadjii-msft Apr 18, 2022
07a1a07
When trying to use Narrator, this gets hit and throws an exception. P…
zadjii-msft Apr 18, 2022
91977be
For this commit, I went with what was in #11501. That seems to have b…
zadjii-msft Apr 15, 2022
082c63b
this seems to work with narrator. I think this is what I was trying t…
zadjii-msft Apr 18, 2022
c588a9c
cleanup from fixed a11y code
zadjii-msft Apr 19, 2022
a74b45a
hey look this assert() doesn't hit anymore
zadjii-msft Apr 19, 2022
446d07e
add logging
zadjii-msft Apr 19, 2022
bbe32f8
Reduce the diff size trivially
zadjii-msft Apr 19, 2022
a38fe5f
woah typos
zadjii-msft Apr 19, 2022
f898855
yes I know this doesn't return that's the whole point
zadjii-msft Apr 20, 2022
02fa24c
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft Apr 20, 2022
7d4ee45
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft Apr 28, 2022
eac5ceb
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft May 5, 2022
223e270
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft May 24, 2022
52f7664
some nits
zadjii-msft May 24, 2022
44ac527
more nits, more a11y stuff
zadjii-msft May 24, 2022
7707716
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft Jun 21, 2022
f7d9384
this was LOAD BEARING
zadjii-msft Jun 21, 2022
023eb75
this was definitely a bug
zadjii-msft Jun 21, 2022
b8cd2b2
that was vestigial anyways
zadjii-msft Jun 22, 2022
702e15c
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft Jul 6, 2022
3434208
Merge remote-tracking branch 'origin/main' into dev/migrie/oop/2/infi…
zadjii-msft Jul 11, 2022
e09b674
Merge branch 'main' into dev/migrie/oop/2/infinity-war
zadjii-msft Sep 1, 2022
852208a
nots from review
zadjii-msft Sep 1, 2022
e52e720
Migrate spelling-0.0.21 changes from main
DHowett Sep 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spelling/allow/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ CLASSNOTAVAILABLE
cmdletbinding
COLORPROPERTY
colspan
combase
COMDLG
commandlinetoargv
comparand
Expand Down
216 changes: 214 additions & 2 deletions scratch/ScratchIslandApp/SampleApp/MyPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@

#include "pch.h"
#include "MyPage.h"
#include "MySettings.h"
#include <LibraryResources.h>
#include "MyPage.g.cpp"
#include "MySettings.h"
#include "..\..\..\src\cascadia\UnitTests_Control\MockControlSettings.h"
#include "..\..\..\src\types\inc\utils.hpp"

using namespace std::chrono_literals;
using namespace winrt::Microsoft::Terminal;
Expand All @@ -26,7 +28,7 @@ namespace winrt::SampleApp::implementation

void MyPage::Create()
{
auto settings = winrt::make_self<implementation::MySettings>();
auto settings = winrt::make_self<MySettings>();

auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted in-proc...",
winrt::hstring{},
Expand All @@ -44,6 +46,216 @@ namespace winrt::SampleApp::implementation
Control::TermControl control{ *settings, *settings, conn };

InProcContent().Children().Append(control);

// Once the control loads (and not before that), write some text for debugging:
control.Initialized([conn](auto&&, auto&&) {
conn.WriteInput(L"This TermControl is hosted in-proc...");
});
}

static wil::unique_process_information _createHostClassProcess(const winrt::guid& g)
{
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(g) };

// Create an event that the content process will use to signal it is
// ready to go. We won't need the event after this function, so the
// unique_event will clean up our handle when we leave this scope. The
// ContentProcess is responsible for cleaning up its own handle.
wil::unique_event ev{ CreateEvent(nullptr, true, false, L"contentProcessStarted") };
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
// Make sure to mark this handle as inheritable! Even with
// bInheritHandles=true, this is only inherited when it's explicitly
// allowed to be.
SetHandleInformation(ev.get(), HANDLE_FLAG_INHERIT, 1);

// god bless, fmt::format will format a HANDLE like `0xa80`
std::wstring commandline{
fmt::format(L"WindowsTerminal.exe --content {} --signal {}", guidStr, ev.get())
};

STARTUPINFO siOne{ 0 };
siOne.cb = sizeof(STARTUPINFOW);
wil::unique_process_information piOne;
auto succeeded = CreateProcessW(
nullptr,
commandline.data(),
nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes
true, // bInheritHandles
CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags
nullptr, // lpEnvironment
nullptr, // startingDirectory
&siOne, // lpStartupInfo
&piOne // lpProcessInformation
);
THROW_IF_WIN32_BOOL_FALSE(succeeded);

// Wait for the child process to signal that they're ready.
WaitForSingleObject(ev.get(), INFINITE);

return std::move(piOne);
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
}

winrt::fire_and_forget MyPage::_writeToLog(std::wstring_view str)
{
winrt::hstring copy{ str };
// Switch back to the UI thread.
co_await resume_foreground(Dispatcher());
winrt::WUX::Controls::TextBlock block;
block.Text(copy);
Log().Children().Append(block);
}

winrt::fire_and_forget MyPage::CreateClicked(const IInspectable& sender,
const WUX::Input::TappedRoutedEventArgs& eventArgs)
{
auto guidString = GuidInput().Text();

// Capture calling context.
winrt::apartment_context ui_thread;

auto canConvert = guidString.size() == 38 &&
guidString.front() == '{' &&
guidString.back() == '}';
bool tryingToAttach = false;
winrt::guid contentGuid{ ::Microsoft::Console::Utils::CreateGuid() };

if (canConvert)
{
GUID result{};
if (SUCCEEDED(IIDFromString(guidString.c_str(), &result)))
{
contentGuid = result;
tryingToAttach = true;
}
}
_writeToLog(tryingToAttach ? L"Attaching to existing content process" : L"Creating new content process");

co_await winrt::resume_background();
if (!tryingToAttach)
{
// Spawn a wt.exe, with the guid on the commandline
piContentProcess = std::move(_createHostClassProcess(contentGuid));
}

// THIS MUST TAKE PLACE AFTER _createHostClassProcess.
// * If we're creating a new OOP control, _createHostClassProcess will
// spawn the process that will actually host the ContentProcess
// object.
// * If we're attaching, then that process already exists.
Control::ContentProcess content{ nullptr };
try
{
content = create_instance<Control::ContentProcess>(contentGuid, CLSCTX_LOCAL_SERVER);
}
catch (winrt::hresult_error hr)
{
_writeToLog(L"CreateInstance the ContentProcess object");
_writeToLog(fmt::format(L" HR ({}): {}", hr.code(), hr.message().c_str()));
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
}

if (content == nullptr)
{
_writeToLog(L"Failed to connect to the ContentProcess object. It may not have been started fast enough.");
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
}

TerminalConnection::ConnectionInformation connectInfo{ nullptr };
Control::IControlSettings settings{ *winrt::make_self<implementation::MySettings>() };

// When creating a terminal for the first time, pass it a connection
// info
//
// otherwise, when attaching to an existing one, just pass null, because
// we don't need the connection info.
if (!tryingToAttach)
{
auto connectionSettings{ TerminalConnection::ConptyConnection::CreateSettings(L"cmd.exe /k echo This TermControl is hosted out-of-proc...",
winrt::hstring{},
L"",
nullptr,
32,
80,
winrt::guid()) };

// "Microsoft.Terminal.TerminalConnection.ConptyConnection"
winrt::hstring myClass{ winrt::name_of<TerminalConnection::ConptyConnection>() };
connectInfo = TerminalConnection::ConnectionInformation(myClass, connectionSettings);

if (!content.Initialize(settings, settings, connectInfo))
{
_writeToLog(L"Failed to Initialize the ContentProcess object.");
co_return; // be sure to co_return or we'll fall through to the part where we clear the log
}
}
else
{
// If we're attaching, we don't really need to do anything special.
}

// Switch back to the UI thread.
co_await ui_thread;

// Create the XAML control that will be attached to the content process.
// We're not passing in a connection, because the contentGuid will be used instead.
Control::TermControl control{ contentGuid, settings, settings, nullptr };
auto weakControl = winrt::make_weak(control);
control.RaiseNotice([this](auto&&, auto& args) {
_writeToLog(L"Content process died, probably.");
_writeToLog(args.Message());
OutOfProcContent().Children().Clear();
GuidInput().Text(L"");
if (piContentProcess.hProcess)
{
piContentProcess.reset();
}
});
control.ConnectionStateChanged([this, weakControl](auto&&, auto&) {
if (auto strongControl{ weakControl.get() })
{
const auto newConnectionState = strongControl.ConnectionState();
if (newConnectionState == TerminalConnection::ConnectionState::Closed)
{
_writeToLog(L"Connection was closed");
OutOfProcContent().Children().Clear();
GuidInput().Text(L"");
if (piContentProcess.hProcess)
{
piContentProcess.reset();
}
}
}
});

Log().Children().Clear();
OutOfProcContent().Children().Append(control);

if (!tryingToAttach)
{
auto guidStr{ ::Microsoft::Console::Utils::GuidToString(contentGuid) };
GuidInput().Text(guidStr);
}
}

void MyPage::CloseClicked(const IInspectable& /*sender*/,
const WUX::Input::TappedRoutedEventArgs& /*eventArgs*/)
{
OutOfProcContent().Children().Clear();
GuidInput().Text(L"");
if (piContentProcess.hProcess)
{
piContentProcess.reset();
}
}

void MyPage::KillClicked(const IInspectable& /*sender*/,
const WUX::Input::TappedRoutedEventArgs& /*eventArgs*/)
{
if (piContentProcess.hProcess)
{
TerminateProcess(piContentProcess.hProcess, (UINT)-1);
piContentProcess.reset();
}
}

// Method Description:
Expand Down
9 changes: 8 additions & 1 deletion scratch/ScratchIslandApp/SampleApp/MyPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ namespace winrt::SampleApp::implementation
MyPage();

void Create();

hstring Title();

winrt::fire_and_forget CreateClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
void CloseClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);
void KillClicked(const IInspectable& sender, const Windows::UI::Xaml::Input::TappedRoutedEventArgs& eventArgs);

private:
friend struct MyPageT<MyPage>; // for Xaml to bind events

wil::unique_process_information piContentProcess;

winrt::fire_and_forget _writeToLog(std::wstring_view str);
};
}

Expand Down
38 changes: 32 additions & 6 deletions scratch/ScratchIslandApp/SampleApp/MyPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,23 @@
<TextBox x:Name="GuidInput"
Width="400"
PlaceholderText="{}{guid here}" />
<Button Grid.Row="0">
<Button x:Name="CreateOutOfProcControl"
Grid.Row="0"
Tapped="CreateClicked">
Create
</Button>
<Button x:Name="CloseOutOfProcControl"
Grid.Row="0"
Margin="4,0,0,0"
Tapped="CloseClicked">
Close
</Button>
<Button x:Name="KillOutOfProcControl"
Grid.Row="0"
Margin="4,0,0,0"
Tapped="KillClicked">
Kill
</Button>

</StackPanel>

Expand All @@ -46,14 +60,26 @@
VerticalAlignment="Stretch"
Background="#ff0000" />

<Grid x:Name="OutOfProcContent"
Grid.Column="1"
Padding="16"
<Grid Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#0000ff" />
VerticalAlignment="Stretch">

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<StackPanel x:Name="Log"
Grid.Row="0"
Orientation="Vertical" />

<Grid x:Name="OutOfProcContent"
Grid.Row="1"
Padding="16"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="#0000ff" />
</Grid>

</Grid>

Expand Down
17 changes: 12 additions & 5 deletions scratch/ScratchIslandApp/SampleApp/SampleAppLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
</PropertyGroup>

<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />

<ItemDefinitionGroup>

<ClCompile>
Expand Down Expand Up @@ -147,14 +153,15 @@
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />

<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />

<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>

<!--
Expand Down
11 changes: 8 additions & 3 deletions scratch/ScratchIslandApp/SampleApp/dll/SampleApp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
Expand Down Expand Up @@ -81,13 +85,11 @@


<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>

<ItemDefinitionGroup>
Expand All @@ -102,4 +104,7 @@
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />

<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
</Project>
Loading