2021年2月18日 星期四
使用 PowerShell 進行硬體資產調查
使用 PowerShell 讀取 Synology NAS LDAP Server
網路上查到的PowerShell 讀取 LDAP 資訊,幾乎清一色都是讀取 Active Directory....
很少講到如何讀取 Linux LDAP Server
找了好久,終於找到 C# 讀取 LDAP 的資訊,改成 PowerShell
使用 PowerShell 批次執行 IE ,自動登入 Synology NAS
這次會想寫這個程式,是因為公司打算將 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 才成功。
2020年12月3日 星期四
使用 PowerShell 對文字進行Escape編碼、Unescape解碼
這個編碼解碼結果,與 JavaScript Escape() 及 Unescape() 相同
$Original = '“Instead of going back to business as usual, Uber is taking this moment as an opportunity to reduce our environmental impact.” The company said in a press release.[p]Uber 在新聞稿中表示:「Uber並沒有像往常一樣重返市場,而是以此為契機,減少對環境的影響。」' $Encode = "" $Alphabet = @(42,43,45,46,47,48,49,50,51,52,53,54,55,56,57,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,95,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122) $Symbol = @(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,44,58,59,60,61,62,63,91,92,93,94,96,123,124,125,126,127) # 編碼文字 for($i = 0; $i -lt $Original.Length; $i++){ If($([int]$($Original[$i])) -in $Alphabet){ $Encode += $Original[$i] }ElseIf($([int]$($Original[$i])) -in $Symbol){ $Encode += [System.String]::Format("%{0:X2}", [int]$Original[$i]) }Else{ $Encode += [System.String]::Format("%u{0:X4}", [int]$Original[$i]) } } Write-host $Encode Write-Host "`r`n" # 還原文字 Add-Type -AssemblyName System.Web [System.Web.HttpUtility]::UrlDecode($Encode) |
使用 PowerShell 讀取 GMail 摘要 RSS
使用 PowerShell 讀取 GMail 信箱資訊,需要先設定應用程式密碼,包括使用 Outlook或是使用Windows 10內建的 Mail 程式收發郵件。
或是想要讓事物機把掃描產生的圖檔,以電子郵件寄出,也需要設定應用程式密碼。
紅字部分,請自行更換成適當的資訊喔
Clear-Host # 讀取 GMail Samples $webclient = new-object System.Net.WebClient
# 這裡輸入的密碼,是 Application Password (應用程式密碼) # 如何產生 Application Password (應用程式密碼) # https://support.google.com/mail/answer/185833?hl=tw $webclient.Credentials = new-object System.Net.NetworkCredential ("my@email.address", "MyApplicationPassword") |
之前使用 .DownloadString Method,會發現中文字都被破壞掉,所以改用 .DownloadData
# 下載 RSS,這裡得到的是一堆十進位數字的陣列,Unicode 文字是三組大於127的10進位數字 $xml= $webclient.DownloadData("https://mail.google.com/mail/feed/atom") |
所以,接下來就是要將變數 $xml 的資訊轉換成文字(包含 Unicode)
$s = "" For($l=0;$l -lt $xml.Count; $l++){ If($xml[$l] -gt 127){ # 當數值大於 127,表示是 Unicode,所以轉換成16進位格式字串 $s += "%" + $xml[$l].ToString('x2') }Else{ # 小於等於 127 ,就直接轉成 Ascii 字元 $s += [char]$xml[$l] } } # 將 Unicode 編碼進行解碼,還原成中文字 $xml = ([URI]::UnescapeDataString($s)) |
這樣 $xml 就變成 XML 格式的字串了
# 輸出成 XML 檔案 $xml | Out-File -FilePath "D:\test.xml" -Encoding utf8 |
接下來要解析 XML內容,分欄顯示
# 雖然字串是 XML 格式,但不代表變數是 XML 型態,所以要進行轉換型態 $xml = [xml]$xml
# 設定 Format-Table 要輸出的格式 $format= @{Expression={$_.author.name};Label="Name"}, @{Expression={"|"};Label="|"}, @{Expression={$_.author.email};Label="E-Mail"}, @{Expression={"|"};Label="|"}, @{Expression={$_.title};Label="Title"}, @{Expression={"|"};Label="|"}, #@{Expression={$_.link|Select 'href'};Label="Link"}, # 當你使用瀏覽器開啟 Link 的連結,就會直接讀取該郵件 @{Expression={$_.link|Select-XML -XPath "@href"};Label="Link"}, @{Expression={"|"};Label="|"}, @{Expression={$_.summary};Label="summary"} # 輸出成 Table ,缺點是過長的欄位資訊就不會出現 $xml.feed.entry | format-table $format |
再來就是將 XML 內容,轉換成簡單的 HTML 檔案
# 所以底下將 XML 資訊轉換成 HTML 表格 $mail = @() $xml.feed.entry | ForEach { $hash = @{ "name" = $_.author.name "email" = $_.author.email "title" = $_.title "link" = ($_.link|Select-XML -XPath "@href") "summary" = $_.summary } $Line = New-Object -TypeName PSObject -Property $Hash $mail += $Line } $mail | ConvertTo-Html | Out-File -FilePath "D:\testxml.html" -Encoding oem |
2020年12月2日 星期三
使用PowerShell 呼叫 ffmpeg,將串流影片合併起來,並轉換成 MP4 格式
串流影片,就是將原始影片切分成多個小影片 *.ts,然後將多個小影片寫在一個清單檔案 *.m3u8檔案
當你辛苦下載了每個 .ts 影片,想要合併所有檔案,以便管理,可以使用ffmpeg來處理。
合併所有 .ts 檔案之後,要再轉換成普遍的mp4格式,也還是使用ffmpeg 來處理。
紅字部分,請自行評估環境修改
# 要讓產生的字串帶有雙引號括起來,是因為路徑有可能包含空白 # 如果不用雙引號括起來,後面程式會發生錯誤 $ffmpeg = """C:\Users\User\Desktop\ffmpeg-4.1.4-win64-static\bin\ffmpeg.exe""" # 目錄不要用中文,ffmpeg 會不認得 $Root = "D:\[tts 影片存放的目錄路徑]" If(Test-Path -Path "$Root\list.txt"){ Remove-Item -Path "$Root\list.txt" } # 輸出檔案格式一定要是 utf8 (with no BOM),不然 ffmpeg 會找不到檔案 Get-ChildItem -Path $Root -Filter *.ts | Sort-Object -Property Name | ForEach{ "file '$Root\$_'" | Out-File -FilePath "$Root\list.txt" -Append -Encoding oem } Write-Host "Combine Files.... Please Wait" # 如果有設定路徑,就需要加 -safe 0 參數 $CombineArgu = "-f concat -safe 0 -i ""{0}\list.txt"" -c copy ""{0}\Combine.ts""" -f $Root Write-Host "$ffmpeg $CombineArgu" -ForegroundColor Red Start-Process -FilePath $ffmpeg -ArgumentList $CombineArgu -Wait -WindowStyle Normal -WorkingDirectory $Root Write-Host "Convert Files.... Please Wait" $ConvertArgu = "-i ""{0}\Combine.ts"" -acodec copy -vcodec copy ""{0}\Combine.mp4""" -f $Root Write-Host "$ffmpeg $ConvertArgu" -ForegroundColor Red Start-Process -FilePath $ffmpeg -ArgumentList $ConvertArgu -Wait -WindowStyle Hidden -WorkingDirectory $Root |
2020年12月1日 星期二
用 Powershell 使用 Google Cloud Text to Speech API 服務
程式主要有兩個部分
1. 驗證(擇一)
l 使用 Service Account 方法
n 在GCP Console設定服務帳號之後,產生金鑰檔,並下載金鑰檔
l 使用 API Key 方法
n 設定可使用 API Key 的 IP清單,以及可使用的 API服務項目
2. 傳送文字設定資料,並取得音效資料進行處理
Google Cloud Text to Speech API 服務是要收費的,所以需要經過驗證
使用 Service Account
# 載入 Google Cloud SDK 的 GoogleCloud Module for PowerShell |
使用 API Key
# 就是在 API 網址後面增加 Key參數 $url = "https://texttospeech.googleapis.com/v1/text:synthesize?key=你的金鑰字串" # ContentType 指定說明傳輸的資料格式是 JSON,編碼是 utf-8 $response = Invoke-RestMethod -ContentType 'application/json;charset=utf-8' -headers $headers -Uri $url -Method Post -body $JSON |
使用 API Key 程式會簡單很多,而且不用安裝 Google Cloud Library or Cloud SDK等
但是要記得設定允許使用此金鑰的 IP及服務,以確保資訊安全
接下來就是將文字及設定資訊傳送給Google Cloud Text to Speech API
格式一定要照規矩來,不然API會回覆錯誤
$content = "你想要讓 Google Text to Speech 唸出來的文字" $AudioEncoding = "MP3" $LanguageCode = "cmn-TW" $VoiceName = "$LanguageCode-Wavenet-A" $Effect="large-home-entertainment-class-device"
$JSON = @{ audioConfig = @{ audioEncoding = $AudioEncoding; effectsProfileId = $Effect; pitch = 0; speakingRate = 0.9; # speakingRate = 0.25 ~ 4.0 volume_gain_db = +6; # volume_gain_db = -96.0 ~ 16.0 }; input = @{ }; voice = @{ languageCode = $LanguageCode; name = $VoiceName; } }
# 如果 Content 不是使用 SSML XML 格式, input 裡的 key 就必須使用 text # 如果 Content 使用 SSML XML 格式, input 裡的 key 就必須使用 ssml # 所以用程式來判斷 key 是要用 text or ssml If($content -match [regex]"^\<speak\>" -AND $content -match [regex]"\<\/speak\>$"){ $body.input.Add("ssml",$content) }Else{ $body.input.Add("text", $content) }
$JSON = ConvertTo-Json ($JSON)
Try{ # Content Type 除了要告知是 JSON 資料之外,還要加上 charset=utf-8,不然只會唸中文字串中的數字 $response = Invoke-RestMethod -ContentType 'application/json;charset=utf-8' -headers $headers -Uri $target -Method Post -body $JSON # 回傳的 Audio Data 是 Base64 編碼的 $base64Audio = $response.audioContent
# 讀取系統環境變數,取得桌面路徑 $Dest = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
# 在桌面產生 PlayTTS.html 網頁檔案(語音資料以 Data URI 方式內嵌在網頁裡) "<html><head><title>Providing HTML5 audio with a base64 encoded Data URI as source</title><meta charset='utf-8'></head><body><h1>Providing HTML5 audio with a base64 encoded Data URI as source</h1><audio controls='' src='data:audio/ogg;base64,{0}'></audio></body></html>" -f $base64Audio | Out-File -FilePath "$Dest\PlayTTS.html" -Encoding oem
# 使用系統預設關聯,呼叫預設瀏覽器開啟網頁檔案,不需要任何外掛JS,即可播放 & "$Dest\PlayTTS.html"
# 將 Base64 Audio Data 存成文字檔 $base64Audio | Out-File -FilePath "./google.txt" -Encoding ascii -Force
# 設定音效檔檔名 $convertedFileName = 'PlayTTS-{0}.mp3' -f (get-date -f yyyy-MM-dd-hh-mm-ss)
# 呼叫 Windows 內建 certutil.exe 將 Base64 編碼檔案解碼,檔案輸出到桌面 certutil -decode google.txt "$Dest\$convertedFileName"
# 開啟檔案總管,並選取輸出的音效檔 Start-Process -FilePath "$($env:WinDir)\explorer.exe" -ArgumentList "/select, $Dest\$convertedFileName"
}Catch { # 如果 Request 發生錯誤,就印出錯誤碼 Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription } |











