|
|
|
WinAPI: AttachConsole(ATTACH_PARENT_PROCESS)/AttachConsole(dwProcessId)
|
|||
|---|---|---|---|
|
#18+
Недавно наткнулся на интересный казус. Имеется winforms-приложение, которому необходимо организовать вывод некоторой информации в консоль. Варианты: если приложение запущено из консоли (cmd, Far, etc.) - использовать консоль родительского процесса; если у родительского процесса консоли нет - приаттачиться к имеющейся консоли (она существует, id консольного процесса известен). Код таков: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. Вызов: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ОС/среда/платформа: WinXP prof. SP3/MS Visual Studio prof. 2008/.Net FW 3.5 SP1. Аттач к консоли родительского процесса происходит нормально, аттач же к заданной консоли выдаёт ошибку 0x5 - это, согласно msdn , "If the calling process is already attached to a console" - что совсем не так: консоли нет ни у самого процесса, ни у родительского. Далее методом научного тыка (поскольку идей на предмет возникновения такой ситуации у меня не оказалось) выяснилось, что виной всему вызов AttachConsole(ATTACH_PARENT_PROCESS) - несмотря на то, что он возвращает false, и никакого аттача не происходит, последующий вызов AttachConsole с указанием id процесса в любом случае выбрасывает access denied. Если в коде закомментировать строчку с AttachConsole(ATTACH_PARENT_PROCESS), то AttachConsole(dwProcessId) происходит вполне нормально. Для очистки совести пробовал после попытки аттача к родительской консыли вызывать FreeConsole - без толку. Проблема вполне решаема заменой AttachConsole(dwProcessId) на AllocConsole(), но мне захотелось узнать причины такого поведения AttachConsole, т.к. в msdn каких-либо разъяснений по поводу вышеописанной ситуации мне найти не удалось. Между AttachConsole(ATTACH_PARENT_PROCESS) и AttachConsole(dwProcessId) никаких отладочных Console.WriteLine, потенциально создающих консоль, нет; FreeConsole перед вызовом AttachConsole(dwProcessId) возвращает false. Разбираемся дальше: посмотрим список процессов консоли, к которой пытаемся приаттачиться, и, поскольку у нас при AttachConsole(dwProcessId) GetLaStError=0x5, что вроде как должно свидетельствовать о том, что вызывающий процесс прицепился к какой-то консоли - посмотрим список консольных процессов в приложении, пытающемся приаттачиться к консоли, после AttachConsole(ATTACH_PARENT_PROCESS): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. В процессе, к консоли которого пытаюсь приаттачиться, вызов GetConsoleProcessList показывает только один процесс - тот, которого консоль (и к которой я пытаюсь приаттачиться); вызов GetConsoleProcessList в точке между вызовами AttachConsole процесса, который пытается приаттачиться, возвращает 0, GetLastError возвращает ERROR_INVALID_HANDLE (6) (что, в принципе, логично - вызывающий процесс не имеет консоли). Наконец, исходя из того факта, что при всей вышеописанной ситуации AllocConsole всё же отрабатывает нормально, мне подсказали вот такой выход: Код: plaintext 1. 2. 3. 4. 5. 6. - и этот вариант отработал нормально, процесс смог-таки приаттачиться к требуемой консоли. Но осталось неясным, что за такая фантомная консоль привязывается, от которой не помогает отцепиться FreeConsole, и которую в упор не видит GetConsoleProcessList. Была высказана (не мной) гипотеза, что часть логики AttachConsole исходит из ложного предположения, что ATTACH_PARENT_CONSOLE всегда завершается успехом. В итоге в случае неудачи она оставляет процесс в промежуточном состоянии - по одним признакам процесс имеет приаттаченную консоль (и именно эти признаки она и проверяет, вероятно в силу этого же ложного предположения), а по другим признакам приаттаченной консоли всё еще нет (и эти другие признаки проверяют AllocConsole, FreeConsole и GetConsoleProcessList). Но это предположение - опять же гипотеза, точные причины всего вышеописанного так пока и не прояснились, поэтому я был бы рад, если бы кто-нибудь мне разъяснил, в чём тут дело. P.S. Поскольку данная проблема, по моему скромному, касается больше WinAPI, чем .Net/C#, я счёл, что данная тема будет уместнее здесь, а не в 34-м разделе. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.12.2010, 16:52 |
|
||
|
|

start [/forum/topic.php?fid=16&tid=1343281]: |
0ms |
get settings: |
10ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
31ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
35ms |
get tp. blocked users: |
2ms |
| others: | 233ms |
| total: | 344ms |

| 0 / 0 |
