C#からSSISパッケージを実行

#概要
今回はSSISパッケージを実行するための、コマンドは既にMSから提供されたソースもありますので、そこを参考して作成します。

#事前参照資料
・Visual Studio 2019とSSISインストール
参照サイト：https://qiita.com/neomi/items/0472af43f65be6230490

・.NET アプリで C# コードを使用して SSIS パッケージを実行する
https://docs.microsoft.com/ja-jp/sql/integration-services/ssis-quickstart-run-dotnet?view=sql-server-ver15
★新しい Visual Studio プロジェクトの作成、参照の追加を参照してください★

・JP1で実行した場合、30秒で終わってしまう処理を追加するコード参照
http://microsoft-ssis.blogspot.com/2015/05/timeout-after-30-seconds-when-executing.html

・Integrated Logging with the Integration Services Package Log Providers
https://www.mssqltips.com/sqlservertip/4070/integrated-logging-with-the-integration-services-package-log-providers/

・エラーメッセージの出力先および形式
https://software.fujitsu.com/jp/manual/manualfiles/m150000/b1x10203/05z200/b0203-00-05-01-00.html

・SSIS Catalog Logging Tables
https://www.timmitchell.net/post/2017/03/31/ssis-catalog-logging-tables/

#ソースコード
下記のソースをVSにコピーペーストします。
エラーメッセージを取得する処理がまだ未作成です。

※正常に実行のため、VSで下記のパッケージをインストールが必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162336/0a0745f2-d709-8c42-6b0b-66fd08abc1d3.png)

~~~
using Microsoft.SqlServer.Management.IntegrationServices;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SSIS
{
    class Program
    {
        static int Main(string[] args)
        {
            // Variables
            string targetServerName = "localhost";
            string folderName = "IKOU";
            string projectName = "TBL001";
            string packageName = "TBL00101.dtsx";
            IntegrationServices integrationServices = null;
            Catalog catalog = null;
            CatalogFolder folder = null;
            ProjectInfo project = null;
            PackageInfo package = null;
            int returnValue = 1; //0:success, 1:failure
            long opid = 0;

            // Create a connection to the server
            string sqlConnectionString = "Data Source=" + targetServerName +
                ";Initial Catalog=master;Integrated Security=SSPI;";

            using (SqlConnection sqlConnection = new SqlConnection(sqlConnectionString))
            {
                try
                {
                    // Create the Integration Services object
                    integrationServices = new IntegrationServices(sqlConnection);

                    // Get the Integration Services catalog
                    catalog = integrationServices.Catalogs["SSISDB"];

                    // Get the folder
                    if (catalog.Folders.Contains(folderName))
                    {
                        folder = catalog.Folders[folderName];
                        // Get the project
                        if (folder.Projects.Contains(projectName))
                        {
                            project = folder.Projects[projectName];

                            if (project.Packages.Contains(packageName))
                            {
                                // Get the package
                                package = project.Packages[packageName];

                                // Run the package
                                opid = package.Execute(false, null);

                                //★★★★★★★★★★★★★★★★★★★★★★★★★
                                // JP1で実行する際に30秒で終わる処理をこれで解決！
                                //★★★★★★★★★★★★★★★★★★★★★★★★★
                                // Get execution details with the executionIdentifier from the previous step
                                ExecutionOperation executionOperation = integrationServices.Catalogs["SSISDB"].Executions[opid];

                                // Workaround for 30 second timeout:
                                // Loop while the execution is not completed
                                while (!(executionOperation.Completed))
                                {
                                    // Refresh execution info
                                    executionOperation.Refresh();

                                    // Wait 5 seconds before refreshing (we don't want to stress the server)
                                    System.Threading.Thread.Sleep(5000);
                                }
                                //★★★★★★★★★★★★★★★★★★★★★★★★★

                                // ★★★★★★★★★★★★★★★★★★★★★★★★★
                                // 実行したopid結果からパッケージのメッセージログを確認
                                // ★★★★★★★★★★★★★★★★★★★★★★★★★
                                // TODO:パッケージのエラーログをopidキーで抽出する処理を追加

                                // return value
                                returnValue = 0;
                            }
                            else
                            {
                                Console.WriteLine("指定したパッケージは存在しません。");
                            }
                        }
                        else
                        {
                            Console.WriteLine("指定したProject名は存在しません。");
                        }
                    }
                    else
                    {
                        Console.WriteLine("指定したフォルダ名は存在しません。");
                    }
                } catch (Exception ex)
                {
                    Console.WriteLine("SSIS実行が失敗しました。");
                    Console.WriteLine("Error=" + ex.Message);
                }

                // return value
                return returnValue;
            }
        }
    }
}
~~~

#実行結果
ローカルPCにはSSIS環境がないため、エラーが表示されています。
下記の実行結果から異常終了の場合、正しく1の異常終了のステータスを返していることが確認できます。正常終了の場合は、0が表示されます。

~~~
C:\repos\SSIS\SSIS\bin\Debug>SSIS.exe
SSIS実行が失敗しました。
Error=Failed to connect to server localhost.

C:\repos\SSIS\SSIS\bin\Debug>echo %errorlevel%
1
~~~

#終わりに
今回のソースには単純にコンソールにエラーメッセージを表示していますが、
各メッセージをLogファイルに出力すればJP1からエラーの原因を調べる際に良いです。
エラーメッセージをSSIDBのビューから取得処理及びLogファイル作成は未作成ですので、
各自追加してみてください。

※参照資料
・catalog.operation_messages (SSISDB データベース)
https://docs.microsoft.com/ja-jp/sql/integration-services/system-views/catalog-operation-messages-ssisdb-database?view=sql-server-ver15