diff --git a/documentation/specs/dotnet-run-for-maui.md b/documentation/specs/dotnet-run-for-maui.md new file mode 100644 index 000000000000..33fd374d8b67 --- /dev/null +++ b/documentation/specs/dotnet-run-for-maui.md @@ -0,0 +1,243 @@ +# `dotnet run` for .NET MAUI Scenarios + +The current state of `dotnet run` for .NET MAUI projects is summarized +by this issue from 2021: + +* [Figure out 'dotnet run' CLI experience for iOS and Android](https://github.com/dotnet/xamarin/issues/26) + +The pain points being: + +* iOS and Android use different properties to select a device, + emulator, or simulator. It is difficult for developers to make this + selection as you need to run platform-specific commands along with + complex MSBuild properties. + +* Each platform has different behavior, regards to displaying console + output, etc. + +* Using an MSIX with WindowsAppSDK doesn't support `dotnet run` at all, + relying completely on IDEs like Visual Studio. + +* `dotnet run` does not have a concept of a "deploy" step. + +This has become more relevant in the AI era, as someone is going to +expect AIs in "agent mode" to build and run their app. If the +command-line options are difficult, AIs will fail just as badly as +humans do today. + +## The `dotnet run` Pipeline + +These are the high-level steps during `dotnet run`, that we would like +to make extensible for .NET MAUI (and future) scenarios. + +* `restore`: unchanged + +* "Pre-run evaluation" + + * If the project is multi-targeted, containing the + `$(TargetFrameworks)` property _and_ that property has more than + one item in it, and `-f` was not supplied... + + * Prompt the user to select from a list of the + `$(TargetFrameworks)` + + * Non-interactive mode will give a friendly error message, + suggesting to supply the `-f` property, listing available target + frameworks in the project. + + * Once a `$(TargetFramework)` is selected, either from previous + steps or `-f`... + + * If a `ComputeAvailableDevices` MSBuild target is available, provided by + the iOS or Android workload, etc. ... + + * Call the MSBuild target, which returns a list of `@(Devices)` items... + +```xml + + + + + + + + + + + +``` + +_NOTE: each workload can decide which metadata values for `%(Type)`, +`%(Status)`, and `%(RuntimeIdentifier)` are useful, filtering offline +devices, etc. The output above would be analogous to running `adb +devices`, `xcrun simctl list devices`, or `xcrun devicectl list +devices`. The `%(RuntimeIdentifier)` metadata is optional but +recommended, as it allows the build system to pass the appropriate RID +to subsequent build, deploy, and run steps._ + +* Continuing on... + + * Prompt the user to select from this list of devices, emulators, + or simulators. + + * Non-interactive mode will error, suggesting to supply the + `--device` switch. Listing the options returned by the + `ComputeAvailableDevices` MSBuild target. + +* `build`: unchanged, but is passed `-p:Device` and optionally `-p:RuntimeIdentifier` + if the selected device provided a `%(RuntimeIdentifier)` metadata value. + +* `deploy` + + * If a `DeployToDevice` MSBuild target is available, provided by the + iOS or Android workload, etc. + + * Call the MSBuild target, passing in the identifier for the selected + `-p:Device` global MSBuild property, and optionally `-p:RuntimeIdentifier` + if the selected device provided a `%(RuntimeIdentifier)` metadata value. + + * This step needs to run, even with `--no-build`, as you may have + selected a different device. + +* `ComputeRunArguments`: unchanged, but is passed `-p:Device` and optionally + `-p:RuntimeIdentifier` if the selected device provided a `%(RuntimeIdentifier)` + metadata value. + +* `run`: unchanged. `ComputeRunArguments` should have set a valid + `$(RunCommand)` and `$(RunArguments)` using the value supplied by + `-p:Device` and optionally `-p:RuntimeIdentifier`. + +## New `dotnet run` Command-line Switches + +So far, it feels like no new subcommand is needed. In interactive +mode, `dotnet run` will now prompt to select a `$(TargetFramework)` +for all multi-targeted projects. Platform-specific projects like +Android, iOS, etc. will prompt for device selection. + +`dotnet run --list-devices` will: + +* Prompt for `$(TargetFramework)` for multi-targeted projects just + like when `--list-devices` is omitted. + + * If there is a single `$(TargetFramework)`, skip to the next step. + +* Call `ComputeAvailableDevices` if the MSBuild target exists, just + like when `--list-devices` is omitted. + + * List the available targets by name, a unique identifier, and an + optional status of the device. + + * Print a friendly message that says how to run `dotnet run` with + the new `--device` switch. + + * If `ComputeAvailableDevices` does not exist in the project + (workload), it can print a friendly message and exit. + +* `dotnet run --list-devices` will then basically exit early, never + running any build, deploy, `ComputeRunArguments`, or run steps. + +A new `--device` switch will: + +* bypass the device-selection portion of the `run` workflow described above + +* Pass in the `-p:Device` global MSBuild property to all build, + deploy, `ComputeRunArguments`, or run steps. + +* The iOS and Android workloads will know how to interpret `$(Device)` + to select an appropriate device, emulator, or simulator. + +## Binary Logs for Device Selection + +When using `-bl` with `dotnet run`, all MSBuild operations are logged to a single +binlog file: device selection, build, deploy, and run argument computation. + +File naming for `dotnet run` binlogs: + +* `-bl:filename.binlog` creates `filename-dotnet-run.binlog` +* `-bl` creates `msbuild-dotnet-run.binlog` + +Note: The build step may also create `msbuild.binlog` separately. Use +`--no-build` with `-bl` to only capture run-specific MSBuild +operations. + +## What about Launch Profiles? + +The iOS and Android workloads ignore all +`Properties/launchSettings.json` files and do nothing with them. + +WindowsAppSDK requires a launch profile to select between "packaged" +MSIX and an "unpackaged" .exe, and so we currently provide this in the +`dotnet new maui` project template: + +```json +{ + "profiles": { + "Windows Machine": { + "commandName": "Project", + "nativeDebugging": false + } + } +} +``` + +Or if you want to be "packaged": + +```json +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": false + } + } +} +``` + +Launch profiles don't immediately look useful for iOS or Android, as +the identifier you'd put in here would be different per developer -- +you wouldn't want the value saved in source control. You could put a +generic selection like device vs emulator/simulator, but that isn't +addressing the problem we are interested in. Full launch profile +support for .NET MAUI projects may be interesting to address in the +future. + +## iOS and Android workload behavior + +We will work to align as much behavior as possible between the +platforms. Most of this work will happen in the dotnet/android and +dotnet/macios repo, and would be orthogonal to the changes in the .NET +SDK. + +## macOS and MacCatalyst Behavior + +`dotnet run` "just works" on macOS Desktop, because `$(RunCommand)` +can launch the app directly -- similar to console apps. + +## WindowsAppSDK Behavior + +Running a `dotnet new maui` project works today because of the default +launch profile in "unpackaged" mode: + +```dotnetcli +> dotnet run -f net10.0-windows10.0.19041.0 +Using launch settings from D:\src\hellomaui\Properties\launchSettings.json... +``` + +To improve the behavior for "packaged" / MSIX, we could: + +* Implement the `DeployToDevice` MSBuild target. + +* `ComputeAvailableDevices` is not needed. + +* Implement the `ComputeRunArguments` MSBuild target. + +In the future, we can either add this logic into the .NET MAUI +workload or WindowsAppSDK itself. + +## Other frameworks: Avalonia, Uno, MonoGame, etc. + +When these frameworks run on iOS or Android, they are basically using +the `ios` and `android` workloads _without_ .NET MAUI. Any iOS or +Android-specific behavior would apply to these project types in the +same way a `dotnet new android` or `dotnet new ios` project template +would. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/CommandDefinitionStrings.resx b/src/Cli/Microsoft.DotNet.Cli.Definitions/CommandDefinitionStrings.resx index a6a7be1c8fd7..2b173efd5745 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/CommandDefinitionStrings.resx +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/CommandDefinitionStrings.resx @@ -675,6 +675,15 @@ If not specified the file will be generated inside the default 'TestResults' dir Do not attempt to use launchSettings.json or [app].run.json to configure the application. {Locked="launchSettings.json"}{Locked=".run.json"} + + The device identifier to use for running the application. + + + DEVICE + + + List available devices for running the application. + PROJECT_PATH diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/Commands/Run/RunCommandDefinition.cs b/src/Cli/Microsoft.DotNet.Cli.Definitions/Commands/Run/RunCommandDefinition.cs index f689ca30ec27..fd646939939b 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/Commands/Run/RunCommandDefinition.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/Commands/Run/RunCommandDefinition.cs @@ -48,6 +48,18 @@ internal sealed class RunCommandDefinition : Command Description = CommandDefinitionStrings.CommandOptionNoLaunchProfileArgumentsDescription }; + public readonly Option DeviceOption = new("--device") + { + Description = CommandDefinitionStrings.CommandOptionDeviceDescription, + HelpName = CommandDefinitionStrings.CommandOptionDeviceHelpName + }; + + public readonly Option ListDevicesOption = new("--list-devices") + { + Description = CommandDefinitionStrings.CommandOptionListDevicesDescription, + Arity = ArgumentArity.Zero + }; + public const string NoBuildOptionName = "--no-build"; public readonly Option NoBuildOption = new(NoBuildOptionName) @@ -98,6 +110,8 @@ public RunCommandDefinition() Options.Add(PropertyOption); Options.Add(LaunchProfileOption); Options.Add(NoLaunchProfileOption); + Options.Add(DeviceOption); + Options.Add(ListDevicesOption); Options.Add(NoBuildOption); Options.Add(InteractiveOption); Options.Add(NoRestoreOption); diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.cs.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.cs.xlf index 344d247cba33..1700afa47926 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.cs.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.cs.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.de.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.de.xlf index 1b0f210ff433..e53f6bae92ae 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.de.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.de.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.es.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.es.xlf index c17a0593d409..0d53ea87e5c1 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.es.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.es.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.fr.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.fr.xlf index a6b3b0f3f4bd..51c4cb9cf62f 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.fr.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.fr.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.it.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.it.xlf index 52179b3e1116..0891c63cbcf7 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.it.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.it.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ja.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ja.xlf index 803bdb7d5b23..b954efbc4d98 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ja.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ja.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ko.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ko.xlf index 75be8a8982e1..d6e1e93b1191 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ko.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ko.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pl.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pl.xlf index 0d9801e04f09..06fd257a5bc6 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pl.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pl.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pt-BR.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pt-BR.xlf index 561a1cf08daf..77c2f424c490 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pt-BR.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.pt-BR.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ru.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ru.xlf index d6ff51db95aa..d4ce1f5ed8f8 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ru.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.ru.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.tr.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.tr.xlf index e16aabe87fd9..b6583aa3fada 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.tr.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.tr.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hans.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hans.xlf index 82c030054ef7..429f270fa145 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hans.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hans.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hant.xlf b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hant.xlf index 7b6c4848b2d1..77ccfc8c62c3 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hant.xlf +++ b/src/Cli/Microsoft.DotNet.Cli.Definitions/xlf/CommandDefinitionStrings.zh-Hant.xlf @@ -743,6 +743,16 @@ Examples: COMMAND_NAME + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). The path to the file-based app to run (can be also passed as the first argument if there is no project in the current directory). @@ -763,6 +773,11 @@ Examples: LAUNCH_PROFILE + + List available devices for running the application. + List available devices for running the application. + + Do not build the project before running. Implies --no-restore. Do not build the project before running. Implies --no-restore. diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs index 0c5aef161367..598d1dfe3483 100644 --- a/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs +++ b/src/Cli/Microsoft.DotNet.Cli.Utils/Constants.cs @@ -29,6 +29,8 @@ public static class Constants // MSBuild targets public const string Build = nameof(Build); public const string ComputeRunArguments = nameof(ComputeRunArguments); + public const string ComputeAvailableDevices = nameof(ComputeAvailableDevices); + public const string DeployToDevice = nameof(DeployToDevice); public const string CoreCompile = nameof(CoreCompile); // MSBuild item metadata diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx index cd5cae271f0d..c1d47a523067 100644 --- a/src/Cli/dotnet/Commands/CliCommandStrings.resx +++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx @@ -923,6 +923,9 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man The build failed. Fix the build errors and run again. + + Deployment to device failed. Fix any deployment errors and run again. + The launch profile "{0}" could not be applied. {1} @@ -986,6 +989,30 @@ Your project targets multiple frameworks. Specify which framework to run using ' The target runtime to run for. + + The device identifier to use for running the application. + + + DEVICE + + + List available devices for running the application. + + + Available devices: + + + No devices are available for this project. + + + Select a device to run on: + + + Move up and down to reveal more devices + + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Path to <application>.runtimeconfig.json file. diff --git a/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs b/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs index 8217e1744580..40e5a2cd07fc 100644 --- a/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs +++ b/src/Cli/dotnet/Commands/Run/Api/RunApiCommand.cs @@ -106,6 +106,8 @@ public override RunApiOutput Execute() launchProfile: null, noLaunchProfile: false, noLaunchProfileArguments: false, + device: null, + listDevices: false, noRestore: false, noCache: false, interactive: false, @@ -115,7 +117,7 @@ public override RunApiOutput Execute() environmentVariables: ReadOnlyDictionary.Empty); var result = runCommand.ReadLaunchProfileSettings(); - var targetCommand = (Utils.Command)runCommand.GetTargetCommand(result.Profile, buildCommand.CreateProjectInstance, cachedRunProperties: null); + var targetCommand = (Utils.Command)runCommand.GetTargetCommand(result.Profile, buildCommand.CreateProjectInstance, cachedRunProperties: null, logger: null); return new RunApiOutput.RunCommand { diff --git a/src/Cli/dotnet/Commands/Run/RunCommand.cs b/src/Cli/dotnet/Commands/Run/RunCommand.cs index 40a21c7f1f7e..66e3e05af9ae 100644 --- a/src/Cli/dotnet/Commands/Run/RunCommand.cs +++ b/src/Cli/dotnet/Commands/Run/RunCommand.cs @@ -86,6 +86,22 @@ public class RunCommand /// public bool NoLaunchProfileArguments { get; } + /// + /// Device identifier to use for running the application. + /// + public string? Device { get; } + + /// + /// Whether to list available devices and exit. + /// + public bool ListDevices { get; } + + /// + /// Tracks whether restore was performed during device selection phase. + /// If true, we should skip restore in the build phase to avoid redundant work. + /// + private bool _restoreDoneForDeviceSelection; + /// unparsed/arbitrary CLI tokens to be passed to the running application public RunCommand( bool noBuild, @@ -94,6 +110,8 @@ public RunCommand( string? launchProfile, bool noLaunchProfile, bool noLaunchProfileArguments, + string? device, + bool listDevices, bool noRestore, bool noCache, bool interactive, @@ -112,6 +130,8 @@ public RunCommand( LaunchProfile = launchProfile; NoLaunchProfile = noLaunchProfile; NoLaunchProfileArguments = noLaunchProfileArguments; + Device = device; + ListDevices = listDevices; ApplicationArgs = applicationArgs; Interactive = interactive; NoRestore = noRestore; @@ -127,90 +147,186 @@ public int Execute() throw new GracefulException(CliCommandStrings.CannotCombineOptions, RunCommandDefinition.NoCacheOptionName, RunCommandDefinition.NoBuildOptionName); } - // Pre-run evaluation: Handle target framework selection for multi-targeted projects - if (ProjectFileFullPath is not null && !TrySelectTargetFrameworkIfNeeded()) + // Create a single logger for all MSBuild operations (device selection + build/run) + // File-based runs (.cs files) don't support device selection and should use the existing logger behavior + FacadeLogger? logger = ProjectFileFullPath is not null + ? LoggerUtility.DetermineBinlogger([.. MSBuildArgs.OtherMSBuildArgs], "dotnet-run") + : null; + try { - return 1; - } + // Pre-run evaluation: Handle target framework and device selection for project-based scenarios + using var selector = ProjectFileFullPath is not null + ? new RunCommandSelector(ProjectFileFullPath, Interactive, MSBuildArgs, logger) + : null; + if (selector is not null && !TrySelectTargetFrameworkAndDeviceIfNeeded(selector)) + { + // If --list-devices was specified, this is a successful exit + return ListDevices ? 0 : 1; + } - // For file-based projects, check for multi-targeting before building - if (EntryPointFileFullPath is not null && !TrySelectTargetFrameworkForFileBasedProject()) - { - return 1; - } + // For file-based projects, check for multi-targeting before building + if (EntryPointFileFullPath is not null && !TrySelectTargetFrameworkForFileBasedProject()) + { + return 1; + } - var launchProfileParseResult = ReadLaunchProfileSettings(); - if (launchProfileParseResult.FailureReason != null) - { - Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, LaunchProfileParser.GetLaunchProfileDisplayName(LaunchProfile), launchProfileParseResult.FailureReason).Bold().Red()); - } + var launchProfileParseResult = ReadLaunchProfileSettings(); + if (launchProfileParseResult.FailureReason != null) + { + Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, LaunchProfileParser.GetLaunchProfileDisplayName(LaunchProfile), launchProfileParseResult.FailureReason).Bold().Red()); + } - Func? projectFactory = null; - RunProperties? cachedRunProperties = null; - VirtualProjectBuildingCommand? projectBuilder = null; - if (ShouldBuild) - { - if (launchProfileParseResult.Profile?.DotNetRunMessages == true) + Func? projectFactory = null; + RunProperties? cachedRunProperties = null; + VirtualProjectBuildingCommand? projectBuilder = null; + if (ShouldBuild) { - Reporter.Output.WriteLine(CliCommandStrings.RunCommandBuilding); + if (launchProfileParseResult.Profile?.DotNetRunMessages == true) + { + Reporter.Output.WriteLine(CliCommandStrings.RunCommandBuilding); + } + + EnsureProjectIsBuilt(out projectFactory, out cachedRunProperties, out projectBuilder); } + else if (EntryPointFileFullPath is not null && launchProfileParseResult.Profile is not ExecutableLaunchProfile) + { + // The entry-point is not used to run the application if the launch profile specifies Executable command. - EnsureProjectIsBuilt(out projectFactory, out cachedRunProperties, out projectBuilder); - } - else if (EntryPointFileFullPath is not null && launchProfileParseResult.Profile is not ExecutableLaunchProfile) - { - // The entry-point is not used to run the application if the launch profile specifies Executable command. + Debug.Assert(!ReadCodeFromStdin); + projectBuilder = CreateProjectBuilder(); + projectBuilder.MarkArtifactsFolderUsed(); - Debug.Assert(!ReadCodeFromStdin); - projectBuilder = CreateProjectBuilder(); - projectBuilder.MarkArtifactsFolderUsed(); + var cacheEntry = projectBuilder.GetPreviousCacheEntry(); + projectFactory = CanUseRunPropertiesForCscBuiltProgram(BuildLevel.None, cacheEntry) ? null : projectBuilder.CreateProjectInstance; + cachedRunProperties = cacheEntry?.Run; + } - var cacheEntry = projectBuilder.GetPreviousCacheEntry(); - projectFactory = CanUseRunPropertiesForCscBuiltProgram(BuildLevel.None, cacheEntry) ? null : projectBuilder.CreateProjectInstance; - cachedRunProperties = cacheEntry?.Run; - } + // Deploy step: Call DeployToDevice target if available + // This must run even with --no-build, as the user may have selected a different device + if (selector is not null && !selector.TryDeployToDevice()) + { + // Only error if we have a valid project (not a .sln file, etc.) + if (selector.HasValidProject) + { + throw new GracefulException(CliCommandStrings.RunCommandDeployFailed); + } + } - var targetCommand = GetTargetCommand(launchProfileParseResult.Profile, projectFactory, cachedRunProperties); + var targetCommand = GetTargetCommand(launchProfileParseResult.Profile, projectFactory, cachedRunProperties, logger); - // Send telemetry about the run operation - SendRunTelemetry(launchProfileParseResult.Profile, projectBuilder); + // Send telemetry about the run operation + SendRunTelemetry(launchProfileParseResult.Profile, projectBuilder); - // Ignore Ctrl-C for the remainder of the command's execution - Console.CancelKeyPress += (sender, e) => { e.Cancel = true; }; + // Ignore Ctrl-C for the remainder of the command's execution + Console.CancelKeyPress += (sender, e) => { e.Cancel = true; }; - return targetCommand.Execute().ExitCode; + return targetCommand.Execute().ExitCode; + } + catch (InvalidProjectFileException e) + { + throw new GracefulException( + string.Format(CliCommandStrings.RunCommandSpecifiedFileIsNotAValidProject, ProjectFileFullPath), + e); + } + finally + { + logger?.ReallyShutdown(); + } } - internal ICommand GetTargetCommand(LaunchProfile? launchSettings, Func? projectFactory, RunProperties? cachedRunProperties) + internal ICommand GetTargetCommand(LaunchProfile? launchSettings, Func? projectFactory, RunProperties? cachedRunProperties, FacadeLogger? logger) => launchSettings switch { - null => GetTargetCommandForProject(launchSettings: null, projectFactory, cachedRunProperties), - ProjectLaunchProfile projectSettings => GetTargetCommandForProject(projectSettings, projectFactory, cachedRunProperties), + null => GetTargetCommandForProject(launchSettings: null, projectFactory, cachedRunProperties, logger), + ProjectLaunchProfile projectSettings => GetTargetCommandForProject(projectSettings, projectFactory, cachedRunProperties, logger), ExecutableLaunchProfile executableSettings => GetTargetCommandForExecutable(executableSettings), _ => throw new InvalidOperationException() }; /// - /// Checks if target framework selection is needed for multi-targeted projects. - /// If needed and we're in interactive mode, prompts the user to select a framework. - /// If needed and we're in non-interactive mode, shows an error. + /// Checks if target framework selection and device selection are needed. + /// Uses a single RunCommandSelector instance for both operations, re-evaluating + /// the project after framework selection to get the correct device list. /// + /// The RunCommandSelector instance to use for selection /// True if we can continue, false if we should exit - private bool TrySelectTargetFrameworkIfNeeded() + private bool TrySelectTargetFrameworkAndDeviceIfNeeded(RunCommandSelector selector) { - Debug.Assert(ProjectFileFullPath is not null); - var globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(MSBuildArgs); - if (TargetFrameworkSelector.TrySelectTargetFramework( - ProjectFileFullPath, - globalProperties, - Interactive, - out string? selectedFramework)) + + // If user specified --device on command line, add it to global properties and MSBuildArgs + if (!string.IsNullOrWhiteSpace(Device)) + { + globalProperties["Device"] = Device; + var properties = new Dictionary { { "Device", Device } }; + var additionalProperties = new ReadOnlyDictionary(properties); + MSBuildArgs = MSBuildArgs.CloneWithAdditionalProperties(additionalProperties); + } + + // Optimization: If BOTH framework AND device are already specified (and we're not listing devices), + // we can skip both framework selection and device selection entirely + bool hasFramework = globalProperties.TryGetValue("TargetFramework", out var existingFramework) && !string.IsNullOrWhiteSpace(existingFramework); + bool hasDevice = globalProperties.TryGetValue("Device", out var preSpecifiedDevice) && !string.IsNullOrWhiteSpace(preSpecifiedDevice); + + if (!ListDevices && hasFramework && hasDevice) + { + // Both framework and device are pre-specified + return true; + } + + // Step 1: Select target framework if needed + if (!selector.TrySelectTargetFramework(out string? selectedFramework)) + { + return false; + } + + if (selectedFramework is not null) { ApplySelectedFramework(selectedFramework); + + // Re-evaluate project with the selected framework so device selection sees the right devices + var properties = CommonRunHelpers.GetGlobalPropertiesFromArgs(MSBuildArgs); + selector.InvalidateGlobalProperties(properties); + } + + // Step 2: Check if device is now pre-specified after framework selection + if (!ListDevices && hasDevice) + { + // Device was pre-specified, we can skip device selection return true; } + // Step 3: Select device if needed + if (selector.TrySelectDevice( + ListDevices, + NoRestore, + out string? selectedDevice, + out string? runtimeIdentifier, + out _restoreDoneForDeviceSelection)) + { + // If a device was selected (either by user or by prompt), apply it to MSBuildArgs + if (selectedDevice is not null) + { + var properties = new Dictionary { { "Device", selectedDevice } }; + + // If the device provided a RuntimeIdentifier, add it too + if (!string.IsNullOrEmpty(runtimeIdentifier)) + { + properties["RuntimeIdentifier"] = runtimeIdentifier; + + // If the device added a RuntimeIdentifier, we need to re-restore with that RID + // because the previous restore (if any) didn't include it + _restoreDoneForDeviceSelection = false; + } + + var additionalProperties = new ReadOnlyDictionary(properties); + MSBuildArgs = MSBuildArgs.CloneWithAdditionalProperties(additionalProperties); + } + + // If ListDevices was set, we return true but the caller will exit after listing + return !ListDevices; + } + return false; } @@ -238,8 +354,8 @@ private bool TrySelectTargetFrameworkForFileBasedProject() return true; // Not multi-targeted } - // Use TargetFrameworkSelector to handle multi-target selection (or single framework selection) - if (TargetFrameworkSelector.TrySelectTargetFramework(frameworks, Interactive, out string? selectedFramework)) + // Use RunCommandSelector to handle multi-target selection (or single framework selection) + if (RunCommandSelector.TrySelectTargetFramework(frameworks, Interactive, out string? selectedFramework)) { ApplySelectedFramework(selectedFramework); return true; @@ -375,7 +491,7 @@ private void EnsureProjectIsBuilt(out Func? projectBuilder = null; buildResult = new RestoringCommand( MSBuildArgs.CloneWithExplicitArgs([ProjectFileFullPath, .. MSBuildArgs.OtherMSBuildArgs]), - NoRestore, + NoRestore || _restoreDoneForDeviceSelection, advertiseWorkloadUpdates: false ).Execute(); } @@ -435,7 +551,7 @@ private MSBuildArgs SetupSilentBuildArgs(MSBuildArgs msbuildArgs) } } - private ICommand GetTargetCommandForProject(ProjectLaunchProfile? launchSettings, Func? projectFactory, RunProperties? cachedRunProperties) + private ICommand GetTargetCommandForProject(ProjectLaunchProfile? launchSettings, Func? projectFactory, RunProperties? cachedRunProperties, FacadeLogger? logger) { ICommand command; if (cachedRunProperties != null) @@ -456,19 +572,10 @@ private ICommand GetTargetCommandForProject(ProjectLaunchProfile? launchSettings else { Reporter.Verbose.WriteLine("Getting target command: evaluating project."); - FacadeLogger? logger = LoggerUtility.DetermineBinlogger([.. MSBuildArgs.OtherMSBuildArgs], "dotnet-run"); - ProjectInstance project; - try - { - project = EvaluateProject(ProjectFileFullPath, projectFactory, MSBuildArgs, logger); - ValidatePreconditions(project); - InvokeRunArgumentsTarget(project, NoBuild, logger, MSBuildArgs); - } - finally - { - logger?.ReallyShutdown(); - } + var project = EvaluateProject(ProjectFileFullPath, projectFactory, MSBuildArgs, logger); + ValidatePreconditions(project); + InvokeRunArgumentsTarget(project, NoBuild, logger, MSBuildArgs); var runProperties = RunProperties.FromProject(project).WithApplicationArguments(ApplicationArgs); command = CreateCommandFromRunProperties(runProperties); @@ -775,6 +882,8 @@ public static RunCommand FromParseResult(ParseResult parseResult) launchProfile: launchProfile, noLaunchProfile: parseResult.HasOption(definition.NoLaunchProfileOption), noLaunchProfileArguments: parseResult.HasOption(definition.NoLaunchProfileArgumentsOption), + device: parseResult.GetValue(definition.DeviceOption), + listDevices: parseResult.HasOption(definition.ListDevicesOption), noRestore: parseResult.HasOption(definition.NoRestoreOption) || parseResult.HasOption(definition.NoBuildOption), noCache: parseResult.HasOption(definition.NoCacheOption), interactive: parseResult.GetValue(definition.InteractiveOption), diff --git a/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs b/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs new file mode 100644 index 000000000000..b2016b765bf4 --- /dev/null +++ b/src/Cli/dotnet/Commands/Run/RunCommandSelector.cs @@ -0,0 +1,511 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Build.Evaluation; +using Microsoft.Build.Exceptions; +using Microsoft.Build.Execution; +using Microsoft.Build.Framework; +using Microsoft.DotNet.Cli.Utils; +using Spectre.Console; + +namespace Microsoft.DotNet.Cli.Commands.Run; + +/// +/// Handles target framework and device selection for dotnet run. +/// Caches the project instance to avoid reloading it multiple times. +/// +internal sealed class RunCommandSelector : IDisposable +{ + // Spectre.Console markup color constants + private const string CyanMarkup = "[cyan]"; + private const string GrayMarkup = "[gray]"; + private const string EndMarkup = "[/]"; + + private readonly string _projectFilePath; + private readonly Dictionary _globalProperties; + private readonly FacadeLogger? _binaryLogger; + private readonly bool _isInteractive; + private readonly MSBuildArgs _msbuildArgs; + + private ProjectCollection? _collection; + private Microsoft.Build.Evaluation.Project? _project; + + /// + /// Gets whether the selector has a valid project that can be evaluated. + /// This is false for .sln files or other invalid project files. + /// + public bool HasValidProject { get; private set; } + + /// Path to the project file to evaluate + /// Whether to prompt the user for selections + /// MSBuild arguments containing properties and verbosity settings + /// Optional binary logger for MSBuild operations. The logger will not be disposed by this class. + public RunCommandSelector( + string projectFilePath, + bool isInteractive, + MSBuildArgs msbuildArgs, + FacadeLogger? binaryLogger = null) + { + _projectFilePath = projectFilePath; + _globalProperties = CommonRunHelpers.GetGlobalPropertiesFromArgs(msbuildArgs); + _isInteractive = isInteractive; + _msbuildArgs = msbuildArgs; + _binaryLogger = binaryLogger; + } + + /// + /// Evaluates the project to determine if target framework selection is needed. + /// If the project has multiple target frameworks and none was specified, prompts the user to select one. + /// + /// The selected target framework, or null if not needed + /// True if we should continue, false if we should exit with error + public bool TrySelectTargetFramework(out string? selectedFramework) + { + selectedFramework = null; + + // If a framework is already specified, no need to prompt + if (_globalProperties.TryGetValue("TargetFramework", out var existingFramework) && !string.IsNullOrWhiteSpace(existingFramework)) + { + return true; + } + + // Evaluate the project to get TargetFrameworks + if (!OpenProjectIfNeeded(out var projectInstance)) + { + // Invalid project file, return true to continue for normal error handling + return true; + } + string targetFrameworks = projectInstance.GetPropertyValue("TargetFrameworks"); + + // If there's no TargetFrameworks property or only one framework, no selection needed + if (string.IsNullOrWhiteSpace(targetFrameworks)) + { + return true; + } + + // parse the TargetFrameworks property and make sure to account for any additional whitespace + // users may have added for formatting reasons. + var frameworks = targetFrameworks.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + return TrySelectTargetFramework(frameworks, _isInteractive, out selectedFramework); + } + + /// + /// Invalidates the loaded project with updated global properties. + /// This is needed after framework selection to get the correct device list for that framework. + /// + public void InvalidateGlobalProperties(Dictionary updatedProperties) + { + // Update our stored global properties + foreach (var (key, value) in updatedProperties) + { + _globalProperties[key] = value; + } + + // Dispose existing project to force re-evaluation + _project = null; + _collection?.Dispose(); + _collection = null; + HasValidProject = false; + } + + /// + /// Opens the project if it hasn't been opened yet. + /// + private bool OpenProjectIfNeeded([NotNullWhen(true)] out ProjectInstance? projectInstance) + { + if (_project is not null) + { + // Create a fresh ProjectInstance for each build operation + // to avoid accumulating state (existing item groups) from previous builds + projectInstance = _project.CreateProjectInstance(); + HasValidProject = true; + return true; + } + + try + { + _collection = new ProjectCollection( + globalProperties: _globalProperties, + loggers: GetLoggers(), + toolsetDefinitionLocations: ToolsetDefinitionLocations.Default); + _project = _collection.LoadProject(_projectFilePath); + projectInstance = _project.CreateProjectInstance(); + HasValidProject = true; + return true; + } + catch (InvalidProjectFileException) + { + // Invalid project file, return false + projectInstance = null; + HasValidProject = false; + return false; + } + } + + public void Dispose() + { + // NOTE: _binaryLogger is not disposed here because it is *owned* by the caller + _collection?.Dispose(); + } + + /// + /// Handles target framework selection when given an array of frameworks. + /// If there's only one framework, selects it automatically. + /// If there are multiple frameworks, prompts the user (interactive) or shows an error (non-interactive). + /// + /// Array of target frameworks to choose from + /// Whether we're running in interactive mode (can prompt user) + /// The selected target framework, or null if selection was cancelled + /// True if we should continue, false if we should exit with error + public static bool TrySelectTargetFramework(string[] frameworks, bool isInteractive, out string? selectedFramework) + { + // If there's only one framework in the TargetFrameworks, we do need to pick it to force the subsequent builds/evaluations + // to act against the correct 'view' of the project + if (frameworks.Length == 1) + { + selectedFramework = frameworks[0]; + return true; + } + + if (isInteractive) + { + selectedFramework = PromptForTargetFramework(frameworks); + return selectedFramework != null; + } + else + { + Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyFramework, "--framework")); + Reporter.Error.WriteLine(); + Reporter.Error.WriteLine(CliCommandStrings.RunCommandAvailableTargetFrameworks); + Reporter.Error.WriteLine(); + + for (int i = 0; i < frameworks.Length; i++) + { + Reporter.Error.WriteLine($" {i + 1}. {frameworks[i]}"); + } + + Reporter.Error.WriteLine(); + Reporter.Error.WriteLine($"{CliCommandStrings.RunCommandExampleText}: dotnet run --framework {frameworks[0]}"); + Reporter.Error.WriteLine(); + selectedFramework = null; + return false; + } + } + + /// + /// Prompts the user to select a target framework from the available options using Spectre.Console. + /// + private static string? PromptForTargetFramework(string[] frameworks) + { + try + { + var prompt = new SelectionPrompt() + .Title($"{CyanMarkup}{Markup.Escape(CliCommandStrings.RunCommandSelectTargetFrameworkPrompt)}{EndMarkup}") + .PageSize(10) + .MoreChoicesText($"{GrayMarkup}({Markup.Escape(CliCommandStrings.RunCommandMoreFrameworksText)}){EndMarkup}") + .AddChoices(frameworks) + .EnableSearch() + .SearchPlaceholderText(CliCommandStrings.RunCommandSearchPlaceholderText); + + return Spectre.Console.AnsiConsole.Prompt(prompt); + } + catch (Exception) + { + // If Spectre.Console fails (e.g., terminal doesn't support it), return null + return null; + } + } + + /// + /// Represents a device item returned from the ComputeAvailableDevices MSBuild target. + /// + public record DeviceItem(string Id, string? Description, string? Type, string? Status, string? RuntimeIdentifier); + + /// + /// Computes available devices by calling the ComputeAvailableDevices MSBuild target if it exists. + /// + /// Whether restore should be skipped before computing devices + /// List of available devices if the target exists, null otherwise + /// True if restore was performed, false otherwise + /// True if the target was found and executed, false otherwise + public bool TryComputeAvailableDevices(bool noRestore, out List? devices, out bool restoreWasPerformed) + { + devices = null; + restoreWasPerformed = false; + + if (!OpenProjectIfNeeded(out var projectInstance)) + { + // Invalid project file, return false + return false; + } + + // Check if the ComputeAvailableDevices target exists + if (!projectInstance.Targets.ContainsKey(Constants.ComputeAvailableDevices)) + { + return false; + } + + // If restore is allowed, run restore first so device computation sees the restored assets + if (!noRestore) + { + // Run the Restore target + var restoreResult = projectInstance.Build( + targets: ["Restore"], + loggers: GetLoggers(), + remoteLoggers: null, + out _); + if (!restoreResult) + { + return false; + } + + restoreWasPerformed = true; + } + + // Build the target + var buildResult = projectInstance.Build( + targets: [Constants.ComputeAvailableDevices], + loggers: GetLoggers(), + remoteLoggers: null, + out var targetOutputs); + + if (!buildResult) + { + return false; + } + + // Get the Devices items from the target output + if (!targetOutputs.TryGetValue(Constants.ComputeAvailableDevices, out var targetResult)) + { + return false; + } + + devices = new(targetResult.Items.Length); + + foreach (var item in targetResult.Items) + { + devices.Add(new DeviceItem( + item.ItemSpec, + item.GetMetadata("Description"), + item.GetMetadata("Type"), + item.GetMetadata("Status"), + item.GetMetadata("RuntimeIdentifier") + )); + } + + return true; + } + + /// + /// Attempts to select a device for running the application. + /// If devices are available and none was specified, prompts the user to select one (interactive mode) + /// or shows an error (non-interactive mode). + /// + /// Whether to list devices and exit + /// Whether restore should be skipped + /// The selected device, or null if not needed + /// The RuntimeIdentifier for the selected device, or null if not provided + /// True if restore was performed, false otherwise + /// True if we should continue, false if we should exit + public bool TrySelectDevice( + bool listDevices, + bool noRestore, + out string? selectedDevice, + out string? runtimeIdentifier, + out bool restoreWasPerformed) + { + selectedDevice = null; + runtimeIdentifier = null; + restoreWasPerformed = false; + + // Try to get available devices from the project + bool targetExists = TryComputeAvailableDevices(noRestore, out var devices, out restoreWasPerformed); + + // If the target doesn't exist, continue without device selection + if (!targetExists) + { + // No device support in this project + return true; + } + + // Target exists - check if we have devices + if (devices is null || devices.Count == 0) + { + if (listDevices) + { + Reporter.Output.WriteLine(CliCommandStrings.RunCommandNoDevicesAvailable); + return true; + } + + // Target exists but no devices available - this is an error + Reporter.Error.WriteLine(CliCommandStrings.RunCommandNoDevicesAvailable); + return false; + } + + // If listing devices, display them and exit + if (listDevices) + { + Reporter.Output.WriteLine(CliCommandStrings.RunCommandAvailableDevices); + Reporter.Output.WriteLine(); + + for (int i = 0; i < devices.Count; i++) + { + var device = devices[i]; + var displayBuilder = new StringBuilder($" {i + 1}. {device.Id}"); + + if (!string.IsNullOrWhiteSpace(device.Description)) + { + displayBuilder.Append($" - {device.Description}"); + } + + if (!string.IsNullOrWhiteSpace(device.Type)) + { + displayBuilder.Append($" ({device.Type}"); + if (!string.IsNullOrWhiteSpace(device.Status)) + { + displayBuilder.Append($", {device.Status}"); + } + displayBuilder.Append(')'); + } + else if (!string.IsNullOrWhiteSpace(device.Status)) + { + displayBuilder.Append($" ({device.Status})"); + } + + Reporter.Output.WriteLine(displayBuilder.ToString()); + } + + Reporter.Output.WriteLine(); + Reporter.Output.WriteLine($"{CliCommandStrings.RunCommandExampleText}: dotnet run --device {ArgumentEscaper.EscapeSingleArg(devices[0].Id)}"); + Reporter.Output.WriteLine(); + return true; + } + + // If there's only one device, automatically select it (similar to single framework selection) + if (devices.Count == 1) + { + selectedDevice = devices[0].Id; + runtimeIdentifier = devices[0].RuntimeIdentifier; + return true; + } + + if (_isInteractive) + { + var deviceItem = PromptForDevice(devices); + if (deviceItem is null) + { + return false; + } + + selectedDevice = deviceItem.Id; + runtimeIdentifier = deviceItem.RuntimeIdentifier; + return true; + } + else + { + Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyDevice, "--device")); + Reporter.Error.WriteLine(); + Reporter.Error.WriteLine(CliCommandStrings.RunCommandAvailableDevices); + Reporter.Error.WriteLine(); + + for (int i = 0; i < devices.Count; i++) + { + var device = devices[i]; + var displayText = $" {i + 1}. {device.Id}"; + + if (!string.IsNullOrWhiteSpace(device.Description)) + { + displayText += $" - {device.Description}"; + } + + Reporter.Error.WriteLine(displayText); + } + + Reporter.Error.WriteLine(); + Reporter.Error.WriteLine($"{CliCommandStrings.RunCommandExampleText}: dotnet run --device {ArgumentEscaper.EscapeSingleArg(devices[0].Id)}"); + Reporter.Error.WriteLine(); + return false; + } + } + + /// + /// Prompts the user to select a device from the available options using Spectre.Console. + /// + private static DeviceItem? PromptForDevice(List devices) + { + List<(string Display, DeviceItem Device)> choices = new(devices.Count); + foreach (var d in devices) + { + var display = d.Id; + if (!string.IsNullOrWhiteSpace(d.Description)) + { + display += $" - {d.Description}"; + } + choices.Add((display, d)); + } + + try + { + var prompt = new SelectionPrompt<(string Display, DeviceItem Device)>() + .Title($"{CyanMarkup}{Markup.Escape(CliCommandStrings.RunCommandSelectDevicePrompt)}{EndMarkup}") + .PageSize(10) + .MoreChoicesText($"{GrayMarkup}({Markup.Escape(CliCommandStrings.RunCommandMoreDevicesText)}){EndMarkup}") + .AddChoices(choices) + .UseConverter(choice => choice.Display) + .EnableSearch() + .SearchPlaceholderText(CliCommandStrings.RunCommandSearchPlaceholderText); + + var (Display, Device) = Spectre.Console.AnsiConsole.Prompt(prompt); + return Device; + } + catch (Exception) + { + // If Spectre.Console fails (e.g., terminal doesn't support it), return null + return null; + } + } + + /// + /// Attempts to deploy to a device by calling the DeployToDevice MSBuild target if it exists. + /// This reuses the already-loaded project instance for performance. + /// + /// True if deployment succeeded or was skipped (no target), false if deployment failed + public bool TryDeployToDevice() + { + if (!OpenProjectIfNeeded(out var projectInstance)) + { + // Invalid project file + return false; + } + + // Check if the DeployToDevice target exists in the project + if (!projectInstance.Targets.ContainsKey(Constants.DeployToDevice)) + { + // Target doesn't exist, skip deploy step + return true; + } + + // Build the DeployToDevice target + var buildResult = projectInstance.Build( + targets: [Constants.DeployToDevice], + loggers: GetLoggers(), + remoteLoggers: null, + out _); + + return buildResult; + } + + /// + /// Gets the list of loggers to use for MSBuild operations. + /// Creates a fresh console logger each time to avoid disposal issues when calling Build() multiple times. + /// + private IEnumerable GetLoggers() + { + if (_binaryLogger is not null) + yield return _binaryLogger; + yield return CommonRunHelpers.GetConsoleLogger(_msbuildArgs); + } +} diff --git a/src/Cli/dotnet/Commands/Run/TargetFrameworkSelector.cs b/src/Cli/dotnet/Commands/Run/TargetFrameworkSelector.cs deleted file mode 100644 index 82f8d7c152ba..000000000000 --- a/src/Cli/dotnet/Commands/Run/TargetFrameworkSelector.cs +++ /dev/null @@ -1,130 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Build.Evaluation; -using Microsoft.Build.Exceptions; -using Microsoft.DotNet.Cli.Utils; -using Spectre.Console; - -namespace Microsoft.DotNet.Cli.Commands.Run; - -internal static class TargetFrameworkSelector -{ - /// - /// Evaluates the project to determine if target framework selection is needed. - /// If the project has multiple target frameworks and none was specified, prompts the user to select one. - /// - /// Path to the project file - /// Global properties for MSBuild evaluation - /// Whether we're running in interactive mode (can prompt user) - /// The selected target framework, or null if not needed - /// True if we should continue, false if we should exit with error - public static bool TrySelectTargetFramework( - string projectFilePath, - Dictionary globalProperties, - bool isInteractive, - out string? selectedFramework) - { - selectedFramework = null; - - // If a framework is already specified, no need to prompt - if (globalProperties.TryGetValue("TargetFramework", out var existingFramework) && !string.IsNullOrWhiteSpace(existingFramework)) - { - return true; - } - - // Evaluate the project to get TargetFrameworks - string targetFrameworks; - try - { - using var collection = new ProjectCollection(globalProperties: globalProperties); - var project = collection.LoadProject(projectFilePath); - targetFrameworks = project.GetPropertyValue("TargetFrameworks"); - } - catch (InvalidProjectFileException) - { - // Invalid project file, return true to continue for normal error handling - return true; - } - - // If there's no TargetFrameworks property or only one framework, no selection needed - if (string.IsNullOrWhiteSpace(targetFrameworks)) - { - return true; - } - - // parse the TargetFrameworks property and make sure to account for any additional whitespace - // users may have added for formatting reasons. - var frameworks = targetFrameworks.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - - return TrySelectTargetFramework(frameworks, isInteractive, out selectedFramework); - } - - /// - /// Handles target framework selection when given an array of frameworks. - /// If there's only one framework, selects it automatically. - /// If there are multiple frameworks, prompts the user (interactive) or shows an error (non-interactive). - /// - /// Array of target frameworks to choose from - /// Whether we're running in interactive mode (can prompt user) - /// The selected target framework, or null if selection was cancelled - /// True if we should continue, false if we should exit with error - public static bool TrySelectTargetFramework(string[] frameworks, bool isInteractive, out string? selectedFramework) - { - // If there's only one framework in the TargetFrameworks, we do need to pick it to force the subsequent builds/evaluations - // to act against the correct 'view' of the project - if (frameworks.Length == 1) - { - selectedFramework = frameworks[0]; - return true; - } - - if (isInteractive) - { - selectedFramework = PromptForTargetFramework(frameworks); - return selectedFramework != null; - } - else - { - Reporter.Error.WriteLine(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyFramework, "--framework")); - Reporter.Error.WriteLine(); - Reporter.Error.WriteLine(CliCommandStrings.RunCommandAvailableTargetFrameworks); - Reporter.Error.WriteLine(); - - for (int i = 0; i < frameworks.Length; i++) - { - Reporter.Error.WriteLine($" {i + 1}. {frameworks[i]}"); - } - - Reporter.Error.WriteLine(); - Reporter.Error.WriteLine($"{CliCommandStrings.RunCommandExampleText}: dotnet run --framework {frameworks[0]}"); - Reporter.Error.WriteLine(); - selectedFramework = null; - return false; - } - } - - /// - /// Prompts the user to select a target framework from the available options using Spectre.Console. - /// - private static string? PromptForTargetFramework(string[] frameworks) - { - try - { - var prompt = new SelectionPrompt() - .Title($"[cyan]{Markup.Escape(CliCommandStrings.RunCommandSelectTargetFrameworkPrompt)}[/]") - .PageSize(10) - .MoreChoicesText($"[grey]({Markup.Escape(CliCommandStrings.RunCommandMoreFrameworksText)})[/]") - .AddChoices(frameworks) - .EnableSearch() - .SearchPlaceholderText(CliCommandStrings.RunCommandSearchPlaceholderText); - - return Spectre.Console.AnsiConsole.Prompt(prompt); - } - catch (Exception) - { - // If Spectre.Console fails (e.g., terminal doesn't support it), return null - return null; - } - } -} diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf index 25de438df13c..aca54ec20616 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf @@ -57,6 +57,21 @@ Autoři Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Sestaví projekt .NET. @@ -902,7 +917,7 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Nejsou nainstalované žádné úlohy, nic se nedá opravit. Pokud chcete najít úlohy, které se mají nainstalovat, spusťte vyhledávání úloh dotnet. + Nejsou nainstalované žádné úlohy, nic se nedá opravit. Pokud chcete najít úlohy, které se mají nainstalovat, spusťte vyhledávání úloh dotnet. @@ -1219,7 +1234,7 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s Specify the output directory (press Enter for default: '{0}', directory must not exist): - Zadejte výstupní adresář (stisknutím klávesy Enter použijete výchozí hodnotu: {0}, adresář nesmí existovat): + Zadejte výstupní adresář ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s Vrací se zpět instalace balíčku {0}… + + Available devices: + Available devices: + + Available target frameworks: - Dostupné cílové architektury: + Available target frameworks: @@ -1337,6 +1357,11 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s Sestavování... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Spuštění cíle {0} ke zjištění příkazů spuštění pro tento projekt se nezdařilo. Opravte chyby a upozornění a spusťte je znovu. @@ -1344,7 +1369,7 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s Example - Příklad + Example @@ -1381,12 +1406,17 @@ Nástroj {1} (verze {2}) se úspěšně nainstaloval. Do souboru manifestu {3} s Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - V projektu {0} nelze pokračovat. -Ujistěte se, že máte spustitelný typ projektu. -Spustitelný projekt by měl cílit na spustitelný TFM (například net{1}) a mít OutputType Exe. -Aktuální OutputType je {2}. + Projekt se nedá spustit. +Ověřte prosím, že máte spustitelný typ projektu, a zajistěte, aby tento projekt podporoval {0}. +Cílem spustitelného projektu by mělo být TFM (například net5.0) a jeho OutputType by měl být Exe. +Aktuální {1} je {2}. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Cílem projektu je více architektur. Pomocí parametru {0} určete, která architektura se má spustit. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Posunutím nahoru a dolů zobrazíte další architektury. + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Cílem projektu je více architektur. Pomocí parametru {0} určete, která arch Type to search - Zadejte hledaný text + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Vyberte cílovou architekturu, která se má spustit: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf index ac5454709239..553a73dc90fc 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf @@ -57,6 +57,21 @@ Autoren Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Hiermit wird ein .NET-Projekt erstellt. @@ -902,7 +917,7 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Es sind keine Workloads installiert, es ist keine Reparatur erforderlich. Führen Sie „dotnet workload search“ aus, um zu installierende Workloads zu finden. + Es sind keine Workloads installiert, es ist keine Reparatur erforderlich. Führen Sie „dotnet workload search“ aus, um zu installierende Workloads zu finden. @@ -1219,7 +1234,7 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der Specify the output directory (press Enter for default: '{0}', directory must not exist): - Geben Sie das Ausgabeverzeichnis an (drücken Sie die EINGABETASTE, um die Standardeinstellung zu verwenden: „{0}“, das Verzeichnis darf nicht vorhanden sein): + Ausgabeverzeichnis ({0}) angeben: {0} is the default value @@ -1327,9 +1342,14 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der Für die Installation von {0} wird ein Rollback ausgeführt... + + Available devices: + Available devices: + + Available target frameworks: - Verfügbare Zielframeworks: + Available target frameworks: @@ -1337,6 +1357,11 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der Buildvorgang wird ausgeführt... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Das {0} Ziel ausführen, um zu ermitteln, dass ein Fehler bei den Ausführungsbefehlen für dieses Projekt aufgetreten ist. Beheben Sie die Fehler und Warnungen, und führen Sie dies erneut aus. @@ -1344,7 +1369,7 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der Example - Beispiel + Example @@ -1381,12 +1406,17 @@ Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. Der Eintrag wird der Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - Ihr Projekt „{0}“ kann nicht fortgesetzt werden. -Stellen Sie sicher, dass der Projekttyp ausführbar ist. -Ein ausführbares Projekt muss ein ausführbares TFM (z. B. net{1}) und den OutputType „Exe“ verwenden. -Der aktuelle OutputType lautet „{2}“. + Ihr Projekt kann nicht ausgeführt werden. +Stellen Sie sicher, dass der Projekttyp ausführbar ist und "{0}" dieses Projekt unterstützt. +Ein ausführbares Projekt muss ein ausführbares TFM (z. B. net5.0) und den OutputType "Exe" verwenden. +{1} lautet aktuell "{2}". {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Ihr Projekt verwendet mehrere Zielframeworks. Geben Sie über "{0}" an, welches Framework ausgeführt werden soll. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Nach oben und unten bewegen, um weitere Frameworks anzuzeigen + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Ihr Projekt verwendet mehrere Zielframeworks. Geben Sie über "{0}" an, welches Type to search - Zum Suchen eingeben + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Wählen Sie das auszuführende Zielframework aus: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf index 8316f3a8bc8c..91c32ff85daa 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf @@ -57,6 +57,21 @@ Autores Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Compila un proyecto de .NET. @@ -902,7 +917,7 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - No hay cargas de trabajo instaladas, no hay nada que reparar. Ejecute "dotnet workload search" para buscar las cargas de trabajo que se van a instalar. + No hay cargas de trabajo instaladas, no hay nada que reparar. Ejecute "dotnet workload search" para buscar las cargas de trabajo que se van a instalar. @@ -1219,7 +1234,7 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Specify the output directory (press Enter for default: '{0}', directory must not exist): - Especifique el directorio de salida (presione Entrar para el valor predeterminado: ''{0}, el directorio no debe existir): + Especifique el directorio de salida ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Revirtiendo el paquete {0} de la instalación... + + Available devices: + Available devices: + + Available target frameworks: - Plataformas de destino disponibles: + Available target frameworks: @@ -1337,6 +1357,11 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Compilando... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Error al ejecutar el destino {0} para detectar comandos de ejecución para este proyecto. Corrija los errores y advertencias y vuelva a ejecutarlo. @@ -1344,7 +1369,7 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Example - Ejemplo + Example @@ -1362,7 +1387,7 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} - No se puede usar el perfil de inicio '{0}' porque no se pudo localizar el archivo de configuración de inicio. Ubicaciones probadas: + No se puede usar el perfil de inicio '{0}' porque no se pudo localizar el archivo de configuración de inicio. Ubicaciones probadas: {1} @@ -1381,12 +1406,17 @@ La herramienta "{1}" (versión "{2}") se instaló correctamente. Se ha agregado Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - No se puede continuar con el proyecto '{0}'. -Asegúrese de que tiene un tipo de proyecto que se puede ejecutar. -Un proyecto ejecutable debe tener como destino un TFM ejecutable (por ejemplo, net{1}) y tener OutputType 'Exe'. -El OutputType actual es '{2}'. + No se puede ejecutar el proyecto. +Asegúrese de tener un tipo de proyecto ejecutable y asegúrese de que "{0}" admita este proyecto. +Un proyecto ejecutable debe tener como destino un TFM ejecutable (por ejemplo, net5.0) y tener como OutputType "Exe". +El valor actual de {1} es "{2}". {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Su proyecto tiene como destino varias plataformas. Especifique la que quiere usar mediante "{0}". + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Subir y bajar para mostrar más marcos + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Su proyecto tiene como destino varias plataformas. Especifique la que quiere usa Type to search - Escriba para buscar + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Seleccione la plataforma de destino que se va a ejecutar: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf index 76d33a50c526..63eae5969a2f 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf @@ -57,6 +57,21 @@ Auteurs Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Générez un projet .NET. @@ -902,7 +917,7 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Aucune charge de travail n’est installée, rien à réparer. Exécutez « recherche de charge de travail dotnet » pour trouver les charges de travail à installer. + Aucune charge de travail n’est installée, rien à réparer. Exécutez « recherche de charge de travail dotnet » pour trouver les charges de travail à installer. @@ -1219,7 +1234,7 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Specify the output directory (press Enter for default: '{0}', directory must not exist): - Spécifiez le répertoire de sortie (appuyez sur Entrée pour utiliser la valeur par défaut : « {0} », le répertoire ne doit pas exister) : + Spécifiez le répertoire de sortie ({0}) : {0} is the default value @@ -1327,9 +1342,14 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Annulation de l'installation {0}... + + Available devices: + Available devices: + + Available target frameworks: - Frameworks cibles disponibles : + Available target frameworks: @@ -1337,6 +1357,11 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Génération... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. L’exécution de la {0} cible pour découvrir les commandes d’exécution a échoué pour ce projet. Corrigez les erreurs et les avertissements, puis réexécutez. @@ -1344,7 +1369,7 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Example - Exemple + Example @@ -1362,7 +1387,7 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} - Impossible d’utiliser le profil de lancement « {0} », car le fichier de paramètres de lancement est introuvable. Emplacements essayés : + Impossible d’utiliser le profil de lancement « {0} », car le fichier de paramètres de lancement est introuvable. Emplacements essayés : {1} @@ -1381,12 +1406,17 @@ L'outil '{1}' (version '{2}') a été correctement installé. L'entrée est ajou Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - Impossible de continuer avec le projet « {0} ». -Vérifiez que vous avez un type de projet exécutable. -Un projet exécutable doit cibler un TFM exécutable (par exemple, net{1}) et avoir OutputType « Exe ». -Le type de sortie actuel (OutputType) est « {2} ». + Impossible d'exécuter votre projet. +Vérifiez que vous avez un type de projet exécutable et que '{0}' prend en charge ce projet. +Un projet exécutable doit cibler un TFM exécutable (par exemple, net5.0) et avoir OutputType 'Exe'. +Le {1} actuel est '{2}'. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Votre projet cible plusieurs frameworks. Spécifiez le framework à exécuter à l'aide de '{0}'. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Montez et descendez pour afficher plus de frameworks + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Votre projet cible plusieurs frameworks. Spécifiez le framework à exécuter à Type to search - Entrer le texte à rechercher + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Sélectionner le framework cible pour exécuter : + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf index 42862d54224e..916c4b11c60e 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf @@ -57,6 +57,21 @@ Autori Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Compila un progetto .NET. @@ -902,7 +917,7 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Nessun carico di lavoro installato, nulla da ripristinare. Eseguire 'ricerca del carico di lavoro DotNet' per trovare i carichi di lavoro da installare. + Nessun carico di lavoro installato, nulla da ripristinare. Eseguire 'ricerca del carico di lavoro DotNet' per trovare i carichi di lavoro da installare. @@ -1219,7 +1234,7 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Specify the output directory (press Enter for default: '{0}', directory must not exist): - Specificare la directory di output (premere INVIO per impostazione predefinita: '{0}', la directory non deve esistere): + Specifica la directory di output ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Rollback dell'installazione del pacchetto {0} in corso... + + Available devices: + Available devices: + + Available target frameworks: - Framework di destinazione disponibili: + Available target frameworks: @@ -1337,6 +1357,11 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Compilazione... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. L'esecuzione della destinazione {0} per individuare i comandi di esecuzione non è riuscita per questo progetto. Correggere gli errori e gli avvisi ed eseguire di nuovo. @@ -1344,7 +1369,7 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Example - Esempio + Example @@ -1362,7 +1387,7 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} - Non è possibile usare il profilo di avvio "{0}" perché il file delle impostazioni di avvio non è stato trovato. Posizioni tentate: + Non è possibile usare il profilo di avvio "{0}" perché il file delle impostazioni di avvio non è stato trovato. Posizioni tentate: {1} @@ -1381,12 +1406,17 @@ Lo strumento '{1}' versione '{2}' è stato installato. La voce è stata aggiunta Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - Non è possibile procedere con il progetto '{0}'. -Assicurarsi che sia presente un tipo di progetto eseguibile. -Un progetto eseguibile deve essere destinato a un TFM eseguibile, ad esempio net{1}, inoltre OutputType deve essere impostato su 'Exe'. -L'OutputType corrente è '{2}'. + Non è possibile eseguire il progetto. +Assicurarsi che sia presente un tipo di progetto eseguibile e che '{0}' supporti tale progetto. +Un progetto eseguibile deve essere destinato a un TFM eseguibile, ad esempio net5.0, inoltre OutputType deve essere impostato su 'Exe'. +Il valore corrente di {1} è '{2}'. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Il progetto è destinato a più framework. Specificare il framework da eseguire con '{0}'. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Spostarsi verso l'alto o verso il basso per visualizzare altri framework + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Il progetto è destinato a più framework. Specificare il framework da eseguire Type to search - Digita per cercare + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Selezionare il framework di destinazione da eseguire: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf index c3ea3a16264a..0f07011cd52d 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf @@ -57,6 +57,21 @@ 作成者 Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. .NET プロジェクトをビルドします。 @@ -902,7 +917,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - ワークロードがインストールされていないため、修復するものがありません。`dotnet ワークロード検索` を実行してインストールするワークロードを検索します。 + ワークロードがインストールされていないため、修復するものがありません。`dotnet ワークロード検索` を実行してインストールするワークロードを検索します。 @@ -1219,7 +1234,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Specify the output directory (press Enter for default: '{0}', directory must not exist): - 出力ディレクトリを指定します (Enter キーを押すと既定値に設定されます: '{0}'、ディレクトリは存在してはなりません): + 出力ディレクトリ ({0}) を指定します: {0} is the default value @@ -1327,9 +1342,14 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man パック {0} のインストールをロールバックしています... + + Available devices: + Available devices: + + Available target frameworks: - 使用可能なターゲット フレームワーク: + Available target frameworks: @@ -1337,6 +1357,11 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man ビルドしています... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. このプロジェクトで実行コマンドを検出するための {0} ターゲットの実行に失敗しました。エラーと警告を修正して、もう一度実行してください。 @@ -1344,7 +1369,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Example - + Example @@ -1362,7 +1387,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} - 起動設定ファイルが見つからないため、起動プロファイル '{0}' を使用できません。試行された場所: + 起動設定ファイルが見つからないため、起動プロファイル '{0}' を使用できません。試行された場所: {1} @@ -1381,12 +1406,17 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - プロジェクト '{0}' を続行できません。 -実行可能なプロジェクト タイプがあることを確認します。 -実行可能なプロジェクトは実行可能な TFM (たとえば、net{1}) を対象としている必要があり、OutputType 'Exe' が必要です。 -現在の OutputType は '{2}' です。 + プロジェクトを実行できません。 +プロジェクト タイプが実行可能であること、このプロジェクトが '{0}' でサポートされていることを確認してください。 +実行可能なプロジェクトは実行可能な TFM (たとえば、net5.0) を対象としている必要があり、OutputType 'Exe' が必要です。 +現在の {1} は '{2}' です。 {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' プロジェクトは複数のフレームワークを対象としています。'{0}' を使用して、実行するフレームワークを指定してください。 + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - 上下に移動して、さらに多くのフレームワークを表示 + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Your project targets multiple frameworks. Specify which framework to run using ' Type to search - 入力して検索します + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - 実行するターゲット フレームワークを選択してください: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf index a9b00d45f66b..20b68d1a3182 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf @@ -57,6 +57,21 @@ 작성자 Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. .NET 프로젝트를 빌드합니다. @@ -902,7 +917,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - 워크로드가 설치되어 있지 않고 복구할 것도 없습니다. ‘dotnet 워크로드 검색’을 실행하여 설치할 워크로드를 찾으세요. + 워크로드가 설치되어 있지 않고 복구할 것도 없습니다. ‘dotnet 워크로드 검색’을 실행하여 설치할 워크로드를 찾으세요. @@ -1219,7 +1234,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Specify the output directory (press Enter for default: '{0}', directory must not exist): - 출력 디렉터리를 지정합니다(Enter 키를 누르면 '{0}' 기본값 사용, 기존 디렉터리가 없어야 함). + 출력 디렉터리 지정({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 팩 {0} 설치를 롤백 중... + + Available devices: + Available devices: + + Available target frameworks: - 사용 가능한 대상 프레임워크: + Available target frameworks: @@ -1337,6 +1357,11 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 빌드하는 중... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. 이 프로젝트에 대해 실행 명령을 검색하기 위해 {0} 대상을 실행하지 못했습니다. 오류 및 경고를 수정하고 다시 실행합니다. @@ -1344,7 +1369,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Example - 예제 + Example @@ -1362,7 +1387,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} - 시작 설정 파일을 찾을 수 없으므로 시작 프로필 '{0}'을(를) 사용할 수 없습니다. 시도한 위치: + 시작 설정 파일을 찾을 수 없으므로 시작 프로필 '{0}'을(를) 사용할 수 없습니다. 시도한 위치: {1} @@ -1381,12 +1406,17 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - 프로젝트 '{0}'을(를) 진행할 수 없습니다. -실행 가능한 프로젝트 형식이 있는지 확인하세요. -실행 가능한 프로젝트는 실행 가능한 TFM(예: net{1})을(를) 대상으로 하고 OutputType 'Exe'가 있어야 합니다. -현재 OutputType은(는) '{2}'입니다. + 프로젝트를 실행할 수 없습니다. +실행 가능한 프로젝트 형식이 있고 '{0}'에서 이 프로젝트를 지원하는지 확인하세요. +실행 가능한 프로젝트는 실행 가능한 TFM(예: net5.0)을 대상으로 하고 OutputType 'Exe'가 있어야 합니다. +현재 {1}은(는) '{2}'입니다. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' 프로젝트에서 여러 프레임워크를 대상으로 합니다. '{0}'을(를) 사용하여 실행할 프레임워크를 지정하세요. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - 더 많은 프레임워크를 보려면 위아래로 이동하세요. + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Your project targets multiple frameworks. Specify which framework to run using ' Type to search - 검색할 형식 + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - 실행할 대상 프레임워크 선택: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf index 7b0e2ff45a1f..dda65dfdf1e3 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf @@ -57,6 +57,21 @@ Autorzy Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Kompiluj projekt platformy .NET. @@ -902,7 +917,7 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Nie zainstalowano żadnych obciążeń i nie ma nic do naprawienia. Uruchom polecenie „dotnet workload search”, aby znaleźć obciążenia do zainstalowania. + Nie zainstalowano żadnych obciążeń i nie ma nic do naprawienia. Uruchom polecenie „dotnet workload search”, aby znaleźć obciążenia do zainstalowania. @@ -1219,7 +1234,7 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis Specify the output directory (press Enter for default: '{0}', directory must not exist): - Określ katalog wyjściowy (naciśnij Enter, aby użyć wartości domyślnej: „{0}”, katalog nie może istnieć): + Określ katalog wyjściowy ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis Trwa wycofywanie instalacji paczki {0}. + + Available devices: + Available devices: + + Available target frameworks: - Dostępne docelowe struktury: + Available target frameworks: @@ -1337,6 +1357,11 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis Trwa kompilowanie... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Uruchomienie obiektu docelowego {0} w celu odnalezienia poleceń przebiegu dla tego projektu nie powiodło się. Usuń błędy i ostrzeżenia, a następnie uruchom ponownie. @@ -1344,7 +1369,7 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis Example - Przykład + Example @@ -1381,12 +1406,17 @@ Narzędzie „{1}” (wersja „{2}”) zostało pomyślnie zainstalowane. Wpis Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - Nie można kontynuować pracy z projektem „{0}”. -Upewnij się, że masz typ projektu, który można uruchomić. -Projekt, który można uruchomić, powinien być przeznaczony dla możliwego do uruchomienia monikera platformy docelowej (na przykład net{1}) i mieć typ OutputType „Exe”. -Bieżący typ OutputType to „{2}”. + Nie można uruchomić projektu. +Upewnij się, że używany typ projektu umożliwia uruchamianie oraz że element „{0}” obsługuje ten projekt. +Projekt z możliwością uruchamiania musi mieć moniker TFM z możliwością uruchomienia (np. net5.0) i typ OutputType „Exe”. +Bieżący element {1}: „{2}”. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Projekt ma wiele platform docelowych. Określ platformę do uruchomienia przy użyciu elementu „{0}”. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Przesuń w górę lub w dół, aby zobaczyć więcej struktur + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Projekt ma wiele platform docelowych. Określ platformę do uruchomienia przy u Type to search - Wpisz, aby wyszukać + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Wybierz docelową strukturę do uruchomienia: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf index 5da015345085..c32d0c5c5c99 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf @@ -57,6 +57,21 @@ Autores Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Criar um projeto do .NET. @@ -902,7 +917,7 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Nenhuma carga de trabalho instalada, nada para reparar. Execute a 'pesquisa de carga de trabalho dotnet' para encontrar cargas de trabalho a serem instaladas. + Nenhuma carga de trabalho instalada, nada para reparar. Execute a 'pesquisa de carga de trabalho dotnet' para encontrar cargas de trabalho a serem instaladas. @@ -1219,7 +1234,7 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici Specify the output directory (press Enter for default: '{0}', directory must not exist): - Especifique o diretório de saída (pressione Enter para o padrão: '{0}', o diretório não deve existir): + Especificar o diretório de saída ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici Revertendo o pacote {0} instalação... + + Available devices: + Available devices: + + Available target frameworks: - Estruturas de destino disponíveis: + Available target frameworks: @@ -1337,6 +1357,11 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici Compilando... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Falha na execução do destino {0} para descobrir comandos de execução para este projeto. Corrija os erros e avisos e execute novamente. @@ -1344,7 +1369,7 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici Example - Exemplo + Example @@ -1381,12 +1406,17 @@ A ferramenta '{1}' (versão '{2}') foi instalada com êxito. A entrada foi adici Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - Não é possível continuar com o projeto "{0}". -Verifique se você tem um tipo de projeto executável. -Um projeto executável deve ter como destino um TFM executável (por exemplo, net{1}) e ter OutputType "Exe". -O OutputType atual é "{2}". + Não é possível executar o projeto. +Verifique se você tem um tipo de projeto executável e se '{0}' dá suporte a esse projeto. +Um projeto executável deve ter como destino um TFM executável (por exemplo, o net5.0) e ter o OutputType 'Exe'. +O {1} atual é '{2}'. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Ele tem diversas estruturas como destino. Especifique que estrutura executar usando '{0}'. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Mover para cima e para baixo para ver mais estruturas + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Ele tem diversas estruturas como destino. Especifique que estrutura executar usa Type to search - Digite para pesquisar + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Selecione a estrutura de destino para executar: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf index 8f144b09ea22..4d108ae99863 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf @@ -57,6 +57,21 @@ Авторы Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Сборка проекта .NET. @@ -902,7 +917,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - Рабочие нагрузки не установлены, не нужно ничего восстанавливать. Запустите "Поиск рабочей нагрузки DotNet", чтобы найти рабочие нагрузки для установки. + Рабочие нагрузки не установлены, не нужно ничего восстанавливать. Запустите "Поиск рабочей нагрузки DotNet", чтобы найти рабочие нагрузки для установки. @@ -1219,7 +1234,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Specify the output directory (press Enter for default: '{0}', directory must not exist): - Укажите выходной каталог (нажмите клавишу ВВОД для значения по умолчанию: "{0}", каталог не должен существовать): + Укажите выходной каталог ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Откат установки пакета {0}... + + Available devices: + Available devices: + + Available target frameworks: - Доступные целевые платформы: + Available target frameworks: @@ -1337,6 +1357,11 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Сборка… + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Не удалось запустить цель {0} для обнаружения команд выполнения для этого проекта. Исправьте ошибки и предупреждения и повторите попытку. @@ -1344,7 +1369,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Example - Пример + Example @@ -1381,12 +1406,17 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - Не удается продолжить работу с проектом "{0}". -Убедитесь, что тип проекта поддерживает запуск. -Чтобы поддерживать запуск, проект должен быть предназначен для TFM с поддержкой запуска (например, net{1}) и иметь тип выдаваемого результата (OutputType) "Exe". -Сейчас тип результата(OutputType) — "{2}". + Не удалось запустить проект. +Убедитесь, что тип проекта поддерживает запуск и что "{0}" поддерживает этот проект. +Запускаемый проект должен быть предназначен для TFM с поддержкой запуска (например, net5.0) и иметь тип выходных данных "EXE". +Текущий {1} — "{2}". {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Проект предназначен для нескольких платформ. Укажите платформу, для которой следует запустить проект, с помощью "{0}". + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Прокрутите вверх и вниз, чтобы увидеть больше платформ + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Your project targets multiple frameworks. Specify which framework to run using ' Type to search - Введите текст для поиска + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Выберите целевую платформу для запуска: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf index be4570e5cc19..5ec84a882619 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf @@ -57,6 +57,21 @@ Yazarlar Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. Bir .NET projesi derler. @@ -902,7 +917,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - İş yükü yüklenmediğinden onarılacak iş yükü yok. Yüklenecek iş yüklerini bulmak için `dotnet workload search` çalıştırın. + İş yükü yüklenmediğinden onarılacak iş yükü yok. Yüklenecek iş yüklerini bulmak için `dotnet workload search` çalıştırın. @@ -1219,7 +1234,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Specify the output directory (press Enter for default: '{0}', directory must not exist): - Çıkış dizinini belirtin (varsayılan için Enter tuşuna basın: '{0}', dizin mevcut olmamalıdır): + Çıkış dizinini belirtin ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man {0} paketi için yükleme geri alınıyor... + + Available devices: + Available devices: + + Available target frameworks: - Mevcut hedef çerçeveler: + Available target frameworks: @@ -1337,6 +1357,11 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Derleniyor... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. Çalıştırma komutlarını bulmak için {0} hedefini çalıştırma bu proje için başarısız oldu. Hataları ve uyarıları düzeltip yeniden çalıştırın. @@ -1344,7 +1369,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Example - Örnek + Example @@ -1381,12 +1406,17 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - '{0}' projesine devam edilemiyor. -Çalıştırılabilir bir proje türüne sahip olduğunuzdan emin olun. -Çalıştırılabilir bir proje, çalıştırılabilir bir TFM'yi (örneğin, net{1}) hedeflemeli ve OutputType ‘Exe’ değerine sahip olmalıdır. -Geçerli OutputType '{2}'. + Projeniz çalıştırılamıyor. +Çalıştırılabilir bir proje türüne sahip olduğunuzdan ve bu projenin '{0}' tarafından desteklendiğinden emin olun. +Çalıştırılabilir proje, çalıştırılabilir bir TFM’yi (örneğin, net5.0) hedeflemeli ve OutputType değeri 'Exe' olmalıdır. +Geçerli {1}: '{2}'. {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' Projeniz birden fazla Framework'ü hedefliyor. '{0}' kullanarak hangi Framework'ün çalıştırılacağını belirtin. + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - Yukarı ve aşağı hareket ederek daha fazla çerçeve görüntüleyin + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Projeniz birden fazla Framework'ü hedefliyor. '{0}' kullanarak hangi Framework' Type to search - Aramak için yazın + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - Çalıştırmak için hedef çerçeveyi seçin: + Select the target framework to run: @@ -1816,9 +1861,9 @@ and the corresponding package Ids for installed tools using the command 'dotnet tool list'. '{0}' paket kimliğine sahip araç bulunamadı. -Araçlar, aracı çağırırken kullandığınız araç adından farklı olabilen -paket kimlikleri kullanılarak kaldırılır. Yüklü araçların araç adlarını ve -karşılık gelen paket kimliklerini bulmak için +Araçlar, aracı çağırırken kullandığınız araç adından farklı olabilen +paket kimlikleri kullanılarak kaldırılır. Yüklü araçların araç adlarını ve +karşılık gelen paket kimliklerini bulmak için 'dotnet tool list' komutunu kullanabilirsiniz. diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf index 04d30caaa767..f1756cdf26a6 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf @@ -57,6 +57,21 @@ 作者 Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. 生成 .NET 项目。 @@ -902,7 +917,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - 未安装工作负载,没有要修复的内容。请运行“dotnet 工作负载搜索”,查找要安装的工作负载。 + 未安装工作负载,没有要修复的内容。请运行“dotnet workload search”,查找要安装的工作负载。 @@ -1219,7 +1234,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Specify the output directory (press Enter for default: '{0}', directory must not exist): - 指定输出目录(按 Enter 使用默认值: ‘{0}’,目录不得存在): + 指定输出目录({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 正在回滚包 {0} 的安装... + + Available devices: + Available devices: + + Available target frameworks: - 可用的目标框架: + Available target frameworks: @@ -1337,6 +1357,11 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 正在生成... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. 为此项目运行 {0} 目标以发现运行命令失败。请修复错误和警告,然后再次运行。 @@ -1344,7 +1369,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Example - 示例 + Example @@ -1381,12 +1406,17 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - 无法继续进行项目 ‘{0}’。 -确保具有可运行的项目类型。 -可运行的项目应面向可运行的 TFM (例如 net{1})且其 OutputType 为 ‘Exe’。 -当前 OutputType 为 ‘{2}’。 + 无法运行项目。 +请确保你具有可运行的项目类型且“{0}”支持此项目。 +可运行的项目应面向可运行的 TFM (例如 net5.0)且其 OutputType 为 "Exe"。 +当前的 {1} 为“{2}”。 {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' 你的项目面向多个框架。请指定要使用“{0}”运行的框架。 + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - 上移或下移以显示更多框架 + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Your project targets multiple frameworks. Specify which framework to run using ' Type to search - 键入以搜索 + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - 选择要运行的目标框架: + Select the target framework to run: diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf index bb8d0a9ca790..e739b31721f7 100644 --- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf @@ -57,6 +57,21 @@ 作者 Table lable + + The device identifier to use for running the application. + The device identifier to use for running the application. + + + + DEVICE + DEVICE + + + + List available devices for running the application. + List available devices for running the application. + + Build a .NET project. 建置 .NET 專案。 @@ -428,7 +443,7 @@ See https://aka.ms/dotnet-test/mtp for more information. The following exception occurred when running the test module with RunCommand '{0}' and RunArguments '{1}': {2} - 使用 RunCommand '{0}' 和 RunArguments '{1}' 執行測試模組時,發生以下例外狀況: + 使用 RunCommand '{0}' 和 RunArguments '{1}' 執行測試模組時,發生以下例外狀況: {2} {Locked="RunCommand"}{Locked="RunArguments"} @@ -902,7 +917,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man No workloads are installed, nothing to repair. Run `dotnet workload search` to find workloads to install. - 未安裝任何工作負載,沒有要修復的項目。請執行 `dotnet workload search` 以尋找要安裝的工作負載。 + 未安裝任何工作負載,沒有要修復的項目。請執行 `dotnet workload search` 以尋找要安裝的工作負載。 @@ -1219,7 +1234,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Specify the output directory (press Enter for default: '{0}', directory must not exist): - 請指定輸出目錄 (按 Enter 鍵以使用預設值: '{0}',目錄必須不存在): + 指定輸出目錄 ({0}): {0} is the default value @@ -1327,9 +1342,14 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 正在回復套件 {0} 安裝... + + Available devices: + Available devices: + + Available target frameworks: - 可用的目標架構: + Available target frameworks: @@ -1337,6 +1357,11 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man 正在建置... + + Deployment to device failed. Fix any deployment errors and run again. + Deployment to device failed. Fix any deployment errors and run again. + + Running the {0} target to discover run commands failed for this project. Fix the errors and warnings and run again. 執行 {0} 目標以探索對此專案的執行命令失敗。修正錯誤和警告,然後重新執行。 @@ -1344,7 +1369,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Example - 範例 + Example @@ -1362,7 +1387,7 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Cannot use launch profile '{0}' because the launch settings file could not be located. Locations tried: {1} - 無法使用啟動設定檔 '{0}',因為找不到啟動設定檔檔案。嘗試的位置: + 無法使用啟動設定檔 '{0}',因為找不到啟動設定檔檔案。嘗試的位置: {1} @@ -1381,12 +1406,17 @@ Tool '{1}' (version '{2}') was successfully installed. Entry is added to the man Ensure you have a runnable project type. A runnable project should target a runnable TFM (for instance, net{1}) and have OutputType 'Exe'. The current OutputType is '{2}'. - 無法繼續處理專案 '{0}'。 -請確定您有可執行的專案類型。 -可執行的專案應以可執行的 TFM (例如 net{1}) 為目標,且 OutputType 應為 'Exe'。 -目前的 OutputType 為 '{2}'。 + 無法執行您的專案。 +請確定您有可執行的專案類型,並確定 '{0}' 支援此專案。 +可執行的專案應以可執行的 TFM (例如 net5.0) 為目標,且 OutputType 應為 'Exe'。 +目前的 {1} 為 '{2}'。 {0} is project file path. {1} is dotnet framework version. {2} is the project output type.{Locked="OutputType"}{Locked="Exe"} + + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + Unable to run this project because multiple devices are available. Please specify which device to use by passing the {0} argument with one of the following values: + + Unable to run your project Your project targets multiple frameworks. Specify which framework to run using '{0}'. @@ -1394,9 +1424,19 @@ Your project targets multiple frameworks. Specify which framework to run using ' 您的專案以多重架構為目標。請使用 '{0}' 指定要執行的架構。 + + Move up and down to reveal more devices + Move up and down to reveal more devices + + Move up and down to reveal more frameworks - 上下移動以顯示更多的架構 + Move up and down to reveal more frameworks + + + + No devices are available for this project. + No devices are available for this project. @@ -1406,12 +1446,17 @@ Your project targets multiple frameworks. Specify which framework to run using ' Type to search - 要搜尋的類型 + Type to search + + + + Select a device to run on: + Select a device to run on: Select the target framework to run: - 選取要執行的目標架構: + Select the target framework to run: diff --git a/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj b/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj new file mode 100644 index 000000000000..04ce32c6db1d --- /dev/null +++ b/test/TestAssets/TestProjects/DotnetRunDevices/DotnetRunDevices.csproj @@ -0,0 +1,57 @@ + + + + Exe + net9.0;$(CurrentTargetFramework) + + + + + + + + + + + + + + + + + + + + + + + $(IntermediateOutputPath)DeviceInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/TestAssets/TestProjects/DotnetRunDevices/Program.cs b/test/TestAssets/TestProjects/DotnetRunDevices/Program.cs new file mode 100644 index 000000000000..5d9e6d61d1e7 --- /dev/null +++ b/test/TestAssets/TestProjects/DotnetRunDevices/Program.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace DotNetRunDevices +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello from multi-targeted app!"); + Console.WriteLine($"Target Framework: {AppContext.TargetFrameworkName}"); + Console.WriteLine($"Runtime: {System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription}"); + + // DeviceInfo class is generated at build time when Device property is set + Console.WriteLine($"Device: {DeviceInfo.Device}"); + Console.WriteLine($"RuntimeIdentifier: {DeviceInfo.RuntimeIdentifier}"); + } + } +} diff --git a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs new file mode 100644 index 000000000000..c2c1948b12a5 --- /dev/null +++ b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunSelectsDevice.cs @@ -0,0 +1,379 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Build.Logging.StructuredLogger; +using Microsoft.DotNet.Cli.Commands; +using StructuredLoggerTarget = Microsoft.Build.Logging.StructuredLogger.Target; + +namespace Microsoft.DotNet.Cli.Run.Tests; + +/// +/// Integration tests for device selection in dotnet run +/// +public class GivenDotnetRunSelectsDevice : SdkTest +{ + public GivenDotnetRunSelectsDevice(ITestOutputHelper log) : base(log) + { + } + + /// + /// Helper method to assert conditions about MSBuild target execution in a binlog file + /// + private static void AssertTargetInBinlog(string binlogPath, string targetName, Action> assertion) + { + var build = BinaryLog.ReadBuild(binlogPath); + var targets = build.FindChildrenRecursive( + target => target.Name == targetName); + + assertion(targets); + } + + [Fact] + public void ItFailsInNonInteractiveMode_WhenMultipleDevicesAvailableAndNoneSpecified() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .WithEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE", "en-US") + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--no-interactive"); + + result.Should().Fail() + .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyDevice, "--device")); + } + + [Fact] + public void ItListsDevicesForSpecifiedFramework() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--list-devices"); + + result.Should().Pass() + .And.HaveStdOutContaining("test-device-1") + .And.HaveStdOutContaining("test-device-2") + .And.HaveStdOutContaining("Emulator"); + } + + [Theory] + [InlineData("test-device-1")] + [InlineData("test-device-2")] + public void ItRunsDifferentDevicesInMultiTargetedApp(string deviceId) + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId) + .Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}"); + } + + [Fact] + public void ItShowsErrorMessageWithAvailableDevices_InNonInteractiveMode() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .WithEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE", "en-US") + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--no-interactive"); + + result.Should().Fail() + .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyDevice, "--device")) + .And.HaveStdErrContaining("test-device-1") + .And.HaveStdErrContaining("test-device-2"); + } + + [Fact] + public void ItDoesNotPromptForDeviceWhenComputeAvailableDevicesTargetDoesNotExist() + { + var testInstance = _testAssetsManager.CopyTestAsset( + "NETFrameworkReferenceNETStandard20", + testAssetSubdirectory: TestAssetSubdirectories.DesktopTestProjects) + .WithSource(); + + string projectDirectory = Path.Combine(testInstance.Path, "MultiTFMTestApp"); + + // This project doesn't have ComputeAvailableDevices target, so it should just run + new DotnetCommand(Log, "run") + .WithWorkingDirectory(projectDirectory) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework) + .Should().Pass() + .And.HaveStdOutContaining("This string came from the test library!"); + } + + [Fact] + public void ItTreatsEmptyDeviceSpecificationAsNotSpecified() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .WithEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE", "en-US") + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "-p:Device=", "--no-interactive"); + + result.Should().Fail() + .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyDevice, "--device")); + } + + [Fact] + public void ItWorksWithDevicePropertySyntax() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string deviceId = "test-device-1"; + new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, $"-p:Device={deviceId}") + .Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}"); + } + + [Fact] + public void ItWorksWithDeviceWithoutRuntimeIdentifier() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string deviceId = "test-device-2"; + new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId) + .Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}") + .And.HaveStdOutContaining("RuntimeIdentifier:"); + } + + [Theory] + [InlineData(true)] // interactive + [InlineData(false)] // non-interactive + public void ItAutoSelectsSingleDeviceWithoutPrompting(bool interactive) + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog"); + + var command = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path); + + var args = new List { "--framework", ToolsetInfo.CurrentTargetFramework, "-p:SingleDevice=true", "-bl" }; + if (!interactive) + { + args.Add("--no-interactive"); + } + + var result = command.Execute(args.ToArray()); + + // Should auto-select the single device and run successfully + result.Should().Pass() + .And.HaveStdOutContaining("Device: single-device") + .And.HaveStdOutContaining($"RuntimeIdentifier: {RuntimeInformation.RuntimeIdentifier}"); + + // Verify the binlog file was created and the ComputeAvailableDevices target ran + File.Exists(binlogPath).Should().BeTrue("the binlog file should be created"); + AssertTargetInBinlog(binlogPath, "ComputeAvailableDevices", + targets => targets.Should().NotBeEmpty("ComputeAvailableDevices target should run to discover available devices")); + } + + [Fact] + public void ItCreatesBinlogWhenRequestedForDeviceSelection() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + // When /bl:device-list.binlog is specified, the verb "dotnet-run" is appended + string binlogPath = Path.Combine(testInstance.Path, "device-list-dotnet-run.binlog"); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--list-devices", "/bl:device-list.binlog"); + + result.Should().Pass() + .And.HaveStdOutContaining("test-device-1"); + + // Verify the binlog file was created with the unified logger and the ComputeAvailableDevices target ran + File.Exists(binlogPath).Should().BeTrue("the binlog file should be created when /bl: argument is provided"); + AssertTargetInBinlog(binlogPath, "ComputeAvailableDevices", + targets => targets.Should().NotBeEmpty("ComputeAvailableDevices target should have been executed")); + } + + [Fact] + public void ItFailsWhenNoDevicesAreAvailable() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .WithEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE", "en-US") + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "-p:NoDevices=true", "--no-interactive"); + + result.Should().Fail() + .And.HaveStdErrContaining(CliCommandStrings.RunCommandNoDevicesAvailable); + } + + [Theory] + [InlineData("--device")] + [InlineData("-p:Device=")] + public void ItDoesNotRunComputeAvailableDevicesWhenDeviceIsPreSpecified(string deviceArgPrefix) + { + string deviceId = "test-device-2"; + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog"); + + var args = new List { "--framework", ToolsetInfo.CurrentTargetFramework }; + if (deviceArgPrefix == "--device") + { + args.Add("--device"); + args.Add(deviceId); + } + else + { + args.Add($"{deviceArgPrefix}{deviceId}"); + } + args.Add("-bl"); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute(args.ToArray()); + + // Should run successfully + result.Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}"); + + // Verify the binlog file was created and the ComputeAvailableDevices target did not run + File.Exists(binlogPath).Should().BeTrue("the binlog file should be created"); + AssertTargetInBinlog(binlogPath, "ComputeAvailableDevices", + targets => targets.Should().BeEmpty("ComputeAvailableDevices target should not have been executed when device is pre-specified")); + } + + [Fact] + public void ItPromptsForTargetFrameworkEvenWhenDeviceIsSpecified() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string deviceId = "test-device-1"; + + // Don't specify --framework, only specify --device + // This should fail in non-interactive mode because framework selection is still needed + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .WithEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE", "en-US") + .Execute("--device", deviceId, "--no-interactive"); + + // Should fail with framework selection error, not device selection error + result.Should().Fail() + .And.HaveStdErrContaining("Your project targets multiple frameworks. Specify which framework to run using '--framework'"); + } + + [Fact] + public void ItCallsDeployToDeviceTargetWhenDeviceIsSpecified() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string deviceId = "test-device-1"; + string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog"); + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId, "-bl"); + + // Should run successfully + result.Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}"); + + // Verify the binlog file was created and the DeployToDevice target ran + File.Exists(binlogPath).Should().BeTrue("the binlog file should be created"); + AssertTargetInBinlog(binlogPath, "DeployToDevice", + targets => targets.Should().NotBeEmpty("DeployToDevice target should have been executed")); + } + + [Fact] + public void ItCallsDeployToDeviceTargetEvenWithNoBuild() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string deviceId = "test-device-1"; + string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog"); + + // First build the project with the device so DeviceInfo gets generated + // Note: dotnet build doesn't support --device flag, use -p:Device= instead + new DotnetCommand(Log, "build") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, $"-p:Device={deviceId}") + .Should().Pass(); + + // Now run with --no-build + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId, "--no-build", "-bl"); + + // Should run successfully + result.Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}"); + + // Verify the binlog file was created and the DeployToDevice target ran + File.Exists(binlogPath).Should().BeTrue("the binlog file should be created"); + AssertTargetInBinlog(binlogPath, "DeployToDevice", + targets => targets.Should().NotBeEmpty("DeployToDevice target should have been executed even with --no-build")); + } + + [Fact] + public void ItCallsDeployToDeviceTargetWhenDeviceIsAutoSelected() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string binlogPath = Path.Combine(testInstance.Path, "msbuild-dotnet-run.binlog"); + + // Run with auto-selection of single device + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "-p:SingleDevice=true", "-bl"); + + // Should run successfully + result.Should().Pass() + .And.HaveStdOutContaining("Device: single-device"); + + // Verify the binlog file was created + File.Exists(binlogPath).Should().BeTrue("the binlog file should be created"); + + // DeployToDevice target should have been called since a device was selected + AssertTargetInBinlog(binlogPath, "DeployToDevice", + targets => targets.Should().NotBeEmpty("DeployToDevice target should have been executed when a device is selected")); + } + + [Fact] + public void ItPassesRuntimeIdentifierToDeployToDeviceTarget() + { + var testInstance = _testAssetsManager.CopyTestAsset("DotnetRunDevices") + .WithSource(); + + string deviceId = "test-device-1"; + string rid = RuntimeInformation.RuntimeIdentifier; + + var result = new DotnetCommand(Log, "run") + .WithWorkingDirectory(testInstance.Path) + .Execute("--framework", ToolsetInfo.CurrentTargetFramework, "--device", deviceId, "--runtime", rid); + + // Should run successfully and show the RuntimeIdentifier in the app output + result.Should().Pass() + .And.HaveStdOutContaining($"Device: {deviceId}") + .And.HaveStdOutContaining($"RuntimeIdentifier: {rid}"); + } +} diff --git a/test/dotnet.Tests/CommandTests/Run/RunCommandTests.cs b/test/dotnet.Tests/CommandTests/Run/RunCommandTests.cs index 5504bd51c710..37a947eb8f2b 100644 --- a/test/dotnet.Tests/CommandTests/Run/RunCommandTests.cs +++ b/test/dotnet.Tests/CommandTests/Run/RunCommandTests.cs @@ -23,11 +23,13 @@ private static RunCommand CreateRunCommand( entryPointFileFullPath: null, launchProfile: null, noLaunchProfile: false, - noLaunchProfileArguments, + noLaunchProfileArguments: noLaunchProfileArguments, + device: null, + listDevices: false, noRestore: false, noCache: false, interactive: false, - MSBuildArgs.FromOtherArgs([]), + msbuildArgs: MSBuildArgs.FromOtherArgs([]), applicationArgs: applicationArgs ?? [], readCodeFromStdin: false, environmentVariables: new Dictionary()); @@ -86,7 +88,7 @@ public void Executable_DefaultWorkingDirectory() }; var runCommand = CreateRunCommand(projectPath); - var command = (Command)runCommand.GetTargetCommand(model, projectFactory: null, cachedRunProperties: null); + var command = (Command)runCommand.GetTargetCommand(model, projectFactory: null, cachedRunProperties: null, logger: null); Assert.Equal("executable", command.StartInfo.FileName); Assert.Equal(dir, command.StartInfo.WorkingDirectory); @@ -111,7 +113,7 @@ public void Executable_NoLaunchProfileArguments() }; var runCommand = CreateRunCommand(projectPath, noLaunchProfileArguments: true); - var command = (Command)runCommand.GetTargetCommand(model, projectFactory: null, cachedRunProperties: null); + var command = (Command)runCommand.GetTargetCommand(model, projectFactory: null, cachedRunProperties: null, logger: null); Assert.Equal("", command.StartInfo.Arguments); } @@ -134,7 +136,7 @@ public void Executable_ApplicationArguments() }; var runCommand = CreateRunCommand(projectPath, applicationArgs: ["app 1", "app 2"]); - var command = (Command)runCommand.GetTargetCommand(model, projectFactory: null, cachedRunProperties: null); + var command = (Command)runCommand.GetTargetCommand(model, projectFactory: null, cachedRunProperties: null, logger: null); Assert.Equal("\"app 1\" \"app 2\"", command.StartInfo.Arguments); } diff --git a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh index 880ac16e77a9..bf969a10f194 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh +++ b/test/dotnet.Tests/CompletionTests/snapshots/bash/DotnetCliSnapshotTests.VerifyCompletions.verified.sh @@ -1379,7 +1379,7 @@ _testhost_run() { prev="${COMP_WORDS[COMP_CWORD-1]}" COMPREPLY=() - opts="--configuration --framework --project --file --launch-profile --no-launch-profile --no-build --interactive --no-restore --no-cache --self-contained --no-self-contained --verbosity --runtime --arch --os --disable-build-servers --artifacts-path --environment --help" + opts="--configuration --framework --project --file --launch-profile --no-launch-profile --device --list-devices --no-build --interactive --no-restore --no-cache --self-contained --no-self-contained --verbosity --runtime --arch --os --disable-build-servers --artifacts-path --environment --help" if [[ $COMP_CWORD == "$1" ]]; then COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) diff --git a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 index e0f1ecad057d..8dc3c5f9aec1 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 +++ b/test/dotnet.Tests/CompletionTests/snapshots/pwsh/DotnetCliSnapshotTests.VerifyCompletions.verified.ps1 @@ -849,6 +849,8 @@ Register-ArgumentCompleter -Native -CommandName 'testhost' -ScriptBlock { [CompletionResult]::new('--launch-profile', '--launch-profile', [CompletionResultType]::ParameterName, "The name of the launch profile (if any) to use when launching the application.") [CompletionResult]::new('--launch-profile', '-lp', [CompletionResultType]::ParameterName, "The name of the launch profile (if any) to use when launching the application.") [CompletionResult]::new('--no-launch-profile', '--no-launch-profile', [CompletionResultType]::ParameterName, "Do not attempt to use launchSettings.json or [app].run.json to configure the application.") + [CompletionResult]::new('--device', '--device', [CompletionResultType]::ParameterName, "The device identifier to use for running the application.") + [CompletionResult]::new('--list-devices', '--list-devices', [CompletionResultType]::ParameterName, "List available devices for running the application.") [CompletionResult]::new('--no-build', '--no-build', [CompletionResultType]::ParameterName, "Do not build the project before running. Implies --no-restore.") [CompletionResult]::new('--interactive', '--interactive', [CompletionResultType]::ParameterName, "Allows the command to stop and wait for user input or action (for example to complete authentication).") [CompletionResult]::new('--no-restore', '--no-restore', [CompletionResultType]::ParameterName, "Do not restore the project before building.") diff --git a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh index a9ec3e4ad8a1..aae722f223fa 100644 --- a/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh +++ b/test/dotnet.Tests/CompletionTests/snapshots/zsh/DotnetCliSnapshotTests.VerifyCompletions.verified.zsh @@ -893,6 +893,8 @@ _testhost() { '--launch-profile=[The name of the launch profile (if any) to use when launching the application.]:LAUNCH_PROFILE: ' \ '-lp=[The name of the launch profile (if any) to use when launching the application.]:LAUNCH_PROFILE: ' \ '--no-launch-profile[Do not attempt to use launchSettings.json or \[app\].run.json to configure the application.]' \ + '--device=[The device identifier to use for running the application.]:DEVICE: ' \ + '--list-devices[List available devices for running the application.]' \ '--no-build[Do not build the project before running. Implies --no-restore.]' \ '--interactive=[Allows the command to stop and wait for user input or action (for example to complete authentication).]: :((False\:"False" True\:"True" ))' \ '--no-restore[Do not restore the project before building.]' \ diff --git a/test/dotnet.Tests/dotnet.Tests.csproj b/test/dotnet.Tests/dotnet.Tests.csproj index d5c8e9a22b22..0cff111bd10f 100644 --- a/test/dotnet.Tests/dotnet.Tests.csproj +++ b/test/dotnet.Tests/dotnet.Tests.csproj @@ -79,6 +79,7 @@ +