[PowerShell] クラスのメソッド内からAdd-Typeで追加したクラスを呼び出す方法

このQ&Aのポイント
  • Win10、PowerShellでアプリの作成を行っています。Add-Typeで追加したクラスを使用することが出来ず困っています。クラスのメソッドからAdd-Typeで追加したクラスを呼び出す方法を教えてください。
  • メソッドの中からAdd-Typeで追加したクラスを呼び出すにはどうすればよいでしょうか。グローバルなファンクションを別途用意せずに、メソッド内から直接呼び出す方法を教えてください。
  • PowerShellのメソッド内からAdd-Typeで追加したクラスを呼び出す方法がわかりません。応用できる方法を教えていただけないでしょうか。
回答を見る
  • ベストアンサー

[PowerShell] メソッド内からの呼び出し

お世話になります。 Win10、PowerShellでアプリの作成を行っています。 アセンブリ追加したクラスを使用したいのですが、Add-Typeで追加したクラスを使用することが出来ず困っております。 ■成功例 Add-Type -Assembly System.Windows.Forms [System.Windows.Forms.MessageBox]::Show("めっせーじ!") # → これだと期待通りにメッセージダイアログが表示されます。 ■失敗例 Add-Type -Assembly System.Windows.Forms class ClsTest {  exec() {   [System.Windows.Forms.MessageBox]::Show("めっせーじ!")  } } $obj = New-Object ClsTest $obj.exec() # → クラスのメソッドに入れた途端、[System.Windows.Forms.MessageBox]が見つかりません、と言うエラーが発生します メソッドの中から期待通りに呼び出すには、どうすればよろしいでしょうか。 なお、当該部分を内包したグローバルなファンクションを別途用意し、それをメソッドから呼び出す方法は無しでお願いします。 うまく行くことは確認していますが、実際にはもっと複雑な処理を複数のクラスを使って行いたいため、応用できませんでした。 以上、なにとぞご教示のほどよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • ballville
  • ベストアンサー率47% (233/487)
回答No.2

当方でも確認できました。 問題は、add-typeによる読み込みより先に、クラス定義がなされてしまうことにあるようです。ですので、スクリプト名が test.ps1だとすれば <コマンドプロンプト(実行ポリシーは設定されているものとします)> powershell -command "add-type -assembly system.windows.forms; test.ps1" とやれば、正常に表示されます(スクリプト側でのadd-typeは不要)。 しかし、add-typeを先に実行しようとして add-type -assembly system.windows.forms sleep 1 class~以下略 とやっても無意味です。ps1ファイルの読み込みと同時にクラス定義されてしまうようです。 ですが、スクリプトを Add-Type -Assembly System.Windows.Forms invoke-expression @" class ClsTest {  exec() {   [System.Windows.Forms.MessageBox]::Show("めっせーじ!")  } } "@ $obj = New-Object ClsTest $obj.exec() とすればさすがに読み込み時にクラス定義されないのでうまくいきます。

sasaki1985
質問者

お礼

回答ありがとうございます。 > 問題は、add-typeによる読み込みより先に、クラス定義がなされてしまうことにあるようです。 そう言う事でしたか……/(^o^)\ナンテコッタイ 先述の通りfunctionなら動作したので、classをfunctionで包んでみたらワンチャン……とも思ったんですが、しっかりガードされました。 どうもスクリプト全体からクラス定義を先行してパースしてるくさいですね。なんでこんな造りになっているんだろう…… ご提案頂いた手法、両方とも選択を戸惑う類のものでしたが、無い袖は振れないので前者のアプローチを採用いたしました。 アセンブリ追加&インスタンス生成部分とクラス定義部分にファイルを分けて、前者から後者を読み込むようにしてようやっとクリア。 大変助かりました。 ご協力、どうもありがとうございました!

その他の回答 (1)

  • ballville
  • ベストアンサー率47% (233/487)
回答No.1

失敗例とありますが貼り付けたら通常通りメッセージボックスが出力されましたよ。 動作環境を詳しく提示したほうがいいと思います。 正常動作した当方の環境は $psversiontable.psversion Major Minor Build Revision ----- ----- ----- -------- 5 1 18362 145 windows 10 pro 1903

