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

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

ただいまの
回答率

87.96%

Powershell_ISE で作成したクラスが別スクリプト上だとインテリセンスに表示されない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,617

score 172

 前提・実現したいこと

powershellで初めてクラスを作成してみたのですが
メインのスクリプトでクラスが定義してあるスクリプトを読み込んでも
New-object クラス[クラス]のような使い方をしようとしても
インテリセンスに表示されません。
(定義したスクリプト上ではインテリセンスが使える)
クラスの利用自体は問題なくできているのですが
利用時すごく不便です。

今まで作成した関数にクラスを利用したほうが
扱いやすくなるものがいくつかあったので
書き直そうとした矢先にこの問題が発覚したので
困っています。

ご助言をお願い致します。

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

定義したクラスが
別スクリプト上だとインテリセンスが使えない

 該当のソースコード

クラスを定義しているスクリプト

<#
非同期で処理をする
    情報源
        guitarrapc_tech 様
            タイトル : PowerShell による同期処理、非同期処理、並列処理 を考えてみる
            URL : http://tech.guitarrapc.com/entry/2013/10/29/100946

        *** 様
            タイトル : [properties] Powershellクラスはget setプロパティを実装します
            URL : https://code-examples.net/ja/q/25e096e
#>
using namespace  System.Management.Automation.Runspaces;
using namespace System.Collections;
using namespace System.Threading;

# クラスを定義します
class _MultiThread
{

   # ノーマル プロパティ
   [array] $RunspaceCollection

   # 非表示 プロパティ
   hidden [RunspacePool] $runspacePool

   # 完了 プロパティ
   hidden [bool]$_AllCompleted = $($this | Add-Member ScriptProperty -Name 'AllCompleted' -Value {
            $($this.runspaceCollection.RunSpace | sort IsCompleted -Unique).IsCompleted -eq $true
        })

   # コンストラクター
   _MultiThread ($MyHost)
   {
        # create Runspace
        [initialsessionstate] $sessionstate = [initialsessionstate]::CreateDefault()
        [int] $minPoolSize = [int] $maxPoolSize = 5000
        $this.runspacePool = [runspacefactory]::CreateRunspacePool($minPoolSize, $maxPoolSize,  $sessionstate, $MyHost) # create Runspace Pool
        $this.runspacePool.ApartmentState = "STA"
        $this.runspacePool.Open() # open pool
   }

   # スレッドの追加
   [void]AddThread([scriptblock]$ScriptBlock)
   {
        # Main Invokation
        [powershell] $powershell = [PowerShell]::Create().AddScript($ScriptBlock)
        $powershell.RunspacePool = $this.runspacePool
        $this.RunspaceCollection += New-Object -TypeName PSObject -Property @{
            Runspace = $powershell.BeginInvoke();
            powershell = $powershell
        }
        $powershell.Dispose()
   }

   # スレッドの追加
   [void]AddThread([scriptblock]$ScriptBlock,[psobject]$Parameters)
   {
        # Main Invokation
        [powershell] $powershell = [PowerShell]::Create().AddScript($ScriptBlock).AddParameters($Parameters)
        $powershell.RunspacePool = $this.runspacePool
        $this.RunspaceCollection += New-Object -TypeName PSObject -Property $(
            [ordered]@{
                Runspace = $powershell.BeginInvoke();
                powershell = $powershell
            }
        )
   }


   # 結果の取得
   [object]GetResult()
   {
        # get process result and end powershell session
        return $(foreach ($runspace in $this.runspaceCollection)
        {
            # get reuslt
            $runspace.powershell.EndInvoke($runspace.Runspace)
        })
   }

   # デストラクタの代わり手動で実行
   [void]Dispose()
   {
        if (!($this.runspacePool.runspacePool.IsDisposed))
        {
            foreach ($Runspace in $this.RunspaceCollection)
            {
                $Runspace.powershell.Dispose()
            }

            # Dispose Runspace
            $this.runspacePool.Dispose()
        }
   }
}

