| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:process/process.dart'; |
| |
| import '../base/io.dart'; |
| import '../base/os.dart'; |
| import '../doctor_validator.dart'; |
| |
| /// Flutter only supports development on Windows host machines version 10 and greater. |
| const List<String> kUnsupportedVersions = <String>[ |
| '6', |
| '7', |
| '8', |
| ]; |
| |
| /// Regex pattern for identifying line from systeminfo stdout with windows version |
| /// (ie. 10.5.4123) |
| const String kWindowsOSVersionSemVerPattern = r'([0-9]+)\.([0-9]+)\.([0-9\.]+)'; |
| |
| /// Regex pattern for identifying a running instance of the Topaz OFD process. |
| /// This is a known process that interferes with the build toolchain. |
| /// See https://github.com/flutter/flutter/issues/121366 |
| const String kCoreProcessPattern = r'Topaz\s+OFD\\Warsaw\\core\.exe'; |
| |
| /// Validator for supported Windows host machine operating system version. |
| class WindowsVersionValidator extends DoctorValidator { |
| const WindowsVersionValidator({ |
| required OperatingSystemUtils operatingSystemUtils, |
| required ProcessLister processLister, |
| }) : _operatingSystemUtils = operatingSystemUtils, |
| _processLister = processLister, |
| super('Windows Version'); |
| |
| final OperatingSystemUtils _operatingSystemUtils; |
| final ProcessLister _processLister; |
| |
| Future<ValidationResult> _topazScan() async { |
| final ProcessResult getProcessesResult = await _processLister.getProcessesWithPath(); |
| if (getProcessesResult.exitCode != 0) { |
| return const ValidationResult(ValidationType.missing, <ValidationMessage>[ValidationMessage.hint('Get-Process failed to complete')]); |
| } |
| final RegExp topazRegex = RegExp(kCoreProcessPattern, caseSensitive: false, multiLine: true); |
| final String processes = getProcessesResult.stdout as String; |
| final bool topazFound = topazRegex.hasMatch(processes); |
| if (topazFound) { |
| return const ValidationResult( |
| ValidationType.missing, |
| <ValidationMessage>[ |
| ValidationMessage.hint( |
| 'The Topaz OFD Security Module was detected on your machine. ' |
| 'You may need to disable it to build Flutter applications.', |
| ), |
| ], |
| ); |
| } |
| return const ValidationResult(ValidationType.success, <ValidationMessage>[]); |
| } |
| |
| @override |
| Future<ValidationResult> validate() async { |
| final RegExp regex = |
| RegExp(kWindowsOSVersionSemVerPattern, multiLine: true); |
| final String commandResult = _operatingSystemUtils.name; |
| final Iterable<RegExpMatch> matches = regex.allMatches(commandResult); |
| |
| // Use the string split method to extract the major version |
| // and check against the [kUnsupportedVersions] list |
| ValidationType windowsVersionStatus; |
| final List<ValidationMessage> messages = <ValidationMessage>[]; |
| String statusInfo; |
| if (matches.length == 1 && |
| !kUnsupportedVersions.contains(matches.elementAt(0).group(1))) { |
| windowsVersionStatus = ValidationType.success; |
| statusInfo = 'Installed version of Windows is version 10 or higher'; |
| |
| // Check if the Topaz OFD security module is running, and warn the user if it is. |
| // See https://github.com/flutter/flutter/issues/121366 |
| final List<ValidationResult> subResults = <ValidationResult>[ |
| await _topazScan(), |
| ]; |
| for (final ValidationResult subResult in subResults) { |
| if (subResult.type != ValidationType.success) { |
| statusInfo = 'Problem detected with Windows installation'; |
| windowsVersionStatus = ValidationType.partial; |
| messages.addAll(subResult.messages); |
| } |
| } |
| } else { |
| windowsVersionStatus = ValidationType.missing; |
| statusInfo = |
| 'Unable to determine Windows version (command `ver` returned $commandResult)'; |
| } |
| |
| return ValidationResult( |
| windowsVersionStatus, |
| messages, |
| statusInfo: statusInfo, |
| ); |
| } |
| } |
| |
| class ProcessLister { |
| ProcessLister(this.processManager); |
| |
| final ProcessManager processManager; |
| |
| Future<ProcessResult> getProcessesWithPath() async { |
| const String argument = 'Get-Process | Format-List Path'; |
| return processManager.run(<String>['powershell', '-command', argument]); |
| } |
| } |