PowerShell学习笔记(13):UC时代的用户对象创建(下)
第三节 统一开启帐号的实现
在上一节中,我们已经实现了了组织架构树,主要目的是方便帐号管理员通过图形界面来选择新建帐号所在OU,而不需要手动输入长串的DN。在本节中我们将利用相关Cmdlets实现帐号的开启。
下面让我们先来看看代码,然后再分析具体代码的作用:
function CreateUser
{
$objForm.Cursor = "WaitCursor"
$objUDN = $objTxtUserDisplayName.Text
$objUPN = $objTxtUserPrincipalName.Text
$objUserTitle = $objTxtUserTitle.Text
$objUserDep = $objTxtUserOU.Text
$objUserTel = $objTxtUserTel.Text
$objUserSN = $objTxtUserStaffNum.Text
$objSAM = $objUPN.split("@")[0]
$objSN = $objUDN.SubString(0,1)
$objGN = $objUDN.SubString(1)
$objCenter = $objTxtUserCenter.Text
if ($objCenter -eq "")
{
[Windows.Forms.Messagebox]::Show("必须设置用户所在中心!","警告", [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Warning)
}
else
{
$objInfo = "用户显示名:$objUDN`n用户登录名:$objUPN`n职务:$objUserTitle`n部门:$objUserDep`n电话:$objUserTel`n工号:$objUserSN`n所在中心:$objCenter"
$objReturn = [Windows.Forms.Messagebox]::Show($objInfo,"新建帐号", [Windows.Forms.MessageBoxButtons]::OKCancel, [Windows.Forms.MessageBoxIcon]::Information)
}
if ($objReturn -eq "OK")
{
New-QADUser -ParentContainer $objCurrentOUDN -Name $objUDN `
-UserPrincipalName $objUPN -SamAccountName $objSAM `
-Company "Contoso" `
-UserPassword 'abcd@123' -Title $objUserTitle -Department $objUserDep `
-telephoneNumber $objUserTel -ObjectAttributes @{employeeID = $objUSN; `
userWorkstations = "Contoso-$objUserTel"; `
displayname=$objUDN;sn=$objSN;givenName=$objGN}
Enable-QADUser "contoso\$objSAM"
Set-QADUser -Identity "contoso\$objSAM" -UserMustChangePassword $True
$objUserDN = (Get-QADUser $objSAM).DN
$colGroups = Get-QADGroup $objCenter.SubString(0,2)
foreach ($objGroup in $colGroups)
{
Add-QADGroupMember -Identity $objGroup.DN -Member $objUserDN
}
Enable-Mailbox -Identity $objUserDN -Alias $objSAM -Database 'MailServer\First Storage Group\Mailbox Database'
#Enable OC
Set-QADUser -Identity $objUserDN -ObjectAttributes @{"msRTCSIP-ArchivingEnabled"=2;"msRTCSIP-OptionFlags"=320;`
"msRTCSIP-PrimaryHomeServer"="CN=LC Services,CN=Microsoft,CN=pool,CN=Pools,CN=RTC Service,CN=Microsoft,CN=System,DC=contoso,DC=com";`
"msRTCSIP-PrimaryUserAddress"="sip:$objUPN";"msRTCSIP-UserEnabled"=$True}
$objTxtUserDisplayName.Text = ""
$objTxtUserPrincipalName.Text = "@contoso.com"
$objTxtUserTitle.Text = ""
$objTxtUserTel.Text = ""
$objTxtUserStaffNum.Text = ""
$objTxtUserCenter.Text = ""
$objTxtUserOU.Text = ""
$objForm.Cursor = "Default"
}
else
{
$objForm.Cursor = "Default"
}
}
在代码的最开始我们将窗体的Cursor属性设置为“WaitCursor”,具体作用就是让鼠标呈现忙碌状态,这是用户很熟悉的一种操作体验。接着我们将文本控件的值赋值给变量,供后续调用。这里需要注意的是Split和SubString两个方法。因为我们的图形界面让用户输入了比较少量的信息,但这些信息对于创建一个普通的用户帐号而言还是有所欠缺的,因此需要使用一定方法从已知信息中得到我们想要的信息。而示例中Split的作用是从UserPrincipalName的属性值中分离出sAMAccountName的属性值,说穿了就是@前面的部分,即我们平时登录域时所使用的帐号。而SubString的作用与VBScript中的Left,Right和Mid方法类似,示例代码中的作用是从显示名中分离出姓和名(对应的AD属性名分别是sn和givenName)。接着为了防止用户没有从左侧树形结构中选择新建用户所在OU,我们需要使用判断语句来处理这个可能发生的错误并提醒用户。如果发生错误,那么将会出现以下提示:
利用MessageBox我们可以很轻松的弹出Windows下的标准信息框,不过比较可惜的是MessageBox是无法被实例化的,也就是说你想用$MsgBox来替代[Windows.Forms.Messagebox]是无法实现的。只能使用示例代码中的方法来调用。如果输入信息没有问题的话,还是会出现一个消息框提示用户核对输入信息:
这里需要注意的是我首先将显示内容保存到变量之中,之间的换行使用`n实现。
接着我们要根据使用者具体点击了哪个按钮进行判断。如果是确定,那么就执行添加用户的代码,如果是取消那么要将鼠标恢复成默认状态。那么让我们着重看一下添加用户的代码。其实利用New-QADUser cmdlet的话新建帐号并不是难事,只要将参数和参数值一一对应即可。相关参数也是非常明了的,比如-ParentContainer指的就是用户所在OU,-Name对应的是AD中的cn属性,-UserPassword参数为用户设置密码(想必厌恶在ADUC中为新建帐号两次输入密码的人不在少数吧?这次我们更省力,只要在写代码的时候输入一遍就可以了)。不过New-QADUser cmdlet本身并不会附带上AD中所有属性名的参数,因为这会使得cmdlet的参数列表十分复杂。因此Quest的开发人员定义了-ObjectAttributes参数,允许我们使用哈希表来定义属性。我这里使用该参数定义了工号,显示名,姓和名,以及用户允许登录到的工作站(假设工作站的命名规则是以字符串Contoso-后跟四位电话分机号实现的)。
然后我们使用Enable-QADUser cmdlet启用用户帐号并用Set-QADUser cmdlet与-UserMustChangePassword参数使得用户下次登录时必须更改密码。到这里新建域账号的工作就所剩无几了,最后我们要做的是将用户添加到相关的组中。在说明代码之前我们先假设一个前提,即我们的环境中为不同的中心建立了两个组,一个是AD用户组,另外一个是Exchange的联系人组。两者的CN相同,但是sAMAccountName不同,如图所示:
再为用户添加组之前,我们首先要取得新建用户的DN。然后根据用户的选择检索相关的OU对象。因为环境决定了用户必定会添加到两个组,因此我们得到的结果将是一个数组。所以我们使用foreach循环遍历这个数组得到其中每个组的DN属性,然后使用Add-QADGroupMember cmdlet来将用户添加到组里面。支持新建域账号的代码就结束了,这是新建帐号中最复杂的一部分。
启用邮箱就很简单了,了解Exchange 2007的朋友都知道我们当我们使用MMC启用邮箱时,最后向导都会给出使用PowerShell开启邮箱的命令,我们只需利用这个命令即可。所要做的只是将其中的参数值利用变量进行替换。总的来说启用邮箱并不难。
接着轮到启用OCS帐号了。也许大家曾今和我一样把这件事想的很复杂,因为Resource Kit里面有一个脚本来启用OCS帐号,而这个脚本非常复杂,事实上这个脚本是自LCS时代沿袭过来的,那么都到UC时代了,有没有简单点的方法呢?产品组自然考虑的很周到,我们只需要设置用户的几个AD属性即可,使用的cmdlet同样是Set-QADUser。相关资料诸位可以阅读OCS_ADGuide文档中的Active Directory属性部分的内容。这涉及到具体的部署环境,在我所处的实际生产环境中,我们为用户启用了聊天记录存档,因此需要将msRTCSIP-ArchivingEnabled属性值设为2,也就是存档内部通信。而msRTCSIP-OptionFlags则是几个设置的叠加。比如我们允许用户邀请匿名用户加入会议并启用了增强状态,那么其结果就是64+256=320。(插一句,有可能诸位下到的中文文档将256代表的EnabledForEnhancedPresence翻译成了允许用户使用公共 IM 连接,这个翻译是错误的。)接着我们要添加用户所在的池的FQDN,其对应的属性是msRTCSIP-PrimaryHomeServer,该值需要查阅你的具体环境中的相关值。然后是用户的SIP地址,因为环境中UPN地址和邮件地址相同,我们就直接使用已知的UPN值。最后我们为用户启用OCS帐号,其对应的是属性为msRTCSIP-UserEnabled。至此,OCS帐号的启用也顺利完成了。接着我们进行扫尾工作,将文本框的内容清空(代表UPN的文本框则保留域的名称,方便用户再次新建帐号),最后将鼠标恢复成默认状态。
新建帐号的工作大致算是完成了,但是为了避免用户的一些输入错误,我们还需要添加辅助代码来避免输入错误的发生。首先我们想要实现这样一个功能,当文本框内的内容为空时给用户一定提示,但并非强制用户必须输入相关内容。以下是代码:
function CheckTextBox($InputObject)
{
if ($InputObject.Text -eq "")
{
$InputObject.BackColor = "LightCoral"
}
else
{
$InputObject.BackColor = "White"
}
}
代码非常简单,当检测到文本框为空时,将该文本框的背景色设置为LightCoral,其效果如下图所示:
因为我们想要使该函数在输入焦点离开当前文本框时生效,所以我们添加了以下代码:
|
$objTxtUserDisplayName.Add_Leave({CheckTextBox($objTxtUserDisplayName)})
|
接下来我们要重点检查用户登录名,还是先放上代码:
function CheckUPN
{
$objTemp = $objTxtUserPrincipalName.Text
$objChkResult = [regex]::Match($objTemp,"\w+@contoso.com")
if ($objChkResult.Success -eq $true)
{
$objChkUser = Get-QADUser $objTemp
if ($objChkUser -ne $null)
{
[Windows.Forms.Messagebox]::Show("该用户名已存在,请重新输入!","错误", [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Stop)
$objTxtUserPrincipalName.Focus()
$objTxtUserPrincipalName.SelectAll()
}
}
else
{
[Windows.Forms.Messagebox]::Show("用户名错误,请重新输入!","错误", [Windows.Forms.MessageBoxButtons]::OK, [Windows.Forms.MessageBoxIcon]::Stop)
$objTxtUserPrincipalName.Focus()
$objTxtUserPrincipalName.SelectAll()
}
在代码开始,我们首先需要获得用户输入的信息,然后将其存放在名为$objTemp的变量中。然后利用正则表达式([regex],代码中使用的还是很简单的一种表达式)对输入信息进行检查,并将检查结果存放在相关变量中。一旦用户输入了错误的信息我们使用MessageBox弹出提示,然后为用户全选文本框内的用户名方便用户重新输入正确信息。而即便用户输入的信息正确,我们也需要检查用户输入的用户名是否已存在,如果已存在那么还是需要用户重新输入信息。
同样,为了使函数生效,我们需要添加以下代码:
|
$objTxtUserPrincipalName.Add_Leave({CheckTextBox($objTxtUserPrincipalName);CheckUPN})
|
在第一节中我提到了,使用;来分隔在同一事件中所要执行的不同函数,事实上我们完全可以把文本框的检查代码写在一起,然后利用switch语句判断不同的文本框,这里我就不去实现相关代码了,有兴趣的朋友不妨动手试试。
结束语
以上就是UC时代的用户帐号创建的所有内容,我个人感觉是真正的用户创建是非常简单的,因为有现成的cmdlet来帮助我们完成。但是我在文章开头提到最终帐号的开启并不是由我负责,所以我们需要创建一个GUI界面来降低帐号管理员的刚接手帐号开启工作时的不适感,并尽可能简化开启的流程,这使我们不得不考虑很多问题。使用普通MMC开启域、邮件、OCS帐号可能需要几分钟的时间,而如果使用以上脚本那么这个过程可能在半分钟内就完成了。这就是PowerShell的魅力吧。
那么就此结束本文,向耐心读完全文的朋友表示由衷地感谢。
注:文中代码仅供交流学习使用,尚有很大改善余地。