最近在多人合作開發項目時遇到一個場景,是關於 Visual Studio 生成事件在不同環境出現的問題。比如大部分人的發布目錄不一樣,這就導致了在執行生成事件時的報錯(通常是:已退出,代碼為4),所以決定使用代碼來統一這個場景,讓代碼盡可能在每台電腦上都能順利的運行。
需求分析
需求1:只操作一次發布,同時將 DLL 和 XML 更新,不需要單獨更新 XML 文件;
需求2:希望每次在上傳待發布文件時,不需要手動排除配置文件(小心翼翼的排除);
針對需求,一邊搜索 BAT 命令,一邊學習寫出了下面的第一版,下面逐行將代碼邏輯分析一遍:
1.代碼開始聲明 path 變量,值為發布目錄路徑;
2.判斷發布路徑是否存在;
3.復制$(TargetDir)目錄下所有 xml 文件至發布目錄;
4.刪除發布目錄下 appsettings.*.json 文件;
5.刪除發布目錄下 appsettings.json 文件;
6.如果路徑不存在;
7.創建發布目錄;
set path = "D:\Website\xXx\API\"
if exist path
{
Copy /y $(TargetDir)*.XML path
DEL /f /q path appsettings.*.json
DEL /f /q path appsettings.json
}
else
{
md path
}
第一次寫出這么長的 CMD 命令,在最開始個人版本中的只有一句:Copy /y $(TargetDir)*.XML D:\Website\xXx\API\,用得好好的也沒見出過問題。直到在團隊成員中出現了文件夾不存在的報錯。才引起重視。
正是因為對 CMD 的不熟悉,這段代碼才漏洞百出,直到寫出正確的版本。感覺就像是寫了個 Hello Word 錯誤警告一大堆一樣讓人沮喪。沮喪歸沮喪,但是決不放棄,這是原則。
又經過一番搜索,根據錯誤提示慢慢的定位到問題。開篇提到最長遇到的錯誤是"已退出,代碼為4",這次的錯誤是“已退出,代碼為1”,就將這個錯誤信息當作突破點一直搜索。慢慢的找出了真相。下面來說說這段代碼中都有哪些錯誤。
錯誤1: | 變量使用時需要待百分號(%path%) |
錯誤2: | 聲明變量時,等號左邊不能出現空格(右邊可以有多個空格); |
錯誤3: | CMD 中的判斷使用的是小括號“()”; |
錯誤4: | 並且小括號必須和 if else 寫在同一行; |
加上大括號一共11行的代碼,可以出 4 個錯誤,真的是無比心碎。下面是修正錯誤並優化后的代碼:
set path="D:\Website\xXx\API\"
if not exist %path% (
md %path%
)
Copy /y $(TargetDir)*.XML %path%
DEL /f /q %path%appsettings.*.json
DEL /f /q %path%appsettings.json
中間還發現 CMD 和部分腳本語言的特性一樣,會嘗試盡可能的運行代碼,有錯的部分跳過並報錯。正確的代碼依然會執行。這與 C# 的語言特性區別有點大,還疑惑了半天,為什么在報錯,但 XML 文件正確的復制了,JSON 文件也正確的刪除了。現在謎底已解開,豁然開朗。
最后還有一點意外,就是 DEL 語句會在發布完成前先執行,然后 Visual Studio 會再次把文件復制一份過來。導致始終不能達到需求二的效果。最開始是希望通過延時執行 CMD 的方式解決,結果延時命令會阻塞發布操作,並且也不能成功。最終通過各種搜索找到微軟的發布配置文件找到排除文件的方法。
在發布項目的 .csproj 中找一個或創建一個 ItemGroup,實現效果如下:
<ItemGroup>
<Content Update="**\*.json" CopyToPublishDirectory="Never" />
</ItemGroup>
這樣那前面 CMD 中的 DEL 也失去意義,索性去掉。至此兩個需求完成了。