Skip to content

Commit 02496b0

Browse files
authored
Merge pull request #3004 from ChrisDenton/show-vs-nonzero
Windows: Improve handling of Visual Studio errors
2 parents feec94b + 60d75df commit 02496b0

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

src/cli/self_update.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use anyhow::{anyhow, Context, Result};
5757
use cfg_if::cfg_if;
5858
use same_file::Handle;
5959

60-
use super::common::{self, ignorable_error, Confirm};
60+
use super::common::{self, ignorable_error, report_error, Confirm};
6161
use super::errors::*;
6262
use super::markdown::md;
6363
use super::term2;
@@ -380,7 +380,22 @@ pub(crate) fn install(
380380
"\nAutomatically download and install Visual Studio 2022 Community edition? (Y/n)",
381381
true,
382382
)? {
383-
try_install_msvc()?;
383+
match try_install_msvc(&opts) {
384+
Err(e) => {
385+
// Make sure the console doesn't exit before the user can
386+
// see the error and give the option to continue anyway.
387+
report_error(&e);
388+
if !common::confirm("\nContinue installing rustup? (y/N)", false)? {
389+
info!("aborting installation");
390+
return Ok(utils::ExitCode(0));
391+
}
392+
}
393+
Ok(ContinueInstall::No) => {
394+
ensure_prompt()?;
395+
return Ok(utils::ExitCode(0));
396+
}
397+
_ => {}
398+
}
384399
} else {
385400
md(&mut term, MSVC_MANUAL_INSTALL_MESSAGE);
386401
if !common::confirm("\nContinue? (y/N)", false)? {

src/cli/self_update/windows.rs

+57-14
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub(crate) fn do_msvc_check(opts: &InstallOpts<'_>) -> Option<VsInstallPlan> {
6666
}
6767
}
6868

69-
#[derive(Debug)]
69+
#[derive(Debug, Eq, PartialEq)]
7070
struct VsInstallError(i32);
7171
impl std::error::Error for VsInstallError {}
7272
impl fmt::Display for VsInstallError {
@@ -97,8 +97,21 @@ impl fmt::Display for VsInstallError {
9797
write!(f, "{} (exit code {})", message, self.0)
9898
}
9999
}
100+
impl VsInstallError {
101+
const REBOOTING_NOW: Self = Self(1641);
102+
const REBOOT_REQUIRED: Self = Self(3010);
103+
}
104+
105+
pub(crate) enum ContinueInstall {
106+
Yes,
107+
No,
108+
}
100109

101-
pub(crate) fn try_install_msvc() -> Result<()> {
110+
/// Tries to install the needed Visual Studio components.
111+
///
112+
/// Returns `Ok(ContinueInstall::No)` if installing Visual Studio was successful
113+
/// but the rustup install should not be continued at this time.
114+
pub(crate) fn try_install_msvc(opts: &InstallOpts<'_>) -> Result<ContinueInstall> {
102115
// download the installer
103116
let visual_studio_url = utils::parse_url("https://aka.ms/vs/17/release/vs_community.exe")?;
104117

@@ -131,16 +144,7 @@ pub(crate) fn try_install_msvc() -> Result<()> {
131144

132145
// It's possible an earlier or later version of the Windows SDK has been
133146
// installed separately from Visual Studio so installing it can be skipped.
134-
let mut has_libs = false;
135-
if let Some(paths) = process().var_os("lib") {
136-
for mut path in split_paths(&paths) {
137-
path.push("kernel32.lib");
138-
if path.exists() {
139-
has_libs = true;
140-
}
141-
}
142-
};
143-
if !has_libs {
147+
if !has_windows_sdk_libs() {
144148
cmd.args([
145149
"--add",
146150
"Microsoft.VisualStudio.Component.Windows11SDK.22000",
@@ -154,12 +158,51 @@ pub(crate) fn try_install_msvc() -> Result<()> {
154158
.context("error running Visual Studio installer")?;
155159

156160
if exit_status.success() {
157-
Ok(())
161+
Ok(ContinueInstall::Yes)
158162
} else {
159-
Err(VsInstallError(exit_status.code().unwrap())).context("failed to install Visual Studio")
163+
match VsInstallError(exit_status.code().unwrap()) {
164+
err @ VsInstallError::REBOOT_REQUIRED => {
165+
// A reboot is required but the user opted to delay it.
166+
warn!("{}", err);
167+
Ok(ContinueInstall::Yes)
168+
}
169+
err @ VsInstallError::REBOOTING_NOW => {
170+
// The user is wanting to reboot right now, so we should
171+
// not continue the install.
172+
warn!("{}", err);
173+
info!("\nRun rustup-init after restart to continue install");
174+
Ok(ContinueInstall::No)
175+
}
176+
err => {
177+
// It's possible that the installer returned a non-zero exit code
178+
// even though the required components were successfully installed.
179+
// In that case we warn about the error but continue on.
180+
let have_msvc = do_msvc_check(opts).is_none();
181+
let has_libs = has_windows_sdk_libs();
182+
if have_msvc && has_libs {
183+
warn!("Visual Studio is installed but a problem ocurred during installation");
184+
warn!("{}", err);
185+
Ok(ContinueInstall::Yes)
186+
} else {
187+
Err(err).context("failed to install Visual Studio")
188+
}
189+
}
190+
}
160191
}
161192
}
162193

194+
fn has_windows_sdk_libs() -> bool {
195+
if let Some(paths) = process().var_os("lib") {
196+
for mut path in split_paths(&paths) {
197+
path.push("kernel32.lib");
198+
if path.exists() {
199+
return true;
200+
}
201+
}
202+
};
203+
false
204+
}
205+
163206
/// Run by rustup-gc-$num.exe to delete CARGO_HOME
164207
pub fn complete_windows_uninstall() -> Result<utils::ExitCode> {
165208
use std::process::Stdio;

0 commit comments

Comments
 (0)