@@ -538,16 +538,28 @@ impl Update {
538
538
539
539
#[ cfg( windows) ]
540
540
enum WindowsUpdaterType {
541
- Nsis ,
542
- Msi ,
541
+ Nsis {
542
+ path : PathBuf ,
543
+ #[ allow( unused) ]
544
+ temp : Option < tempfile:: TempPath > ,
545
+ } ,
546
+ Msi {
547
+ path : PathBuf ,
548
+ #[ allow( unused) ]
549
+ temp : Option < tempfile:: TempPath > ,
550
+ } ,
543
551
}
544
552
545
553
#[ cfg( windows) ]
546
554
impl WindowsUpdaterType {
547
- fn extension ( & self ) -> & str {
548
- match self {
549
- WindowsUpdaterType :: Nsis => ".exe" ,
550
- WindowsUpdaterType :: Msi => ".msi" ,
555
+ fn nsis ( path : PathBuf , temp : Option < tempfile:: TempPath > ) -> Self {
556
+ Self :: Nsis { path, temp }
557
+ }
558
+
559
+ fn msi ( path : PathBuf , temp : Option < tempfile:: TempPath > ) -> Self {
560
+ Self :: Msi {
561
+ path : path. wrap_in_quotes ( ) ,
562
+ temp,
551
563
}
552
564
}
553
565
}
@@ -580,24 +592,19 @@ impl Update {
580
592
Win32 :: UI :: { Shell :: ShellExecuteW , WindowsAndMessaging :: SW_SHOW } ,
581
593
} ;
582
594
583
- let ( updater_type, path, _temp) = Self :: extract ( bytes) ?;
584
-
585
- let mut msi_path = std:: ffi:: OsString :: new ( ) ;
586
- msi_path. push ( "\" " ) ;
587
- msi_path. push ( & path) ;
588
- msi_path. push ( "\" " ) ;
595
+ let updater_type = Self :: extract ( bytes) ?;
589
596
590
597
let install_mode = self . config . install_mode ( ) ;
591
- let installer_args: Vec < & OsStr > = match updater_type {
592
- WindowsUpdaterType :: Nsis => install_mode
598
+ let installer_args: Vec < & OsStr > = match & updater_type {
599
+ WindowsUpdaterType :: Nsis { .. } => install_mode
593
600
. nsis_args ( )
594
601
. iter ( )
595
602
. map ( OsStr :: new)
596
603
. chain ( once ( OsStr :: new ( "/UPDATE" ) ) )
597
604
. chain ( self . nsis_installer_args ( ) )
598
605
. chain ( self . installer_args ( ) )
599
606
. collect ( ) ,
600
- WindowsUpdaterType :: Msi => [ OsStr :: new ( "/i" ) , msi_path . as_os_str ( ) ]
607
+ WindowsUpdaterType :: Msi { path , .. } => [ OsStr :: new ( "/i" ) , path . as_os_str ( ) ]
601
608
. into_iter ( )
602
609
. chain ( install_mode. msiexec_args ( ) . iter ( ) . map ( OsStr :: new) )
603
610
. chain ( once ( OsStr :: new ( "/promptrestart" ) ) )
@@ -609,17 +616,17 @@ impl Update {
609
616
on_before_exit ( ) ;
610
617
}
611
618
612
- let parameters = installer_args. join ( OsStr :: new ( " " ) ) ;
613
- let parameters = encode_wide ( parameters) ;
614
-
615
- let path = match updater_type {
616
- WindowsUpdaterType :: Msi => std:: env:: var ( "SYSTEMROOT" ) . as_ref ( ) . map_or_else (
619
+ let file = match & updater_type {
620
+ WindowsUpdaterType :: Nsis { path, .. } => path. as_os_str ( ) . to_os_string ( ) ,
621
+ WindowsUpdaterType :: Msi { .. } => std:: env:: var ( "SYSTEMROOT" ) . as_ref ( ) . map_or_else (
617
622
|_| OsString :: from ( "msiexec.exe" ) ,
618
623
|p| OsString :: from ( format ! ( "{p}\\ System32\\ msiexec.exe" ) ) ,
619
624
) ,
620
- WindowsUpdaterType :: Nsis => path. as_os_str ( ) . to_os_string ( ) ,
621
625
} ;
622
- let file = encode_wide ( path) ;
626
+ let file = encode_wide ( file) ;
627
+
628
+ let parameters = installer_args. join ( OsStr :: new ( " " ) ) ;
629
+ let parameters = encode_wide ( parameters) ;
623
630
624
631
unsafe {
625
632
ShellExecuteW (
@@ -649,7 +656,7 @@ impl Update {
649
656
. collect :: < Vec < _ > > ( )
650
657
}
651
658
652
- fn extract ( bytes : & [ u8 ] ) -> Result < ( WindowsUpdaterType , PathBuf , Option < tempfile :: TempPath > ) > {
659
+ fn extract ( bytes : & [ u8 ] ) -> Result < WindowsUpdaterType > {
653
660
#[ cfg( feature = "zip" ) ]
654
661
if infer:: archive:: is_zip ( bytes) {
655
662
return Self :: extract_zip ( bytes) ;
@@ -659,9 +666,7 @@ impl Update {
659
666
}
660
667
661
668
#[ cfg( feature = "zip" ) ]
662
- fn extract_zip (
663
- bytes : & [ u8 ] ,
664
- ) -> Result < ( WindowsUpdaterType , PathBuf , Option < tempfile:: TempPath > ) > {
669
+ fn extract_zip ( bytes : & [ u8 ] ) -> Result < WindowsUpdaterType > {
665
670
let tmp_dir = tempfile:: Builder :: new ( ) . tempdir ( ) ?. into_path ( ) ;
666
671
667
672
let archive = Cursor :: new ( bytes) ;
@@ -670,38 +675,38 @@ impl Update {
670
675
671
676
let paths = std:: fs:: read_dir ( & tmp_dir) ?;
672
677
for path in paths {
673
- let found_path = path?. path ( ) ;
674
- let ext = found_path . extension ( ) ;
678
+ let path = path?. path ( ) ;
679
+ let ext = path . extension ( ) ;
675
680
if ext == Some ( OsStr :: new ( "exe" ) ) {
676
- return Ok ( ( WindowsUpdaterType :: Nsis , found_path , None ) ) ;
681
+ return Ok ( WindowsUpdaterType :: nsis ( path , None ) ) ;
677
682
} else if ext == Some ( OsStr :: new ( "msi" ) ) {
678
- return Ok ( ( WindowsUpdaterType :: Msi , found_path , None ) ) ;
683
+ return Ok ( WindowsUpdaterType :: msi ( path , None ) ) ;
679
684
}
680
685
}
681
686
682
687
Err ( crate :: Error :: BinaryNotFoundInArchive )
683
688
}
684
689
685
- fn extract_exe (
686
- bytes : & [ u8 ] ,
687
- ) -> Result < ( WindowsUpdaterType , PathBuf , Option < tempfile:: TempPath > ) > {
688
- use std:: io:: Write ;
689
-
690
- let updater_type = if infer:: app:: is_exe ( bytes) {
691
- WindowsUpdaterType :: Nsis
690
+ fn extract_exe ( bytes : & [ u8 ] ) -> Result < WindowsUpdaterType > {
691
+ if infer:: app:: is_exe ( bytes) {
692
+ let ( path, temp) = Self :: write_to_temp ( bytes, ".exe" ) ?;
693
+ Ok ( WindowsUpdaterType :: nsis ( path, temp) )
692
694
} else if infer:: archive:: is_msi ( bytes) {
693
- WindowsUpdaterType :: Msi
695
+ let ( path, temp) = Self :: write_to_temp ( bytes, ".msi" ) ?;
696
+ Ok ( WindowsUpdaterType :: msi ( path, temp) )
694
697
} else {
695
- return Err ( crate :: Error :: InvalidUpdaterFormat ) ;
696
- } ;
698
+ Err ( crate :: Error :: InvalidUpdaterFormat )
699
+ }
700
+ }
697
701
698
- let ext = updater_type. extension ( ) ;
702
+ fn write_to_temp ( bytes : & [ u8 ] , ext : & str ) -> Result < ( PathBuf , Option < tempfile:: TempPath > ) > {
703
+ use std:: io:: Write ;
699
704
700
705
let mut temp_file = tempfile:: Builder :: new ( ) . suffix ( ext) . tempfile ( ) ?;
701
706
temp_file. write_all ( bytes) ?;
702
- let temp_path = temp_file. into_temp_path ( ) ;
703
707
704
- Ok ( ( updater_type, temp_path. to_path_buf ( ) , Some ( temp_path) ) )
708
+ let temp = temp_file. into_temp_path ( ) ;
709
+ Ok ( ( temp. to_path_buf ( ) , Some ( temp) ) )
705
710
}
706
711
}
707
712
@@ -1005,3 +1010,34 @@ fn encode_wide(string: impl AsRef<OsStr>) -> Vec<u16> {
1005
1010
. chain ( std:: iter:: once ( 0 ) )
1006
1011
. collect ( )
1007
1012
}
1013
+
1014
+ #[ cfg( windows) ]
1015
+ trait PathExt {
1016
+ fn wrap_in_quotes ( & self ) -> Self ;
1017
+ }
1018
+
1019
+ #[ cfg( windows) ]
1020
+ impl PathExt for PathBuf {
1021
+ fn wrap_in_quotes ( & self ) -> Self {
1022
+ let mut msi_path = OsString :: from ( "\" " ) ;
1023
+ msi_path. push ( self . as_os_str ( ) ) ;
1024
+ msi_path. push ( "\" " ) ;
1025
+ PathBuf :: from ( msi_path)
1026
+ }
1027
+ }
1028
+
1029
+ #[ cfg( test) ]
1030
+ mod tests {
1031
+
1032
+ #[ test]
1033
+ #[ cfg( windows) ]
1034
+ fn it_wraps_correctly ( ) {
1035
+ use super :: PathExt ;
1036
+ use std:: path:: PathBuf ;
1037
+
1038
+ assert_eq ! (
1039
+ PathBuf :: from( "C:\\ Users\\ Some User\\ AppData\\ tauri-example.exe" ) . wrap_in_quotes( ) ,
1040
+ PathBuf :: from( "\" C:\\ Users\\ Some User\\ AppData\\ tauri-example.exe\" " )
1041
+ )
1042
+ }
1043
+ }
0 commit comments