【发布时间】:2021-07-27 00:12:33
【问题描述】:
大约 1 年前,我的任务是使用 powershell/EWS 在我公司用户的日历中创建约会。我很幸运,在 www 上找到了一个运行良好的脚本(代码如下)。该脚本导入多个 CSV 文件并为 CSV 中的每一行创建 1 个约会。该脚本运行了几个月,没有任何问题。但在过去的几周里,剧本不断失败。但它不会一直失败。有时重新启动它就足够了。有时它需要 3 或 4 次重新启动。它不会在同一个文件上失败,而且——正如所说——它并不总是失败。所以我猜脚本以及处理后的数据必须是有效的。
当脚本失败时,它通常会说“请求失败。远程服务器返回错误 (503)。服务器不可用。”错误并不总是相同的,但它总是与交换服务器的连接失败有关。在许多情况下,会显示我应该输入我的凭据以进行在线交换的弹出窗口。但显然我之前输入了这些凭据(导入加密密码)。所以我认为连接中断了,所以我被要求重新输入它们。
没有防火墙或 AV 阻止连接。我的互联网连接没有中断...
我的问题是: 目前,发生错误时,powershell完全停止,脚本无法继续。是否可以更改此脚本以使其自行重新启动(包括凭据的导入)而不仅仅是失败?
脚本如下:
param([string]$CSVFileName,[string]$EmailAddress,[string]$Username,[string]$Password,[string]$Domain,[bool]$Impersonate,[string]$EwsUrl,[string]$EWSManagedApiPath);
#
# Import-CalendarCSV.ps1
#
# By David Barrett, Microsoft Ltd. Use at your own risk.
# C:\Program Files\Microsoft\Exchange Server\V14\Bin
Function ShowParams()
{
Write-Host "Import-CalendarCSV -CSVFileName <string> -EmailAddress <string>";
Write-Host " [-Username <string> -Password <string> [-Domain <string>]]";
Write-Host " [-Impersonate <bool>]";
Write-Host " [-EwsUrl <string>]";
Write-Host " [-EWSManagedApiPath <string>]";
Write-Host "";
Write-Host "Required:";
Write-Host " -CSVFileName : Filename of the CSV file to import appointments for this user from.";
Write-Host " -EmailAddress : Mailbox SMTP email address";
Write-Host "";
Write-Host "Optional:";
Write-Host " -Username : Username for the account being used to connect to EWS (if not specified, current user is assumed)";
Write-Host " -Password : Password for the specified user (required if username specified)";
Write-Host " -Domain : If specified, used for authentication (not required even if username specified)";
Write-Host " -Impersonate : Set to $true to use impersonation.";
Write-Host " -EwsUrl : Forces a particular EWS URl (otherwise autodiscover is used, which is recommended)";
Write-Host " -EWSManagedApiDLLFilePath : Full and path to the DLL for EWS Managed API (if not specified, default path for v1.1 is used)";
Write-Host "";
}
$RequiredFields=@{
"Subject" = "Subject";
"StartDate" = "Start Date";
"StartTime" = "Start Time";
"EndDate" = "End Date";
"EndTime" = "End Time"
}
# Check email address
# if (!$EmailAddress)
# {
# ShowParams;
# throw "Required parameter EmailAddress missing";
# }
# CSV File Checks
if (!$CSVFileName)
{
ShowParams;
throw "Required parameter CSVFileName missing";
}
if (!(Get-Item -Path $CSVFileName -ErrorAction SilentlyContinue))
{
throw "Unable to open file: $CSVFileName";
}
# Import CSV File
try
{
$CSVFile = Import-Csv -Path $CSVFileName;
}
catch { }
if (!$CSVFile)
{
Write-Host "CSV header line not found, using predefined header: Subject;StartDate;StartTime;EndDate;EndTime";
$CSVFile = Import-Csv -Path $CSVFileName -header Subject,StartDate,StartTime,EndDate,EndTime;
}
# Check file has required fields
foreach ($Key in $RequiredFields.Keys)
{
if (!$CSVFile[0].$Key)
{
# Missing required field
throw "Import file is missing required field: $Key";
}
}
# Check EWS Managed API available
if (!$EWSManagedApiPath)
{
$EWSManagedApiPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
}
if (!(Get-Item -Path $EWSManagedApiPath -ErrorAction SilentlyContinue))
{
throw "EWS Managed API could not be found at $($EWSManagedApiPath).";
}
# Load EWS Managed API
[void][Reflection.Assembly]::LoadFile($EWSManagedApiPath);
# Create Service Object. We only need Exchange 2007 schema for creating calendar items (this will work with Exchange>=12)
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
# Set credentials if specified, or use logged on user.
if ($Username -and $Password)
{
if ($Domain)
{
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Username,$Password,$Domain);
} else {
$service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials($Username,$Password);
}
} else {
$service.UseDefaultCredentials = $true;
}
# Set EWS URL if specified, or use autodiscover if no URL specified.
if ($EwsUrl)
{
$service.URL = New-Object Uri($EwsUrl);
}
else
{
try
{
Write-Host "Performing autodiscover for $EmailAddress";
$service.AutodiscoverUrl($EmailAddress, {$true});
}
catch
{
throw;
}
}
# Bind to the calendar folder
# Parse the CSV file and add the appointments
foreach ($CalendarItem in $CSVFile)
{
# Create the appointment and set the fields
$NoError=$true;
if ($Impersonate)
{
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $CalendarItem."Email");
}
try {
$CalendarFolder = [Microsoft.Exchange.WebServices.Data.CalendarFolder]::Bind($service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar);
} catch {
throw;
}
try
{
$Appointment = New-Object Microsoft.Exchange.WebServices.Data.Appointment($service);
$Appointment.Subject=$CalendarItem."Subject";
$StartDate=[DateTime]($CalendarItem."StartDate" + " " + $CalendarItem."StartTime");
$Appointment.Start=$StartDate;
$EndDate=[DateTime]($CalendarItem."EndDate" + " " + $CalendarItem."EndTime");
$Appointment.End=$EndDate;
$Appointment.LegacyFreeBusyStatus = [Microsoft.Exchange.WebServices.Data.LegacyFreeBusyStatus]::Busy;
$Appointment.IsAllDayEvent= $CalendarItem."IsAllDayEvent";
$Appointment.IsReminderSet= $CalendarItem."IsReminderSet";
}
catch
{
# If we fail to set any of the required fields, we will not write the appointment
$NoError=$false;
}
# Check for any other fields
foreach ($Field in ($CalendarItem | Get-Member -MemberType Properties))
{
if (!($RequiredFields.Keys -contains $Field.Name))
{
# This is a custom (optional) field, so try to map it
try
{
$Appointment.$($Field.Name)=$CalendarItem.$($Field.Name);
}
catch
{
# Failed to write this field
Write-Host "Failed to set custom field $($Field.Name)" -ForegroundColor yellow;
}
}
}
if ($NoError)
{
# Save the appointment
$Appointment.Save([Microsoft.Exchange.WebServices.Data.SendInvitationsMode]::SendToNone)
Write-Host "Created $($CalendarItem."Subject")" -ForegroundColor green;
}
else
{
# Failed to set a required field
Write-Host "Failed to create appointment: $($CalendarItem."Subject")" -ForegroundColor red;
}
}
以下脚本用于登录在线交流,清除约会,然后调用上面的脚本以创建新约会:
Get-PSSession | Remove-PSSession
$AdminName = “XXXXXXXX@XXXXXXX.COM”
$Pass = Get-Content “C:\Scripte\CalendarUpdate\cred.txt” | ConvertTo-SecureString
$Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection
Import-PSSession $Session
$TCredentials = New-Object System.Management.Automation.PSCredential $AdminName, $Pass
$TPassword = $TCredentials.GetNetworkCredential().Password
$Emails = import-csv "C:\Scripte\CalendarUpdate\Users.csv"
ForEach ($i in $Emails) {
$TEMP = Search-Mailbox $i.Emails -SearchQuery 'Subject:"Frei/Abwesend - Automatische Anlage"' -SearchDumpster:$false -EstimateResultOnly
While($TEMP.ResultItemsCount -ne 0){
Search-Mailbox $i.Emails -SearchQuery 'Subject:"Frei/Abwesend - Automatische Anlage"' -SearchDumpster:$false -DeleteContent -Force
$TEMP = Search-Mailbox $i.Emails -SearchQuery 'Subject:"Frei/Abwesend - Automatische Anlage"' -SearchDumpster:$false -EstimateResultOnly
}
$userfilename = 'C:\Scripte\CalendarUpdate\Users\' + $i.Emails + '.csv'
C:\Scripte\CalendarUpdate\Import-CalendarCSV.ps1 -CSVFileName $userfilename -Username XXXXXXX@XXXXXXX.com -Password $TPassword -Impersonate $true -EwsUrl https://outlook.office365.com/EWS/Exchange.asmx -EWSManagedApiPath "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"
Remove-Item $userfilename
}
stop-Process -Name powershell
我真的希望这里的任何人都可以帮助我!提前非常感谢。 亲切的问候 蒂姆
【问题讨论】:
标签: powershell exchange-server exchangewebservices