@@ -19,7 +19,7 @@ import * as path from 'path';
1919import * as os from 'os' ;
2020import { spawn } from 'child_process' ;
2121import { getUbuntuVersion } from '../helper' ;
22- import { linuxLddDirectories , BrowserDescriptor } from '../install/browserPaths.js' ;
22+ import { linuxLddDirectories , windowsExeAndDllDirectories , BrowserDescriptor } from '../install/browserPaths.js' ;
2323
2424const accessAsync = util . promisify ( fs . access . bind ( fs ) ) ;
2525const checkExecutable = ( filePath : string ) => accessAsync ( filePath , fs . constants . X_OK ) . then ( ( ) => true ) . catch ( e => false ) ;
@@ -41,8 +41,65 @@ const DL_OPEN_LIBRARIES = {
4141
4242async function validateDependencies ( browserPath : string , browser : BrowserDescriptor ) {
4343 // We currently only support Linux.
44- if ( os . platform ( ) !== 'linux' )
44+ if ( os . platform ( ) === 'linux' )
45+ return await validateDependenciesLinux ( browserPath , browser ) ;
46+ if ( os . platform ( ) === 'win32' && os . arch ( ) === 'x64' )
47+ return await validateDependenciesWindows ( browserPath , browser ) ;
48+ }
49+
50+ async function validateDependenciesWindows ( browserPath : string , browser : BrowserDescriptor ) {
51+ const directoryPaths = windowsExeAndDllDirectories ( browserPath , browser ) ;
52+ const lddPaths : string [ ] = [ ] ;
53+ for ( const directoryPath of directoryPaths )
54+ lddPaths . push ( ...( await executablesOrSharedLibraries ( directoryPath ) ) ) ;
55+ const allMissingDeps = await Promise . all ( lddPaths . map ( lddPath => missingFileDependenciesWindows ( lddPath ) ) ) ;
56+ const missingDeps : Set < string > = new Set ( ) ;
57+ for ( const deps of allMissingDeps ) {
58+ for ( const dep of deps )
59+ missingDeps . add ( dep ) ;
60+ }
61+
62+ if ( ! missingDeps . size )
4563 return ;
64+
65+ let isCrtMissing = false ;
66+ let isMediaFoundationMissing = false ;
67+ for ( const dep of missingDeps ) {
68+ if ( dep . startsWith ( 'api-ms-win-crt' ) )
69+ isCrtMissing = true ;
70+ else if ( dep === 'mf.dll' || dep === 'mfplat.dll' || dep === 'msmpeg2vdec.dll' )
71+ isMediaFoundationMissing = true ;
72+ }
73+
74+ const details = [ ] ;
75+
76+ if ( isCrtMissing ) {
77+ details . push (
78+ `Some of the Universal C Runtime files cannot be found on the system. You can fix` ,
79+ `that by installing Microsoft Visual C++ Redistributable for Visual Studio from:` ,
80+ `https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads` ,
81+ `` ) ;
82+ }
83+
84+ if ( isMediaFoundationMissing ) {
85+ details . push (
86+ `Some of the Media Foundation files cannot be found on the system. If you are` ,
87+ `on Windows Server try fixing this by running the following command in PowerShell` ,
88+ `as Administrator:` ,
89+ `` ,
90+ ` Install-WindowsFeature Server-Media-Foundation` ,
91+ `` ) ;
92+ }
93+
94+ details . push (
95+ `Full list of missing libraries:` ,
96+ ` ${ [ ...missingDeps ] . join ( '\n ' ) } ` ,
97+ `` ) ;
98+
99+ throw new Error ( `Host system is missing dependencies!\n\n${ details . join ( '\n' ) } ` ) ;
100+ }
101+
102+ async function validateDependenciesLinux ( browserPath : string , browser : BrowserDescriptor ) {
46103 const directoryPaths = linuxLddDirectories ( browserPath , browser ) ;
47104 const lddPaths : string [ ] = [ ] ;
48105 for ( const directoryPath of directoryPaths )
@@ -100,14 +157,25 @@ async function validateDependencies(browserPath: string, browser: BrowserDescrip
100157 throw new Error ( 'Host system is missing dependencies!\n\n' + missingPackagesMessage + missingDependenciesMessage ) ;
101158}
102159
160+ function isSharedLib ( basename : string ) {
161+ switch ( os . platform ( ) ) {
162+ case 'linux' :
163+ return basename . endsWith ( '.so' ) || basename . includes ( '.so.' ) ;
164+ case 'win32' :
165+ return basename . endsWith ( '.dll' ) ;
166+ default :
167+ return false ;
168+ }
169+ }
170+
103171async function executablesOrSharedLibraries ( directoryPath : string ) : Promise < string [ ] > {
104172 const allPaths = ( await readdirAsync ( directoryPath ) ) . map ( file => path . resolve ( directoryPath , file ) ) ;
105173 const allStats = await Promise . all ( allPaths . map ( aPath => statAsync ( aPath ) ) ) ;
106174 const filePaths = allPaths . filter ( ( aPath , index ) => allStats [ index ] . isFile ( ) ) ;
107175
108176 const executablersOrLibraries = ( await Promise . all ( filePaths . map ( async filePath => {
109177 const basename = path . basename ( filePath ) . toLowerCase ( ) ;
110- if ( basename . endsWith ( '.so' ) || basename . includes ( '.so.' ) )
178+ if ( isSharedLib ( basename ) )
111179 return filePath ;
112180 if ( await checkExecutable ( filePath ) )
113181 return filePath ;
@@ -117,6 +185,21 @@ async function executablesOrSharedLibraries(directoryPath: string): Promise<stri
117185 return executablersOrLibraries as string [ ] ;
118186}
119187
188+ async function missingFileDependenciesWindows ( filePath : string ) : Promise < Array < string > > {
189+ const dirname = path . dirname ( filePath ) ;
190+ const { stdout, code} = await spawnAsync ( path . join ( __dirname , '../../bin/PrintDeps.exe' ) , [ filePath ] , {
191+ cwd : dirname ,
192+ env : {
193+ ...process . env ,
194+ LD_LIBRARY_PATH : process . env . LD_LIBRARY_PATH ? `${ process . env . LD_LIBRARY_PATH } :${ dirname } ` : dirname ,
195+ } ,
196+ } ) ;
197+ if ( code !== 0 )
198+ return [ ] ;
199+ const missingDeps = stdout . split ( '\n' ) . map ( line => line . trim ( ) ) . filter ( line => line . endsWith ( 'not found' ) && line . includes ( '=>' ) ) . map ( line => line . split ( '=>' ) [ 0 ] . trim ( ) ) ;
200+ return missingDeps ;
201+ }
202+
120203async function missingFileDependencies ( filePath : string ) : Promise < Array < string > > {
121204 const dirname = path . dirname ( filePath ) ;
122205 const { stdout, code} = await spawnAsync ( 'ldd' , [ filePath ] , {
0 commit comments