从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
问题原因分析
- 模块安装范围不匹配:PowerShell ISE以当前用户身份运行,模块可能仅安装在用户级目录;而IIS应用池使用系统/专用身份,无法访问用户级模块路径。
- 运行空间未显式加载模块:C#创建的PowerShell运行空间不会自动加载模块,需显式导入。
- 权限不足:IIS应用池身份无PowerShell模块目录的读取/执行权限。
- 脚本拼写错误:PowerShell脚本中
$enddatehora为笔误,应为$enddatehour。 - 参数传递错误: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
相关产品推荐
相关产品推荐

