master
cpp 222 lines 7.1 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 SessionTasks.cpp
8
9 Abstract:
10
11 Implementation of session command related execution logic.
12
13 --*/
14 #include "Argument.h"
15 #include "ArgumentConvertedTypes.h"
16 #include "CLIExecutionContext.h"
17 #include "JsonUtils.h"
18 #include "SessionService.h"
19 #include "SessionTasks.h"
20 #include "TableOutput.h"
21 #include "Task.h"
22 #include "WSLCUserSettings.h"
23
24 using namespace wsl::shared;
25 using namespace wsl::windows::common::string;
26 using namespace wsl::windows::common::wslutil;
27 using namespace wsl::windows::wslc::execution;
28 using namespace wsl::windows::wslc::models;
29 using namespace wsl::windows::wslc::services;
30
31 namespace wsl::windows::wslc::task {
32
33 static void WriteSessionTable(Terminal& terminal, const std::vector<SessionInformation>& sessions)
34 {
35 TableOutput<3> table(
36 terminal,
37 {Localization::MessageWslcHeaderId(), Localization::MessageWslcHeaderCreatorPid(), Localization::MessageWslcHeaderDisplayName()});
38
39 for (const auto& session : sessions)
40 {
41 table.WriteRow({
42 std::to_wstring(session.SessionId),
43 std::to_wstring(session.CreatorPid),
44 session.DisplayName,
45 });
46 }
47
48 table.Complete();
49 }
50
51 void AttachToSession(CLIExecutionContext& context)
52 {
53 auto& session = context.Data.Get<Data::Session>();
54 context.ExitCode = SessionService::Attach(context.Terminal, session);
55 }
56
57 void OpenSessionIfSpecified(CLIExecutionContext& context)
58 {
59 if (context.GlobalArgs.Contains(ArgType::Session))
60 {
61 const auto& sessionName = context.GlobalArgs.GetValue<ArgType::Session>();
62 context.Data.Add<Data::Session>(SessionService::OpenSession(sessionName));
63 }
64 }
65
66 void OpenOrCreateDefaultSession(CLIExecutionContext& context)
67 {
68 if (!context.Data.Contains(Data::Session))
69 {
70 context.Data.Add<Data::Session>(SessionService::OpenOrCreateDefaultSession(context.Terminal));
71 }
72 }
73
74 void OpenDefaultSession(CLIExecutionContext& context)
75 {
76 if (!context.Data.Contains(Data::Session))
77 {
78 context.Data.Add<Data::Session>(SessionService::OpenDefaultSession());
79 }
80 }
81
82 void ResolveSession(CLIExecutionContext& context)
83 {
84 OpenSessionIfSpecified(context);
85 OpenOrCreateDefaultSession(context);
86 }
87
88 void ListSessions(CLIExecutionContext& context)
89 {
90 auto sessions = SessionService::List();
91 if (context.Args.GetValue<ArgType::Verbose>())
92 {
93 const wchar_t* plural = sessions.size() == 1 ? L"" : L"s";
94 context.Terminal.Output(L"[wslc] Found {} session{}\n", sessions.size(), plural);
95 }
96
97 WriteSessionTable(context.Terminal, sessions);
98 }
99
100 static std::wstring FormatManagerVersion(const WSLCVersion& version)
101 {
102 return std::format(L"{}.{}.{}", version.Major, version.Minor, version.Revision);
103 }
104
105 void ShowSystemInfo(CLIExecutionContext& context)
106 {
107 const auto windowsVersion = wsl::windows::common::helpers::GetWindowsVersionString();
108 const auto settingsFilePath = settings::User().SettingsFilePath().wstring();
109
110 switch (context.Args.GetValue<ArgType::Format>(FormatType::Table))
111 {
112 case FormatType::Json:
113 {
114 // A JSON document can't be emitted partially, so an unreachable service fails the whole command.
115 const auto managerVersionText = FormatManagerVersion(SessionService::ManagerVersion());
116 const auto sessions = SessionService::List();
117
118 nlohmann::json root;
119
120 auto& client = root["Client"];
121 client["Version"] = std::string{WSL_PACKAGE_VERSION};
122 client["KernelVersion"] = std::string{KERNEL_VERSION};
123 client["Direct3DVersion"] = std::string{DIRECT3D_VERSION};
124 client["DxCoreVersion"] = std::string{DXCORE_VERSION};
125 client["WindowsVersion"] = windowsVersion;
126 client["SettingsFile"] = settingsFilePath;
127
128 if constexpr (!wsl::shared::OfficialBuild)
129 {
130 client["MsBuildVersion"] = _MSC_VER;
131 client["Commit"] = std::string{COMMIT_HASH};
132 client["BuildTime"] = std::string{__TIME__ " " __DATE__};
133 }
134
135 auto& server = root["Server"];
136 server["SessionManagerVersion"] = managerVersionText;
137
138 auto& sessionArray = server["Sessions"];
139 sessionArray = nlohmann::json::array();
140 for (const auto& session : sessions)
141 {
142 sessionArray.push_back({{"ID", session.SessionId}, {"CreatorPid", session.CreatorPid}, {"Name", session.DisplayName}});
143 }
144
145 context.Terminal.Output(L"{}\n", ToJsonW(root, c_jsonCompactIndent));
146 break;
147 }
148 case FormatType::Table:
149 {
150 const auto managerVersionText = FormatManagerVersion(SessionService::ManagerVersion());
151 const auto sessions = SessionService::List();
152
153 context.Terminal.Output(L"{}\n", Localization::WSLCCLI_SystemInfoClientHeader());
154 context.Terminal.Output(
155 L"{}\n", Localization::WSLCCLI_SystemInfoVersions(WSL_PACKAGE_VERSION, KERNEL_VERSION, DIRECT3D_VERSION, DXCORE_VERSION, windowsVersion));
156
157 if constexpr (!wsl::shared::OfficialBuild)
158 {
159 context.Terminal.Output(L"{}\n", Localization::MessageBuildInfo(_MSC_VER, COMMIT_HASH, __TIME__ " " __DATE__));
160 }
161
162 context.Terminal.Output(L"{}\n", Localization::WSLCCLI_SystemInfoSettingsFile(settingsFilePath));
163
164 context.Terminal.Output(L"\n{}\n", Localization::WSLCCLI_SystemInfoServerHeader());
165 context.Terminal.Output(L"{}\n", Localization::WSLCCLI_SystemInfoSessionManagerVersion(managerVersionText));
166 context.Terminal.Output(L"{}\n", Localization::WSLCCLI_SystemInfoSessions(sessions.size()));
167
168 if (!sessions.empty())
169 {
170 WriteSessionTable(context.Terminal, sessions);
171 }
172
173 break;
174 }
175 default:
176 THROW_HR(E_UNEXPECTED);
177 }
178 }
179
180 void TerminateSession(CLIExecutionContext& context)
181 {
182 auto& session = context.Data.Get<Data::Session>();
183 context.ExitCode = SessionService::TerminateSession(context.Terminal, session);
184 }
185
186 void RunInSession(CLIExecutionContext& context)
187 {
188 auto& session = context.Data.Get<Data::Session>();
189
190 std::vector<std::string> arguments;
191 arguments.emplace_back(wsl::windows::common::string::WideToMultiByte(context.Args.GetValue<ArgType::Command>()));
192 if (context.Args.Contains(ArgType::ForwardArgs))
193 {
194 for (const auto& arg : context.Args.GetValue<ArgType::ForwardArgs>())
195 {
196 arguments.emplace_back(wsl::windows::common::string::WideToMultiByte(arg));
197 }
198 }
199
200 context.ExitCode = SessionService::Run(context.Terminal, session, arguments);
201 }
202
203 void EnterSession(CLIExecutionContext& context)
204 {
205 auto storagePath = std::filesystem::absolute(context.Args.GetValue<ArgType::StoragePath>());
206
207 std::wstring sessionName;
208 if (context.Args.Contains(ArgType::Name))
209 {
210 sessionName = context.Args.GetValue<ArgType::Name>();
211 }
212 else
213 {
214 GUID guid{};
215 THROW_IF_FAILED(CoCreateGuid(&guid));
216 sessionName = wsl::shared::string::GuidToString<wchar_t>(guid, wsl::shared::string::GuidToStringFlags::None);
217 }
218
219 context.ExitCode = SessionService::Enter(context.Terminal, storagePath.wstring(), sessionName);
220 }
221
222 } // namespace wsl::windows::wslc::task