You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asp.Net Core Blazor调用PowerShell脚本在Windows Server 2019无结果排查

Troubleshooting PowerShell Invoke Issue in Blazor App on Windows Server 2019

Let's break down why your Blazor app works on your dev machine but returns empty results on Windows Server 2019—this is almost always a mix of subtle code gaps and server-specific configuration differences, not a hard bug in your core logic.

First, Check for Code Defects

Your current code has a few blind spots that could cause silent failures even if the PowerShell command runs:

  1. Cmdlet Spelling Typo
    You wrote get-Hotfixe in your script, but the official Windows PowerShell cmdlet is Get-HotFix (no trailing 'e'). If your dev machine has a custom alias for the misspelled version but the server doesn't, this would explain the empty result. Even if you meant to call an ECM-specific cmdlet (like something for ConfigMgr), double-check the spelling—PowerShell will silently return nothing if it can't find a cmdlet with that name (no error thrown unless you set $ErrorActionPreference = Stop).

  2. PSObject ToString() Limitation
    When you call item.ToString() on results from PowerShell.Invoke(), you're only getting the type name of the PSObject (like System.Management.Automation.PSCustomObject) instead of actual data. This means even if the cmdlet returns valid output, your code will append empty strings to the StringBuilder. Fix this by either accessing PSObject properties directly or converting output to JSON in the script:

    // Option 1: Access PSObject properties explicitly
    foreach (var item in result)
    {
        foreach (var prop in item.Properties)
        {
            sb.AppendLine($"{prop.Name}: {prop.Value}");
        }
        sb.AppendLine("---");
    }
    
    // Option 2: Modify script to return JSON for easy parsing
    string script = "Get-HotFix | ConvertTo-Json";
    
  3. Incomplete Error Handling
    Your code only checks Streams.Error, but PowerShell might generate non-terminating errors that don't populate this stream. Add checks for warning/verbose streams and force non-terminating errors to become terminating ones with $ErrorActionPreference = 'Stop':

    string script = "$ErrorActionPreference = 'Stop'; Get-HotFix";
    
  4. Missing Module Imports
    If you're calling ConfigMgr-specific cmdlets (not just Get-HotFix), your dev machine might auto-load the Configuration Manager module because you've run the console, but the server's runspace is a clean session. Explicitly import the module in your script:

    string script = @"
        $ErrorActionPreference = 'Stop'
        # Load ConfigMgr module (adjust path if needed)
        Import-Module $env:SMS_ADMIN_UI_PATH\..\ConfigurationManager.psd1 -Force
        # Replace with your actual ConfigMgr cmdlet, e.g., Get-CMDevice
    ";
    

Next, Server-Specific Configuration Checks

Even with fixed code, Windows Server 2019 has key differences from Windows 10 that could cause this issue:

  1. Application Pool Identity Mismatch
    You said the same user can run the command interactively, but Blazor apps hosted on IIS run under the application pool identity by default (e.g., IIS AppPool\DefaultAppPool), not your user account. To fix this:

    • Open IIS Manager, navigate to your app's application pool
    • Under "Advanced Settings", set "Identity" to the user account that can run the PowerShell command successfully
    • Ensure this user has permissions to access ConfigMgr and run scripts on the server
  2. Non-Interactive Session Environment Variables
    The SMS_ADMIN_UI_PATH variable (used to load the ConfigMgr module) is only set when you launch the ConfigMgr console interactively. In a non-interactive runspace (like your Blazor app uses), this variable doesn't exist. Hardcode the module path instead:

    string script = @"
        $ErrorActionPreference = 'Stop'
        # Hardcode ConfigMgr module path (adjust to your server's path)
        Import-Module 'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' -Force
        # Your cmdlet here
    ";
    
  3. 32-bit vs 64-bit Mismatch
    If your Blazor app runs in a 32-bit application pool (check IIS app pool settings: "Enable 32-bit Applications" set to True), it will launch a 32-bit PowerShell runspace. The ConfigMgr module is 64-bit only, so this will silently fail with no results. Set "Enable 32-bit Applications" to False to use 64-bit PowerShell.

  4. Execution Policy Restrictions
    While you can run the command interactively, non-interactive sessions might have a stricter execution policy. Check the server's policy with Get-ExecutionPolicy -List, and if needed, set a policy that allows script execution for the app's user (e.g., Set-ExecutionPolicy RemoteSigned -Scope CurrentUser).

Fixed Code Example

Here's a revised version of your code with these fixes applied:

string script = @"
    $ErrorActionPreference = 'Stop'
    # Load ConfigMgr module (adjust path as needed)
    Import-Module 'C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1' -Force
    # Replace with your actual ConfigMgr cmdlet, e.g., Get-CMDevice
    Get-HotFix | ConvertTo-Json
";

using (PowerShell powerShell = PowerShell.Create())
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
    runspace.Open();
    powerShell.Runspace = runspace;
    powerShell.AddScript(script);
    
    var result = powerShell.Invoke();
    
    // Check all error/warning streams
    if (powerShell.Streams.Error.Count > 0)
    {
        var errors = string.Join(Environment.NewLine, powerShell.Streams.Error.Select(e => e.ToString()));
        return $"Error: {errors}";
    }
    if (powerShell.Streams.Warning.Count > 0)
    {
        var warnings = string.Join(Environment.NewLine, powerShell.Streams.Warning.Select(w => w.ToString()));
        return $"Warning: {warnings}";
    }
    
    if (result.Count == 0)
    {
        return "No results returned from PowerShell command.";
    }
    
    // Since we used ConvertTo-Json, the result is a single string
    return $"{result[0].ToString()} Success!";
}

内容的提问来源于stack exchange,提问作者TheBlackOne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 18:32:56