2011-01-17 13 views
6

मैं कम स्तर के पढ़ने/लिखने के कंसोल फ़ंक्शंस का उपयोग कर cmd.exe एप्लिकेशन के इनपुट पर आदेश भेजने की कोशिश कर रहा हूं। मुझे प्रोसेस कंसोल से जुड़े होने के बाद ReadConsole...() और WriteConsole() फ़ंक्शंस का उपयोग करके टेक्स्ट (स्क्रैपिंग) पढ़ने में कोई परेशानी नहीं है, लेकिन मुझे यह नहीं पता है कि उदाहरण के लिए "dir" कैसे लिखना है और कंसोल को इसे एक कमांड कमांड के रूप में समझना है।निम्न स्तर कंसोल इनपुट और पुनर्निर्देशन

यहाँ मेरी कोड का एक सा है:

CreateProcess(NULL, "cmd.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); 
AttachConsole(pi.dwProcessId); 

strcpy(buffer, "dir"); 
WriteConsole(GetStdHandle(STD_INPUT_HANDLE), buffer, strlen(buffer), &charRead, NULL); 

STARTUPINFO प्रक्रिया की विशेषताओं सब शून्य करने के लिए, निश्चित रूप से, सेट कर रहे हैं को छोड़कर .cb विशेषता।

स्क्रीन पर कुछ भी बदलाव नहीं है, हालांकि मुझे Error 6: Invalid HandleWriteConsole से STD_INPUT_HANDLE पर लौटा रहा है। अगर मैं (STD_OUTPUT_HANDLE) पर लिखता हूं तो मुझे स्क्रीन पर लिखा गया मेरा dir मिलता है, लेकिन कुछ भी नहीं होता है। मुझे लगता है कि SetConsoleMode() मदद की जा सकती है, लेकिन मैंने कई मोड संयोजनों की कोशिश की है, कुछ भी मदद नहीं की है। मैंने एक त्वरित कंसोल एप्लिकेशन भी बनाया है जो इनपुट (scanf()) के लिए इंतजार कर रहा है और जो भी हो रहा है उसे वापस लेता है, काम नहीं करता है।

मैंने scanf() प्रोप में टाइप करने का प्रयास किया है और फिर PeekConsoleInput() का उपयोग कर इनपुट बफर में देखा है, 0 देता है, लेकिन INPUT_RECORD सरणी खाली है।

मुझे पता है कि WriteConsoleInput() का उपयोग करके इसके आसपास एक और तरीका है ताकि सीधे INPUT_RECORD संरचित ईवेंट को कंसोल में इंजेक्ट किया जा सके, लेकिन यह बहुत लंबा होगा, मुझे इसमें प्रत्येक कीप्रेस भेजनी होगी।

मुझे आशा है कि प्रश्न स्पष्ट है। अगर आपको कोई और जानकारी चाहिए तो कृपया मुझे बताएं। आपकी सहायता के लिए धन्यवाद.

अद्यतन 1:

मैं एक cmd प्रक्रिया WriteConsoleInput()INPUT_RECORD साथ structs का उपयोग करने के keypresses भेजने के लिए कर रहा हूँ, फिर भी, AttachConsole कभी कभी ERROR_GEN_FAILURE #31: A device attached to the system is not functioning. फेंकता है, और इस तरह INPUT_RECORD नहीं भेजा जाता है (Error 6: Invalid Handle)। Sleep(1000)CreateProcess() के बाद AttachConsole() इससे पहले हल करता है। पात्रों dir स्वचालित रूप में लिखे जाते हैं, लेकिन मैं समझ नहीं RETURN कुंजी भेजने के लिए कैसे:

ir[0].EventType = KEY_EVENT; 
ir[0].Event.KeyEvent.bKeyDown = TRUE; 
ir[0].Event.KeyEvent.dwControlKeyState = 0; 
ir[0].Event.KeyEvent.uChar.UnicodeChar = '\n'; 
ir[0].Event.KeyEvent.wRepeatCount = 1; 
ir[0].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; 
ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC); 
ir[1].EventType = KEY_EVENT; 
ir[1].Event.KeyEvent.bKeyDown = FALSE; 
ir[1].Event.KeyEvent.dwControlKeyState = 0; 
ir[1].Event.KeyEvent.uChar.UnicodeChar = '\n'; 
ir[1].Event.KeyEvent.wRepeatCount = 1; 
ir[1].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; 
ir[1].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC); 

WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ir, 2, &charRead); 

