PowerShell が難しい場合は C#, または VB.NET で書いた方が早いよね

PowerShell って難しい?

PowerShell のメリットは、Visual Studio が入っていない環境で .NET Framework なアプリを作れること+ PowerShell の各コマンドレット命令を組み合わせられることが1つあると思います。

何かやりたい時、すでに専用の命令が用意されていればそれを呼び出すだけで終わるのですが、ほとんどの場合は、C#, または VB.NET ライクな書き方になります。

特に C#er/VB.NETer の方が PowerShell に入ってくる場合、C#/VB.NET で書いた方が早い気がします。できれば PowerShell の文化に倣って書きたいところですが。最初のうちは・・・とか甘いこと言っているとアレなコードが増殖しちゃうかな?

まぁ、自分だけが使うような場合は、ルールにこだわらなくてもいい気もします。というわけで前置きでしたが、クラス設計は C#/VB.NET で、実行は PowerShell でやるという作業分担な書き方です。

C#

cs.ps1

# 参照追加したい dll をここに書きます。
$assemblies = (
    "System",
    "System.Windows.Forms"
)

# C# コードをここに書きます。少し古い C# バージョンで書きます。
# (私の環境の場合)$"{name}" は効かないですが、型推論は効くみたいです。($PSVersionTable のバージョン相当)
$source = @'
using System;

public class Class1
{
    public static string Hello(string name)
    {
        var msg = name + "様、おはようございます!";
        Console.WriteLine(msg);
        return msg;
    }

    public void Hello2(string name)
    {
        var msg = name + "様、おはようございます!2";
        Console.WriteLine(msg);
    }
}

'@

Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language CSharp
[Class1]::Hello("太郎")

$obj = New-Object Class1
$obj.Hello2("次郎")

VB.NET

vbnet.ps1

# 参照追加したい dll をここに書きます。
$assemblies = (
    "System",
    "System.Windows.Forms"
)

# VB.NET コードをここに書きます。少し古い VB.NET バージョンで書きます。
# (私の環境の場合)$"{name}" は効かないですが、型推論は効くみたいです。($PSVersionTable のバージョン相当)
$source = @'
Imports System

Public Class Class1
    
    Public Shared Function Hello(ByVal name As String) As String
        
        Dim msg = name & "様、おはようございます!"
        Console.WriteLine(msg)
        Return msg

    End Function
    
    Public Sub Hello2(ByVal name As String)
        
        Dim msg = name & "様、おはようございます!2"
        Console.WriteLine(msg)

    End Sub

End Class

'@

Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language VisualBasic
[Class1]::Hello("太郎")

$obj = New-Object Class1
$obj.Hello2("次郎")

出力結果

1つ目のメソッドは、メソッド内で1回、(ISE で実行しているので)戻り値をそのまま出力するので1回の計2回出力されています。2つ目のメソッドはメソッド内で1回出力しています。戻り値無しなので戻ってきても何もしないで終わりです。

太郎様、おはようございます!
太郎様、おはようございます!
次郎様、おはようございます!2

WinForms を表示する

C#

cs2.ps1

# 参照追加したい dll をここに書きます。
$assemblies = (
    "System",
    "System.Drawing",
    "System.Windows.Forms"
)

# C# コードをここに書きます。少し古い C# バージョンで書きます。
# (私の環境の場合)$"{name}" は効かないですが、型推論は効くみたいです。
$source = @'
using System;
using System.Drawing;
using System.Windows.Forms;

public class Program
{
    public static void Main()
    {
        Application.EnableVisualStyles();
        
        var frm = new Form();
        frm.Name = "form1";
        frm.Text = "form1";
        frm.Size = new Size(800, 600);

        var btn1 = new Button();
        btn1.Name = "btn1";
        btn1.Text = "btn1";
        btn1.Location = new Point(10, 10);
        btn1.Size = new Size(120, 80);
        btn1.Click += Button1_Click;
        frm.Controls.Add(btn1);

        frm.ShowDialog();
    }

    private static void Button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("ボタンをクリックしました!", "情報", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

'@

Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language CSharp
[Program]::Main()

VB.NET

vbnet2.ps1

# 参照追加したい dll をここに書きます。
$assemblies = (
    "System",
    "System.Core",
    "System.Data",
    "System.Data.DataSetExtensions",
    "System.Deployment",
    "System.Drawing",
    "System.Net.Http",
    "System.Windows.Forms",
    "System.Xml",
    "System.Xml.Linq"
)

# VB.NET コードをここに書きます。少し古い VB.NET バージョンで書きます。
# (私の環境の場合)$"{name}" 、型推論共に効かないみたいです。
$source = @'
Imports System
Imports System.Data
Imports System.Data.DataSetExtensions
Imports System.Drawing
Imports System.Net.Http
Imports System.Windows.Forms
Imports System.Xml
Imports System.Xml.Linq

Public Class Program
    
    Public Shared Sub Main()
        
        Application.EnableVisualStyles()
        
        Dim frm As New Form
        frm.Name = "form1"
        frm.Text = "form1"
        frm.Size = New Size(800, 600)

        Dim btn1 As New Button
        btn1.Name = "btn1"
        btn1.Text = "btn1"
        btn1.Location = New Point(10, 10)
        btn1.Size = New Size(120, 80)
        AddHandler btn1.Click, AddressOf Button1_Click
        frm.Controls.Add(btn1)

        frm.ShowDialog()

    End Sub

    Private Shared Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        
        MessageBox.Show("ボタンをクリックしました!", "情報", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

End Class

'@

Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language VisualBasic
[Program]::Main()

実行時に表示される画面

f:id:sutefu7:20191019153704p:plain