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

从Asp.Net调用PowerShell Graph脚本报错:Connect-MgGraph未识别

问题:ASP.NET C#调用PowerShell脚本创建O365日历日程时提示Connect-MgGraph未识别

我有一个用于在O365日历中创建日程的PowerShell脚本,在Windows PowerShell ISE中运行完全正常,但通过ASP.NET C#页面调用时,返回错误:

The term 'Connect-MgGraph' 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.


C# 调用代码

public static string SetEvent(string Subject, string Date, string StartHour, string EndHour, string Location, string[] Attendees, string Body)
{
    string result = "";

    try
    {
        //Subject
        string strSubject = Subject;

        //Param StartDateHour && EndDateHour
        DateTime datDate = Convert.ToDateTime(Date);
        string strStartDateHour = datDate.Year.ToString() + "-" + datDate.Month.ToString() + "-" + datDate.Day.ToString() + "T" + StartHour;
        string strEndDateHour = datDate.Year.ToString() + "-" + datDate.Month.ToString() + "-" + datDate.Day.ToString() + "T" + EndHour;

        // Location
        string strLocation = Location;

        // Attendees
        string strAttendees = "@(";

        foreach (string item in Attendees)
        {
            strAttendees += "@{EmailAddress = @{" +
            "Address = ' + item.ToString() + ' " +
            "} " +
            "Type = 'Required'" +
        "}";
        }

        strAttendees += ")";

        // Body
        string strBody = Body;

        //Secrets!
        string strAppID = HIDDEN;
        string strTenantID = HIDDEN;
        string strClientSecret = HIDDEN;

        // create Powershell runspace
        RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
        Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
        runspace.Open();

        RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);

        string scriptfile = HttpContext.Current.Server.MapPath(@"~/PowerShell/scripts/Calendar/SetEvent.ps1");

        // create a pipeline and feed it the script text
        Pipeline pipeline = runspace.CreatePipeline();
        Command myCommand = new Command(scriptfile);

        CommandParameter SubjectParam = new CommandParameter("subject", strSubject);
        myCommand.Parameters.Add(SubjectParam);
        CommandParameter StartDateHourParam = new CommandParameter("startdatehour", strStartDateHour);
        myCommand.Parameters.Add(StartDateHourParam);
        CommandParameter EndDateHourParam = new CommandParameter("enddatehour", strEndDateHour);
        myCommand.Parameters.Add(EndDateHourParam);
        CommandParameter LocationParam = new CommandParameter("location", strLocation);
        myCommand.Parameters.Add(LocationParam);
        CommandParameter AttendeesParam = new CommandParameter("attendees", strAttendees);
        myCommand.Parameters.Add(AttendeesParam);
        CommandParameter BodyParam = new CommandParameter("body", strBody);
        myCommand.Parameters.Add(BodyParam);
        CommandParameter AppIDParam = new CommandParameter("appid", strAppID);
        myCommand.Parameters.Add(AppIDParam);
        CommandParameter TenantIDParam = new CommandParameter("tenantid", strTenantID);
        myCommand.Parameters.Add(TenantIDParam);
        CommandParameter ClientSecretParam = new CommandParameter("clientsecret", strClientSecret);
        myCommand.Parameters.Add(ClientSecretParam);

        pipeline.Commands.Add(myCommand);

        pipeline.Invoke();
        runspace.Close();
    }
    catch (Exception ex)
    {
        result = ex.Message;
    }

    return result;
}

PowerShell 脚本代码

param(
    [string]$subject,
    [string]$startdatehour,
    [string]$enddatehour,
    [string]$location,
    [string]$attendees,
    [string]$appid,
    [string]$tenantid,
    [string]$clientsecret
)

Import-Module MSAL.PS
Import-Module Microsoft.Graph.Calendar

#Generate Access Token to use in the connection string to MSGraph
$AppId = $appid
$TenantId = $tenantid
$ClientSecret = $clientsecret

$MsalToken = Get-MsalToken -TenantId $TenantId -ClientId $AppId -ClientSecret ($ClientSecret | ConvertTo-SecureString -AsPlainText -Force)
 
#Connect to Graph using access token
Connect-MgGraph -AccessToken $MsalToken.AccessToken -Scopes "User.Read.All","Calendars.ReadWrite"

$params = @{
    Subject = $subject
    Start = @{
        DateTime = $startdatehour
        TimeZone = "GMT Standard Time"
    }
    End = @{
        DateTime = $enddatehora
        TimeZone = "GMT Standard Time"
    }
    Location = @{
        DisplayName = $location
        LocationType = "Default"
    }
    IsOnlineMeeting = $true
    OnlineMeetingProvider = "teamsForBusiness"
    Attendees = $attendees
}

# Create event
New-MgUserEvent -UserId "a@a.net" -BodyParameter $params

问题原因分析

  1. 模块安装范围不匹配:PowerShell ISE以当前用户身份运行,模块可能仅安装在用户级目录;而IIS应用池使用系统/专用身份,无法访问用户级模块路径。
  2. 运行空间未显式加载模块:C#创建的PowerShell运行空间不会自动加载模块,需显式导入。
  3. 权限不足:IIS应用池身份无PowerShell模块目录的读取/执行权限。
  4. 脚本拼写错误:PowerShell脚本中$enddatehora为笔误,应为$enddatehour。
  5. 参数传递错误:C#拼接的Attendees是字符串格式,PowerShell无法直接解析为对象数组。

解决方案

1. 全局安装PowerShell模块

以管理员身份运行PowerShell,执行命令将模块安装到所有用户可见的路径:

Install-Module -Name MSAL.PS -Scope AllUsers -Force
Install-Module -Name Microsoft.Graph.Calendar -Scope AllUsers -Force

2. 显式指定模块路径导入

在PowerShell脚本中替换Import-Module命令为完整路径(替换版本号为实际安装版本):

Import-Module "C:\Program Files\WindowsPowerShell\Modules\MSAL.PS\4.3.0\MSAL.PS.psd1"
Import-Module "C:\Program Files\WindowsPowerShell\Modules\Microsoft.Graph.Calendar\1.28.0\Microsoft.Graph.Calendar.psd1"

3. 调整IIS应用池权限

  • 打开IIS管理器,找到对应应用池,设置身份为LocalSystem(生产环境建议使用最小权限专用账户)。
  • 确保应用池身份对C:\Program Files\WindowsPowerShell\Modules目录拥有读取和执行权限。

4. 修正脚本拼写错误

将PowerShell脚本中的$enddatehora改为$enddatehour:

End = @{
    DateTime = $enddatehour
    TimeZone = "GMT Standard Time"
}

5. 修正Attendees参数传递

C#中调整Attendees字符串拼接(修复转义问题),并在PowerShell中解析为对象数组:

  • C#代码修正:
    string strAttendees = "@(";
    foreach (string item in Attendees)
    {
        strAttendees += "@{EmailAddress = @{Address = '" + item + "'}; Type = 'Required'},";
    }
    strAttendees = strAttendees.TrimEnd(',') + ")";
    
  • PowerShell代码修正:
    $AttendeesArray = Invoke-Expression $attendees
    $params = @{
        # 其他参数保持不变
        Attendees = $AttendeesArray
    }
    

6. 在C#中预加载模块

调用脚本前,先在运行空间中执行模块导入命令:

RunspaceInvoke runSpaceInvoker = new RunspaceInvoke(runspace);
runSpaceInvoker.Invoke("Import-Module Microsoft.Graph.Calendar");
runSpaceInvoker.Invoke("Import-Module MSAL.PS");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 02:25:48