Изпратете низ към командния ред (cmd) от Windows Form Application с помощта на SendMessage

Прочетох много отговори за това как да изпратя команда до cmd подкана.

Но не искам да използвам StreamWriter или подобни неща за въвеждане и получаване на изход.

Искам да използвам SendMessage, за да изпратя своя низ или да изрека команда в прозореца за подкана на cmd.

Може ли някой да помогне по въпроса?

Само да дам подробности за моята кандидатура. 1. Моето приложение е WinForm App. 2. Има 4-5 бутона. 3. Button1 отваря прозореца на командния ред, докато Button5 затваря или излиза от прозореца на командния ред. 4. Бутони 2,3,4 са командни бутони. Когато потребителят щракне върху Button2, команда 1 се изпраща до прозореца на командния ред. Подобно, когато се щракне върху бутон 3 и 4, команда 2 и команда 3 се изпращат до същия прозорец на командния ред.

Кажете ми, ако някой има написан код, който изпраща низ към командния ред.

Благодаря и поздрави,

Рахул


person rahoolm    schedule 08.05.2011    source източник
comment
Знаете, че можете просто да изпълните програмите в командния ред директно, като извикате cmd.exe (или самия изпълним файл) с подходящи аргументи. Това наистина е ненужно сложен и заобиколен начин да направите нещо просто.   -  person siride    schedule 08.05.2011
comment
Звучи доста решен да използвате грешна функция, за да направите това. Не е умен начин да зададете въпрос.   -  person Hans Passant    schedule 09.05.2011


Отговори (3)


Получих решението.
Използвах PostMessage().
Cmd има манипулатор и можете да изпратите низ към него.
Просто се мъчех да намеря правилния начин да хвана дръжката.
Сега имам такава.

/*
 * Created by SharpDevelop.
 * User: Rahul
 * Date: 5/12/2011
 * Time: 1:49 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace GetChildWindows
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : Form
{
    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    IntPtr hWnd = FindWindow(null, "Untitled - Notepad");

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool PostMessage(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)] uint Msg, IntPtr wParam, IntPtr lParam);


    [DllImport("user32.dll", SetLastError = true)]
    static extern bool PostMessage(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)] uint Msg, int wParam, int lParam);        

    const int WM_KEYDOWN = 0x0100;
    const int WM_KEYUP = 0x0101;
    const int WM_CHAR = 0x0102;

    public static IntPtr cmdHwnd = IntPtr.Zero;

    public MainForm()
    {
        //
        // The InitializeComponent() call is required for Windows Forms designer support.
        //
        InitializeComponent();

        //
        // TODO: Add constructor code after the InitializeComponent() call.
        //

        foreach (IntPtr child in GetChildWindows(FindWindow(null, "WinPlusConsole")))
        {
            StringBuilder sb = new StringBuilder(100);
            GetClassName(child, sb, sb.Capacity);


            if (sb.ToString() == "ConsoleWindowClass")
            {
//                  uint wparam = 0 << 29 | 0;
//                  string msg = "Hello";
//                  int i = 0;
//                  for (i = 0 ; i < msg.Length ; i++)
//                  {
//                      //PostMessage(child, WM_KEYDOWN, (IntPtr)Keys.Enter, (IntPtr)wparam);
//                      PostMessage(child, WM_CHAR, (int)msg[i], 0);
//                  }
//                  PostMessage(child, WM_KEYDOWN, (IntPtr)Keys.Enter, (IntPtr)wparam);

                cmdHwnd = child;
            }
        }

}

/// <summary>
    /// Returns a list of child windows
    /// </summary>
    /// <param name="parent">Parent of the windows to return</param>
    /// <returns>List of child windows</returns>
    public static List<IntPtr> GetChildWindows(IntPtr parent)
    {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        }
        finally
        {
            if (listHandle.IsAllocated)
            listHandle.Free();
        }
        return result;
    }

    /// <summary>
    /// Callback method to be used when enumerating windows.
    /// </summary>
    /// <param name="handle">Handle of the next window</param>
    /// <param name="pointer">Pointer to a GCHandle that holds a reference to the list to fill</param>
    /// <returns>True to continue the enumeration, false to bail</returns>

    private static bool EnumWindow(IntPtr handle, IntPtr pointer)
    {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
        {
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        }
        list.Add(handle);
        // You can modify this to check to see if you want to cancel the operation, then return a null here
        return true;
    }

    /// <summary>
    /// Delegate for the EnumChildWindows method
    /// </summary>
    /// <param name="hWnd">Window handle</param>
    /// <param name="parameter">Caller-defined variable; we use it for a pointer to our list</param>
    /// <returns>True to continue enumerating, false to bail.</returns>
    public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);





    void BtnHelloClick(object sender, EventArgs e)
    {
        uint wparam = 0 << 29 | 0;
                string msg = "Hello";
                int i = 0;
                for (i = 0 ; i < msg.Length ; i++)
                {
                    //PostMessage(child, WM_KEYDOWN, (IntPtr)Keys.Enter, (IntPtr)wparam);
                    PostMessage(cmdHwnd, WM_CHAR, (int)msg[i], 0);
                }
                PostMessage(cmdHwnd, WM_KEYDOWN, (IntPtr)Keys.Enter, (IntPtr)wparam);
    }

    void BtnCommandClick(object sender, EventArgs e)
    {
        uint wparam = 0 << 29 | 0;
                string msg = textBox1.Text;
                int i = 0;
                for (i = 0 ; i < msg.Length ; i++)
                {
                    //PostMessage(child, WM_KEYDOWN, (IntPtr)Keys.Enter, (IntPtr)wparam);
                    PostMessage(cmdHwnd, WM_CHAR, (int)msg[i], 0);
                }
                PostMessage(cmdHwnd, WM_KEYDOWN, (IntPtr)Keys.Enter, (IntPtr)wparam);
    }

    void TextBox1TextChanged(object sender, EventArgs e)
    {

    }
}
} 


Благодаря на всички!

person rahoolm    schedule 13.05.2011

Изглежда малко вероятно да успеете да постигнете това с SendMessage(). SendMessage() изисква манипулатор на прозорец и не вярвам, че cmd.exe има подходящ манипулатор на прозореца, за да получи съобщението.

Моят съвет е да потърсите метод, който решава проблема ви, вместо да решавате какво решение искате и да се опитвате да го накарате да отговаря на проблема.

person David Heffernan    schedule 08.05.2011
comment
SendMessage не работи, но PostMessage работи, така че cmd.exe наистина има подходящ прозорец за получаване на съобщения. - person ThreeStarProgrammer57; 07.02.2018

не е ясно от вашето обяснение (поне не за мен) защо не можете да използвате streamWriter в сценария, който описвате. можеш ли да разясниш това?

бих проверил класа Process за разговор с други програми чрез stdin/out

person aL3891    schedule 08.05.2011