purebasic.info
http://purebasic.info/phpBB3ex/

Консоль
http://purebasic.info/phpBB3ex/viewtopic.php?f=1&t=4728
Страница 1 из 1

Автор:  knower [ Сб июл 08, 2017 2:48 pm ]
Заголовок сообщения:  Консоль

Как можно подключиться к уже запущенной консоли/процессу? По типу как #PB_Program_Write после RunProgram(), но его использовать нельзя так как открывается ещё одно консольное окно. Хэндл консольного окна (уже запущенного) известен и сейчас могу отправлять различные команды в него (SendMessage_), НО мне нужно чтобы самих команд не было видно, а только результат их выполнения. @echo off не помогает. Кто подскажет?

Автор:  Сергейчик [ Сб июл 08, 2017 7:40 pm ]
Заголовок сообщения:  Re: Консоль

Не понятно мне одно раз pid окна известен,то зачем нужен как говоришь запуск для общения с ним,а не просто обращения к этому запущенному окну?

Автор:  knower [ Сб июл 08, 2017 7:55 pm ]
Заголовок сообщения:  Re: Консоль

Сергейчик, как раз говорил об обратном, что нельзя использовать RunProgram() или OpenConsole() потому как это породит новое окно, а надо работать с тем что уже существует. Сейчас могу отправить в окно строку с нужной командой и она отобразится, чего быть не должно. Это равносильно тому, что в открытой консоли вводить команды с клавиатуры. Вот и думал как-то "приаттачиться" к уже существующему процессу с получением доступа и отправлять строку в stdin.
Как ещё подробней объяснить-то? Вот к примеру два "батника":

1.cmd
Код:
1
2
echo 12345
pause


и
2.cmd
Код:
1
2
3
@echo off
echo 12345
pause


Вот второй-то вариант и нужно получить в итоге, но как?

Добавлено:
Извини, поправлю: pid = processID; хэндл окна - это другое.

Автор:  Сергейчик [ Вс июл 09, 2017 8:41 am ]
Заголовок сообщения:  Re: Консоль

Я понял изначально так запущенное чужое окно проги и с ним нужно общение из своей напрямую ,или ты хочешь сказать что окно к обращаемой проги не запущено нет процесса этой проги и ты хочешь что то получить от её тела(функций)?

Автор:  qpAHToMAS [ Вс июл 09, 2017 3:12 pm ]
Заголовок сообщения:  Re: Консоль

А я понял так:
Запущено (работает) консольное приложение (сервер например, какой-нибудь) и ему (в его консоль) надо отсылать команды из PureBasic команды, но при этом не простой отсылкой символов (команд) в окно консоля, ибо палево.

Автор:  knower [ Вс июл 09, 2017 9:36 pm ]
Заголовок сообщения:  Re: Консоль

Сергейчик, не заморачивайся более. Мне уже помогли. Ниже приведу код. Может он прояснит то, чего я добивался и о чём изначально спрашивал. Больше не знаю как объяснить.

qpAHToMAS, примерно так.

Собственно код, налетайте :D
Код:
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#SystemProcessInformation = 5
 
Structure UNICODE_STRING Align #PB_Structure_AlignC
  Length.w
  MaximumLength.w
  Buffer.i
EndStructure
 
Structure VM_COUNTERS
  PeakVirtualSize.l
  VirtualSize.l
  PageFaultCount.l
  PeakWorkingSetSize.l
  WorkingSetSize.l
  QuotaPeakPagedPoolUsage.l
  QuotaPagedPoolUsage.l
  QuotaPeakNonPagedPoolUsage.l
  QuotaNonPagedPoolUsage.l
  PagefileUsage.l
  PeakPagefileUsage.l
EndStructure
 
Structure IO_COUNTERS
  ReadOperationCount.LARGE_INTEGER
  WriteOperationCount.LARGE_INTEGER
  OtherOperationCount.LARGE_INTEGER
  ReadTransferCount.LARGE_INTEGER
  WriteTransferCount.LARGE_INTEGER
  OtherTransferCount.LARGE_INTEGER
EndStructure
 
Structure SYSTEM_THREAD
  KernelTime.LARGE_INTEGER
  UserTime.LARGE_INTEGER
  CreateTime.LARGE_INTEGER
  WaitTime.l
  StartAddress.l
  UniqueProcess.l
  UniqueThread.l
  Priority.l
  BasePriority.l
  ContextSwitchCount.l
  State.l
  WaitReason.l
  Reserved1.l
EndStructure
 
Structure SYSTEM_PROCESS_INFORMATION
  NextEntryOffset.l
  NumberOfThreads.l
  Reserved1.LARGE_INTEGER[3]
  CreateTime.LARGE_INTEGER
  UserTime.LARGE_INTEGER
  KernelTime.LARGE_INTEGER
  ModuleName.UNICODE_STRING
  BasePriority.i
  ProcessID.l
  InheritedFromProcessId.l
  HandleCount.l
  Reserved2.l[2]
  VirtualMemoryCounters.VM_COUNTERS
  PrivatePageCount.l
  IOCounters.IO_COUNTERS
  ThreadInfo.SYSTEM_THREAD[0]
EndStructure
 
Prototype protoAttachConsole(dwProcessId)
 
