1

私のコードは以前はAllocConsole次のように使用していました:

AllocConsole();
var arg = Console.ReadLine();
// do stuff with arg

そしてそれはうまく機能していました。MyApp.exeただし、コンソールからアプリケーションを起動すると ( CMD ウィンドウで実行するなど)、新しいコンソール インスタンスが作成されるという事実が気に入らなかったため、次のように変更AllocConsoleしました。

if(!AttachConsole(-1))
    AllocConsole();

出力は引き続きコンソールに出力されますが、「Enter」を押すと、奇妙なことが起こります。 実行中のアプリケーション

画像ではわかりにくいかもしれませんが、実際にアプリケーションを実行しました。次に、使用方法に関する数行を出力し、入力を求めます ("Action [run|install|uninstall|quit]")。「実行」と書いてEnterキーを押しましたが、コンソールはアプリケーションではなくCMDに入力を向けています。そのため、アプリケーションがまだ実行されている間は、入力が得られません。これは、最後に を使用して Linux でアプリケーションを実行するのに少し似ています&

アプリケーションを起動した CMD ウィンドウからアプリケーションに入力を取得させる方法はありますか?

[編集] 完全なコード:

#region Custom Launching Helpers (for when not launced as a service)

private enum Action
{
    Run,
    Install,
    Uninstall
}

private static string PrintUsage()
{
    Console.WriteLine("Usage: <application-name> [run|install|uninstall]");
    Console.WriteLine("Use run to run a single itteration of the program.");
    Console.WriteLine("Use install to install the service.");
    Console.WriteLine("Use uninstall to uninstall the service.");
    Console.Write("Action [run|install|uninstall|quit]: ");
    return Console.ReadLine();
}

[DllImport("kernel32.dll")]
private static extern bool AttachConsole(int dwProcessId);

[DllImport("kernel32.dll")]
private static extern bool AllocConsole();

[DllImport("kernel32.dll")]
private static extern bool FreeConsole();

[DllImport("kernel32.dll")]
private static extern bool SetConsoleTitle(String lpConsoleTitle);

private static void RequireConsole()
{
    if (!AttachConsole(-1))
        AllocConsole();
}

#endregion


/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
    // Environment.UserInteractive will be true when launced as a normal application
    // (for instance by double-clicking, or running form a cmd-prompt).
    // 
    // Services can't run this way, thus we present the user with a menu (if no spesific action
    // was passed allong as a startup-parameter) that enables the user either to run a single
    // itteration, or to install/uninstall the service.
    if (Environment.UserInteractive)
    {
        try
        {
            // open a console
            // since AssemblyService isn't a console-application, one must be crated explicitly.
            RequireConsole();
            SetConsoleTitle("AssemblyService 2");
            Action action;

            // If no command-line arguments are provided, print usage
            // and enable the user to input an argument while running.
            var arg = args.Length == 0 ? PrintUsage() : args[0];

            while (true)
            {
                switch (arg)
                {
                    case "run":
                        action = Action.Run;
                        goto execute;

                    case "install":
                        action = Action.Install;
                        goto execute;

                    case "uninstall":
                        action = Action.Uninstall;
                        goto execute;

                    case "quit":
                        return;

                    default:
                        // If the argument is invalid, keep asking the user
                        // untill a valid argument is given.
                        arg = PrintUsage();
                        Console.WriteLine("Got arg: {0}", arg);
                        break;
                }
            }

        execute:
            ; // empty statement so it compiles
            // unimportant, does stuff;
        }
        finally
        {
            // Release the console.
            Console.WriteLine();
            FreeConsole();
        }
    }
    else
    {
        // Run as service (only in non-interactive session).
        //ServiceBase.Run(new AssemblyService());
        // rather just exit
    }
}

[編集2] 以下を追加してみました:

var inputHandle = GetStdHandle((int) StdHandle.Stdin);
var safeInputHandle = new SafeFileHandle(inputHandle, true);
var input = new FileStream(safeInputHandle, FileAccess.Read);
Console.SetIn(new StreamReader(input));

その結果、コンソールには何も出力されませんでした (そのため、何が起こっているのかわかりませんでした)。次に、StdOut と StdErr のセッターも追加しようとしました。

var outputHandle = GetStdHandle((int) StdHandle.Stdout);
var safeOutputHandle = new SafeFileHandle(outputHandle, true);
var output = new FileStream(safeOutputHandle, FileAccess.Write);
Console.SetOut(new StreamWriter(output));

var errHandle = GetStdHandle((int) StdHandle.Stderr);
var safeErrHandle = new SafeFileHandle(errHandle, true);
var err = new FileStream(safeErrHandle, FileAccess.Write);
Console.SetError(new StreamWriter(err));

それでも、コンソールへの出力はまったくありません。

[編集3] でアプリケーションを起動する

start /wait "AssemblyService 2.exe"

CMDプロンプトを表示する新しいウィンドウが作成されますが、それでもアプリケーションに入力できません。また、出力も表示されません。 開始コマンドの使用

4

0 に答える 0