越接觸PowerShell感受越喜歡這門腳本語言,簡單易懂,功能強大,操做也方便,同時得益於微軟的鼎力支持,在不一樣的微軟產品平臺均可以使用,若是想研究微軟這方面的東西,會點PowerShell絕對是好處多多。
app
以前也寫了一些關於PowerShell的文章,也至關因而本身不斷摸索的過程,最近也陸陸續續寫了一些腳本,有一些是工做環境裏使用的,沒辦法拿出來分享,有一些是不一樣環境裏均可以使用的,因此決定拿出來分享一下,腳本都很簡單,寫的也絕對算不上專業,只是基本的功能能夠實現。運維
今天和你們分享的是寫的一個比較簡單的腳本,主要應用的場景也很常見,就是AD環境中,若是用戶密碼將要過時的話如何即便提醒用戶即便更改密碼,固然Windows會按期的自動提醒,這也是不少時候咱們不須要這種腳本的一個緣由,可是若是說是不一樣的環境呢?好比像咱們經常使用的企業AD環境是公司的IT在運維,咱們本身還會負責運維其餘的AD環境,這些環境可能不會天天都登錄,甚至很長時間也不會登錄一次,這時候若是密碼過時的話咱們是看不到提醒的,因此這種狀況下就很須要咱們有這樣一套密碼過時提醒的機制來督促咱們修改密碼,同時若是是IT基礎很薄弱的公司,咱們還能夠經過在郵件模板中加入修改密碼方法的方式來告訴普通用戶如何修改他們的密碼,這樣的話能夠很大程度上減輕IT的負擔。ide
這種相似的腳本實現的方法並不止一種,網上也有不少相似的腳本均可以實現這樣的功能,可是這裏要注意的一點是,有一些腳本由於寫的年頭比較久遠了,以後微軟在AD這方面又進行了一些更新,因此在一些比較新的環境裏(好比Server 2012或者R2等)有些腳本可能就顯得不會特別嚴謹,好比微軟以前推出的顆粒化密碼策略的功能,就有可能會致使對於密碼過時時間的判斷出現誤差。
orm
這類腳本的實現方法基本都很簡單,思路也都差很少,就是找出用戶上次密碼重置的時間,而後再加上容許密碼最長的期限,這樣算出來就是用戶密碼下一次的過時時間,可是若是是顆粒化密碼策略的話實際上用戶的容許密碼最長期限就會不一樣於AD裏的其餘帳戶,在這一點上若是不注意,一視同仁的話那麼就會致使最後的判斷出現問題。文檔
下邊開始進入正題了,把腳本粘出來你們本身看一下就能夠了,基本上都很簡單
get
Function LogFile ($output, $initLog) { if ($initLog -eq $True) { $input | out-file -filepath $output -encoding default -width 17384 } else { $input | out-file -filepath $output -encoding default -width 17384 -append } } function Send-Report { param($LogConent,$LogPath,$MailAddress) try { Send-MailMessage -From "NO-Reply@contoso.com" -To $MailAddress -Subject 'Contoso Password check report' -Body $LogConent -Priority 'High' -SmtpServer mail.contoso.com -Port 25 -ErrorAction 'SilentlyContinue' } catch { $ErrorMessage = $Error[0].Exception.Message Write-Host -ForegroundColor 'Red' "$(Get-Date -uFormat %Y%m%d-%H:%M:%S)" $ErrorMessage ("$(Get-Date -uFormat %Y%m%d-%H:%M:%S): " + $ErrorMessage) | LogFile -output $LogPath } } #Main Code #Import ActiveDirectory module Import-Module ActiveDirectory #Log initialization [string]$LogDate = Get-Date -Format "yyyyMMdd" $LogPath = "C:\PasswordLogs\DomainPasswordLog$LogDate.txt" if ((Test-Path 'C:\PasswordLogs') -eq $false) { New-Item -ItemType directory 'C:\PasswordLogs' | Out-Null } #====================================================================================== #Get MaxPasswordAge $RootDSE = Get-ADRootDSE $PasswordPolicy = Get-ADObject $RootDSE.defaultNamingContext -Property maxPwdAge $maxPwdAge = $PasswordPolicy.maxPwdAge/-864000000000 if (($maxPwdAge -eq 0) -or ($maxPwdAge -eq $null)) { $ErrorMessage = "MaxPasswordAge is not correct" Write-Host -ForegroundColor 'Red' "$(Get-Date -uFormat %Y%m%d-%H:%M:%S)" $ErrorMessage ("$(Get-Date -uFormat %Y%m%d-%H:%M:%S): " + $ErrorMessage) | LogFile -output $LogPath $LogConent = Get-Content $LogPath -raw Send-Report -LogConent $LogConent -LogPath $LogPath -MailAddress 'abc@contoso.com' exit } #====================================================================================== #Check userlist #我這裏的用戶列表是寫在一個txt文檔裏的,這是由於在個人環境中大部分用戶是不須要這種郵件提醒的,他們的帳戶會由咱們負責維護 #若是須要在AD裏檢索須要檢查的用戶的話能夠直接這樣寫$userList=Get-ADUser -Filter *|Select-Object -ExpandProperty SamAccountName #這樣的話下邊這段就不須要了 $userList = "C:\Users\abc\UserList.txt" if ((Test-Path $UserList) -eq $false) { $ErrorMessage = "Can't find userList.txt" Write-Host -ForegroundColor 'Red' "$(Get-Date -uFormat %Y%m%d-%H:%M:%S)" $ErrorMessage ("$(Get-Date -uFormat %Y%m%d-%H:%M:%S): " + $ErrorMessage) | LogFile -output $LogPath $LogConent = Get-Content $LogPath -raw Send-Report -LogConent $LogConent -LogPath $LogPath -MailAddress 'abc@contoso.com' exit } #====================================================================================== #這裏若是是使用檢索AD用戶的方法的話能夠直接寫 #foreach($user in $userlist)替代get-content便可 Get-Content $UserList | %{ $name = $null $userinfo = $null $ExpireDate = $null $PasswordSetDate = $null $Today = $null $leftDays = $null $body = $null $subject = $null $IndividualPasswordPolicy = $null $OutputMessage = $null $name = $_ $userinfo = Get-ADUser -Identity $name -Properties * #這裏首先判斷該用戶信息是否存在,若是不存在直接進行記錄便可 if ($userinfo -eq $null) { $ErrorMessage = $name + ": " + $Error[0].Exception.Message Write-Host -ForegroundColor 'Red' "$(Get-Date -uFormat %Y%m%d-%H:%M:%S)" $ErrorMessage ("$(Get-Date -uFormat %Y%m%d-%H:%M:%S): " + $ErrorMessage) | LogFile -output $LogPath } else { if ($userinfo.PasswordNeverExpires -eq $true) { #這裏記錄誰的密碼被設置爲永久不過時了 $ErrorMessage = "$name's Password has been set to NeverExpires" Write-Host -ForegroundColor 'Cyan' "$(Get-Date -uFormat %Y%m%d-%H:%M:%S)" $ErrorMessage ("$(Get-Date -uFormat %Y%m%d-%H:%M:%S): " + $ErrorMessage) | LogFile -output $LogPath } else { #這裏會讀取顆粒化密碼策略的設置,它的優先級應該高於域策略的設置 $IndividualPasswordPolicy = (Get-AduserResultantPasswordPolicy $name) if ($IndividualPasswordPolicy -ne $null) { $maxPwdAge = $IndividualPasswordPolicy.MaxPasswordAge.TotalDays } $PasswordSetDate = $userinfo.PasswordLastSet $ExpireDate = $PasswordSetDate.AddDays($maxPwdAge) $Today = Get-Date #對比過時時間和今天,得出的數值就是還有多少天過時 $leftDays = (New-TimeSpan -Start $Today -End $ExpireDate).Days if ($leftDays -lt 0) { $body = " Dear $name , <p> Your Password has expired!!.<br> Please change your Password as soon as possible so that you can work normally<br> <p>Thanks, <br> </P>" $subject = "Your Password has expired!!" $OutputMessage = "$(Get-Date -uFormat %Y%m%d-%H:%M:%S): $name's Password has expired" Write-Output $OutputMessage | LogFile -output $LogPath } elseif ($leftDays -eq 1) { $body = " Dear $name , <p> Your Password will expire in <b><font size=`"20px`" color=`"red`"> $leftDays </font></b> Day!!.<br> Please change your Password as soon as possible so that you can work normally <br> <p>Thanks, <br> </P>" $subject = "Your Password will expire in $leftDays day!!" $OutputMessage = "$(Get-Date -uFormat %Y%m%d-%H:%M:%S): $name's Password will expire in $leftDays day" Write-Output $OutputMessage | LogFile -output $LogPath } elseif ($leftDays -le 10) { $body = " Dear $name , <p> Your Password will expire in <b><font size=`"20px`" color=`"red`"> $leftDays </font></b> Days!!.<br> Please change your Password as soon as possible so that you can work normally <br> <p>Thanks, <br> </P>" $subject = "Your Password will expire in $leftDays days" $OutputMessage = "$(Get-Date -uFormat %Y%m%d-%H:%M:%S): $name's Password will expire in $leftDays days" Write-Output $OutputMessage | LogFile -output $LogPath } else { $OutputMessage = "$(Get-Date -uFormat %Y%m%d-%H:%M:%S): $name's Password will expire in $leftDays days" Write-Output $OutputMessage | LogFile -output $LogPath } #這裏設置的是若是10天之內過時的話就會發送提醒 if ($leftDays -le 10) { #注意若是EmailAddress爲空的話就須要本身處理如何找到郵件發送的地址了 $MailAddress = $userinfo.EmailAddress if ($MailAddress -ne $null) { try { Send-MailMessage -From "No-Reply@contoso.com" -To $MailAddress -Subject $subject -Body $body -BodyAsHtml -Priority 'High' -SmtpServer mail.contoso.com -Port 25 -ErrorAction 'SilentlyContinue' } catch { $ErrorMessage = $Error[0].Exception.Message Write-Host -ForegroundColor 'Red' "$(Get-Date -uFormat %Y%m%d-%H:%M:%S)" $ErrorMessage ("$(Get-Date -uFormat %Y%m%d-%H:%M:%S): " + $ErrorMessage) | LogFile -output $LogPath } } } } } } #最後把這份報告發送給IT管理員 if ((Test-Path $LogPath) -eq $true) { $LogConent = Get-Content $LogPath -Raw Send-Report -LogConent $LogConent -LogPath $LogPath -MailAddress 'it@contoso.com' }
以後設置一個任務計劃,天天運行這個腳本就能夠了。input
基本上功能就實現了,整體來講比較簡單string