メイン(利用側)のスクリプト

#ここに大タイトルを記入#

$ErrorActionPreference = "Stop"
$Error.Clear()

try
{
#初期処理#
    if (!($PSScriptRoot -eq ""))
    {
        #カレントディレクトリをスクリプトパスに設定
        Set-Location -Path($PSScriptRoot)
    }
    #ライブラリパスの作成#
    $PSScriptRoot = $(Convert-Path -Path $(Get-Location))
    $Library = "$PSScriptRoot\Library"

    if (Test-Path -Path $Library)
    {
        #登録関数の削除
        Remove-Item Function::_*
        #ソースの取得
        $SFuncs = $($(Get-ChildItem -Path $Library) | where {$_.Extension -eq ".ps1"} | foreach {$(Get-Content -Path $_.FullName) -join "`r`n"})
        #ソースの読み込み
        $SFuncs | foreach {Invoke-Expression $_}
    }
    else
    {
        $PSScriptRoot = ""
        $Library = ""
    }

    if ($(Get-Item function::_*).count -eq 0)
    {

        throw "関数が定義されていません。"
    }

    #ここに処理を描く#
    $Thread = New-Object _MultiThread($host)
    $Block = {
        param
        (
            [parameter(
                mandatory,
                position = 0)]
            [int]
            $Start,

            [parameter(
                mandatory,
                position = 1)]
            [int]
            $End
        )
        [int]$i = 0

        foreach ($item in $Start..$End)
        {
            $i += $item
        }
        return $i

    }
    for ($i = 1; $i -le 10; $i++)
    { 
        $Thread.AddThread(
            $Block,
            [ordered]@{
                Start = 1
                End = $i
            }
        )
    }
    while(!($Thread.AllCompleted)){}
    $Thread.GetResult()
    $Thread.Dispose()
    Remove-Variable Thread
}
catch
{
    Write-Host $Error
    $null = read-host "Enter を押して終了"
}

 試したこと

クラスが定義してあるスクリプトの読み込み

  1. ドットソースによる読み込み
  2. Invoke-Expressionを利用した読み込み (記載のスクリプトはこの方法)

--追記--
「Ctrl + J」押したときに出てくるクラスのテンプレート
のクラス名だけ変えて確認しても
同様の状態になりました。
クラスの処理内容は関係ないようです。

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

メインのスクリプトにて
メインのスクリプトと同じ親フォルダ内にあるSysフォルダを読み込むように
記述してあります。
そのSysフォルダにクラス定義をしているスクリプトをps1で保存していただければ
実行できるはずです。

win 10

Name                           Value
----                           -----
PSVersion                      5.1.17134.228
PSEdition                      Desktop

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

こんばんは。

VSCode PowerShell拡張での類似の例を見る限りドットソースやそれに類する行為でのインテリセンスの有効化は現状無理な様です。

いわんやPowerShell ISEをやというところでしょうか。

そして、あくまで推測ですが、関数だけインテリセンスが効くのは一度F8などでソースを実行すれば関数がセッション中でグローバルに定義済みになるため検索可能になるからと思います。
ただ後から追加されたクラスを検索対象にする方法は現在のPowerShellエンジンに無いのでしょう...

User VoiceやGitHubでIssueを上げることはできますが、個人的には望みは薄いと思いますし、正直諦めるしかないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/19 09:13

    現状は出来ないということが分かったので次へ進めます
    ありがとうございました

    キャンセル

0

何をしても結局どうにもならなかったため
苦肉の策としてインスタンス化だけ関数でくるむことにしました。
関数ならば読み込みしていれば別スクリプトでもインテリセンス使えるので...

Comオブジェクト操作時と同じようにF8等でその関数を実行して変数に結果を格納すれば
とりあえずインテリセンスが使えるようになります。

でもこんな方法しかないのでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る