The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何讓 LINQPad 查詢直接當成 Console 來執行

我現在幾乎所有的 Side Project 都是在 LINQPad 寫的,因為實在是太方便,不但啟動速度快,而且也很好管理,萬能的 Dump() 方法有好多神奇用法,實在讓人愛不釋手。除此之外,你其實也可以拿 LINQPad 來寫「腳本」(C# Script),使用上雖然不能直接編譯成 *.exe 可執行檔,但是搭配 lprun8 來執行其實也不會很麻煩,對於需要快速 Prototyping 的時候,使用 LINQPad 不失為一個好選擇。

image2

LINQPad 內建一個 lprun 執行檔,但不同的 LINQPad 版本,其執行檔的名稱與路徑稍微有點不同:

  • LINQPad 5: C:\Program Files (x86)\LINQPad5\LPRun.exe
  • LINQPad 6: C:\Program Files\LINQPad6\LPRun6.exe
  • LINQPad 7: C:\Program Files\LINQPad7\LPRun7.exe
  • LINQPad 8: C:\Program Files\LINQPad8\LPRun8.exe

直接執行 lprun8 會看到一些說明:

Usage: lprun8 [<options>] <scriptfile> [<script-args>]

options: (all case-insensitive)
 -format={text|html|htmlfrag|csv|csvi}   Output format. csvi=invariant CSV.
 -cxname=<connection-name>               Sets/overrides a script's connection.
 -lang=<language>                        Sets/overrides a script's language.
 -warn                                   Writes compiler warnings (to stderr).
 -optimize                               Enables compiler optimizations.
 -compileonly                            Just checks that query will compile.
 -recompile                              Ignores compiler cache, forces build.
 -nunuget                                Freshens NuGet references to latest.
 -fx=<major.minor>                       Run under specified .NET version.

scriptfile: Path to script. If it's a .linq file, -lang & -cxname are optional.

script-args: Args following <script-filepath> are passed to the script itself.

Examples:
  lprun8 TestScript.linq
  lprun8 TestScript.linq > results.txt
  lprun8 script1.linq | lprun8 script2.linq
  lprun8 -format=csv script.linq HelloWorld

Go to https://www.linqpad.net/lprun.aspx for detailed help.
Version=8.2.4

以下我就列出幾個常見的使用方式。

  1. 執行 LINQPad 查詢 (預設輸出 text 格式)

    lprun8 test.linq
    
  2. 執行 LINQPad 查詢,並以 html 格式輸出

    使用 html 格式輸出,其輸出的內容將會跟你在 LINQPad 中直接執行的結果長的一模一樣!

    lprun8 -format=html test.linq > output.html
    

    你可以用 Google Chrome 直接開啟這個檔案:

    PowerShell

    & "${env:ProgramFiles(x86)}\Google\Chrome\Application\chrome.exe" "$(PWD)\output.html"
    

    Command Prompt

    "%programfiles(x86)%\Google\Chrome\Application\chrome.exe" "%CD%\a.html"
    
  3. 執行 LINQPad 查詢,並帶入命令列參數

    要將命令列參數傳入 LINQPad 查詢,其 Language 必須使用 C# Program,而且 Main() 方法要加入 string[] args 參數:

    void Main(string[] args)
    {
      args.Dump();
    }
    

    如果你執行 lprun8 test2.linq 的話,你會看到類似這樣的輸出:

    args: []
    

    如果你執行 lprun8 test2.linq Hello World 的話,你會看到這樣的輸出:

    args: [
      "Hello",
      "World"
    ]
    
  4. 執行 LINQPad 查詢,並輸出 CSV 格式

    要輸出 CSV 格式,首先你要在查詢中輸出「表格」或「清單」(兩筆以上) 類型的資料,這樣輸出 CSV 才有意義。

    我用以下程式碼為例:

    void Main(string[] args)
    {
      Encoding.GetEncodings().Dump();
    }
    

    如果你執行 lprun8 -format=csv test3.linq 的話,你會看到這樣的輸出:

    CodePage,Name,DisplayName
    1200,utf-16,Unicode
    1201,utf-16BE,Unicode (Big-Endian)
    12000,utf-32,Unicode (UTF-32)
    12001,utf-32BE,Unicode (UTF-32 Big-Endian)
    20127,us-ascii,US-ASCII
    28591,iso-8859-1,Western European (ISO)
    65001,utf-8,Unicode (UTF-8)
    

    注意: 就算你在程式碼中輸出字串,只要不是「表格」或「清單」的形式,就不會輸出。

    例如:

    void Main(string[] args)
    {
      Encoding.GetEncodings().Dump();
    
      "Header".Dump();
    
      Encoding.GetEncodings().Dump();
    }
    

    如果你執行 lprun8 -format=csv test3.linq 的話,你會看到這樣的輸出:

    CodePage,Name,DisplayName
    1200,utf-16,Unicode
    1201,utf-16BE,Unicode (Big-Endian)
    12000,utf-32,Unicode (UTF-32)
    12001,utf-32BE,Unicode (UTF-32 Big-Endian)
    20127,us-ascii,US-ASCII
    28591,iso-8859-1,Western European (ISO)
    65001,utf-8,Unicode (UTF-8)
    CodePage,Name,DisplayName
    1200,utf-16,Unicode
    1201,utf-16BE,Unicode (Big-Endian)
    12000,utf-32,Unicode (UTF-32)
    12001,utf-32BE,Unicode (UTF-32 Big-Endian)
    20127,us-ascii,US-ASCII
    28591,iso-8859-1,Western European (ISO)
    65001,utf-8,Unicode (UTF-8)
    

    注意:你也可以直接在查詢中呼叫 Util.ToCsvString (IEnumerable<T> elements, ...) 函式,他會自動將「表格」或「清單」等內容變成 CSV 格式的字串。

  5. 將一個 LINQPad 查詢的執行結果透過 Pipe 傳給下一個 LINQPad 查詢

    你可以透過 Pipe | 來將一個 LINQPad 查詢的執行結果傳給下一個 LINQPad 查詢,組成強大的自動化腳本。

    假設 test4.linq 內容如下:

    void Main(string[] args)
    {
      Encoding.ASCII.Dump();
    }
    

    假設 test5.linq 內容如下:

    void Main(string[] args)
    {
      string str = args?.Length > 0 ? args[0] : "Hello World";
    
      #if CMD
      str = Console.In.ReadToEnd();
      #endif
    
      str.Dump();
    }
    

    這裡特別值得一提的地方,在於 #if CMD#endif 這兩個條件式編譯語法(C# 前置處理器指示詞),這裡的 CMD 是 LINQPad 專屬的條件式常數,只要你是透過 lprun8 執行,這個 CMD 就會被設定,這樣你就可以在 LINQPad 查詢中使用 Console.In.ReadToEnd() 來讀取 Pipe 進來的資料。

    所以當你執行以下程式時:

    lprun8 test4.linq | lprun8 test5.linq
    

    就會得到以下結果:

    str: Encoding.ASCII: {
      "IsSingleByte": true,
      "BodyName": "us-ascii",
      "EncodingName": "US-ASCII",
      "HeaderName": "us-ascii",
      "WebName": "us-ascii",
      "WindowsCodePage": 1252,
      "IsBrowserDisplay": false,
      "IsBrowserSave": false,
      "IsMailNewsDisplay": true,
      "IsMailNewsSave": true,
      "EncoderFallback": {
        "DefaultString": "?",
        "MaxCharCount": 1
      },
      "DecoderFallback": {
        "DefaultString": "?",
        "MaxCharCount": 1
      },
      "IsReadOnly": true,
      "CodePage": 20127
    }
    
  6. 除了用 | (Pipe) 來串接 LINQPad 查詢外,你也可以用 Util.Run() 工具函式,讓你直接從查詢中執行另外一個查詢

    以下是一段 LINQPad 查詢的範例:

    void Main(string[] args)
    {
      string result = Util.Run("test2.linq", QueryResultFormat.Text, "Hello", "World").AsString();
      result.Dump();
    }
    

    執行結果如下:

    result: args: [
      "Hello",
      "World"
    ]
    

    這裡特別值得一提的地方,在於 Util.Run() 最後可以用 As*() 方法來轉換成不同的型別:

    • Util.Run().AsString(): 將結果轉換成字串
    • Util.Run().AsStringAsync(): 將結果轉換成 Task<string> 非同步版本
    • Util.Run().AsMailAttachment("attachment.txt"): 將內容轉成 System.Net.Mail.Attachment 物件,便於寄出郵件並夾帶附件
    • Util.Run().AsMailAttachmentAsync("attachment.txt"): 將內容轉成 Task<System.Net.Mail.Attachment> 非同步版本
    • Util.Run().Save("filename.txt"): 將結果儲存成檔案
    • Util.Run().SaveAsync("filename.txt"): 將結果儲存成檔案,回傳非同步的 Task 物件
    • Wait(): 等待 Util.Run() 執行完畢
    • WaitAsync(): 回傳非同步的 Task 物件,可搭配 await 等待 Util.Run() 執行完畢
  7. 從批次檔捕捉例外狀況

    lprun8 test.linq
    if %errorlevel% neq 0 echo Error!
    
  8. 變更「編譯」選項

    加入 -optimize 參數,可讓 LINQPad 查詢執行在最佳化的狀態下,執行速度較快!

    lprun8 -optimize test4.linq
    

    加入 -warn 參數,可讓 LINQPad 查詢執行時顯示編譯器的警告訊息。

    lprun8 -warn test4.linq
    

    加入 -compileonly 參數,可以自動編譯 LINQPad 查詢中的程式碼,但不執行。

    注意: 首次透過 lprun8 執行一個新的 LINQPad 查詢時,預設就會包含編譯的過程,因此啟動速度較慢。但如果你預先編譯過,下次執行就會快很多!

    lprun8 -compileonly test4.linq
    lprun8 test4.linq
    

相關連結

留言評論