2010-02-16 8 views
6

सिस्टम। डायग्नोस्टिक्स.प्रोसेस मानक इनपुट नामक स्ट्रीमवाइटर का खुलासा करता है, जो केवल मुझे पता है कि केवल वर्ण स्वीकार करता है।किसी प्रक्रिया के वर्णों की बजाय कुंजी कैसे भेजें?

लेकिन मुझे कीस्ट्रोक भी भेजने की ज़रूरत है, और कुछ कीस्ट्रोक पात्रों को अच्छी तरह से मैप नहीं करते हैं।

मुझे क्या करना चाहिए?

+0

कौन सा कीस्ट्रोक, उदाहरण के लिए? –

+0

@ रिक बैकस्पेस, Ctrl + C –

+1

यूनिक्स पाइप अबास्ट्रक्शन में यह अंतिम रिसाव है। पुनर्निर्देशन चरित्र धाराओं के माध्यम से होता है, यह गैर-टाइपिंग कुंजी स्ट्रोक अनुकरण नहीं कर सकता है। –

उत्तर

23

आप इनपुट मिश्रण कर रहे हैं होना चाहिए नियंत्रण संकेतों के साथ धाराओं। एक कंसोल प्रक्रिया में एक डिफ़ॉल्ट इनपुट स्ट्रीम होती है जिसे आप मानक इनपुट के साथ नियंत्रित कर सकते हैं, जैसा कि आप पहले ही जानते हैं। लेकिन Ctrl-C और Ctrl-तोड़ इस धारा के माध्यम से प्रक्रिया के लिए भेजा वर्ण नहीं हैं, लेकिन इसके बावजूद वे बजाय हैं नियंत्रण संकेत है कि इस प्रक्रिया पंजीकृत संकेत संचालकों का उपयोग कर प्राप्त करता, CTRL+C and CTRL+BREAK Signals देखें:

डिफ़ॉल्ट रूप से, जब एक कंसोल विंडो में कीबोर्ड फोकस होता है, CTRL + C या CTRL + BREAK को सिग्नल (SIGINT या SIGBREAK) के रूप में माना जाता है और कीबोर्ड इनपुट के रूप में नहीं माना जाता है।

एक प्रक्रिया आप GenerateConsoleCtrlEvent का उपयोग करें और या तो CTRL_C_EVENT या CTRL_BREAK_EVENT भेज सकते हैं करने के लिए नकली संकेत भेजने के लिए। इस एपीआई में कोई नेट समतुल्य नहीं है, इसलिए आपको इसे PInvoke करना होगा।

से इसका इस्तेमाल करने के लिए नेट आप बस समारोह परिभाषा शामिल करने की जरूरत:

const int CTRL_C_EVENT = 0; 
const int CTRL_BREAK_EVENT = 1; 

[DllImport("kernel32.dll")] 
static extern bool GenerateConsoleCtrlEvent(
    uint dwCtrlEvent, 
    uint dwProcessGroupId); 
+0

http: // www होना चाहिए। google.com/codesearch/p?hl=hi#ncfzeHH4QLA/pubs/consoledotnet/consoledotnet.zip%7CYrqh4ujA6zA/ConsoleDotNet/WinCon.cs –

+0

मैं स्क्रीन रिकॉर्डिंग की FFmpeg प्रक्रिया का उपयोग कर रहा हूं। क्या यह मेरे लिए काम है? असल में मैं एफएफएमपीई – Ahmad

3

क्या आपने यह शानदार टूल देखा है - AutoIt। यह एक स्क्रिप्टिंग उपकरण है। बैकस्पेस भेजने के लिए आप Send("{BACKSPACE}")

यह एक अच्छा टूल है और यह कई मैन्युअल क्लिक/डबल-क्लिक/आदि को स्वचालित करने में सहायता कर सकता है।

क्या यह आपके प्रश्न के लिए प्रासंगिक है?

+0

हाय, यह प्रासंगिक है, लेकिन मैं एक समाधान पसंद करता हूं जिसे मैं सीधे .NET में उपयोग कर सकता हूं। –

+1

@ जेडर; ऑटोआईटी के लिए एक डीएल उपलब्ध है कि आप आसानी से अपने आवेदन में जोड़ सकते हैं ... – jvenema

0

यदि आपके पास एक विंडोज़ फॉर्म विंडो है जिसे आप कुंजी भेज सकते हैं, तो SendKeys एक उचित समाधान हो सकता है।

