[PowerShell]鬼擋牆之呼叫function回傳多個值

  • 8155
  • 0

[PowerShell]鬼擋牆之呼叫function回傳多個值

前言
雖然知道PowerShell跟.NET的設計方式完全不一樣,但今天還是被一個小地方卡了好幾個小時,這邊分享一下莫名其妙的慘痛經驗給大家笑一下。

案例

功能需求:將某一段資訊記成log,寫在某個路徑底下。當路徑不存在時,要建立對應的資料夾。

簡單到爆的需求吧,我們把程式列出來:


function Logging
{
	param ($logFile, $logInfo)

	$logInfo >> $logFile
}

#資料夾不存在,就建立
function CheckFolderExist($path)
{	
	if ((Test-Path $path) -eq $false)
    {			
		mkdir $path		
    }
}

#取得Log檔路徑與檔名
function GetLogFileName
{		
	# log file
	$todayStr = Get-Date -format "yyyyMMdd"
	
	$logPath = "\\127.0.0.1\c$\temp\"
	
	CheckFolderExist $logPath

	$logFile = $logPath + "Joey-" + $todayStr + ".log"
		
	return $logFile
}


Logging (GetLogFileName)"test by Joey"

我們把『檢查資料夾,建立資料夾』抽成一個function,使用mkdir來建立資料夾。

這樣的程式碼看起來很合情合理吧?實際跑一次,我們來看結果:

image 

為什麼我的路徑變成『
\\127.0.0.1\c$\temp\127.0.0.1\c$\temp\Joey-20110629.log』了?見鬼了…

檢查一下結果,資料夾有被明確的建立起來,那就是寫檔的問題囉?再執行一次發現,檔案成功寫進去了。

image 

為什麼第二次執行就可以寫進去?看來原因是在建立資料夾,但是資料夾也有被成功建立啊,就這樣鬼擋牆了。

用偵錯模式下去跑跑看:

image 

logFile的值的確就是我們要的:
\\127.0.0.1\c$\temp\Joey-20110629.log

但錯誤資訊還是一樣:Could not find a part of the path '\\127.0.0.1\c$\temp\127.0.0.1\c$\temp\Joey-20110629.log'.

折騰了好一陣子,換個寫法檢查,才發現GetLogFileName這個function回來的東西,跟想像的完全不一樣。

拆牆
我們先將GetLogFileName回傳值放到$result裡面,接著進行偵錯。

  1. function中return的$logFile仍然是:
    image 

    但是$result呢?

    image

    見鬼了!為什麼$result是array,把$logPath跟$logFile一起回傳了??
  2. 找了老半天後發現,$result的結果:{\\127.0.0.1\c$\temp, \\127.0.0.1\c$\temp\Joey-20110629.log}
    第一個element並不是想像中在GetLogFileName function裡面的$logPath變數,而是CheckFolderExist這個function裡面的回傳值。(天啊!mkdir $path竟然會回傳$path的值)
  3. 更機車的是,我並沒有宣告變數去接CheckFolderExist這個function回傳的東西。讓我更納悶的是,啊我不是在GetLogFileName最後一行,寫著『return $logFile』嗎?為什麼兩個都回來了…
     

就是這麼機車的過程中,找到兇手了。

  1. CheckFolderExist的function中,呼叫了mkdir的function,會回傳$path。沒有用變數接就代表會回傳回去。
  2. GetLogFileName的function中,呼叫了CheckFolderExist,也沒有用變數去接,所以代表GetLogFileName最後也會回傳$path。但function還沒結束,所以會繼續往下跑。
  3. GetLogFileName的function中,最後return了$logFile,加上剛剛CheckFolderExist回傳的$path,所以最後就回傳了{$path, $logFile}


知道原因之後,我們修改一下程式:

image 

宣告一個$path來接CheckFolderExist的回傳值,然後就不管它。

執行結果正確無誤。

結論
PowerShell果然跟一般的.NET完全不一樣啊…呼叫function記得要用變數去接,不然會回傳一個array。相對的,如果需要回傳多個值,也可以透過這樣的方式去接。

把我的青春還來啊…真的是書到用時方恨少啊 >”<


blog 與課程更新內容,請前往新站位置:http://tdd.best/