在 Windows Server 2022 上通过 PowerShell 无头安装 .NET 7 SDK 的脚本

huangapple go评论89阅读模式
英文:

Script Headless Install .NET 7 SDK on Windows Server 2022 via PowerShell

问题

是否可以在全新安装的 Windows Server 2022 实例上通过 PowerShell 或批处理脚本无头安装 .NET 7 SDK?

我的目标是启动一个新实例,然后能够安装并执行全局工具,例如这个 PowerShell 命令:

> dotnet tool install -g nbgv
> nbgv --version
3.5.13

然而,如果我使用 dotnet 安装 PowerShell 脚本我会收到“dotnet”命令未找到的错误

dotnet : The term 'dotnet' is not recognized as the name of a cmdlet, function, script file, or operable program.

到目前为止,我正在使用 AWS EC2 创建一个新的 Microsoft Windows Server 2022 基础镜像:

private async<string> Task StartWindowsServer(Amazon.EC2.IAmazonEC2 ec2Client)
{
   var response = await _ec2Client.RunInstancesAsync(new RunInstanceRequest{
      InstanceType = InstanceType.C4Large,
      ImageId = "ami-0bde1eb2c18cb2abe", //windows2022BaseUSEast1
      KeyName = ...,
      IamInstanceProfile ...
   });

   return response.Reservation.Instances.First();
}

然后,一旦实例被创建,我使用系统管理器运行 PowerShell 脚本进行安装:

private async Task InstallDotNetAndThirdPartyTool(
    Amazon.SimpleSystemsManagement.IAmazonSimpleSystemsManagement ssmClient,
    string instanceId)
{
    var installDotNet7 = 
            // https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script?WT.mc_id=dotnet-35129-website#examples
            @"&powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 7.0""" +
            Environment.NewLine +          
            "Restart-Computer";

     await ExecuteRemotePowerShell(ssmClient, instanceId, installDotNet7);

     var installNerdBank = "dotnet tool install -g nbgv";

     await ExecuteRemotePowerShell(ssmClient, instanceId, installNerdBank);

    // 脚本报错 - 找不到“dotnet”
}

private async Task ExecuteRemotePowerShell(
   Amazon.SimpleSystemsManagement.IAmazonSimpleSystemsManagement _ssmClient,
   string instanceId,
   string powershellScript)
{
    await _ssmClient.SendCommandAsync(
        new SendCommandRequest
        {
            DocumentName = commandName,
            Targets = new ()
            {
                new Target
                {
                    Key = "InstanceIds",
                    Values = new List<string>{ instanceId }
                }
            },
            Parameters = new Dictionary<string, List<string>>
            {
                {
                    "commands",
                    new List<string> { powershellScript }
                }
            }
        });
}

错误:

dotnet : The term 'dotnet' is not recognized as the name of a cmdlet, function, script file, or operable program.

Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

At C:\ProgramData\Amazon\SSM\InstanceData\i-07f13f9a7dacaf6b0\document\orchestration\c8de6390-d27f-4e78-ad88-cf62e85b07

0d\downloads\ExampleScript-638208821382795610.ps1:18 char:1

