iT邦幫忙

0

關於PowerShell的問題

  • 分享至 

  • xImage

各位達人大家好:
以下是小弟不才的語法,該程式的目的是:
「偵測內部網路主機中的資料,其路徑(資料夾)是否有檔案,若有檔案則壓縮該資料中的所有檔案為zip檔,並將壓縮檔以Email附件的方式寄出。」
註:
以下程式碼,皆是以「工作排程」來執行,時間一到就自動執行該程式。

但是,目前偶爾會發生的問題如下:

1、明明該資料夾(路徑)有檔案,卻沒有壓縮檔(zip),導致寄出的Email沒有夾附件(Email主旨、本文是搭配有附件的變數);

2、明明該資料夾(路徑)有檔案,程式卻判斷該資料夾沒有檔案(即沒有壓縮該資料夾),寄出沒有附件的Email主旨與本文(Email主旨、本文是搭配沒有附件的變數)。

而且當上述問題發生時,我手動執行該工作排程,其結果就正常;我平常是使用 「Windows 的工作排程」來執行的,時間到就自動執行該程式碼。

按照程式的邏輯來說,應該是沒錯才對!還是有我沒有看到、想到的地方,導致以上的問題發生,故請有經驗的達人能幫忙查看一下,是否哪裏有問題;
謝謝!!

==========================以下為程式內容==========================

#Email收件、寄件者資訊
$EmailTo = "收件人群組"
$EmailFrom = "寄件人信箱"

#Email主旨
$Subject1 = "$((get-date).ToString('yyMMdd')) Exact Taipei Scan Docs." 
$Subject2 = "$((get-date).ToString('yyMMdd')) ""No"" Exact Taipei Scan Docs."

#Email本文內容
$Body1 = "Today's Scan Documents From Exact Taipei." 
$Body2 = "Today ""No"" Scan Documents From Exact Taipei." 

#Email寄送主機
$SMTPServer = "ms.mailcloud.com.tw"  

#If判斷目的資料夾中是否存有任何檔案
$condtion = Test-Path "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\*.*"
if ($condtion)
{
    # If判斷若為True,則執行以下程式碼
    #壓縮附件
    Compress-Archive -Path "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))" -Force -Destinationpath "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"
    
$filenameAndPath = "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"
    
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject1,$Body1)
    
$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
    
$SMTPMessage.Attachments.Add($attachment)
    
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25) 
}
else
{
    
#If判斷若為False,則執行以下程式碼
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject2,$Body2)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
}
#執行寄送Email動作
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxxxxxxxxx", "xxxxxxxxx"); 
$SMTPClient.Send($SMTPMessage)

以下是我04/14在「壓縮」程式碼後,加上「 start-sleep -s 5」程式碼的完整程式內容

===================以下為04/14修改後的程式內容===================

#Email收件、寄件者資訊
$EmailTo = "收件人群組"
$EmailFrom = "寄件人信箱"

#Email主旨
$Subject1 = "$((get-date).ToString('yyMMdd')) Exact Taipei Scan Docs." 
$Subject2 = "$((get-date).ToString('yyMMdd')) ""No"" Exact Taipei Scan Docs."

#Email本文內容
$Body1 = "Today's Scan Documents From Exact Taipei." 
$Body2 = "Today ""No"" Scan Documents From Exact Taipei." 

#Email寄送主機
$SMTPServer = "ms.mailcloud.com.tw"  

#If判斷目的資料夾中是否存有任何檔案
$condtion = Test-Path "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\*.*"
if ($condtion)
{
    # If判斷若為True,則執行以下程式碼
    #壓縮附件
    Compress-Archive -Path "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))" -Force -Destinationpath "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"
    start-sleep -s 5    
$filenameAndPath = "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"
    
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject1,$Body1)
    
$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
    
