PowerShellを使ってTwinCATプロジェクトのプログラム更新を行うまで
TwinCATのXAEを使って作ったプロジェクトを、実際の量産装置などに展開する場合、TwinCATの操作を行う必要なくインストールを行いたい。これを実現する方法は以下の通りファイル操作にて行うことができる。
https://beckhoff-jp.github.io/TwinCATHowTo/auto_deploy/index.html
しかし、これだとやはりXAEを経由しないので正しくデプロイできているのか信頼できない、という声をよく聞く。
この代替手段として、Powershellを用いてXAEをリモート操作し、装置にプログラムをダウンロードする処理を自動化する方法を検証してみた。
まず、参考にできそうなサイトから。
このまま実行すると以下のエラーが発生。
PS > .\example.ps1
new-object : CLSID {00000000-0000-0000-0000-000000000000} を含むコンポーネントの COM クラス ファクトリを取得中に、次
のエラーが発生しました: 80040154 クラスが登録されていません (HRESULT からの例外:0x80040154 (REGDB_E_CLASSNOTREG))。
発生場所 C:\Users\Takashii\Documents\develop\TcAutomationInterface\original_example.ps1:4 文字:8
+ $dte = new-object -com VisualStudio.DTE.10.0
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand
:
:
dteオブジェクト生成に失敗しているらしい。Visual StudioのProgram IDについて下記の通り記述があった。
そういえば、私が使っているTwinCATはシェル版。次の通り書き換える。
#$dte = new-object -com VisualStudio.DTE.10.0
$dte = new-object -com TcXaeShell.DTE.15.0
すると今度は下記のようなエラーが。WindowオブジェクトのプロパティVisibleをTrueにしたいだけのようだが、エラーが。キャスト??
指定されたキャストは有効ではありません。
発生場所 C:\Users\Takashii\Documents\develop\TcAutomationInterface\original_example.ps1:10 文字:23
+ ... indow | % { $_.gettype().InvokeMember("Visible", [System.Reflection.B ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidCastException
+ FullyQualifiedErrorId : System.InvalidCastException
エラー原因がgettype()
なのか、InvokeMember()
なのか区別するため、次の通り書き換える。
$window = $dte.MainWindow.gettype()
$dte.MainWindow | % { $window.InvokeMember("Visible", "SetProperty", $null, $dte.MainWindow, $true) }
#$dte.MainWindow | % { $_.gettype().InvokeMember("Visible", [System.Reflection.BindingFlags]::InvokeMethod, $null, $_, $true) }
結果、以下のエラーが。gettype()
が問題らしい。
指定されたキャストは有効ではありません。
発生場所 C:\Users\Takashii\Documents\develop\TcAutomationInterface\original_example.ps1:8 文字:1
+ $window = $dte.MainWindow.gettype()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidCastException
+ FullyQualifiedErrorId : System.InvalidCastException
いろいろググるも原因分からず。ただ、VisibleではないもののちゃんとActiveConfigurationされていてタスクスタートしているので問題なし。
以下の行は無効化だけしておく。どなたか原因わかる方居られましたらアドバイスお願いします。
#$dte.MainWindow | % { $_.gettype().InvokeMember("Visible", [System.Reflection.BindingFlags]::InvokeMethod, $null, $_, $true) }
なお、SolutionプロジェクトにTwinCAT以外のプロジェクト(MeasurementやDatabaseServer等)がぶら下がっている場合、以下の行に与えるItemの要素番号をTwinCATプロジェクトのものに適宜書き換える必要があります。
$project = $sln.Projects.Item(1)
また、通常通りプロジェクトをXAEで開く際に、何か確認ダイアログが出る状況だとうまく構成の更新とスタートができません。
なお、ソースとなるソリューションを配置するフォルダ$prjDir
は絶対パスでないといけないのですが、このスクリプトを実行するディレクトリを起点とした相対パスにする場合、$PSScriptRoot
にて、実行するスクリプトのあるディレクトリが取得できます。例えば以下の例では、スクリプトが有る場所と同じディレクトリ以下にサブディレクトリTestSolution
を作って、そこにソリューションプロジェクトを格納しておくことで、相対パスでプロジェクトの場所を指定する事ができます。
$prjDir = $PSScriptRoot + "\TestSolution\"
$prjName = "TestSolution.sln"
$prjPath = $prjDir += $prjName
$dte = new-object -com TcXaeShell.DTE.15.0
#$dte = new-object -com VisualStudio.DTE.10.0
$dte.SuppressUI = $false
#$dte.MainWindow | % { $_.gettype().InvokeMember("Visible", [System.Reflection.BindingFlags]::InvokeMethod, $null, $_, $true) }
$sln = $dte.Solution
$sln.Open($prjPath)
$project = $sln.Projects.Item(1)
$systemManager = $project.Object
$systemManager.ActivateConfiguration()
$systemManager.StartRestartTwinCAT()