質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Framework

Frameworkは、アプリケーションソフトを開発する際に、一般的な機能をより簡単に、より早く完了させる事を目的とした、ソフトウェアやライブラリのセットを指します。開発にフレームワークを使用する事で、追加で必要となる機能だけを開発するだけで済む為、開発効率の向上が見込めます。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Q&A

解決済

1回答

1957閲覧

New-Module と Export-ModuleMembet がどういうものか教えてください。

kamikazelight

総合スコア305

Framework

Frameworkは、アプリケーションソフトを開発する際に、一般的な機能をより簡単に、より早く完了させる事を目的とした、ソフトウェアやライブラリのセットを指します。開発にフレームワークを使用する事で、追加で必要となる機能だけを開発するだけで済む為、開発効率の向上が見込めます。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

0グッド

0クリップ

投稿2019/01/16 23:57

編集2019/01/18 01:37

--追記--

imihito様より 「自分の環境でもISEからはエラーは出ないですね」との情報を頂いたので別PCで確認を取ったところそちらのPCではエラーは出ませんでした。
1/18 時間があれば再度 該当PCにて検証したいと思います。
検証した結果エラーは出なくなっていました。

前提・実現したいこと

前回の質問でimihito様に頂いたコードの中に
New-ModuleExport-ModuleMembet が使われているのですが
どういうものだかよくわかりません。
公式のヘルプを見たのですがそれでもわかりません。

触ってみてカプセル化のようなものだと検討をつけて
試に 頂いたコードを書き換えて タイマーをスクリプトブロック内に入れて
みたのですが
動作的には正しく動くのですがエラーが頻発します。

New-ModuleExport-ModuleMembetの正しい使い方、及び挙動と
何故 該当のソースコードの内容でエラーが出てしまうのか教えて頂きたいです。
お願い致します。

発生している問題・エラーメッセージ

"Opacity" の設定中に例外が発生しました: "破棄されたオブジェクトにアクセスできません。 オブジェクト名 'Form' です。" 発生場所 D:\Users\Desktop\Formサンプル.ps1:60 文字:13 + $mainForm.Opacity = $newOpacity + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], SetValueInvocationException + FullyQualifiedErrorId : ExceptionWhenSetting

該当のソースコード

powershell

