@@ -54,6 +54,21 @@ pub fn is_program_in_path(program: &str) -> bool {
5454 . unwrap_or ( false )
5555}
5656
57+ #[ cfg( windows) ]
58+ pub fn is_program_in_path ( program : & str ) -> bool {
59+ std:: env:: var_os ( "PATH" )
60+ . and_then ( |paths| {
61+ paths. to_str ( ) . map ( |paths| {
62+ paths. split ( ';' ) . any ( |dir| {
63+ fs:: metadata ( format ! ( "{}\\ {}.exe" , dir, program) ) . is_ok ( )
64+ || fs:: metadata ( format ! ( "{}\\ {}.cmd" , dir, program) ) . is_ok ( )
65+ || fs:: metadata ( format ! ( "{}\\ {}.bat" , dir, program) ) . is_ok ( )
66+ } )
67+ } )
68+ } )
69+ . unwrap_or ( false )
70+ }
71+
5772#[ macro_export]
5873macro_rules! println_info {
5974 ( $( $arg: tt) * ) => { {
@@ -71,68 +86,68 @@ macro_rules! println_error {
7186}
7287
7388#[ cfg( windows) ]
74- fn install_dependency ( path : & Path , args : & [ & str ] ) {
75- if path. exists ( ) {
76- match runas:: Command :: new ( path) . args ( args) . status ( ) {
77- Ok ( status) if status. success ( ) || matches ! ( status. code( ) , Some ( 1638 ) | Some ( 3010 ) ) => {
78- info ! ( "{} installed successfully" , path. display( ) ) ;
79- }
80- Ok ( status) => {
81- println_error ! ( "Error installing dependency {}, {status}" , path. display( ) ) ;
82- }
83- Err ( e) if e. raw_os_error ( ) == Some ( 740 ) => {
84- println_error ! (
85- "Error: Process requires elevation. Please run the launcher as administrator or install {} manually" ,
86- path. display( )
87- ) ;
88- }
89- Err ( e) => {
90- println_error ! ( "Error running file {}: {e}" , path. display( ) ) ;
91- }
92- }
89+ pub async fn install_dependencies ( _install_path : & Path , force_reinstall : bool ) {
90+ if force_reinstall {
91+ crate :: println_info!( "Force reinstalling redistributables..." ) ;
9392 } else {
94- println_error ! ( "Installer not found: {}" , path . display ( ) ) ;
93+ crate :: println_info !( "Installing redistributables..." ) ;
9594 }
96- }
97-
98- #[ cfg( windows) ]
99- async fn download_and_install_dependency ( url : & str , path : & Path , args : & [ & str ] ) {
100- if !path. exists ( ) {
101- info ! ( "Downloading {} from {url}" , path. display( ) ) ;
102- if let Some ( parent) = path. parent ( ) {
103- if let Err ( e) = fs:: create_dir_all ( parent) {
104- println_error ! ( "Error creating directory {}: {e}" , parent. display( ) ) ;
105- return ;
106- }
107- }
108- match crate :: http_async:: download_file ( url, & std:: path:: PathBuf :: from ( path) ) . await {
109- Ok ( _) => info ! ( "Downloaded {}" , path. display( ) ) ,
110- Err ( e) => {
111- println_error ! ( "Error downloading {}: {e}" , path. display( ) ) ;
112- return ;
113- }
114- }
95+
96+ if !is_program_in_path ( "winget" ) {
97+ crate :: println_info!(
98+ "winget is not available. Unable to install redistributables automatically."
99+ ) ;
100+ crate :: println_info!(
101+ "Please install Visual C++ Redistributables and DirectX manually if needed."
102+ ) ;
103+ return ;
115104 }
116- install_dependency ( path, args) ;
117- }
118105
119- #[ cfg( windows) ]
120- pub async fn install_dependencies ( install_path : & Path ) {
121- println ! ( "If you run into issues during dependency installation, open alterware-launcher.json and set \" skip_redist\" to true" ) ;
122-
123- let redist_dir = install_path. join ( "redist\\ alterware" ) ;
124- let redists = [
125- ( "VC++ 2005" , "https://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x86.EXE" , "vcredist_2005_x86.exe" , & [ "/Q" ] as & [ & str ] ) ,
126- ( "VC++ 2008" , "https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe" , "vcredist_2008_x86.exe" , & [ "/Q" ] as & [ & str ] ) ,
127- ( "VC++ 2010" , "https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe" , "vcredist_2010_x86.exe" , & [ "/Q" ] as & [ & str ] ) ,
128- ( "VC++ 2015" , "https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe" , "vcredist_2015_x86.exe" , & [ "/install" , "/passive" , "/norestart" ] as & [ & str ] ) ,
129- ( "DirectX End User Runtime" , "https://download.microsoft.com/download/1/7/1/1718CCC4-6315-4D8E-9543-8E28A4E18C4C/dxwebsetup.exe" , "dxwebsetup.exe" , & [ "/Q" ] as & [ & str ] ) ,
106+ let packages = [
107+ "Microsoft.VCRedist.2005.x86" ,
108+ "Microsoft.VCRedist.2008.x86" ,
109+ "Microsoft.VCRedist.2010.x86" ,
110+ "Microsoft.VCRedist.2015+.x86" ,
111+ "Microsoft.DirectX" ,
130112 ] ;
131113
132- for ( name, url, file, args) in redists. iter ( ) {
133- let path = redist_dir. join ( file) ;
134- println_info ! ( "Installing {name}" ) ;
135- download_and_install_dependency ( url, & path, args) . await ;
114+ for package in packages. iter ( ) {
115+ let mut args = vec ! [
116+ "install" ,
117+ "--id" ,
118+ package,
119+ "--silent" ,
120+ "--accept-package-agreements" ,
121+ "--accept-source-agreements" ,
122+ ] ;
123+
124+ if force_reinstall {
125+ args. push ( "--force" ) ;
126+ }
127+
128+ let result = std:: process:: Command :: new ( "winget" )
129+ . args ( & args)
130+ . output ( ) ;
131+
132+ match result {
133+ Ok ( output) => {
134+ if output. status . success ( ) {
135+ crate :: println_info!( "Successfully installed {}" , package) ;
136+ } else {
137+ crate :: println_info!(
138+ "Failed to install {} (may already be installed)" ,
139+ package
140+ ) ;
141+ }
142+ }
143+ Err ( _) => {
144+ crate :: println_info!( "Unable to install redistributables automatically." ) ;
145+ crate :: println_info!(
146+ "Please install Visual C++ Redistributables and DirectX manually if needed."
147+ ) ;
148+ break ;
149+ }
150+ }
136151 }
137152}
138153
0 commit comments