multithreading - 使用多个线程运行 powershell 脚本
问题描述
我正在尝试从另一个 powershell 脚本中执行一个 powershell 脚本。我当前的脚本运行良好,但如果可能的话,我想尝试加快它的速度。
我的脚本所做的是通过 EWS 将联系人列表导入每个用户的联系人文件夹。
在我的 powershell 脚本中,处理导入的脚本我这样称呼它(ImportContacts 是一个没有任何参数的函数):
. $rootPath\ImportContacts\ImportContacts.ps1
ImportContacts
当我正常运行它时,正如我上面提到的,一切正常,我只是想加快它的速度。我尝试按照一些在 Powershell 中实现 runspacepool 的示例来利用多个线程,但它似乎对我来说不能正常工作。我确定这是一个愚蠢的语法错误,但我目前有这个:
Measure-Command{
$MaxThreads = 5
$RunspacePool = [runspacefactory]::CreateRunspacePool(1, $MaxThreads)
$RunspacePool.Open()
$Jobs = @()
ImportContacts | Foreach-Object {
$PowerShell = [powershell]::Create()
$PowerShell.RunspacePool = $RunspacePool
$PowerShell.AddScript({ImportContacts})
$Jobs += $PowerShell.BeginInvoke()
}
while ($Jobs.IsCompleted -contains $false)
{
Start-Sleep 1
}}
这似乎可以完成这项工作,但我无法区分速度。
编辑 5-15-21 为了更好地帮助解决这个问题,这是我检索用户数据的方式。我有一个名为“ExportedContacts.ps1”的文件,它的名称如下:
$Users = & $rootPath\ExportContacts\ExportContacts.ps1
文件内容是这样的
$Users = Get-ADUser -Filter * -Properties extensionAttribute2, middlename, mobile, OfficePhone, GivenName, Surname, DisplayName, EmailAddress, Title, Company, Department, thumbnailPhoto | Where-Object {($_.extensionAttribute2 -like "DynamicDistro") -AND (($_.Mobile -ne $NULL) -OR ($_.OfficePhone -ne $NULL))} | Select-Object @{Name="First Name";Expression={$_.GivenName}},@{Name="Last Name";Expression={$_.Surname}},@{Name="Display Name";Expression={$_.DisplayName}},@{Name="Job Title";Expression={$_.Title}},@{Name="Company";Expression={$_.Company}},@{Name="Department";Expression={$_.Department}},@{Name="Mobile Phone";Expression={$_.Mobile}},@{Name="Home Phone";Expression={$_.OfficePhone}}, @{Name="Middle Name";Expression={$_.MiddleName}}, @{Name="E-mail Address";Expression={$_.EmailAddress}}, thumbnailPhoto | Sort-Object "Last Name"
return $Users
然后我导入这些联系人,类似于我上面提到的方式。导入内容如下:
Function ImportContacts
{
Write-Host "Importing Contacts. This can take several minutes."
#******************************************************************
foreach ($ContactItem in $Users)
{
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress);
$ExchangeContact = New-Object Microsoft.Exchange.WebServices.Data.Contact($service);
$ExchangeContact.NickName = ('{0} {1}' -f $ContactItem."First Name", $ContactItem."Last Name"). Trim()
$ExchangeContact.DisplayName = $ExchangeContact.NickName;
$ExchangeContact.FileAs = $ExchangeContact.NickName;
$ExchangeContact.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1] = $ContactItem."E-mail Address";
$ExchangeContact.PhoneNumbers[[Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::HomePhone] = $ContactItem."Home Phone";
$ExchangeContact.PhoneNumbers[[Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::MobilePhone] = $ContactItem."Mobile Phone";
$ExchangeContact.Department = $ContactItem."Department";
$ExchangeContact.CompanyName = $ContactItem."Company";
$ExchangeContact.JobTitle = $ContactItem."Job Title";
$ExchangeContact.MiddleName = $ContactItem."Middle Name";
# Save the contact
$ExchangeContact.Save($ContactsFolder.Id);
}
}
我还包括创建我指定的联系人文件夹并删除现有联系人(如果该文件夹已存在)的文件,以便每次导入都是干净且更新的导入。我很好奇是否有更快的方法来清洁现有物品?
Function CreateContactsFolder
{
Write-Host "Creating Contacts Folder and Cleaning up stale items. This can take a couple minutes."
Try
{
$service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $EmailAddress);
$RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot)
$RootFolder.Load()
#Check to see if they have a contacts folder that we want
$FolderView = new-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$ContactsFolderSearch = $RootFolder.FindFolders($FolderView) | Where-Object {$_.DisplayName -eq $FolderName}
if($ContactsFolderSearch)
{
$ContactsFolder = [Microsoft.Exchange.WebServices.Data.ContactsFolder]::Bind($service,$ContactsFolderSearch.Id);
#If folder exists, connect to it. Clear existing Contacts, and reupload new (UPDATED) Contact Info
Write-Host "Folder alreads exists. We will remove all contacts under this folder."
# Attempt to empty the target folder up to 10 times.
$tries = 0
$max_tries = 0
while ($tries -lt 2)
{
try
{
$tries++
$ErrorActionPreference='Stop'
$ContactsFolder.Empty([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete, $true)
$tries++
}
catch
{
$ErrorActionPreference='SilentlyContinue'
$rnd = Get-Random -Minimum 1 -Maximum 10
Start-Sleep -Seconds $rnd
$tries = $tries - 1
$max_tries++
if ($max_tries -gt 100)
{
Write-Host "Error; Cannot empty the target folder; `t$EmailAddress"
}
}
}
}
else
{
#Contact Folder doesn't exist. Let's create it
try
{
Write-Host "Creating new Contacts Folder called $FolderName"
$ContactsFolder = New-Object Microsoft.Exchange.WebServices.Data.ContactsFolder($service);
$ContactsFolder.DisplayName = $FolderName
$ContactsFolder.Save([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot)
}
catch
{
Write-Host "Error; Cannot create the target folder; `t$EmailAddress"
}
}
return $ContactsFolder
}
Catch
{
Write-Host "Couldn't connect to the user's mailbox. Make sure the admin account you're using to connect to has App Impersonization permissions"
Write-Host "Check this link for more info: https://help.bittitan.com/hc/en-us/articles/115008098447-The-account-does-not-have-permission-to-impersonate-the-requested-user"
}
}
解决方案
推荐阅读
- jenkins - 当 xUnit 测试未通过时 Jenkins 构建失败
- angular - AOT Angular 2 忽略库
- javascript - How to add a preloader to an iframe that its src changes dynamically?
- python - 如何在单独的列表中拆分字符串中的每个单词
- ios - How to override Alamofire SessionManager to modify response in order to add headers?
- java - FragmentPagerAdapter 的第二个片段中的访问受限
- html - Safari中右侧的空白空间
- swift - Firestore querysnapshot returning nil swift
- ios - IOS/Objective-C:从 NSManagedObject 构建 NSDictionary
- vba - Answer this and you're a true genius: Error removing then re-adding missing reference