[PowerShell] Integrated PowerShell with C# Application

มาต่อบทความการใช้ C# กับ PowerShell สักที หลังจากไปลองสร้าง Winform Application จาก PowerShell เพียวๆกันแล้ว โดยคราวนี้ เราใช้โจทย์ของคราวที่แล้วแหละ โดยมีการออกแบบหน้าจอ ดังรูป

หน้าตาของโปรแกรม

จัดการ Add Code Event ต่างๆให้เรียบร้อย (อันนี้ผมใช้ Pattern MVP นะครับ เผื่อคนโหลดไปแกะ Code)
จากนั้น เราต้องทำให้ C# รู้จักกับ PowerShell กันก่อน โดยการ Add Reference DLL เข้ามาใน Project ครับ โดยเราจะ Add DLL System.Management.Automation แต่ก่อนที่เรา Add DLL เข้ามาใน Project ของเรา ผมอยากให้ตรวจสอบ Version ของ PowerShell ครับ เพราะมันต้องเลือกให้เหมาะกับเวอร์ชัน Target Framework ในของ Project เราด้วยนะครับ โดยผมได้สรุปเป็นข้อมูล ดังนี้

.Net FrameworkPowerShell
.NET Framework 3.5PowerShell 2.0
.NET Framework 4.0PowerShell 3.0
.NET Framework 4.5PowerShell 4.0

เมื่อตรวจสอบเวอร์ชั่นของ DLL และ Target Framework ของ Project เราเรียบร้อยแล้ว

Target Framework

เริ่มทำการ Add Reference DLL System.Management.Automation ซึ่งอยู่ใน Path C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\-เวอร์ชั่น-

โดยของผมก็จะเป็น C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0 ดังรูป (ของผมใช้ PowerShell 4.0 นะ แต่งงเหมือนกันว่าทำไมโพลเดอร์ที่เก็บเป็น 1.0)

Add Reference ของ Power Shell
DLL ถูก Add เข้าไปใน Project แล้ว

จากนั้น เราก็มาจัดการกับ Code ของเราเลย โดยในที่นี้ ผมจะใช้ Class PowerShell และ ใช้ Method AddScript แต่ก่อนอื่น เราต้อง import Library ที่จำเป็นเข้ามาใช้งานตาม Code ดังนี้

using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.Collections;

เพื่อนำ Code ในส่วนของ PowerShell มาใส่ใน C# ครับ โดยสังเกตุได้ว่าตรง PowerShell ทำคล้ายๆกับการต่อ String นะครับ เพื่อรับข้อมูลที่เป็น Dynamic ได้

  • SearchPath
  • File Version
  • File Extension

ตาม Code ดังนี้ ครับ (คำอธิบายผมได้แทรกไว้ใน Comment แล้วครับ)

private void SearchFile()
{
    //สร้าง Instance ของ PowerShell Class
    using (PowerShell powershell = PowerShell.Create())
    {
        /*
            * ======= POWER SHELL SCRIPT =======
            *
            * $searchDataArr = Get-ChildItem $filePath -recurse -Include *.exe, *.ocx, *.dll -ErrorAction Stop |
            *                  Where-Object {(($_.VersionInfo).FileVersion -eq $fileVersion) -or ($_.Name -like '*'+$fileName+'*')} |
            *                  Select-Object -ExpandProperty VersionInfo |
            *                  Select-Object -Property @{l='ParentPath';e={Split-Path $_.FileName}},FileName, FileVersion, Productversion, ProductName
            *
            * ======= POWER SHELL SCRIPT =======
            */
        string extension = "";
        if (findExeView.SearchEXE)
        {
            extension = extension + "*.exe_";
        }
 
        if (findExeView.SearchOCX)
        {
            extension = extension + "*.ocx_";
        }
 
        if (findExeView.SearchDLL)
        {
            extension = extension + "*.dll";
        }
        extension = extension.Replace('_', ',');
        extension = extension.TrimEnd(',');
        string script = "";
        script = script + "Get-ChildItem '" + findExeView.SearchPath + "' -recurse -Include " + extension + " -ErrorAction Stop | ";
        if (findExeView.SelectFileName || findExeView.SelectFileVersion)
        {
            script = script + "Where-Object { ";
            if (findExeView.SelectFileVersion)
            {
                script = script + "(($_.VersionInfo).FileVersion -eq '" + findExeView.SearchVersion + "')";
                if (findExeView.SelectFileName)
                {
                    script = script + " -or ";
                }
            }
 
            if (findExeView.SelectFileName)
            {
                script = script + " ( $_.Name -like '*" + findExeView.SearchName + "*') ";
            }
            script = script + "} | ";
        }
        script = script + "Select-Object -ExpandProperty VersionInfo | ";
        script = script + "Select-Object -Property @{l='ParentPath';e={Split-Path $_.FileName}},FileName, FileVersion, Productversion, ProductName";
 
        //เพิ่ม Script ให้กับตัวแปร PowerShell
        powershell.AddScript(script);
        if (Runspace.DefaultRunspace == null)
        {
            //เริ่มการทำงาน
            Runspace.DefaultRunspace = powershell.Runspace;
        }
 
        //ดึงผลลัพธ์กลับมาในรูปแบบของ Collection
        Collection results = powershell.Invoke();
        //สร้าง List มารองรับ
        List objects = new List();
        //ใส่ Result เข้าไปใน List ที่เพิ่งสร้าง
        objects.AddRange(results);
        //ส่งไปแสดงผลลัพธ์บน Grid
        findExeView.GridDataSource = objects;
    }
}

สังเกตุดูนะครับว่า Script ของ PowerShell มีเงื่อนไขในจัดการเยอะมาก ต้องรอ Refactor Code อีกที เพื่อให้ Code สวยงามครับ (หาเรื่องเขียน Blog อันต่อไปครับ 555) โดยลองทดสอบดูแล้วได้ผลลัพธ์ ดังนี้

ผลการรันโปรแกรม
ผลการรันโปรแกรมอีกอันครับ

สำหรับ Source Code อยู่ใน GitHub ครับผม


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.