बैकस्पेस और Ctrl + C दबाने के लिए, कि

SendKeys.Send("{BACKSPACE}^C"); 
+0

Ctrl + C भेजना वास्तव में एक प्रक्रिया में काम नहीं करता है, यह^{BREAK} ... – t0mm13b

6

वहाँ एक इनपुट सिम्युलेटर Codeplex पर यहां पाया जो केवल आपके लिए काम करते हैं सकता है। मैं एक नमूना कोड पर काम कर रहा हूँ और मन में शीघ्र ही यहाँ वापस पोस्ट करेंगे, भालू इनपुट सिम्युलेटर क्या लिंक Remus द्वारा आपूर्ति में पाया गया था के समान है ...

संपादित करें: मैं पाया है है कि वहाँ इसके साथ एक सीमा, आप निश्चित रूप से विशिष्ट System.Windows.Forms.SendKeys.Send विधि से दूर हो सकते हैं, यह प्रभावी ढंग से काम करता है! , लेकिन, इस प्रक्रिया

  • धाराओं
  • खिड़की छुपाया नहीं जा सकता का कोई पुनर्निर्देशन (यह यह करने के लिए लाने का कोई रास्ता नहीं है जहां यह असफल हो जायेगी, क्योंकि खिड़की के हैंडल कहीं नहीं देखा जा सकता है, होना आवश्यक है इसे सक्रिय बनाने के लिए अग्रभूमि!)
  • एक खिड़की प्रभावी होने के लिए प्रक्रिया दिखा रही है!

आपके मामले में, यह खिड़की खोजने की बात है, यह PInvoke के माध्यम से सक्रिय सेट 'SetForegroundWindow', और दृश्यों ^{BREAK} जो प्रक्रिया के लिए Ctrl + तोड़ संकेत भेजता है भेजने जो बहुत अच्छी तरह से काम करता है (खासकर यदि प्रक्रिया एक कमांड लाइन प्रोग्राम/बैच फ़ाइल है)। असल में मैं काफी हैरान हूं ... के रूप में: यहाँ CodeProject पर एक लेख है कि वास्तव में यह करता है और SendKeys दर्पण ... मैं अभी तक इस में कुछ कोड प्रदर्शित करने के लिए चिपकाने के लिए है ....

# 2 संपादित है इस कोड (अवधारणा का सबूत) दिखाएगा ... यह उपयोग कर रहा है:

  • InputSimulator (जैसा कि पहले उल्लेख के रूप में)
  • एक खिड़कियों रूप है कि एक बटन के होते हैं, जब प्रपत्र लोड होने पर स्वचालित रूप से वर्ग चलाता है । बटन पर क्लिक करने पर, यह छुपा प्रक्रिया
  • पर एक ctrl-break पोस्ट करता है आउटपुट स्ट्रीम वास्तव में पुनर्निर्देशित होती है और एक छिपी हुई विंडो होती है।
  • अजीब चीज, आउटपुट कैप्चर किया जा रहा है लेकिन डीबग विंडो में परिणाम नहीं दिखाता है, वास्तविक समय में, यह प्रक्रिया समाप्त होने तक buffered (मुझे लगता है), पूरा आउटपुट दिखाया जाता है ..
  • मैंने FindWindow एपीआई कॉल पर थोड़ा सा धोखा दिया, क्योंकि मुझे पता था कि खिड़की का शीर्षक था और किसी भी तरह से, इसे अग्रभूमि में लाने में सक्षम था, और इनपुट सिम्युलेटर का उपयोग करके कीस्ट्रोक भेजने के लिए ... या पारंपरिक का उपयोग करें सादा पुराना SendKeys फ़ंक्शन ... कारण यह है कि मेरे पास Thread.Sleep था यह सुनिश्चित करना है कि कुंजीस्ट्रोक को "सक्रिय अग्रभूमि विंडो" की कुंजीपटल कतार में धक्का दिया जा सके, इसके बावजूद, छुपा हुआ है '
  • I लूप forev के लिए 'netstat -e 5' कमांड का इस्तेमाल किया er, प्रत्येक 5 सेकंड के परिणामों को ताज़ा करने तक, जब तक कि अनंत लूप को तोड़ने के लिए 'Ctrl + C' प्राप्त नहीं होता है।
