📌

Powershellで電源をチェックできる関数を実装する

2023/11/03に公開

Powershellに電源を確認するコマンドレットは無いです。
よって、windowsのcuiで簡単に電源を確認する方法はありません!

困りましたね。
ということで実装しましょう。

今現在、dotnetに電源の状態を取得する方法が実装されていないので、csharpからC++のwin32apiの
関数を呼び出し、そのcsharpのソースコードをPowershellから読み込み、型定義を行うことによって、
Powershellに関数の定義を行います。

一応、最近できたcsharpからwin32を実行するためのCsWin32というライブラリを使うこともできますが、ビルドする必要があるうえ、dotnet 5.0以上縛りがあり、Powershell7.2以上でないと動作できない関数になります。

GetSystemPowerStatusの定義は
ここにあるのでそれを参考にcsharp側にC++と同じ作りの構造体を作り上げ、その構造体を参照渡しすることで実現できます。

Kernel32Dll.cs
using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct LPSYSTEM_POWER_STATUS {
    public byte ACLineStatus;
    public byte BatteryFlag;
    public byte BatteryLifePercent;
    public byte SystemStatusFlag;
    public uint BatteryLifeTime;
    public uint BatteryFullLifeTime;
}

public class Kernel32Dll {
    [DllImport("Kernel32.dll")]
    private static extern int GetSystemPowerStatus(ref LPSYSTEM_POWER_STATUS lPSYSTEM_POWER_STATUS);

    public static LPSYSTEM_POWER_STATUS GetSystemPowerStatus() {

        var power_status= new LPSYSTEM_POWER_STATUS();

        var result = GetSystemPowerStatus(ref power_status);

        return power_status;

    }
}

このcsharpのソースコードを下のように読み込み実行すると、
Powershellから電源の情報を取得できるようになります。

$src = Get-Content Kernel32Dll.cs -Raw

# C++のDLLをインポート
Add-Type -TypeDefinition $src

# DLL内の関数を呼び出し
[Kernel32Dll]::GetSystemPowerStatus()

モジュールにする場合

モジュールにする場合は下記のようにします。

下記のKernel32dll.csと同じフォルダに入れてください。

GetSystemPowerStatus.ps1
$path = (Split-Path $MyInvocation.MyCommand.Path -Parent)
$src = Get-Content (Join-Path $path Kernel32Dll.cs) -Raw

# C++のDLLをインポート
Add-Type -TypeDefinition $src

function Get-SystemPowerStatus {
    param(
    )

    # DLL内の関数を呼び出し
    [Kernel32Dll]::GetSystemPowerStatus()
}

このモジュールをImportするとGet-SystemPowerStatusから電源の情報を取得できるようになります。

Import-Module path/to/GetSystemPowerStatus.ps1

Get-SystemPowerStatus

まとめ

C++の基礎がわからんとキツイ気もしますが、何とかなることが分かったと思います。
このソースコードはpowershell5系列でも、最新のdotnet core系のPowershellでも正しく動きます。

Discussion