Skip to content

Commit ebbe961

Browse files
committed
Add an entry to the installed programs on windows
1 parent 88c08bf commit ebbe961

File tree

3 files changed

+64
-10
lines changed

3 files changed

+64
-10
lines changed

src/cli/self_update.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ pub fn install(
344344
do_write_env_files()?;
345345

346346
if !opts.no_modify_path {
347+
do_add_to_programs()?;
347348
do_add_to_path()?;
348349
}
349350
utils::create_rustup_home()?;
@@ -855,6 +856,7 @@ pub fn uninstall(no_prompt: bool) -> Result<utils::ExitCode> {
855856

856857
// Remove CARGO_HOME/bin from PATH
857858
do_remove_from_path()?;
859+
do_remove_from_programs()?;
858860

859861
// Delete everything in CARGO_HOME *except* the rustup bin
860862

src/cli/self_update/unix.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ pub fn do_write_env_files() -> Result<()> {
120120
Ok(())
121121
}
122122

123+
pub fn do_add_to_programs() -> Result<()> {
124+
Ok(())
125+
}
126+
127+
pub fn do_remove_from_programs() -> Result<()> {
128+
Ok(())
129+
}
130+
123131
/// Tell the upgrader to replace the rustup bins, then delete
124132
/// itself. Like with uninstallation, on Windows we're going to
125133
/// have to jump through hoops to make everything work right.

src/cli/self_update/windows.rs

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use std::env::consts::EXE_SUFFIX;
2+
use std::ffi::{OsStr, OsString};
3+
use std::os::windows::ffi::{OsStrExt, OsStringExt};
24
use std::path::Path;
35
use std::process::Command;
46

@@ -10,6 +12,9 @@ use crate::process;
1012
use crate::utils::utils;
1113
use crate::utils::Notification;
1214

15+
use winreg::enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE};
16+
use winreg::{RegKey, RegValue};
17+
1318
pub fn ensure_prompt() -> Result<()> {
1419
writeln!(process().stdout(),)?;
1520
writeln!(process().stdout(), "Press the Enter key to continue.")?;
@@ -42,7 +47,6 @@ pub fn do_msvc_check(opts: &InstallOpts<'_>) -> Result<bool> {
4247

4348
/// Run by rustup-gc-$num.exe to delete CARGO_HOME
4449
pub fn complete_windows_uninstall() -> Result<utils::ExitCode> {
45-
use std::ffi::OsStr;
4650
use std::process::Stdio;
4751

4852
wait_for_parent()?;
@@ -150,8 +154,6 @@ fn _apply_new_path(new_path: Option<Vec<u16>>) -> Result<()> {
150154
use winapi::um::winuser::{
151155
SendMessageTimeoutA, HWND_BROADCAST, SMTO_ABORTIFHUNG, WM_SETTINGCHANGE,
152156
};
153-
use winreg::enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE};
154-
use winreg::{RegKey, RegValue};
155157

156158
let new_path = match new_path {
157159
Some(new_path) => new_path,
@@ -198,8 +200,6 @@ fn _apply_new_path(new_path: Option<Vec<u16>>) -> Result<()> {
198200
// should not mess with it.
199201
fn get_windows_path_var() -> Result<Option<Vec<u16>>> {
200202
use std::io;
201-
use winreg::enums::{HKEY_CURRENT_USER, KEY_READ, KEY_WRITE};
202-
use winreg::RegKey;
203203

204204
let root = RegKey::predef(HKEY_CURRENT_USER);
205205
let environment = root
@@ -270,9 +270,6 @@ fn _with_path_cargo_home_bin<F>(f: F) -> Result<Option<Vec<u16>>>
270270
where
271271
F: FnOnce(Vec<u16>, Vec<u16>) -> Option<Vec<u16>>,
272272
{
273-
use std::ffi::OsString;
274-
use std::os::windows::ffi::OsStrExt;
275-
276273
let windows_path = get_windows_path_var()?;
277274
let mut path_str = utils::cargo_home()?;
278275
path_str.push("bin");
@@ -285,6 +282,55 @@ pub fn do_remove_from_path() -> Result<()> {
285282
_apply_new_path(new_path)
286283
}
287284

285+
const RUSTUP_UNINSTALL_ENTRY: &str = r"Software\Microsoft\Windows\CurrentVersion\Uninstall\Rustup";
286+
287+
pub fn do_add_to_programs() -> Result<()> {
288+
use std::path::PathBuf;
289+
290+
let key = RegKey::predef(HKEY_CURRENT_USER)
291+
.create_subkey(RUSTUP_UNINSTALL_ENTRY)
292+
.chain_err(|| ErrorKind::PermissionDenied)?
293+
.0;
294+
295+
// Don't overwrite registry if Rustup is already installed
296+
let prev = key
297+
.get_raw_value("UninstallString")
298+
.map(|val| from_winreg_value(&val));
299+
if let Ok(Some(s)) = prev {
300+
let mut path = PathBuf::from(OsString::from_wide(&s));
301+
path.pop();
302+
if path.exists() {
303+
return Ok(());
304+
}
305+
}
306+
307+
let mut path = utils::cargo_home()?;
308+
path.push("bin\rustup.exe");
309+
let mut uninstall_cmd = OsString::from("\"");
310+
uninstall_cmd.push(path);
311+
uninstall_cmd.push("\" self uninstall");
312+
313+
let reg_value = RegValue {
314+
bytes: to_winreg_bytes(uninstall_cmd.encode_wide().collect()),
315+
vtype: RegType::REG_SZ,
316+
};
317+
318+
key.set_raw_value("UninstallString", &reg_value)
319+
.chain_err(|| ErrorKind::PermissionDenied)?;
320+
key.set_value("DisplayName", &"Rustup: the Rust toolchain installer")
321+
.chain_err(|| ErrorKind::PermissionDenied)?;
322+
323+
Ok(())
324+
}
325+
326+
pub fn do_remove_from_programs() -> Result<()> {
327+
match RegKey::predef(HKEY_CURRENT_USER).delete_subkey_all(RUSTUP_UNINSTALL_ENTRY) {
328+
Ok(()) => Ok(()),
329+
Err(ref e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()),
330+
Err(e) => Err(e).chain_err(|| ErrorKind::PermissionDenied),
331+
}
332+
}
333+
288334
/// Convert a vector UCS-2 chars to a null-terminated UCS-2 string in bytes
289335
pub fn to_winreg_bytes(mut v: Vec<u16>) -> Vec<u8> {
290336
v.push(0);
@@ -296,7 +342,6 @@ pub fn to_winreg_bytes(mut v: Vec<u16>) -> Vec<u8> {
296342
/// does a lossy unicode conversion.
297343
pub fn from_winreg_value(val: &winreg::RegValue) -> Option<Vec<u16>> {
298344
use std::slice;
299-
use winreg::enums::RegType;
300345

301346
match val.vtype {
302347
RegType::REG_SZ | RegType::REG_EXPAND_SZ => {
@@ -364,7 +409,6 @@ pub fn self_replace() -> Result<utils::ExitCode> {
364409
pub fn delete_rustup_and_cargo_home() -> Result<()> {
365410
use std::io;
366411
use std::mem;
367-
use std::os::windows::ffi::OsStrExt;
368412
use std::ptr;
369413
use std::thread;
370414
use std::time::Duration;

0 commit comments

Comments
 (0)