$SMTPMessage.Attachments.Add($attachment)
    
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25) 
}
else
{
    
#If判斷若為False,則執行以下程式碼
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject2,$Body2)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
}
#執行寄送Email動作
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxxxxxxxxx", "xxxxxxxxx"); 
$SMTPClient.Send($SMTPMessage)
看更多先前的討論...收起先前的討論...
dophintil iT邦新手 4 級 ‧ 2022-04-13 15:22:35 檢舉
不知道是不是...
1. 路徑應該是雙斜線\\192.168.10.210?
2. 不需要登入嗎?
runan5678 iT邦研究生 1 級 ‧ 2022-04-13 17:16:50 檢舉
那當有問題的時候手動執行工作排程器的工作,而不是執行Script會正常嗎?
dophintil您好:
首先很感謝您的回覆;針對您建議的答案:
1. 路徑應該是雙斜線\\192.168.10.210?
答:我確定我原始程式是"雙斜線",不知道為什麼語法貼上來就變成"單斜線",
以下是我原始程式碼的截圖:
https://imgbox.com/iwI2Xd0P
所以,壓縮檔案及確認有無檔案語法,確認都是雙斜線,而且執行沒有問題。

2. 不需要登入嗎?
答:該部電腦已經在控制台的「認證管理員」中,
將登入資訊(帳號及密碼)輸入進去了;所以,實際登入沒有問題。

==========我是分隔線==========

runan5678您好:
很感謝您的回覆;
>>那當有問題的時候手動執行工作排程器的工作,而不是執行Script會正常嗎?
答:有問題的時候,其實第一步我是到工作排程中查看,看執行的狀況是什麼,
一般都是顯示"正常";接下來我就再次"手動"執行排程,再次手動執行排程,其
結果就正常,也就是該資料夾就正常壓縮其附件,然後,就會Email寄出該附件。

謝謝!!
題外話:
"Outfax$((Get-Date -Format "yyyyMMdd").ToString())" 這樣會不會好閱讀點.
nwm310 iT邦新手 4 級 ‧ 2022-04-14 20:52:55 檢舉
多做幾次Test-Path
nwm310 iT邦新手 4 級 ‧ 2022-04-15 07:20:49 檢舉
用new-psdrive 掛載UNC路徑為PS磁碟機
再用test-path檢查PS磁碟機裡有沒有檔案
nwm310 您好:
首先很感謝您的回覆,您說使用「new-psdrive」來掛載PS磁碟機,此用意是什麼?
是避免該路徑(名稱)過長,導致程式在執行時,偵測或是壓縮檔案失敗嗎?
謝謝!!
nwm31您好:
我使用「new-psdrive」語法來掛載磁碟機,語法如下:

#新增掛載 PowerShell 磁碟機為「NAS」;根目錄路徑為"當天日期"之資料夾
New-PSDrive -Name NAS -PSProvider FileSystem -Root "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))"

也成功掛載了一個磁碟機:NAS
test-path也成功偵測到,該路徑資料夾有檔案,語法如下:
$condtion = Test-Path NAS:
write-output $condtion
輸出結果為 "True";

也成功壓縮了該路徑資料夾的檔案,語法如下:
Compress-Archive -Path "NAS:" -Force -Destinationpath "NAS:\$((get-date).tostring('yyMMdd')).zip"

但是,現在卻似乎發生要寄件時,不支援該路徑,或是檔案找不到的問題;
Email可以寄得出去,但是,都沒有附件(確定該路徑有檔案且有壓縮檔);

相關語法如下:

一、當"$filenameAndPath" 語法如下時:
$filenameAndPath = "NAS:\$((get-date).tostring('yyMMdd')).zip"

在執行下方程式語法時,會出現錯誤訊息為:(不支援指定的路徑格式)
==========錯誤訊息=========
New-Object : 以 "1" 引數呼叫 ".ctor" 時發生例外狀況: "不支援指定的路徑格式。"
位於 線路:2 字元:19
+ ... $attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object],MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

二、當"$filenameAndPath" 語法如下時:
#$filenameAndPath = "$((get-date).tostring('yyMMdd')).zip"

在執行下方程式語法時,會出現錯誤訊息為:(找不到檔案)
==========錯誤訊息=========
New-Object : 以 "1" 引數呼叫 ".ctor" 時發生例外狀況: "找不到檔案 'C:\WINDOWS\system32\220415.zip'。"
位於 線路:2 字元:19
+ ... $attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object],MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

==========程式語法==========
$SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject1,$Body1)
$attachment = New-Object System.Net.Mail.Attachment($filenameAndPath)
$SMTPMessage.Attachments.Add($attachment)
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 25)
==========程式語法==========

$filenameAndPath 路徑語法,我不知道如何修改才是正確的,可以告知如何
修正才能程式找得到該壓縮檔嗎?
謝謝!!
nwm310 iT邦新手 4 級 ‧ 2022-04-15 13:57:22 檢舉
1.用new-psdrive的原因:
test-path \\192.168 這種路徑判斷錯誤
所以,換別種形式的路徑試試看
google搜尋 powershell test-path unc
網友提供的方法