1using namespace System.Windows.Forms 2using namespace System.Drawing 3 4Set-StrictMode -Version Latest 5 6[scriptblock]$_Get_Form = { 7 #フォームの作成 8 [Form]$Form = 9 New-Object -TypeName Form -Property @{ 10 Width = 600 11 Height = 300 12 Opacity = 0.1 13 Text = 'Test' 14 TopMost = $true 15 } 16 17 #データグリッドビューの作成 18 [string[]]$ListName = @('test1', 'test2') 19 [DataGridView[]]$List = 20 $ListName | 21 ForEach-Object -Process { 22 # 共通の設定は生成時に`-Property`で設定 23 New-Object -TypeName DataGridView -Property @{ 24 AutoSizeColumnsMode = [DataGridViewAutoSizeColumnsMode]::AllCells 25 AutoSizeRowsMode = [DataGridViewAutoSizeColumnsMode]::AllCells 26 Name = 'List_{0}' -f $_ 27 Dock = [DockStyle]::Fill 28 } 29 } 30 #$List[0].Add_SelectionChanged($_ListNowUp) 31 $List[0].MultiSelect = $false 32 #$List[1].Columns[0].DefaultCellStyle.WrapMode = [DataGridViewTriState]::True 33 34 [SplitContainer]$SplitContainer = [SplitContainer]::new() 35 $SplitContainer.Panel1.Controls.Add($List[0]) 36 $SplitContainer.Panel2.Controls.Add($List[1]) 37 $SplitContainer.Name = "SplitContainer_1" 38 $Form.Controls.Add($SplitContainer) 39 40 [Timer]$mouseMonitor = 41 New-Object -TypeName Timer -Property @{ 42 Interval = 50 43 Enabled = $true 44 Tag = $Form 45 } 46 $X = 1 # こちらの$XをAとする 47 $mouseMonitor.add_Tick({ 48 Write-host $X # Aの$Xの値が出力される 49 [Form]$mainForm = $Form # [Form]::ActiveForm 50 51 # タイトルバー含めたフォームの大きさは`Bounds`から、 52 # マウスの位置は`[Cursor]::Position`から取得できるため 53 # フォームの中に、マウスが入っているかどうかで確認 54 [Double]$newOpacity = 55 if ($mainForm.Bounds.Contains([Cursor]::Position)) { 56 1 57 } else { 58 0.1 59 } 60 61 if ($mainForm.Opacity -ne $newOpacity) { # 負荷軽減のため(意味があるか未確認) 62 $mainForm.Opacity = $newOpacity 63 } 64 $Script:X += 10 # Aの$Xの値が加算される 2回目以降の実行結果から値が保持されていることが確認できる 65 }) 66 67 Export-ModuleMember -Variable Form, mouseMonitor, List 68} 69 70# `Export-ModuleMember`で設定した要素(Form, List)をメンバーとして持つPSCustomObjectを生成($Scirpt:~を避けたかったため) 71[psobject]$formContainer = New-Module -AsCustomObject -ScriptBlock $_Get_Form 72 73# タイマーの生成 74$X = 2 # こちらの$XをBとする 75$formContainer.mouseMonitor.Start() 76$formContainer.Form.ShowDialog() > $null 77$formContainer.Form.Dispose() 78$formContainer.mouseMonitor.Dispose() # Formとの紐付けが無いため、忘れないように

補足情報(FW/ツールのバージョンなど)

Win10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まずはじめに。トリッキーなコードを書いてしまい、混乱させてしまったようですみません。

New-Module -AsCustomObject ~の使い方は一般的な使い方では無いため、基本のモジュールの話から簡単に書いておきます。

about_Modules | Microsoft Docs
about_Modules 非公式?日本語版

PowerShell のモジュール詳解とモジュールへのコマンドレット配置手法を考える - tech.guitarrapc.cóm

VBAを触っていらっしゃっているのでVBAの概念で例えると、標準モジュールがイメージにもっとも近いです。
任意の変数・関数を格納でき、必要に応じてそれらを外部に公開できるものです。

PowerShellのモジュールの場合、動的なロード・アンロード、引数を渡しての初期化なども行えますが、通常使う分には上記のようなイメージです。

中の変数・関数のうち、「何を公開するか」の指定に使用するのが、質問の一つであるExport-ModuleMemberです。


PowerShellのモジュールは、通常は$env:PSModulePath以下にフォルダとして配置します。
フォルダ名がモジュール名となり、フォルダの中に「モジュール名.psm1」や「モジュール名.psd1」といったファイルを配置することでモジュールとして読み込めるようになります。

質問のもう一つであるNew-Moduleは、ファイルとしてのスクリプトの代わりにスクリプトブロックを読み込んで、動的にモジュールを生成するものです。


普通に読み込んだモジュールはExport-ModuleMemberで指定された変数・関数を公開するだけです。
しかし-AsCustomObjectスイッチを設定することで、指定された変数・関数をメンバーとして持つPSCustomObjectを生成します。
これもVBAに例えると、標準モジュールのコードをクラスモジュールに書いてインスタンスできるようにした、というイメージです。

前回の質問では、
変数のスコープがややわかりにくい、などの理由から、スコープを切り分けたい・カプセル化したいと考えました。

その方法として、クラスなどいくつか候補がありましたが、処理がスクリプトブロックの形でまとまっていたため、比較的変更量が少ないNew-Module -AsCustomObjectを使用した、ということになります。

New-Module自体はモジュールを生成するためのものであるため、そのあたりでどうしてもトリッキーな書き方となってしまいました。

投稿2019/01/17 14:13

imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamikazelight

2019/01/18 03:01

変数の中に変数や関数などを格納できるところに魅力を感じていたのですが その場合は Classを使った方がいいでしょうか? 今までは ClassA.ps1 に ClassA を記載して Main.ps1 でClassAのインスタンスを作成しようとしたときに 事前にドットソースで読み込んでもインテリセンスが効かず 苦肉の策でClassA.ps1にClassAのインスタンスを作成する関数を記載して Main.ps1でその関数を呼び出して使ったりとかだったのでClassを極力避けていたのですが 今回の件で考えなおしてみたらClassA.ps1をClassAのインスタンスを返すようにしてしまえば Static とかは意味がなくなってしまいますが 変数の中に変数や関数などを格納したいという目的は達成できそうです。 ですがこれも一般的な使い方から外れていると思うのですが こういった場合は Class と New-Module どちらを使った方が見やすい(扱いやすい)と思いますか?
imihito

2019/01/18 11:59

New-ModuleはPowerShell v2からありましたが、その上でPowerShell v5でクラス構文が追加されました。という事でクラスの方が良いと思われます。 PowerShell v5はあまり使ったことがありませんが、`using module モジュール名`でモジュール内のクラスのインテリセンスは効きそうですね
kamikazelight

2019/01/19 00:43 編集

インテリセンスが効かないと思っていたのですが そういうことだったのですね 試してみます。 しばらくはクラスを使ってみることにします。 今回も ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問