public partial class Form1 : Form 
{ 
    private TestNetStat netStat = new TestNetStat(); 
    public Form1() 
    { 
     InitializeComponent(); 
     using (BackgroundWorker bgWorker = new BackgroundWorker()) 
     { 
      bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); 
      bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted); 
      bgWorker.RunWorkerAsync(); 
     } 
    } 

    void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("BGWORKER ENDED!"); 
    } 

    private void bgWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     netStat.Run(); 
    } 
    void btnPost_Click(object sender, EventArgs e) 
    { 
     netStat.PostCtrlC(); 
     System.Diagnostics.Debug.WriteLine(string.Format("[{0}] - {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), this.netStat.OutputData.Replace(Environment.NewLine, ""))); 
    } 
} 

public class TestNetStat 
{ 
    private StringBuilder sbRedirectedOutput = new StringBuilder(); 
    // 
    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 
    [DllImport("user32")] 
    public static extern int SetForegroundWindow(IntPtr hwnd); 
    public string OutputData 
    { 
     get { return this.sbRedirectedOutput.ToString(); } 
    } 
    public void PostCtrlC() 
    { 
     IntPtr ptr = FindWindow(null, @"C:\Windows\System32\netstat.exe"); 
     if (ptr != null) 
     { 
      SetForegroundWindow(ptr); 
      Thread.Sleep(1000); 
      WindowsInput.InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.CANCEL); 
      // SendKeys.Send("^{BREAK}"); 
      Thread.Sleep(1000); 
     } 
    } 
    public void Run() 
    { 
     System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo(); 
     ps.FileName = "netstat"; 
     ps.ErrorDialog = false; 
     ps.Arguments = "-e 5"; 
     ps.CreateNoWindow = true; 
     ps.UseShellExecute = false; 
     ps.RedirectStandardOutput = true; 
     ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; 
     using (System.Diagnostics.Process proc = new System.Diagnostics.Process()) 
     { 
      proc.StartInfo = ps; 
      proc.EnableRaisingEvents = true; 
      proc.Exited += new EventHandler(proc_Exited); 
      proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived); 
      proc.Start(); 
      proc.BeginOutputReadLine(); 
      proc.WaitForExit(); 
     } 
    } 

    void proc_Exited(object sender, EventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended"); 
    } 

    void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e) 
    { 
     if (e.Data != null) 
     { 
      this.sbRedirectedOutput.Append(e.Data + Environment.NewLine); 
      System.Diagnostics.Debug.WriteLine("proc_OutputDataReceived: Data: " + e.Data); 
     } 
    } 
} 

nitpicky अलग रूप में, मुझे पता है कि netStat 'BackgroundWorker' धागा बंद चल रहा है, और मैं सीधे मुख्य जीयूआई धागे से 'PostCtrlC' विधि लागू ... यह एक के रूप में पंडिताऊ है सबूत-ऑफ-अवधारणा कोड, लेकिन यह दिखाता है कि इसे 'ISynchronizeInvoke' को इसे थ्रेड-सुरक्षित बनाने के लिए लागू करने की आवश्यकता है, एक तरफ ... यह वास्तव में काम करता है।

+0

का उपयोग कर स्क्रीन रिकॉर्डिंग की प्रक्रिया शुरू करना चाहता हूं लेकिन यदि आप नेटस्टैट का उपयोग करने वाली कई प्रक्रियाएं चला रहे हैं।exe, तो आप PostCtrlC() के साथ सभी को प्रभावित करेंगे? जब आप प्रक्रिया सत्र को जानते हैं तो वही काम करने का कोई तरीका है? – Constantin

+0

@ कॉन्स्टेंटिन कोड केवल netstat.exe चलाने वाली एक विंडो को लक्षित करता है। आप [EnumWindows] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633497 (v = vs.85) .aspx का उपयोग कर सकते हैं) और कॉलबैक फ़ंक्शन [EnumWindowsProc] (http: //msdn.microsoft.com/en-us/library/windows/desktop/ms633498(v=vs.85).aspx) हैंडल प्राप्त करने के लिए और यह देखने के लिए निरीक्षण करें कि उस हैंडल का शीर्षक netstat.exe में है या नहीं शीर्षक ... यदि यह पाया जाता है, तो इसे अग्रभूमि में लाएं और उपरोक्त सबूत-अवधारणा कोड के रूप में इसे "ज़ैप" करें :) – t0mm13b

संबंधित मुद्दे