2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Proccess.Start()で起動するけど うまく動作しないとき

Posted at

事の発端

それは TwitterのAPIとPythonとTweepyを使って、使いづらいブックマークを自分用に使いやすくしようとしていた時であった。

TwitterのAPIを使う部分はPythonで、収集したデータを表示するのをC#フォームで作っていた。

C#からPythonスクリプトを起動できないかと思って調べていた。

検索して出てきたコードは以下の通り。

var process = new Process()
{
    StartInfo = new ProcessStartInfo("python.exe")
    {
        UseShellExecute = false,
        RedirectStandardOutput = true,
        Arguments = new string[]
        {
            "Test.py" //,
            //...       コマンドライン引数
        }
    }
};

サイトによって"Python.exe"の部分が絶対パスであったり、いくつかの細かい部分に違いはあれど、基本的に上記のプログラムが書かれていた。

実際この方法で起動してみたものの、一瞬だけPython.exeのプロンプト(?)が表示され、Pythonスクリプトは作動しなかった。

Pythonのコード自体に文法ミスやエラーとなり得るものは無かった。

その後、StartInfoWorkingDirectoryを指定したりpython.exeではなくpy.exe(C:\\Windows\\py.exe)を指定して見たりと、試行錯誤をしたものの全て撃沈。

同じ症状がないかと検索してみたものの、ヒットするものは無かった。

うまく"動作"させるには?

実際、1年かな2年かな、いつだか忘れたが以前にも同じような症状に苦しめられた時があった。

たくさんあったゲームをひとまとめにしようと、ランチャーを作ったことがあった。

その時、某(´・ω・`)鬼畜ゲームをProcess.Startで起動した時に、なぜかリソースが読み込まれなかった。

その時に編み出した方法は、コマンドプロンプトを経由させる方法だった。

結局今回もそれに頼ることにした...。


以前の私はStart.batを手動で用意して、それを起動させるように指定したのだが、今回はバッチファイルを生成して、起動、削除まで自動で行うことにした。

この方法はおそらく良くないだろう... 何かほかの解決策があるなら教えてください。

それでは、アプリケーションの階層が次のようだとする。

📁 TwitterAPI_App
├─ 📄 GetTweet.py (Process.Startで起動したいPythonスクリプト)
├─ 📄 TwitterAPI_Test.exe (アプリケーション)
└─ 📄 TwitterAPI_Test.exe.config

この場合は次のようなコードになる。

Form1.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace TwitterAPI_App
{
    public partial class Form1 : Form
    {
        private void LaunchPython(object sender, EventArgs e)
        {
            // バッチファイルの作成
            string curDict = Directory.GetCurrentDirectory();
            string batfilePath = Path.Combine(curDict, "Start.bat");
            string[] batfileData = new string[2];
            batfileData[0] = "@echo off"; // コマンドプロンプトに結果を表示しないだけなので、任意
            batfileData[1] = "cmd /c start GetTweet.py"; // "cmd /c"は任意
            File.WriteAllLines(batfilePath, batfileData);
            // プロセスの開始
            Process cmd = new Process();
            cmd.StartInfo.UseShellExecute = false;
            cmd.StartInfo.FileName = batfilePath;
            //cmd.StartInfo.CreateNoWindow = true; // 任意
            cmd.Start();
            // 終わるのを待ってからファイルを削除
            cmd.WaitForExit();
            // cmd.Close() // "cmd /c"が無いならおそらく必要
            File.Delete(batfilePath);
        }
    }
}

もう1パターンある。 それはアプリケーションの階層が次のような時だ。
📁 TwitterAPI_App
├─ 📁 TwitterAPI
│   └─ 📄 GetTweet.py (Process.Startで起動したいPythonスクリプト)
├─ 📄 TwitterAPI_Test.exe (アプリケーション)
└─ 📄 TwitterAPI_Test.exe.config

この場合はbatファイルの内容が少しだけ変わる。コードは変わる部分のみを書き記す。

Form1.cs
namespace TwitterAPI_App
{
    public partial class Form1 : Form
    {
        private void LaunchPython(object sender, EventArgs e)
        {
            // ...
            string batfilePath = Path.Combine(curDict, "TwitterAPI", "Start.bat");
            string[] batfileData = new string[3]; // フォルダの数だけ増える
            // string と File.WriteAllText 使う方法もあるけど ここでは省略
            batfileData[0] = "@echo off";
            batfileData[1] = "cd \"TwitterAPI\""; // 必ずしも\"\"で囲む必要は無いが、フォルダ名に空白があるなら必要
            batfileData[2] = "cmd /c start GetTweet.py";
            // ...
        }
    }
}

Start.batをどこに生成しようが、 "cd \"TwitterAPI\""のくだりは必要となる。
(StartInfo.WorkingDirectoryを指定すれば必要がないかもしれないけど)

以上です。


ちなみに`cmd.StartInfo.CreateNoWindow = true;`を指定しても、Pythonのウインドウは絶対開くよ。 ('START'になんらかの引数渡せば何とかなるとは思うけど)
2
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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?