Procedure cmdGetProcessId(ModuleName.s)
  *spi.SYSTEM_PROCESS_INFORMATION
  *spi = AllocateMemory(1024 * 1024)
  NtQuerySystemInformation_(#SystemProcessInformation, *spi, MemorySize(*spi), #Null)
  *spi\ModuleName\Buffer = AllocateMemory(#MAX_PATH)
 
  While *spi\NextEntryOffset
    If LCase(PeekS(*spi\ModuleName\Buffer, *spi\ModuleName\Length, #PB_Unicode)) = ModuleName
      dwProcessId = *spi\ProcessID : Break
    Else
      *spi + *spi\NextEntryOffset
    EndIf
  Wend
  ProcedureReturn dwProcessId
EndProcedure
 
Procedure.l cmdOpenConsole(dwProcessId)
  Protected AttachConsole.protoAttachConsole
 
  kernel32 = OpenLibrary(#PB_Any, "kernel32.dll")
 
  If IsLibrary(kernel32)
    AttachConsole = GetFunction(kernel32, "AttachConsole")
 
    If AttachConsole(dwProcessId) : hStdInput.l = GetStdHandle_(#STD_INPUT_HANDLE) : EndIf
 
    CloseLibrary(kernel32)
  EndIf
  ProcedureReturn hStdInput
EndProcedure
 
Procedure cmdAddAlias(Source.s, Target.s)
  ProcedureReturn AddConsoleAlias_(Source, Target, "cmd.exe")
EndProcedure
 
Procedure cmdRunScript(hStdInput.l, ScriptText.s, RunAndWait = #False)
  ScriptText + Chr(13)
  nLength = Len(ScriptText) + 1
 
  If nLength > 1
    Dim lpBuffer.INPUT_RECORD(nLength)
 
    For rtnCount = 0 To nLength - 2
      ascKey = Asc(Mid(ScriptText, rtnCount + 1, 1))
      vkKey = VkKeyScanEx_(ascKey, GetKeyboardLayout_(0)) & $FF
      lpBuffer(rtnCount)\EventType = #KEY_EVENT
      lpBuffer(rtnCount)\Event\KeyEvent\bKeyDown = #True
      lpBuffer(rtnCount)\Event\KeyEvent\dwControlKeyState = 0
      lpBuffer(rtnCount)\Event\KeyEvent\uChar = ascKey
      lpBuffer(rtnCount)\Event\KeyEvent\wRepeatCount = 1
      lpBuffer(rtnCount)\Event\KeyEvent\wVirtualKeyCode = vkKey
      lpBuffer(rtnCount)\Event\KeyEvent\wVirtualScanCode = MapVirtualKey_(vkKey, 0)
    Next
    lpBuffer(nLength - 1)\EventType = #KEY_EVENT
    lpBuffer(nLength - 1)\Event\KeyEvent\bKeyDown = #True
    lpBuffer(nLength - 1)\Event\KeyEvent\dwControlKeyState = 0
    lpBuffer(nLength - 1)\Event\KeyEvent\uChar = #VK_RETURN
    lpBuffer(nLength - 1)\Event\KeyEvent\wRepeatCount = 1
    lpBuffer(nLength - 1)\Event\KeyEvent\wVirtualKeyCode = #VK_RETURN
    lpBuffer(nLength - 1)\Event\KeyEvent\wVirtualScanCode = MapVirtualKey_(#VK_RETURN, 0)
    WriteConsoleInput_(hStdInput, @lpBuffer(), nLength, @lpNumberOfCharsWritten)
 
    If RunAndWait
      Repeat
        Result = WaitForSingleObject_(hStdInput, 100)
 
        Select Result
          Case #WAIT_ABANDONED : Break
          Case #WAIT_OBJECT_0 : Delay(100)
          Case #WAIT_TIMEOUT : Break
          Case #WAIT_FAILED : Break
        EndSelect
      ForEver
    EndIf
  EndIf
EndProcedure
 
dwProcessId = cmdGetProcessId("cmd.exe")
 
If Not dwProcessId : RunProgram("cmd") : Delay(200) : dwProcessId = cmdGetProcessId("cmd.exe") : EndIf
 
If dwProcessId
  hStdInput.l = cmdOpenConsole(dwProcessId)
 
  If hStdInput
    If cmdAddAlias(".", "cd C:\&&dir") : cmdRunScript(hStdInput, ".") : EndIf
  EndIf
EndIf



Благодарности товарищу JHPJHP с англоязычного форума.

Добавлено:
Буду благодарен, если Пётр или кто-то ещё посмотрит этот код и поможет избавиться от первоначальной точки и двойного перевода каретки по окончании работы. Чтобы было красиво.
Помнится в командном файле чтобы добиться отступа вставлял вначале один из непечатаемых символов и помоему это была русская буква "я". Не помню, давно было. Может можно как-то применить в этом случае такой подход?

Добавлено:
по поводу перевода строки - закомментировать строку ScriptText + Chr(13).

Автор:  Пётр [ Вс июл 09, 2017 10:05 pm ]
Заголовок сообщения:  Re: Консоль

knower писал(а):
Помнится в командном файле чтобы добиться отступа вставлял вначале один из непечатаемых символов и помоему это была русская буква "я"
Если программа с выключенной поддержкой юникода, то можно поступить также.
Код:
1
If cmdAddAlias(Chr(255), "cd C:\&&dir") : cmdRunScript(hStdInput, Chr(255)) : EndIf

Для юникодной программы
Код:
1
If cmdAddAlias(Chr(160), "cd C:\&&dir") : cmdRunScript(hStdInput, Chr(160)) : EndIf


Автор:  knower [ Вс июл 09, 2017 10:23 pm ]
Заголовок сообщения:  Re: Консоль

Спасибо конечно, Пётр. Но то ли у меня консоль неправильная, то ли ОС, то ли PB.
PB531 и win7x86 - в настройках стоит галочка юникода и формат файла выставлен как utf-8. Всё по умолчанию. В итоге Chr(160) печатает букву "а". Chr(255) - "y". :cry:

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/