Home > Windows にまつわる e.t.c.

PowerShell での Class 定義分離


PowerShell Class を利用していると、Class の定義と Class を使っているスクリプトを物理的に分けて管理したくなることがあります。

そんな時は、「.」を使って Class を定義した .ps1 を読み込ませると分離することができます。

[class.ps1]

class BaseClass {
    [string] hoge(){
        return "This is Base Class !!"
    }


class SubClass : BaseClass {
    [string] pyo(){
        return "This is Sub Class !!"
    }
}

[main01.ps1]

# include class
. ".\class.ps1"

$TestObject = New-Object SubClass

$TestObject.hoge()

 

PS C:\Temp\Classtest> .\main01.ps1
This is Base Class !!

 

単純分離はこの方法で良いのですが、base class は変更しないので base class を独立分離したいときに、base class が見つからないエラーになってしまいます。

× NG ケース

[NG_base.ps1]

class BaseClass {
    [string] hoge(){
        return "This is Base Class !!"
    }
}

[NG_sub.ps1]

# include base class
. ".\NG_base.ps1"

class SubClass : BaseClass {
    [string] pyo(){
        return "This is Sub Class !!"
    }
}

[NG_main02.ps1]

# include class
. ".\NG_sub.ps1"

$TestObject = New-Object SubClass

$TestObject.hoge()

 

PS C:\Temp\Classtest> .\NG_main02.ps1
発生場所 C:\Temp\Classtest\NG_sub.ps1:4 文字:18
+ class SubClass : BaseClass {
+                  ~~~~~~~~~
型 [BaseClass] が見つかりません。
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : TypeNotFound

New-Object : 型 [SubClass] が見つかりません。この型を含むアセンブリが読み込まれていることを確認してください。
発生場所 C:\Temp\Classtest\NG_main02.ps1:4 文字:15
+ $TestObject = New-Object SubClass
+               ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidType: (:) [New-Object], PSArgumentException
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

null 値の式ではメソッドを呼び出せません。
発生場所 C:\Temp\Classtest\NG_main02.ps1:6 文字:1
+ $TestObject.hoge()
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) []、RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

 

この問題を回避するには、base class を .ps1 ではなく .psm1 にしてモジュール化し、using module で読み込みます。

[base.psm1]

class BaseClass {
    [string] hoge(){
        return "This is Base Class !!"
    }
}

[sub.ps1]

# include base class
using module ".\base.psm1"

class SubClass : BaseClass {
    [string] pyo(){
        return "This is Sub Class !!"
    }
}

[main03.ps1]

# include class
. ".\sub.ps1"

$TestObject = New-Object SubClass

$TestObject.hoge()

 

sub.ps1 を sub.psm1 にして、クラスを使用する .ps1 で using module してもかまわないのですが、using module はコメントを除くスクリプトの先頭に書かなくてはならない制限があるので、そこだけ注意する必要があります。

OK ケース

[main04.ps1]

# include class
using module ".\sub.psm1"

 

× NG ケース

[NG_main04.ps1]

$a = 1

# include class
using module ".\sub.psm1"

 

発生場所 C:\Temp\Classtest\NG_main04.ps1:4 文字:1
+ using module ".\sub.psm1"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
'using' ステートメントは、スクリプト内の他のどのステートメントよりも前に記述する必要があります。
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : UsingMustBeAtStartOfScript

 

 

参考情報

How to Write a PowerShell Script Module(英語)
https://msdn.microsoft.com/en-us/library/dd878340(v=vs.85).aspx

 

関連情報

PowerShell Class
http://www.vwnet.jp/Windows/etc.asp#PowerShell_Class

PowerShell スクリプトで使う「設定」を分離する
http://www.vwnet.jp/Windows/PowerShell/2018013002/SeparateConfig.htm

 

back.gif (1980 バイト)

home.gif (1907 バイト)

Copyright © MURA All rights reserved.