WriteConsoleInput रिटर्न 0, लेकिन कुछ भी सांत्वना में होता है, मैं ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT और एक करने के लिए SetConsoleMode() स्थापित करने की कोशिश की है इसके परिणाम, बिना किसी परिणाम के। यदि मैं कीबोर्ड से एंटर दबाता हूं, हालांकि, स्वचालित रूप से टाइप किए गए dir कमांड निष्पादित होते हैं (उस समय के विपरीत जब मैं केवल WriteConsole()), तो मुझे लगता है कि मैं सही रास्ते पर हूं।

एसएसएच वास्तविक कीप्रेस पर नहीं भेजता है और वास्तविक स्क्रीन बफर (जैसे टैब, और CTRL + C CTRL + D काम) प्राप्त करता है? मैं कुछ पसंद के बाद हूँ।

अद्यतन 2:

मैं वापसी आदेश इंजेक्शन लगाने के साथ समस्या पाया। , सुपर सरल के बजाय ir[1].Event.KeyEvent.uChar.AsciiChar = '\r'; यानी \r होना चाहिए था।

ऐसा लगता है इनपुट आदेशों का WriteConsole() का उपयोग करने का कोई रास्ता नहीं है कि वहाँ, एक WriteConsoleInput() INPUT_RECORDs भेजकर या पाइप (जो हमेशा सही है, लेकिन सबसे सीधे आगे अनुप्रयोगों के लिए महान नहीं हैं) बनाने के द्वारा द्वारा मिलना चाहिए। WriteConsoleInput() का उपयोग करने का एक बड़ा फायदा यह है कि आप कंसोल इतिहास तक पहुंचने के लिए VK_UP और VK_DOWN भेज सकते हैं, (यदि हम सीएमडी में हैं) और VK_TAB स्वत: पूर्णता के लिए, सभी CTRL + _ अनुक्रम, ईएससी और फ़ंक्शन कुंजी और यहां तक ​​कि माउस CLICKS ।

अधिक यहाँ जानकारी: http://msdn.microsoft.com/en-us/library/ms687403%28v=vs.85%29.aspx यहाँ उदाहरण के प्लस टन: http://controllingtheinter.net/forums/viewtopic.php?f=116&t=366

किसी को भी है, तो अन्य महान विचारों में चिप के लिए स्वतंत्र महसूस उन सभी जो इस में दिलचस्पी ली को धन्यवाद।। उम्मीद है कि यह भविष्य में किसी की मदद करेगा।

उत्तर

2

अभी आप cmd.exe प्रक्रिया के लिए नहीं, अपने स्वयं के stdin हैंडल पर लिखने की कोशिश कर रहे हैं। उस के लिए इनपुट हैंडल को रीडायरेक्ट करने के लिए आपको बहुत अधिक काम करना होगा। इसे एक पाइप की आवश्यकता है। यहां एक KB article है जो बॉयलरप्लेट कोड दिखाता है।

बीटीडब्ल्यू: हमेशा एपीआई कार्यों के वापसी मूल्य की जांच करें।

+0

मैंने सोचा कि मैं नई प्रक्रिया 'कंसोल से जुड़ा हुआ हूं। AttachConsole() 'इसके लिए अनुमति देता है; जब मैं संलग्न करने के बाद 'printf() 'वास्तव में' cmd.exe' में प्रिंट कर रहा हूं। मैंने त्रुटि कोड को अपडेट किया है जो मुझे 'WriteConsole() 'से' STD_INPUT_HANDLE' – soulseekah

+0

से मिला है, आप केवल कंसोल विंडो साझा करते हैं, यही वह है। हां, त्रुटि कोड आपको दिखाता है कि क्या गलत हो रहा है, आप इनपुट हैंडल पर नहीं लिख सकते हैं। –

+0

मैंने उस कोड को पढ़ लिया है और कल इसे आजमाया है, एक आकर्षण की तरह काम करता है, जैसे 'FTP.exe' और 'EDIT.exe' जैसे ऐसे स्पॉन्डेड प्रोग्राम अपने स्वयं के बफर होते हैं, जिन्हें रीडायरेक्ट नहीं किया जाता है, यह निम्न स्तर को पढ़ने और लिखने के लिए कॉल करता है कंसोल के लिए। अनिवार्य रूप से मैं एक कंसोल विंडो को क्लोन करना चाहता हूं, सबकुछ एक से दूसरे में रीडायरेक्ट करके। – soulseekah

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