.NETでエクセルを制御しようとして沼った話②

はじめに

前回の続きです
今回は前回と違いCOMに苦しめられました

動かない

前回のカス同然のミスも修正し、本番環境で実際に動作させて問題無かったので、そのままリリースした
ただ毎日動作させる用途のソフトなのに一々手動で実行させる訳にもいかないので、タスクスケジューラで操作させることにしている

だがリリース翌日動作の確認を行ったら、何故かソフトが動作していなかった
原因究明の為、エラーログを見てみると・・・

CLSID {00024500-0000-0000-C000-000000000046} を含むコンポーネントの COM クラス ファクトリを取得中に、次のエラーが発生しました: 80080005 サーバーの実行に失敗しました (HRESULT からの例外:0x80080005 (CO_E_SERVER_EXEC_FAILURE))。
   場所 System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType objectType)
   場所 System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(RuntimeType serverType)
   場所 System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(RuntimeType serverType, Object[] props, Boolean bNewObj)
   場所 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   場所 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   場所 System.Activator.CreateInstance(Type type, Boolean nonPublic)
   場所 System.Activator.CreateInstance(Type type)
   場所 ソフト.ExcelClass.Open(ExcelPath) 場所 C:\"省略"\ソフト\ExcelClass.vb:行 ○○
   場所 ソフト.MainModule.Main() 場所 C:\"省略"\ソフト\MainModule.vb:行 ○○

またCOMエラーかよ・・・
しかも、
Main.vb

    Sub Main()
        Using KanriExcel As New ExcelClass(ExcelPath) '⇐ここでエラー
            DataRead(KanriExcel)
            DataAdd(KanriExcel)
        End Using
    End Sub

ExcelClass.vb

    Private disposedValue As Boolean

    Private Property ExcelApp As Application
    Private Property ExcelBook As Workbook
    Private Property Savepath As String
    Private Property NewBookThen As Boolean
    Private Property ExcelSheets As List(Of Worksheet)

    Friend Sub New(ExcelPath As String)
        Open(ExcelPath As String)
    End Sub

    Friend Sub Open(ExcelPath As String)
        'ここでエラー
        ExcelApp = New Application With {
            .Visible = False
        }
    End Sub

で落ちてるからエクセル起動時(COMオープン時)に死んでますので明らかにプログラム以外の要因が絡んでそうなバグ*1ですね、はい
自分は「寧ろ前回みたいな凡ミスであってくれ」と思いながら検証していました

解決

EXEから直接開くと動くので、タスクスケジューラで実行して検証した
タスクスケジューラのデフォルト設定*2だと動く事が確認できたが、本番環境だと色々設定を弄っているのでその設定に合わせると、全く同じエラーを確認できました
その設定が・・・
f:id:CT_murasaki:20220304195951j:plain
結局の所、「ユーザーがログオンしているかどうかにかかわらず実行する」を有効にしたのが原因でした

何故こうなったのか

原因は、タスクスケジューラを舐めていた事です

「タスクスケジューラって結局自動的にexeファイルとかを指定時間に開いてくれるやつでしょ?w」

としか思っておらず、「ユーザーがログオンしているかどうかにかかわらず実行する」を有効にした理由も、

「ログオンしてなくてもこの設定をオンにすれば動作するでしょ」

と考えて検証すら行わなかったのが問題でした
そもそも常時ログオンするPCなのでそこを気にする必要も無かったのに「念のため」ってことでやったことが完全に裏目りました

結局、「ユーザーがログオンしているかどうかにかかわらず実行する」を有効にして動作させるには、非対話的ログオンで実行し無いといけなかったみたいですね*3
まぁ上述の様にそもそもそこまでする意味が無いので試して無いですが・・・*4

参考元↓
gagaj.hateblo.jp

まとめ

・タスクマネージャーは思っているよりも複雑
・「ユーザーがログオンしているかどうかにかかわらず実行する」は無対策だと大概バグる*5

あとがき

COM(Microsoft Office Excel 16.0 Object Library)がかなり不安定でどえらい苦労しましたorz
色々な要因で渋ってたけど、別の人の作ったソフトはClosedXML使っていたし*6自分もCOM見限ってそっちにするかと思いました(小並)

*1:まぁ前回もそんなこと考えていたのだが

*2:動作トリガーとパスの設定をしただけ

*3:なおマイクロソフトは推奨もサポートもしていない模様

*4:あと自分以外のPCを不必要に弄りたくない

*5:ググったら色んなバグ報告や質問が出てきた

*6:しかも「ユーザーがログオンしているかどうかにかかわらず実行する」を有効にしていても普通に動作していた