LoginSignup
5
3

More than 5 years have passed since last update.

PowerShellのGetObject相当操作の違い

Posted at

PowerShellではNew-ObjectコマンドレットのComObjectオプションを指定することで新規COMオブジェクトのインスタンスが可能1です。
しかし、状況によっては新規インスタンスではなく、既存のインスタンスを取得したい場合があります。

その場合、

  • Microsoft.Visualbasic 名前空間の Interaction.GetObject メソッド
  • System.Runtime.InteropServices 名前空間の Marshal.GetActiveObject / BindToMoniker メソッド

などを使用することで既存のインスタンスを取得することができます。

実際に試してみる

各方法で、Excelを取得・型名を表示させるスクリプトです。
$xlFileNameには実在するExcelファイルのパスを指定してください。

色々な取得方法
[String]$xlFileName = 'C:\hoge.xlsx'

# New-Object

# キャスト不要
Write-Host "`nNew-Object -ComObject Excel.Application"
[Microsoft.Office.Interop.Excel.ApplicationClass]$xlAppNewObj = New-Object -ComObject Excel.Application
$xlAppNewObj.GetType().FullName
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($xlAppNewObj)>$null #
$xlAppNewObj = $null


# Microsoft.Visualbasic
Add-Type -AssemblyName Microsoft.Visualbasic

Write-Host "`nGetObject('', 'Excel.Application')"
[Microsoft.Office.Interop.Excel.ApplicationClass]$xlAppGetObjCls = [Microsoft.VisualBasic.Interaction]::GetObject('', 'Excel.Application') -as [Microsoft.Office.Interop.Excel.ApplicationClass]
$xlAppGetObjCls.GetType().FullName
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($xlAppGetObjCls)>$null #
$xlAppGetObjCls = $null

# [Microsoft.Office.Interop.Excel.Workbook]へキャスト不可
Write-Host "`nGetObject(`'$xlFileName`', '')"
$xlWbGetObjPath = [Microsoft.VisualBasic.Interaction]::GetObject($xlFileName, '') #-as [Microsoft.Office.Interop.Excel.Workbook]
$xlWbGetObjPath.GetType().FullName
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($xlWbGetObjPath)>$null #
$xlWbGetObjPath = $null


# System.Runtime.InteropServices.Marshal

# [Microsoft.Office.Interop.Excel.ApplicationClass]へキャスト不可
Write-Host "`nGetActiveObject('Excel.Application')"
$xlAppMarshal = [System.Runtime.InteropServices.Marshal]::GetActiveObject('Excel.Application') #-as [Microsoft.Office.Interop.Excel.ApplicationClass]
$xlAppMarshal.GetType().FullName
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($xlAppMarshal)>$null #
$xlAppMarshal = $null

# [Microsoft.Office.Interop.Excel.Workbook]へキャスト不可
Write-Host "`nBindToMoniker(`'$xlFileName`')"
$xlWbMarshal = [System.Runtime.InteropServices.Marshal]::BindToMoniker($xlFileName) #-as [Microsoft.Office.Interop.Excel.Workbook]
$xlWbMarshal.GetType().FullName
[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($xlWbMarshal)>$null #
$xlWbMarshal = $null

私の環境では以下のような結果となりました。

結果
New-Object -ComObject Excel.Application
Microsoft.Office.Interop.Excel.ApplicationClass

GetObject('', 'Excel.Application')
Microsoft.Office.Interop.Excel.ApplicationClass

GetObject('C:\hoge.xlsx', '')
System.__ComObject

GetActiveObject('Excel.Application')
System.__ComObject

BindToMoniker('C:\hoge.xlsx')
System.__ComObject

まとめ?

OfficeのインスタンスをSystem.Runtime.InteropServices.Marshalのメソッドで取得した場合、Office.Interop~型へキャストできない(少なくともPowerShellの -as演算子では)。

またファイル名指定で取得した場合は、キャスト不可。

とりあえず使う分には問題無いけど、型を気にするならMicrosoft.Visualbasicをロードした方が無難。

参考

OfficeのNew-Objectの時の挙動

Office のプロセス インスタンス制御について
Office オートメーション サーバーの GetObject および CreateObject の動作

メソッド

Marshal.GetActiveObject メソッド (String)
Marshal.BindToMoniker メソッド (String)

他参考サイト

C# 4.0 からの dynamic 型を使った Excel 操作 [プログラム(全般)]

関連(宣伝)

GetObject(, "Excel~")だけで無く、GetObject(ファイル名)も活用しよう
GetObject('パス', '')やBindToMonikerメソッドは状況によっては便利。


  1. 一部COMオブジェクトは既存インスタンスを再利用します(例:PowerPoint)。 

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3