@@ -35,7 +35,7 @@ import {
35
35
CodeActionResolveRequest ,
36
36
} from 'vscode-languageclient/node' ;
37
37
import { PlatformInformation } from '../shared/platform' ;
38
- import { DotnetResolver } from '../shared/DotnetResolver ' ;
38
+ import { acquireDotNetProcessDependencies } from './dotnetRuntime ' ;
39
39
import { readConfigurations } from './configurationMiddleware' ;
40
40
import OptionProvider from '../shared/observers/OptionProvider' ;
41
41
import { DynamicFileInfoHandler } from '../razor/src/DynamicFile/DynamicFileInfoHandler' ;
@@ -147,12 +147,7 @@ export class RoslynLanguageServer {
147
147
* Resolves server options and starts the dotnet language server process.
148
148
*/
149
149
public async start ( ) : Promise < void > {
150
- const dotnetResolver = new DotnetResolver ( this . platformInfo ) ;
151
-
152
150
let options = this . optionProvider . GetLatestOptions ( ) ;
153
- let resolvedDotnet = await dotnetResolver . getHostExecutableInfo ( options ) ;
154
- _channel . appendLine ( "Dotnet version: " + resolvedDotnet . version ) ;
155
-
156
151
let logLevel = options . languageServerOptions . logLevel ;
157
152
const languageClientTraceLevel = this . GetTraceLevel ( logLevel ) ;
158
153
@@ -343,10 +338,9 @@ export class RoslynLanguageServer {
343
338
return capabilities ;
344
339
}
345
340
346
- private async startServer ( logLevel : string | undefined ) : Promise < cp . ChildProcess > {
341
+ private getServerPath ( options : Options ) {
347
342
let clientRoot = __dirname ;
348
343
349
- let options = this . optionProvider . GetLatestOptions ( ) ;
350
344
let serverPath = options . commonOptions . serverPath ;
351
345
if ( ! serverPath ) {
352
346
// Option not set, use the path from the extension.
@@ -357,6 +351,37 @@ export class RoslynLanguageServer {
357
351
throw new Error ( `Cannot find language server in path '${ serverPath } '` ) ;
358
352
}
359
353
354
+ return serverPath ;
355
+ }
356
+
357
+ private async startServer ( logLevel : string | undefined ) : Promise < cp . ChildProcess > {
358
+
359
+ let options = this . optionProvider . GetLatestOptions ( ) ;
360
+ let serverPath = this . getServerPath ( options ) ;
361
+
362
+ let dotnetRuntimePath = options . commonOptions . dotnetPath ;
363
+ if ( ! dotnetRuntimePath )
364
+ {
365
+ let dotnetPath = await acquireDotNetProcessDependencies ( serverPath ) ;
366
+ dotnetRuntimePath = path . dirname ( dotnetPath ) ;
367
+ }
368
+
369
+ const dotnetExecutableName = this . platformInfo . isWindows ( ) ? 'dotnet.exe' : 'dotnet' ;
370
+ const dotnetExecutablePath = path . join ( dotnetRuntimePath , dotnetExecutableName ) ;
371
+ if ( ! fs . existsSync ( dotnetExecutablePath ) ) {
372
+ throw new Error ( `Cannot find dotnet path '${ dotnetExecutablePath } '` ) ;
373
+ }
374
+
375
+ _channel . appendLine ( "Dotnet path: " + dotnetExecutablePath ) ;
376
+
377
+ // Take care to always run .NET processes on the runtime that we intend.
378
+ // The dotnet.exe we point to should not go looking for other runtimes.
379
+ const env : NodeJS . ProcessEnv = { ...process . env } ;
380
+ env . DOTNET_ROOT = dotnetRuntimePath ;
381
+ env . DOTNET_MULTILEVEL_LOOKUP = '0' ;
382
+ // Save user's DOTNET_ROOT env-var value so server can recover the user setting when needed
383
+ env . DOTNET_ROOT_USER = process . env . DOTNET_ROOT ?? 'EMPTY' ;
384
+
360
385
let args : string [ ] = [ ] ;
361
386
362
387
if ( options . commonOptions . waitForDebugger ) {
@@ -402,7 +427,8 @@ export class RoslynLanguageServer {
402
427
let childProcess : cp . ChildProcessWithoutNullStreams ;
403
428
let cpOptions : cp . SpawnOptionsWithoutStdio = {
404
429
detached : true ,
405
- windowsHide : true
430
+ windowsHide : true ,
431
+ env : env
406
432
} ;
407
433
408
434
if ( serverPath . endsWith ( '.dll' ) ) {
0 commit comments