sasaki1985
質問者

お礼

回答ありがとうございます 情報が足りず申し訳ありません。 psバージョンは5.1.17763.592でwin10pro1809になります。 Windows powershell ISE を使用してデバッグ実行するとうまく行くのですが、 コマンドプロンプトから powershell -ExcutionPolisy RemoteSigned -File Ps1ファイル と言う形で呼び出すとエラーになってしまいます。 ※スマホからの打ち込みのため、細かい誤字等があったら見逃してください……

関連するQ&A

  • C#の継承関係。

    すこし、疑問におもい質問いたします。 以下のようなコードなのですが using System; using System.Windows.Forms; public class MainClass{ public static void Main (){ Test01 obj01 , obj02; Test02 obj03 , obj04; obj01= new Test01(); obj01.method01(); obj03 = new Test02(); obj03.method02(); try{ obj02 = (Test01)obj03;(1) //obj02.methodp();(2) obj04 = (Test02)obj01;(3) }catch(Exception e){ MessageBox.Show(e.Message); } } } public class Test01{ public void method01(){ MessageBox.Show("スーパークラスメソッド"); } private void methodp (){ MessageBox.Show("スーパークラスプライベートメソッド"); } } public class Test02 : Test01{ public void method02(){ MessageBox.Show("サブクラスメソッド"); } } まず(1)の箇所ですが、これはTest02というTest01のクラスを継承したサブクラスを Test01という親クラスにキャストしてます。 これは、問題なく動いているようです。 ただ、その下の(2)の箇所でキャストしたインスタンスから親クラスのプライベートメソッドにアクセスしようとしたらコンパイル時にエラーとなりました。 サブクラスを親クラスにしても親クラスのプライベートメソッドって使えないのでしょうか?であれば親クラスへのキャストって何のためにあるのでしょうか? 次に(3)の箇所ですが、これはTest01という親クラスをTest02という子クラスにキャストしようとしていますが、どうも、親クラスから子クラスへキャストできないといいう例外が 発生するようです。 これはなぜなのでしょうか? 以上の点でご教授いただけませんでしょうか? よろしくお願いします。

  • DataGridViewのRowsにメソッド追加

    VB2013で、DataGridViewのRowsコレクションに独自のメソッドを追加することは可能でしょうか。 Inherits System.Windows.Forms.DataGridViewで継承してメソッドを追加するだけでは DataGridView.XXXといった形式になってしまうので・・・。 よろしくお願いいたします。

  • 別クラスのメソッドの呼び出し

    どうしても期待した値が取れず、バイナリが返ってきてしまいます。 簡単な内容なので申し訳ないのですが書き方を教えて下さい。 下記内容です。↓ クラス01にmainメソッドを作成。 そこに「一」「二」「三」を格納する変数を宣言。 クラス02にpublic以外のメソッドを作成。 そこで「一」「二」「三」を引数として受け取り、その3つを「+」以外で文字列連結する。 クラス01のmainメソッドから、クラス02のメソッドを呼び出し、最後にSystem.out.printlnで戻ってきた文字列を出力。 ソース貼っておらず申し訳ないのですが宜しくお願いします。

    • ベストアンサー
    • Java
  • MessageBoxを継承したい

    C#2.0を使用しています。 MessageBoxを継承して拡張させたいと思い、MessageBoxExなるクラスで 次のように記述したのですが public class MessageBoxEx : System.Windows.Forms.MessageBox { } 型 'System.Windows.Forms.MessageBox' のコンストラクタが定義されていません。 というエラーが出てしまいます・・・ これはどういうことなのでしょうか? コンストラクタが定義されてないクラスは継承できないのでしょうか?

  • メソッドのオーバーライド(java)

    class A3{ void hello(){ System.out.println("A3"); } void hello(int i){ System.out.println("A3"+i); } } class B3 extends A3{ void hello(){ System.out.println("B3"); } } class C3 extends B3{ void hello(String s){ System.out.println("C3"+s); } } class MethodOverriding3{ public static void main(String args[]){ A3 obj = new C3(); obj.hello(); } } 上のプログラムを実行すると"B3"と表示されまが、どうしてクラスBのメソッドが実行されるのでしょうか? クラスAのメソッドが無視される仕組みがわかりません。 また、クラスMethodOverriding3でobj.hello("abc")としてコンパイルすると mo.java:25: シンボルを見つけられません。 シンボル: メソッド hello(java.lang.String) 場所 : A3 の クラス obj.hello("abc");   ^ エラー 1 個 とエラーが出ます。 どうしてでしょうか? 誰か教えてください、お願いします。

    • ベストアンサー
    • Java
  • 親クラスと子クラスのフィールドとメソッドについて

    親クラスと子クラスのフィールドとメソッドについて 以下のサンプルソースを実行した時の動作の原理について 教えてください。 oya型変数にkoクラスのインスタンスを作成した場合、 メソッドはkoクラスのものなのに、 フィールドはoyaクラスのものになるということが イマイチすっきり理解できません。 どういうことなんでしょうか。 ------------------------------------------------------- [ソース] public class exec { public static void main( String args[]){ oya obj = new ko(); System.out.println(obj.str_field); obj.disp_field(); } } public class oya{ String str_field="親実行"; public void disp_field(){ System.out.println(str_field); } } public class ko extends oya { String str_field = "子実行"; public void disp_field(){ System.out.println(str_field); } } ------------------------------------------------------- [実行結果] > 親実行 > 子実行 -------------------------------------------------------

    • ベストアンサー
    • Java
  • voidの性質や使い方、showメソッドについて

    1ファイル1クラスの原則に反しますが、敢えて1ファイルに2クラスあるプログラムにおいて、voidの性質や使い方、showメソッド等について教えてほしいです。 ファイル名はStart.javaです。 --------------------------------- package sample; class Cat { String name; int age; void show(String name,int age) { System.out.println("名前は" + name + "です"); System.out.println("年齢は" + age + "歳です"); } } public class Start { public static void main(String[] args) { Cat cat1 = new Cat(); cat1.name = "太郎"; cat1.age = 28; cat1.show(); } } --------------------------------- 「cat1.show();」のところでエラーが出ていますが、Eclipseでそのまま実行してみますと。 ~~~~~~~~~~~~~~~~~~~ Exception in thread "main" java.lang.Error: Unresolved compilation problem: 型 Cat のメソッド show(String, int) は引数 () に適用できません at sample.Start.main(Start.java:16) ~~~~~~~~~~~~~~~~~~~ といったエラーが出てきます。しかし、Catクラスの「void show(String name,int age) 」の箇所を「void show() 」のように、Startクラスと同じく引数の中身を空にしますと。 |||||||| 名前は太郎です 年齢は28歳です |||||||| と、正しい結果が出力されたのです。 最初のプログラムは、Catクラスのshowメソッドには引数があり、Startメソッドのshowメソッドには引数が無い状態でした。 修正したプログラムでは、どちらのクラスのshowメソッドにも引数はありませんでした。 最初のプログラムでも、mainメソッドを実行して、nameとageに値を格納して、showメソッドでCatクラスの方で定義したshowメソッドを呼び出すといった流れで、正しい値は出るはずだと自分は考えたのですが。 なぜエラーになってしまったのか、どうして2つのクラスのshowメソッドの引数が空だとうまく結果が出力されたかにつきまして、お教えいただけないでしょうか。 よろしくお願い致します。 ※OKWAVEより補足:「Webシステム開発」についての質問です。

    • ベストアンサー
    • Java
  • C#のビルド方法について質問です。

    IDEをつかわず、コマンドプロンプト上でC#のソースをビルドする時の方法について質問です。 まず以下のようなコードがあるとします。 まずC:\の直下に以下のソースを作成しました。 =================================================== using System; using System.IO; using System.Windows.Forms; namespace Add.TestClass{ public class LibraryClass{ public LibraryClass(){ MessageBox.Show("クラスライブラリコンストラクタの実行"); } } } =================================================== 上記クラスをdllファイルとしてビルドします。 csc /t:library /out:Add.TestClass library.class  と上記のようにビルドしました。するとAdd.TestClass.dllというファイルが確かにできあがりました。 次にこれを実際に実行するためのファイルをつくりました。 それが以下になります。 同じくC:\直下に以下のようなソースを作成します。 =================================================== using System; using System.IO; using System.Windows.Forms; using Add.TestClass; public class MainClass{ public static void Main(String [] args){ LibraryClass obj = new LibraryClass(); } } =================================================== このファイルをビルドします。 csc /r:Add.TestClass.dll main.cs としてビルドし、その後 mainというファイルを実行しました。 するとキチンとMessageBoxで MessageBox.Show("クラスライブラリコンストラクタの実行");が実行されました。 ここまでは問題ないのですが、この場合 main.exeファイルとAdd.TestClass.dllというファイルが 同じ階層に存在するような状態になっているのですが、これを main.exeファイルのある階層にdllというディレクトリを作成し そのdllの中にAdd.TestClass.dllというファイルをおいた階層状況でmain.exeファイルを実行したいのです。 そのためにまず、 csc /r:”C:\dll\Add.TestClass.dll" main.cs 上記のようなビルドオプションでビルドしてみたのですが、ビルドはとおりましたが -------------------------------------------------------------------------------------------------------------------- ハンドルされていない例外: System.IO.FileNotFoundException: ファイルまたはアセン ブリ 'Add.TestClass, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'、ま たはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりませ ん。 場所 MainClass.Main(String[] args) -------------------------------------------------------------------------------------------------------------------- というエラーがでました。 このdllファイルを特定の任意のディレクトリ内において、main.exeを実行してうまく動くようにするためには どのようなビルドオプションをつけたらいいのでしょうか? よろしくご教授お願いいたしま。

  • [C#]FormクラスのShowメソッドの挙動について

    C#のSystem.Windows.Forms.FormクラスのShowメソッドについて調べています。 Showメソッドを使うことで、モードレスでフォームを表示できます。 http://msdn2.microsoft.com/ja-jp/library/39wcs2dh.aspx 例えば、ボタンがクリックされたときに、モードレスでフォームを表示する場合は、以下のようになると思います。 // ボタンがクリックされたときにコールされるメソッド private void button1_Click(object sender, EventArgs e) { MyForm form = new MyForm(); // MyFormはFormの継承クラス form.Show(); } このとき、button1_Clickメソッドが終了しても、 つまり、変数formのスコープから処理が外れても、MyFormは表示され続けます。 別スレッドで表示しているのかと思いましたが、MyFormを表示してもスレッド数は変わりませんでした。 なぜ、変数formのスコープから処理が外れても、MyFormが表示され続けるのかわかりません。 どなたかご存知の方がいらっしゃいましたら、ご教授いただけると幸いです。 環境 : WindowsXP SP2, .NET Framework 2.0, Visual Studio 2005

  • メソッドの処理の同期化

    いつもお世話になっています。 メソッド処理の同期化についてなのですが、 いろいろ調べてみたのですが、いまいちうまく実行できません。 ソースを考えてみたのですが、どこがどう悪いのかご指摘お願いできますでしょうか? 以下のクラスがある場合で public void Add(){ synchronized(this){ System.out.println("待機しています!"); //おそらくここら辺にwait()/notify()処理が来るきがする //同期中に行わない処理をここに記載する? } System.out.println("Addメソッド実行しました"): } public void Change(){ synchronized(this) { //おそらくここら辺にwait()/notify()処理が来るきがする //同期中に行わない処理をここに記載する? //一時停止 処理時間をずらすためループを使用 try { for(int a=0;a<3;a++){ System.out.println("a="+a); Thread.sleep(10000); } }catch (InterruptedException e) { } System.out.println("Changeメソッド完了です"); } } このとき、Add対Change/Add対Addといった形で同期化処理をしたいのですが、どうしてもうまくできません。 仮にThreadを使用して実行してみようとしたのですが、 順番に実行されてしまいます。 したいのが、 1.Addメソッド実行 2・Addメソッド実行 この場合、現状だと a=0 a=0 a=1 a=1 a=2 a=2  と表示されてしまうので、 a=0 a=1 a=2 a=0 a=1 a=2  と表示することはできるのでしょうか? 原因として、wait()/notify()が記載されていないことが影響していると思うのですが。 宜しくお願いします。