這次會想寫這個程式,是因為公司打算將 G Workspace 轉移到 Synology NAS
公司本來也沒有使用 AD or LDAP 做驗證,打算將帳號整合到 LDAP 做未來準備。
轉移郵件的功能 MailPlus 本身的功能就很完整,不需要太多操心
但是Synology Drive 卻沒辦法自動批次轉移全公司的 Google Drive!
使用Cloud Sync ,必須讓使用者自行操作,也沒辦法限制使用者只能加入指定的 Google Workspace
幸運的是,Synology Active Backup for G Suite可以將全部使用者的Google Drive 都備份下來,只要把使用者備份檔案複製到使用者家目錄,就可以正常在Synology Drive 使用。
只是因為整合了 LDAP 驗證,所以家目錄變成 "帳號-LDAP uidNumber" 這樣的格式。
手動去建立家目錄也很麻煩(一兩百個帳號),用PowerShell 讀取 LDAP 也有點麻煩,所以最簡單的方法就是使用者登入Synology NAS,Synology NAS 會自動建立家目錄。
以下不多說,就直接看程式吧
之前在每個 Page 變動後,都去偵測 $ie.ReadyState = 4 或是 $ie.Busy = $False 程式才繼續執行,都會發生錯誤
後來改成檢查 $ie.Document.getElementById('ext-gen84') 是否為物件也會誤判
再改成檢查 $ie.Document.getElementById('ext-gen84') 是否存在,也還是會誤判
最後改成判斷 $ie.Document.getElementById('ext-gen84')的 Type 才成功。
# 指定 帳號清單的 csv 檔案
# 格式:"信箱","家目錄","帳號","密碼"
Clear-Host
$Error.Clear()
Remove-Variable * -ErrorAction SilentlyContinue
$List = Get-ChildItem -Path "$PSScriptRoot\AccountList-*.csv" | Sort-Object -Property name -Descending | Select-Object -First 1
$Count = 0
# Synology NAS 的登入頁面網址
$Login = "http://192.168.1.123:5000/"
Get-Content -Path $List.FullName | ForEach{
$Count++
$Line = $_
# 取得四欄資料
$fields = $Line -split ","
$EMail = $fields[0]
$UserHome = $fields[1]
$account = $fields[2]
$password = $fields[3] -replace [regex]"`r`n",""
# 顯示目前處理的帳號資訊
$msg = "{0:000} {1} {2}" -f $Count, $account, $password
Write-Host $msg
# 使用 COM 物件呼叫 IE (Chrome 沒有 COM 物件,所以這個方法不適用 Chrome.exe)
$ie = New-Object -com "InternetExplorer.Application"
#$ie.Navigate("about:blank")
$ie.Visible = $True
$ie.Navigate($Login)
# 設定 IE 視窗位置及大小
# 您可以先用程式開啟 IE 之後,將 IE 視窗調整到你喜歡的位置,再去讀取Left, Top, Width, Height 等屬性
# 然後將數值寫在程式中
$ie.Left = -8
$ie.Top = -8
$ie.Width = 1296
$ie.Height = 1056
# 等待 DOM Ready,才能進行 Javascript 相關指令操作
Do{
#"$($ie.ReadyState) $($ie.Busy)";
Start-Sleep -Milliseconds 100
}While($ie.ReadyState -ne 4)
# 如果前一個使用者沒登出,就會停在登入畫面;如果找到登出 Button,就按下登出鈕
# 雖然 瀏覽器 ReadyState = 4 或是 Busy = $False,但是 JScript Engine/COM Object/DOM 似乎都不一定 Ready
# 單純只判斷 $ie.Document.getElementById('ext-gen84') 是否存在或者是否為物件都會有誤判機率發生
# 一定要確認該元素的 Type 不等於 "DBNull"
If((($ie.Document.getElementById('ext-gen84')).GetType()).Name -ne "DBNull"){
$ie.Document.getElementById("ext-gen84").click()
}
# 等待登入畫面的登入鈕出現,而且 Type 不等於 DBNull 才能繼續下去
Do{
Start-Sleep -Milliseconds 100
}While((($ie.Document.getElementById('ext-gen47')).GetType()).Name -eq "DBNull")
# 自動填入帳號密碼,並按下登入鈕
$ie.Document.getElementById("login_username").value = $account
$ie.Document.getElementById("login_passwd").value = $password
$ie.Document.getElementById("ext-gen47").click()
# 等待登出鈕出現,而且 Type 不等於 DBNull 才能繼續下去
Do{
Start-Sleep -Milliseconds 100
}While((($ie.Document.getElementById('ext-gen84')).GetType()).Name -eq "DBNull")
# 按下登出鈕
$ie.Document.getElementById("ext-gen84").click()
# 等待登入畫面的登入鈕出現,而且 Type 不等於 DBNull ,才算完成登出
Do{
Start-Sleep -Milliseconds 100
}While((($ie.Document.getElementById('ext-gen47')).GetType()).Name -eq "DBNull")
# 結束 IE
$ie.Quit()
# 清除變數 ie
Remove-Variable ie, account, password
}
$LoginURL = "http://192.168.1.123:5000"
$login = Invoke-WebRequest -Uri $LoginURL -WebSession $synology
$PostParams = @{username="$account";passwd="$password"}
$Method = $login.Forms['login-form'].Method
$Action = $login.Forms['login-form'].Action
$Content = Invoke-WebRequest -Uri "$LoginURL/$Action" -Body $PostParams -Method $Method -WebSession $synology
$C = Invoke-WebRequest -Uri "$LoginURL/webapi/encryption.cgi" -Body $PostParams -Method Post -WebSession $synology
$D = Invoke-WebRequest -Uri "$LoginURL/webman/login.cgi?enable_syno_token=yes" -Body $PostParams -Method Post -WebSession $synology
$Token = ($D.Content | ConvertFrom-Json).SynoToken
$Entry = "$LoginURL/webapi/entry.cgi?api=SYNO.Core.Desktop.Defs&version=1&method=getjs&SynoToken={0}&v=1614173144" -f $Token
$E = Invoke-WebRequest -Uri $Entry -Method Get -WebSession $synology
$E.RawContent
使用 Invoke-WebRequest 可以登入 Synology NAS,但是不會觸發 DSM 自動建立使用者家目錄,歡迎大家來討論
0 意見:
張貼留言