2.附件的路徑,用\\192.168 那種路徑試試看

3.不確定以下這幾行是否有一樣的意義
test-path NAS:
test-path NAS:\
test-path NAS:\*.*

4.如果檔案存在,不先test-path,而直接去壓縮檔案(以\\192.168的路徑)
可以壓縮成功嗎?
想知道:有問題的,只有test-path本身?
nwm310,您好:
很感謝您的回覆;針對您的回答,以下是我的回覆;

1.用new-psdrive的原因:
test-path \\192.168 這種路徑判斷錯誤
所以,換別種形式的路徑試試看
google搜尋 powershell test-path unc網友提供的方法
答:
我使用您給的keyword(powershell test-path unc),去Google搜尋,出現有許多文章,不過,發現使用UNC路徑,好像很容易出問題;但是,來源檔案不在本機,就變成一定要使用UNC路徑來獲取檔案;是無法避免的事。



2.附件的路徑,用\\192.168 那種路徑試試看
答:
附件用回我原本的語法,也就是"\\192.168.10.210..."就成功了,不會出現錯誤訊息;但是,如果使用原本的程式語法的話,是不是就失去用"new-psdrive"的用意了?

原本的程式語法:
$filenameAndPath = "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"


3.不確定以下這幾行是否有一樣的意義
test-path NAS:
test-path NAS:\
test-path NAS:\*.*
答:
以上三個語法,我測試後都為"True",所以應該都是一樣的意思,偵測「NAS」磁碟機路徑下有無檔案。


4.如果檔案存在,不先test-path,而直接去壓縮檔案(以\\192.168的路徑)
可以壓縮成功嗎?
想知道:有問題的,只有test-path本身?
答:
我最早先前的程式碼,其實一開始就是先執行「壓縮」的程式碼,也就是不管該路徑下有沒有檔案,我都先執行壓縮指令,那時候就會出現我本文出現的那兩個問題。
問題是不是只有「test-path」而已?
應該不是只有這個問題,因為會發生該路徑中有檔案(test-path偵測有檔案),而且寄出去的Email主旨與本文,都是搭配有附件的變數),但是,就是沒有夾附件;而有時候也會發生,該路徑中有檔案,但是,程式卻判斷成沒有檔案,所以,就沒去壓縮檔案,寄出的Email也就是搭配沒有附件的主旨與本文;然而,以上這些情況發生後,我再次手動執行工作排程,也就是透過工作排程再次執行程式,就又正常執行(正常壓縮檔案,搭配有附件的主旨正本文);這真的很怪,每次發生問題、不正常的時候,我手動執行(透過工作排程)就會正常,屢試不爽。
nwm310 iT邦新手 4 級 ‧ 2022-04-15 21:18:12 檢舉
如果附件的路徑要用"NAS:\$((get-date).tostring('yyMMdd')).zip" ,可以改用Send-MailMessage這個cmdlet來寄信

我在本機做了測試
確認資料夾是否存在
test-path NAS:
test-path NAS:\

確認資料夾裡有沒有檔案or子資料夾
test-path NAS:\*

確認資料夾裡有沒有檔案or子資料夾
(需要有副檔名)
test-path NAS:\*.*
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
打雜工
iT邦研究生 1 級 ‧ 2022-04-14 08:59:48

建議你分段測試,先確定手動執行是OK的;另外偶爾會發生"明明該資料夾(路徑)有檔案,程式卻判斷該資料夾沒有檔案(即沒有壓縮該資料夾),寄出沒有附件的Email主旨與本文",可能為壓縮檔還未完成,就開始跑寄件了

看更多先前的回應...收起先前的回應...

