retireSakiの日記

たぶん引退した?ソフトウエアエンジニアのブログ

GTKmm (3.0) と glade によるアプリ (6) - (Qtでも使える)アプリケーションの多重起動の防止 v2

f:id:retireSaki:20181020221243j:plain

 今回は、前回の"GTKmm (3.0) と glade によるアプリ (5) - アプリケーションのアイコンをセット "で作成したプログラムをベースに、アプリケーションの多重起動の防止の改良を行います。

retiresaki.hatenablog.com

 今回改良で、もう少しだけシステム負荷を抑えたいと思います。

 今回、修正したソースは main.cc 内の chk_multiple_startup という関数だけです。

 前回まで
   "ps x | grep %s"
により ps コマンドの結果を grep にて抽出しています。
これだと、2つのコマンドをごく短時間といえ実行しています。

 そこで、以下のように ps コマンド内で完結するようにします。
"ps --no-headers -o '%%c' -C %s"
これにより、%s で指定したコマンドプロセス名のみの結果を取得することができます。

 ps コマンドの引数の説明をしますと、
  "--no-headers" :出力にヘッダーを表示しない
  "-o '%%c'" :プロセスのコマンドのみ出力
  " -C %s" :%s で指定したコマンドプロセスのみを対象

 これにより、ps コマンドのみで処理することができるようになります。
起動されていた場合はプロセスのコマンドと改行コードを出力し、起動されていなかった場合は改行コードのみ出力します。

今回修正したソース main.cc

 今回の変更に伴って、ps コマンドの出力結果の処理ロジックも若干ですが修正していますので確認してください。

#include "MainWindow.h"

Glib::RefPtr<Gtk::Builder> refBuilder;

bool chk_multiple_startup(const gchar *);

/*******************************************************************************
    main
*******************************************************************************/

int main(int argc, char* argv[])
{
    Gtk::Main kit(&argc, &argv);
    
    // multiple startup check
    const gchar *appname = g_get_application_name();
    if (!chk_multiple_startup(appname)){
        std::cout << "this application has already been started :"
                  << appname << std::endl;
        return 1;
    }

    try
    {
        refBuilder=Gtk::Builder::create_from_file("paned_test.glade");
    }
    catch(const Glib::FileError& ex)
    {
        std::cerr << "FileError: " << ex.what() << std::endl;
        return 1;
    }
    catch(const Glib::MarkupError& ex)
    {
        std::cerr << "MarkupError: " << ex.what() << std::endl;
        return 1;
    }
    catch(const Gtk::BuilderError& ex)
    {
        std::cerr << "BuilderError: " << ex.what() << std::endl;
        return 1;
    }

    MainWindow* m_main = nullptr;
    refBuilder->get_widget_derived("mainWindow", m_main);
    if (m_main){

        kit.run(*m_main);

        delete m_main;
        return 0;
    }

    std::cerr << "mainWindow load failed\n" << std::endl;
    delete m_main;
    return 1;
}

bool chk_multiple_startup(const gchar *process_name)
{
    FILE *fp;
    char str[256];
    int  ncnt;

    ncnt=0;
    // sprintf(str,"ps x | grep %s",process_name);
    sprintf(str,"ps --no-headers -o '%%c' -C %s",process_name);
    if ((fp=popen(str,"r"))==NULL)
        return(true);
    while(1){
        if(fgets(str,255,fp)==NULL){
            break;
        }
        if (strlen(str)>1)
            ncnt++;
        if(feof(fp)){
            break;
        }
    }
    pclose(fp);
    if (ncnt>1){
        return(false);
    }
    return(true);
 }

 今回はzipファイルは用意していません。

 簡単でしたね!

 Qt, GTK+ のこんな入門書はいかがでしょうか?

Qtで簡単 GUIプログラミング―Qt入門書を読む前に読む「入門書」

Qtで簡単 GUIプログラミング―Qt入門書を読む前に読む「入門書」

注目記事

「Amazon.co.jpアソシエイト」または「[乙の名称を挿入]は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。