求助:.NET 8 C#函数应用如何用Azure ARM SDK远程执行Azure VM上的EXE?
问题
我需要编写一个.NET 8 C#函数应用,用于远程运行Azure虚拟机(VM)上的EXE文件。尝试使用Azure.ResourceManager SDK实现,但无法正确创建RunCommandInput实例。
目前的代码如下:
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req) { _logger.LogInformation("Invoking remote executable on Windows VM using RunCommand"); // Azure authentication and setup string tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID"); string clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); string clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET"); string subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); string resourceGroupName = "YOUR_RESOURCE_GROUP"; string vmName = "YOUR_VM_NAME"; // Use DefaultAzureCredential for authentication var credential = new DefaultAzureCredential(); // Initialize Azure resource manager client var armClient = new ArmClient(credential, subscriptionId); // Get the specific VM resource var subscription = armClient.GetSubscriptionResource(new ResourceIdentifier($"/subscriptions/{subscriptionId}")); ResourceGroupResource resourceGroup = subscription.GetResourceGroup(resourceGroupName); VirtualMachineResource vmResource = resourceGroup.GetVirtualMachine(vmName); try { // Use Azure Compute's RunCommand to execute a PowerShell script on the VM var runCommandInput = new RunCommandInput("RunPowerShellScript"); //{ // Script = new List<string> { commandToExecute }, // Parameters = new List<RunCommandInputParameter> {} //}; _logger.LogInformation("Running command on VM..."); // Execute the command var runCommandResult = await vmResource.RunCommandAsync(WaitUntil.Completed, runCommandInput); // Log the result //_logger.LogInformation($"Command executed successfully. Status: {runCommandResult.Value.Status}"); } catch (RequestFailedException ex) { _logger.LogError($"Failed to execute command on VM: {ex.Message}"); } return new OkObjectResult("OK"); }
现在RunCommandInput类的Parameters和Script字段均为只读,无法直接赋值,也未找到可设置这些字段的辅助/扩展方法。该类有一个可设置这些字段的构造函数,但它是内部构造函数,无法调用。
解决方案
1. 方案可行性确认
完全可行,Azure.ResourceManager.Compute SDK支持通过RunCommand功能远程在VM上执行PowerShell脚本(或其他类型命令),进而调用EXE文件。
2. 正确创建RunCommandInput实例的方法
RunCommandInput是SDK生成的模型类,官方提供了静态创建方法RunCommandInput.CreateRunCommandInput来实例化,该方法支持传入脚本内容和参数。
3. 修改后的完整代码
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req) { _logger.LogInformation("Invoking remote executable on Windows VM using RunCommand"); // Azure authentication and setup string tenantId = Environment.GetEnvironmentVariable("AZURE_TENANT_ID"); string clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); string clientSecret = Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET"); string subscriptionId = Environment.GetEnvironmentVariable("AZURE_SUBSCRIPTION_ID"); string resourceGroupName = "YOUR_RESOURCE_GROUP"; string vmName = "YOUR_VM_NAME"; // 替换为你的EXE路径和命令 string exeCommand = @"& ""C:\path\to\your\application.exe"""; // Use DefaultAzureCredential for authentication var credential = new DefaultAzureCredential(); // Initialize Azure resource manager client var armClient = new ArmClient(credential, subscriptionId); // Get the specific VM resource var subscription = armClient.GetSubscriptionResource(new ResourceIdentifier($"/subscriptions/{subscriptionId}")); ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync(resourceGroupName); VirtualMachineResource vmResource = await resourceGroup.GetVirtualMachineAsync(vmName); try { // 使用静态创建方法构建RunCommandInput var runCommandInput = RunCommandInput.CreateRunCommandInput( commandId: "RunPowerShellScript", script: new List<string> { exeCommand }, parameters: new List<RunCommandInputParameter>() ); _logger.LogInformation("Running command on VM..."); // Execute the command var runCommandResult = await vmResource.RunCommandAsync(WaitUntil.Completed, runCommandInput); // 打印命令执行的详细输出 var resultValue = runCommandResult.Value; _logger.LogInformation($"Command execution status: {resultValue.Status}"); foreach (var output in resultValue.Value.Message) { _logger.LogInformation($"Output: {output}"); } } catch (RequestFailedException ex) { _logger.LogError($"Failed to execute command on VM: {ex.Message}, Error code: {ex.Status}"); } return new OkObjectResult("Command execution initiated"); }
4. 关键注意事项
- 权限配置:用于认证的服务主体或系统分配身份必须拥有对目标VM的
Microsoft.Compute/virtualMachines/runCommand/action权限(可通过"虚拟机参与者"或自定义角色配置)。 - VM网络要求:VM必须能与Azure服务通信(无需公网IP,但需启用Azure实例元数据服务)。
- EXE路径处理:PowerShell中执行EXE需注意路径包含空格时的引号转义,示例中使用
& ""路径""的格式避免解析错误。 - 结果处理:
RunCommandResult包含命令执行的状态和输出日志,建议捕获并记录这些信息用于调试。
内容的提问来源于stack exchange,提问作者Dhawal Dhingra
相关产品推荐
相关产品推荐