+ dotnet tool install ` 

我尝试过的其他事情

  • 我在 .NET 7 安装脚本中添加了“Restart-Computer”,以为这样会刷新,但没有解决问题。
  • 怀疑是路径问题,所以尝试在 .NET 7 安装脚本中手动设置路径,也没有成功:
$env:PATH=";C:\Users\Administrator\AppData\Local\Microsoft\dotnet"
[Environment]::SetEnvironmentVariable("Path", $env:Path,[System.EnvironmentVariableTarget]::Machine)
英文:

Is it possible to headlessly install the .NET 7 SDK on a fresh instance of Windows Server 2022 via powershell or batch script?

My goal is to spin up a new Instance and then be able to install and execute a global tool, ie this powershell:

> dotnet tool install -g nbgv
> nbgv --version
3.5.13

However, if I use the dotnet install powershell scripts, I get command not found errors on dotnet:

dotnet : The term 'dotnet' is not recognized as the name of a cmdlet, function, script file, or operable program.

So far, I'm using AWS EC2 to create a new Microsoft Windows Server 2022 Base image:

在 Windows Server 2022 上通过 PowerShell 无头安装 .NET 7 SDK 的脚本

private async<string> Task StartWindowsServer(Amazon.EC2.IAmazonEC2 ec2Client)
{
   var response = await _ec2Client.RunInstancesAsync(new RunInstanceRequest{
      InstanceType = InstanceType.C4Large,
      ImageId = "ami-0bde1eb2c18cb2abe", //windows2022BaseUSEast1
      KeyName = ...,
      IamInstanceProfile ...
   });

   return response.Reservation.Instances.First();
}

Then, once the instance is provisioned, I am using System Manager to run a powershell script to do the install:

private async Task InstallDotNetAndThirdPartyTool(
    Amazon.SimpleSystemsManagement.IAmazonSimpleSystemsManagement ssmClient,
    string instanceId)
{
    var installDotNet7 = 
            // https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script?WT.mc_id=dotnet-35129-website#examples
            @"&powershell -NoProfile -ExecutionPolicy unrestricted -Command ""[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel 7.0""" +
            Environment.NewLine +          
            "Restart-Computer";

     await ExecuteRemotePowerShell(ssmClient, instanceId, installDotNet7);

     var installNerdBank = "dotnet tool install -g nbgv";

     await ExecuteRemotePowerShell(ssmClient, instanceId, installNerdBank);

    // scritp errors out - can't find `dotnet`
}

private async Task ExecuteRemotePowerShell(
   Amazon.SimpleSystemsManagement.IAmazonSimpleSystemsManagement _ssmClient,
   string instanceId,
   string powershellScript)
{
    await _ssmClient.SendCommandAsync(
        new SendCommandRequest
        {
            DocumentName = commandName,
            Targets = new ()
            {
                new Target
                {
                    Key = "InstanceIds",
                    Values = new List<string>{ instanceId }
                }
            },
            Parameters = new Dictionary<string, List<string>>
            {
                {
                    "commands",
                    new List<string> { powershellScript }
                }
            }
        });
}

ERROR:

dotnet : The term 'dotnet' is not recognized as the name of a cmdlet, function, script file, or operable program.

Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

At C:\ProgramData\Amazon\SSM\InstanceData\i-07f13f9a7dacaf6b0\document\orchestration\c8de6390-d27f-4e78-ad88-cf62e85b07

0d\downloads\ExampleScript-638208821382795610.ps1:18 char:1

+ dotnet tool install ` 

Additional things I tried

  • I added the Restart-Computer into the .NET 7 install script thinking that would refresh things, but didn't solve it.
  • Figured there was a path issue, so I tried to manually set the path in the .NET 7 installd script, also did NOT work.:
$env:PATH=";C:\Users\Administrator\AppData\Local\Microsoft\dotnet"
[Environment]::SetEnvironmentVariable("Path", $env:Path,[System.EnvironmentVariableTarget]::Machine)
         

答案1

得分: 2

以下是翻译好的内容:

"Turns out I was missing two pieces:

  1. I need to manually set PATH as the .NET Install Script does not set environment variables (https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#set-environment-variables)
  2. I need to refresh the Path environment variable.

Here is the final PowerShell Script I ended up using (note the explicit -InstallDir):

&powershell -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((iwr -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel STS -InstallDir c:\dotnet"

[Environment]::SetEnvironmentVariable("DOTNET_ROOT","$HOME\.dotnet", "User")

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\dotnet\;$HOME\.dotnet;$HOME\.dotnet\Tools", "User")

[Environment]::SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT","1", "Machine")

[Environment]::SetEnvironmentVariable("DOTNET_NOLOGO", "true", "Machine")

[Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "true", "Machine")

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

dotnet --version

And special thanks to https://stackoverflow.com/questions/17794507/reload-the-path-in-powershell for the answer on how to reload Path."

英文:

Turns out I was missing two pieces:

  1. I need to manually set PATH as the .NET Install Script does not set environment variables (https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script#set-environment-variables)
  2. I need to refresh the Path environment variable.

Here is the final PowerShell Script I ended up using (note the explicit -InstallDir):

&powershell -NoProfile -ExecutionPolicy unrestricted -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; &([scriptblock]::Create((iwr -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) -Channel STS -InstallDir c:\dotnet"

[Environment]::SetEnvironmentVariable("DOTNET_ROOT","$HOME\.dotnet", "User")

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\dotnet\;$HOME\.dotnet;$HOME\.dotnet\Tools", "User")

[Environment]::SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT","1", "Machine")

[Environment]::SetEnvironmentVariable("DOTNET_NOLOGO", "true", "Machine")

[Environment]::SetEnvironmentVariable("DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "true", "Machine")

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")

dotnet --version

And special thanks to https://stackoverflow.com/questions/17794507/reload-the-path-in-powershell for the answer on how to reload Path.

huangapple
  • 本文由 发表于 2023年5月29日 10:22:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354337.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定