打雜工,您好:
首先很感謝您的回覆;您建議分段測試,先確定手動執行是否正常;
當初在測試程式的時候,就是一段程式一段程式測試的,就是壓縮附件
的語法是否正常?偵測路徑資料夾中是否有檔案?寄件語法是否能將
Email寄出…?都正常無誤後,最後程式再整個合起來後,測試程式語法
的效果,也就是當初在撰寫、測試程式時,其結果都是正常的,最後程式
內容就決定是這樣子;還有您提到可能壓縮檔還未完成,就開始跑寄件
了,這個我還真的沒有想到,不過,一般程式在執行的時候,不是應該
要等該段程式碼執行完後,再執行下一段程式碼嗎?如果有可能是這種情
況的話,程式要怎麼改比較好?要怎麼知道或是讓檔案已經壓縮完成後,
再將Email寄出?而且也曾經有發生過,目的路徑中的資料夾有檔案,但是
,程式卻誤判沒有檔案,當然就沒有壓縮檔案,所以,寄出的Email就是沒
有附件的主旨與內文,這個情況就是我上述原文提到發生的問題第2點;
這個就不太可能跟壓縮檔案的程式有關,因為連壓縮檔案的動作都沒有;

目前我的做法是跟程式語法無關;先將該部電腦的"防毒軟體
(Symantec Endpoint Protection)"移除;再將Windows 內建的防火
牆關閉,雖然感覺不是這個原因,不過還是試試看這樣子問題會不會不再發生;謝謝!!

打雜工 iT邦研究生 1 級 ‧ 2022-04-15 08:20:50 檢舉

我早期寫vbs及後來寫PowerShell時有遇過類似時好時壞的經驗,其中的經驗就是程式上一段結果尚未產生,就跑到下一段了;後來我索性讓它停個幾秒的時間(sleep),就解決了。當然可能還有其它的情況,因您給的線索會讓我先想到這個經驗,所以先提供您參考

打雜工您好:
謝謝您的回覆,昨天在看完您的建議後,我想了一下,於是在程式「壓縮」語法後的位置加上「start-sleep -s 5」的程式碼;也就是在壓縮完資料夾後,讓程式停個5秒左右(壓縮Excel檔案),再執行下一段程式,如下所示,這樣子應該就可以避免在還沒有壓縮完檔案,就直接進行下一段程式;不過,加完這個程式碼後,在測試的時候是正常的,也就是:
1、判斷路徑資料夾有檔案;
2、壓縮檔案成附件,並將Email寄出。
但是,工作排程時間一到執行全部的程式碼,竟然出現我原文所述的第二個問題,也就是程式誤判資料夾中沒有檔案,所以,就沒有壓縮檔案成附件,導致Email以"沒有"附件的主旨與內文,將Email寄出;而當此狀況發生時,我馬上在「工作排程」中再執行一次,此次又正常執行,也就是判斷路徑資料夾有檔案,並且壓縮該資料夾檔案成附件,且寄出該封Email(搭配有附件的主旨與內文);所以…;真的很奇怪;不知道問題是
出在哪裏?
謝謝!

程式碼如下:

略....
Compress-Archive -Path "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))" -Force -Destinationpath "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"
    start-sleep -s 5
    $filenameAndPath = "\\192.168.10.210\Exact Commerce Taipei\00.共用資料\00.共享資料\DailyScan\Outfax\$((get-date).tostring('yyyy'))\$((get-date).tostring('MM'))\$((get-date).tostring('dd'))\$((get-date).tostring('yyMMdd')).zip"
    $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject1,$Body1)
....略
打雜工 iT邦研究生 1 級 ‧ 2022-04-16 16:26:59 檢舉

抱歉,你的程式碼我就先不看了,以我的經驗,如果你手動執行每次都OK,排程執行確找不到檔案,請您先確定檔案是否有產生,如果檔案有產生,那可能就是你PowerShell與排程內"動作"內"開始位置"的路徑有關,您再參考看看。

0
htcj0110
iT邦新手 5 級 ‧ 2022-04-18 11:38:55

的確對於這種手動執行都ok,但自動排程進行就"偶爾"出問題的情況較難排查問題.有以下建議供參考.
1.把UNC網路連接方式改為掛載為網路磁碟,先掛載好再判斷檔案是否存在,處理完畢時卸載網路磁碟.也許你會覺得都嘛沒差,都是透過網路,但換個方式處理,也是提供一個排查問題的有利面向.
2.視需要在重要階段的處理結果都刻意輸出存成文字檔,以利除錯.例如判斷掛載網路磁碟是否成功外也要輸入磁碟代號,判斷檔案是否存在外也要輸出檔案名稱等等.
目的就是為抓出那"偶爾"出錯的部份會是在發生在哪個階段,以及錯在哪裡,希望以上建議有所幫助.

我要發表回答

立即登入回答