powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Чтение результатов работы консольного приложения
42 сообщений из 42, показаны все 2 страниц
Чтение результатов работы консольного приложения
    #35049083
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть консольное приложение proga.exe. Смысл:через TAPI посылаем факс, в консоли наблюдаем как дела:

2008/01/09 02:44:29> DialTone
2008/01/09 02:44:29> Dialing
2008/01/09 02:44:29> Proceeding
2008/01/09 02:44:30> RingBack
2008/01/09 02:44:32> Connected
2008/01/09 02:44:50> Sending Page 1
2008/01/09 02:45:43> Sending Page 2
2008/01/09 02:46:40> Idle
> >> SUCCEEDED

Хочется:
Запустить его из VB и все эти строки(что пишет на экран) в VB и выводить в режиме REAL-TIME
Как запустить понятно
В1: shell(proga.exe) или ShellAndContinue(proga.exe)
В2: http://www.sources.ru/msdn/howto/q171654.shtml -здесь тоже уже почитал, даже воспроизвел

Есть конечно вариант: shell(proga.exe > 1.txt)
Но в этом случае 1.txt мы получим только в 02:46:40 (до этого там будет пусто), т.е. по окончании работы программы, а надо уже в 02:44:29 прочесть слово Dialing.

Есть ли способ?
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35050173
шпщк_123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в мсдн был пример перенаправления вывода консоли в нужное тебе место. В том числе и на VB. Поищи!
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35050516
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я нашел 2 ссылки: 1-я по сути повторяет уже приведенную выше
http://support.microsoft.com/kb/171654/en-us#appliesto


Вот это может быть? Но ощущение, что не то.
http://support.microsoft.com/kb/150767/en-us

Нужен непрерывный вывод, а целиком под конец все из файла можно и так считать (proga.exe > 1.txt) -это не интересно.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35051401
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сегодня добрый, на инструкцию:
http://www.sources.ru/msdn/howto/q171654.shtml
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35051716
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я там уже дважды был-см.выше.
sOut = "Hi There" & vbCrLf -выводит в консоль
C:\TEST.BAT -запускается в этой консоли
А как мне сделать Msgbox "Результаты деятельности test.bat",
причем не после завершения test.bat а в процессе получения информации от test.bat
test.bat не очень удачный пример, см.мой пример, кот.выводит в течении 2-3 минут.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35051719
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Т.е. надо считывать информацию по мере поступления в консоль, аналогично тому как я это делаю в MSComm (com-порт-gjhn) и WinSock(TCP-IP)
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35053618
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По идее если копать глубже:
http://msdn2.microsoft.com/en-us/library/ms682073.aspx

Код: 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.
BOOL WINAPI WriteConsole(
  __in        HANDLE hConsoleOutput,
  __in        const VOID* lpBuffer,
  __in        DWORD nNumberOfCharsToWrite,
  __out       LPDWORD lpNumberOfCharsWritten,
  __reserved  LPVOID lpReserved
);
//Implemented as WriteConsoleW (Unicode) and WriteConsoleA (ANSI).


BOOL WINAPI ReadConsole(
  __in      HANDLE hConsoleInput,
  __out     LPVOID lpBuffer,
  __in      DWORD nNumberOfCharsToRead,
  __out     LPDWORD lpNumberOfCharsRead,
  __in_opt  LPVOID pInputControl
);
//Implemented as ReadConsoleW (Unicode) and ReadConsoleA (ANSI).


BOOL WINAPI ReadConsoleOutput(
  __in     HANDLE hConsoleOutput,
  __out    PCHAR_INFO lpBuffer,
  __in     COORD dwBufferSize,
  __in     COORD dwBufferCoord,
  __inout  PSMALL_RECT lpReadRegion
);
//Implemented as ReadConsoleOutputW (Unicode) and ReadConsoleOutputA (ANSI).


В укажанной вами ссылке для VB имеем пример:
Код: plaintext
1.
2.
3.
   Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" _
           (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal _
           nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, _
           lpReserved As Any) As Long

По аналогии я бы задекларировал это дело так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
   Declare Function ReadConsole Lib "kernel32" Alias "ReadConsoleA" _
           (ByVal hConsoleInput As Long, lpBuffer As Any, ByVal _
           nNumberOfCharsToRead As Long, lpNumberOfCharsRead As Long, _
           pInputControl As Any) As Long

   Declare Function ReadConsoleOutput Lib "kernel32" Alias "ReadConsoleOutputA" _
           (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal _
           dwBufferSize As Long, dwBufferCoord As Long, _
           lpReadRegion As Any) As Long

(первую видимо угадал, в правильности написания второй есть сомнения, но пока не уловил, которая из них мне нужна)

Далее туплю,попытался "модифицировать" код из примера,типа

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
   Private Sub Command1_Click()
   Dim Result As Long, sOut As String, cWritten As Long
   Dim Result1 As Long, sIn As String, cWritten1 As Long
     sOut = "Hi There" & vbCrLf
     Result = WriteConsole(hConsole, ByVal sOut, Len(sOut), cWritten, _
                           ByVal  0 &)
     Shell "C:\111\TEST.BAT"
     Result1 = ReadConsole(hConsole, sIn,  200 , cWritten1, ByVal  0 &)
     MsgBox sIn
   End Sub

Оно не ругнулось, стало быть угадал в декларировании, однако MsgBox выдался пустой.
Техники не могу уловить, как этот буфер консоли отлавливать.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35053667
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
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.
157.
158.
159.
Option Explicit

Private Declare Function CreatePipe Lib "kernel32" (phReadPipe _
        As Long, phWritePipe As Long, lpPipeAttributes As Any, _
        ByVal nSize As Long) As Long
        
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile _
        As Long, ByVal lpBuffer As String, ByVal _
        nNumberOfBytesToRead As Long, lpNumberOfBytesRead As _
        Long, ByVal lpOverlapped As Any) As Long
          
Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
        lpApplicationName As Long, ByVal lpCommandLine As _
        String, lpProcessAttributes As Any, lpThreadAttributes _
        As Any, ByVal bInheritHandles As Long, ByVal _
        dwCreationFlags As Long, ByVal lpEnvironment As Long, _
        ByVal lpCurrentDirectory As Long, lpStartupInfo As Any, _
        lpProcessInformation As Any) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal _
        hObject As Long) As Long

Private Declare Function PeekNamedPipe Lib "kernel32" (ByVal _
        hNamedPipe As Long, lpBuffer As Any, ByVal nBufferSize _
        As Long, lpBytesRead As Long, lpTotalBytesAvail As Long, _
        lpBytesLeftThisMessage As Long) As Long

Private Declare Function WaitForSingleObject Lib "kernel32" ( _
        ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
        
Private Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Long
End Type
      
Private Type STARTUPINFO
  cb As Long
  lpReserved As Long
  lpDesktop As Long
  lpTitle As Long
  dwX As Long
  dwY As Long
  dwXSize As Long
  dwYSize As Long
  dwXCountChars As Long
  dwYCountChars As Long
  dwFillAttribute As Long
  dwFlags As Long
  wShowWindow As Integer
  cbReserved2 As Integer
  lpReserved2 As Long
  hStdInput As Long
  hStdOutput As Long
  hStdError As Long
End Type
      
Private Type PROCESS_INFORMATION
  hProcess As Long
  hThread As Long
  dwProcessID As Long
  dwThreadID As Long
End Type
         
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const STARTF_USESTDHANDLES = &H100&
Private Const STARTF_USESHOWWINDOW = &H1
      
Private Declare Function CharToOem Lib "user32" Alias "CharToOemA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Private Declare Function OemToChar Lib "user32" Alias "OemToCharA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
            
Private Sub Command1_Click()
    
    If Len(Trim$(Me.Text2.Text)) >  0  Then
        Screen.MousePointer =  11 
        Me.Text1.Text = ""
        Text1.Text = ExecCmd(Me.Text2.Text)
        Screen.MousePointer =  0 
    End If
    
End Sub

Private Function ExecCmd(ByVal cmdline As String) As String
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim sa As SECURITY_ATTRIBUTES
Dim hReadPipe As Long, hWritePipe As Long
Dim L As Long, Result As Long, bSuccess As Long
Dim Buffer As String
Dim s As String
Dim sss As String
Dim retText As String
    
    sa.nLength = Len(sa)
    sa.bInheritHandle =  1 &
    sa.lpSecurityDescriptor =  0 &
    Result = CreatePipe(hReadPipe, hWritePipe, sa,  0 )
   
    If Result =  0  Then
        MsgBox "CreatePipe failed Error!"
        Exit Function
    End If
   
    start.cb = Len(start)
    start.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
    start.hStdOutput = hWritePipe
    
    
    Result = CreateProcessA( 0 &, cmdline, sa, sa,  1 &, _
        NORMAL_PRIORITY_CLASS,  0 &,  0 &, start, proc)

    If Result <>  0  Then
        
        Dim lPeekData As Long
        
        Do
            Call PeekNamedPipe(hReadPipe, ByVal  0 &,  0 &, ByVal  0 &, _
                lPeekData, ByVal  0 &)
            
            If lPeekData >  0  Then
                Buffer = Space$(lPeekData)
                bSuccess = ReadFile(hReadPipe, Buffer, Len(Buffer), L,  0 &)
                
                If bSuccess =  1  Then
                    
                    s = Left(Buffer, L)
                    sss = Space$(Len(s))
                    OemToChar s, sss
                    
                    retText = retText & sss
                    
                Else
                    MsgBox "ReadFile failed!"
                End If
            Else
                bSuccess = WaitForSingleObject(proc.hProcess,  0 &)
                        
                If bSuccess =  0  Then
                    Exit Do
                End If
            End If
            
            DoEvents
        Loop
            
    Else
        MsgBox "Error while starting process!"
    End If
    
    Call CloseHandle(proc.hProcess)
    Call CloseHandle(proc.hThread)
    Call CloseHandle(hReadPipe)
    Call CloseHandle(hWritePipe)
    
    ExecCmd = retText
End Function

Private Sub Form_Load()
    Command1.Caption = "Start"
End Sub
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35054004
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я ваш код оценил, даже сделал для теста вот так:
Код: 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.
       Do
            Call PeekNamedPipe(hReadPipe, ByVal  0 &,  0 &, ByVal  0 &, _
                lPeekData, ByVal  0 &)
            
            If lPeekData >  0  Then
                Buffer = Space$(lPeekData)
                bSuccess = ReadFile(hReadPipe, Buffer, Len(Buffer), L,  0 &)
                
                If bSuccess =  1  Then
                    
                    s = Left(Buffer, L)
                    sss = Space$(Len(s))
                    OemToChar s, sss
'-------------------------------------------------------------------------------------------
                    MsgBox sss
'-------------------------------------------------------------------------------------------
                    retText = retText & sss
                    
                Else
                    MsgBox "ReadFile failed!"
                End If
            Else
                bSuccess = WaitForSingleObject(proc.hProcess,  0 &)
                        
                If bSuccess =  0  Then
                    Exit Do
                End If
            End If
            
            DoEvents
        Loop
 

И те строчки, которые я привел в начале топика, т.е. то что выводится в течении нескольких минут, выдались мне в MsgBox целиком , мне же надо их считывать в тот момент, как они возникают на экране.
Если я просто в командной строке пишу proga.exe > 1.txt то файл 1.txt у меня пустой и заполняется целиком лишь по окончании процесса. А ваш код ведет себя похоже точно также, т.е.Buffer не заполняется до самого конца работы программы, или я что-то не допонял?

Т.е. на экране я уже вижу строчку, следующая будет напр.через минуту, но ни в 1.txt, ни в bufer ничего нет, а надо чтобы это уже где-то было.
Понятно, чтобы получить лог, вполне достаточно прочесть все в конце процесса, но хочется еще наблюдать за процессом из удобного интерфейса, коим консоль на мой взгляд не является, и я бы ее запускал "невидимо". Ибо если у меня одна консоль, это еще худо-бедно, а если у меня 4 линии (консоли) то это уже совсем хреново.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35054437
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нашел вот даже такую умную штуку,где есть куча всего:

http://vb.mvps.org/samples/project.asp?id=console

Максимум чего научился, считывать то что введено в консоль с клавиатуры.

А если переформулировать вопрос.
Можно ли тупо прочитать все то что написано в консоли в текущий момент времени?
Т.е. msgbox "все то, что вижу на черном экране".
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35055416
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Debug.Print вместо MsgBox не пробовали использовать?
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35055464
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и еще вот это почитай, возможно в твоем случае ничего не поможет.
http://support.microsoft.com/kb/190351
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35055561
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и еще , попробуй добавить:



...
start.hStdOutput = hWritePipe
start.hStdError = hWritePipe
...
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35055945
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот попробуй так, stderror сам прикрути по аналогии:


Код: 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.
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.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
Option Explicit

Private Declare Function DuplicateHandle Lib "kernel32" (ByVal hSourceProcessHandle As Long, ByVal hSourceHandle As Long, ByVal hTargetProcessHandle As Long, lpTargetHandle As Long, ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwOptions As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Function ExitProcess Lib "kernel32" (ByVal uExitCode As Long)
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long

Private Declare Function CreatePipe Lib "kernel32" (phReadPipe _
        As Long, phWritePipe As Long, lpPipeAttributes As Any, _
        ByVal nSize As Long) As Long
        
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile _
        As Long, ByVal lpBuffer As String, ByVal _
        nNumberOfBytesToRead As Long, lpNumberOfBytesRead As _
        Long, ByVal lpOverlapped As Any) As Long
          
Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
        lpApplicationName As Long, ByVal lpCommandLine As _
        String, lpProcessAttributes As Any, lpThreadAttributes _
        As Any, ByVal bInheritHandles As Long, ByVal _
        dwCreationFlags As Long, ByVal lpEnvironment As Long, _
        ByVal lpCurrentDirectory As Long, lpStartupInfo As Any, _
        lpProcessInformation As Any) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal _
        hObject As Long) As Long

Private Declare Function PeekNamedPipe Lib "kernel32" (ByVal _
        hNamedPipe As Long, lpBuffer As Any, ByVal nBufferSize _
        As Long, lpBytesRead As Long, lpTotalBytesAvail As Long, _
        lpBytesLeftThisMessage As Long) As Long

Private Declare Function WaitForSingleObject Lib "kernel32" ( _
        ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
        
Private Type SECURITY_ATTRIBUTES
  nLength As Long
  lpSecurityDescriptor As Long
  bInheritHandle As Long
End Type
      
Private Type STARTUPINFO
  cb As Long
  lpReserved As Long
  lpDesktop As Long
  lpTitle As Long
  dwX As Long
  dwY As Long
  dwXSize As Long
  dwYSize As Long
  dwXCountChars As Long
  dwYCountChars As Long
  dwFillAttribute As Long
  dwFlags As Long
  wShowWindow As Integer
  cbReserved2 As Integer
  lpReserved2 As Long
  hStdInput As Long
  hStdOutput As Long
  hStdError As Long
End Type
      
Private Type PROCESS_INFORMATION
  hProcess As Long
  hThread As Long
  dwProcessID As Long
  dwThreadID As Long
End Type

Private Const INFINITE = &HFFFF
Private Const DUPLICATE_SAME_ACCESS = &H2
         
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const STARTF_USESTDHANDLES = &H100&
Private Const STARTF_USESHOWWINDOW = &H1
      
Private Declare Function CharToOem Lib "user32" Alias "CharToOemA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Private Declare Function OemToChar Lib "user32" Alias "OemToCharA" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
            
            
Dim bExit As Boolean
'

Private Sub Command1_Click()
Dim s As String

    If Len(Trim$(Me.Text2.Text)) >  0  Then
        Screen.MousePointer =  11 
        bExit = False
        Me.Command2.Enabled = True
        s = ExecCmd(Me.Text2.Text, Me.Text1)
        Me.Text1.SelStart = Len(Me.Text1.Text)
        Me.Text1.SelText = s
        Me.Command2.Enabled = False
        Screen.MousePointer =  0 
    End If
    
End Sub

Private Function ExecCmd(ByVal cmdline As String, ByRef OUT As VB.TextBox) As String
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim sa As SECURITY_ATTRIBUTES
Dim L As Long, Result As Long, bSuccess As Long
Dim Buffer As String
Dim s As String
Dim sss As String
Dim hReadPipe As Long, hWritePipe As Long
Dim hReadStdOutputDup As Long
Dim hReadStdError As Long
Dim hWriteStdError As Long
Dim hReadStdErrorDup As Long

    OUT.Text = ""
    
    sa.nLength = Len(sa)
    sa.bInheritHandle =  1 &
    sa.lpSecurityDescriptor =  0 &
    
    start.cb = Len(start)
    start.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
    
    Result = CreatePipe(hReadPipe, hWritePipe, sa,  0 )
    If Result =  0  Then
        ExecCmd = "ERROR: CreatePipe failed Error!"
        GoTo lb_out
    End If
    If DuplicateHandle(GetCurrentProcess(), hReadPipe, GetCurrentProcess(), hReadStdOutputDup,  0 &,  0 &, DUPLICATE_SAME_ACCESS) =  0  Then
        ExecCmd = "ERROR: " & Err.LastDllError & " DuplicateHandle ReadPipe."
        GoTo lb_out
    End If
    start.hStdOutput = hWritePipe
    
    If CreatePipe(hReadStdError, hWriteStdError, sa,  0 ) =  0  Then
        ExecCmd = "ERROR: " & Err.LastDllError & " CreatePipe StdError."
        GoTo lb_out
    End If
    If DuplicateHandle(GetCurrentProcess(), hReadStdError, GetCurrentProcess(), hReadStdErrorDup,  0 &,  0 &, DUPLICATE_SAME_ACCESS) =  0  Then
        ExecCmd = "ERROR: " & Err.LastDllError & " DuplicateHandle ReadStdError."
        GoTo lb_out
    End If
    start.hStdError = hWriteStdError
    
    
    Result = CreateProcessA( 0 &, cmdline, sa, sa,  1 &, _
        NORMAL_PRIORITY_CLASS,  0 &,  0 &, start, proc)

    If Result <>  0  Then
        
        Dim lPeekData As Long
        
        Do
            Call PeekNamedPipe(hReadStdOutputDup, ByVal  0 &,  0 &, ByVal  0 &, _
                lPeekData, ByVal  0 &)
            
            If lPeekData >  0  Then
                Buffer = Space$(lPeekData)
                bSuccess = ReadFile(hReadStdOutputDup, Buffer, Len(Buffer), L,  0 &)
                
                If bSuccess =  1  Then
                    
                    s = Left(Buffer, L)
                    sss = Space$(Len(s))
                    OemToChar s, sss
                    
                    OUT.SelStart = Len(OUT.Text)
                    OUT.SelText = sss
                    
                Else
                    ExecCmd = "ERROR: ReadFile failed!"
                    Exit Do
                End If
            Else
                bSuccess = WaitForSingleObject(proc.hProcess,  0 &)
                        
                If bSuccess =  0  Then
                    Exit Do
                End If
            End If
            
            If bExit Then
                bExit = False
                TerminateProcess proc.hProcess, Result
                ExecCmd = vbCrLf & "Stopped."
                GoTo lb_out
            End If
            
            DoEvents
        Loop
        ExecCmd = vbCrLf & "Success."
            
    Else
        ExecCmd = "ERROR: Error while starting process!"
    End If
    
lb_out:
    Call CloseHandle(proc.hProcess)
    Call CloseHandle(proc.hThread)
    Call CloseHandle(hReadPipe)
    Call CloseHandle(hWritePipe)
    Call CloseHandle(hReadStdError)
    Call CloseHandle(hWriteStdError)
    Call CloseHandle(hReadStdOutputDup)
    Call CloseHandle(hReadStdErrorDup)
    
    
End Function

Private Sub Command2_Click()
    bExit = True
    Me.Command1.Enabled = True
    Me.Command2.Enabled = False
    Screen.MousePointer =  0 
End Sub

Private Sub Form_Load()
    Command1.Caption = "Start"
    Me.Command2.Enabled = False
End Sub
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35055984
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет, ничего не помогло. Выводит все скопом и лишь в конце своей работы.

Приложение, о котором идет речь - маленькая утилита от разработчика и назначение ее - дослать факс через свою спецефическую TAPI-fax-line. Прелесть ее в том, что она каким-то боком используя Microsoft Fax не использует сам сервер,т.е. работает "в обход". Т.е. если например в XP есть ограничение 1 факс-девайс одновременно, то ничто не мешает запустить мне 3 экземпляра этой программы одновременно.
У меня мной давно написано приложение, кот. делает то же самое, но в отличие от утилиты работает непосредсвенно с Microsoft-fax сервером.Т.е. создает факс-задание а потом отслеживает состояние этого задания через ф-ции факс-сервера. Эдакий непрерывный долбеж по факс серверу. В принципе моя штука работает достаточно устойчиво но:

1)Многоканально она может работать только на win2003, ибо xp позволяет только один канал, и на мою программу это распостраняется
2)Периодически надо вычищать консоль факсов от мусора из недосланных и досланных факсов (на эту тему утилиту я тоже написал)
3) Т.к. консольное приложение написано профессионалами, оно надежней, да оно и по логике гораздо более прямолинейное и понятное, я бы конечно предпочел запускать его, а не возиться с сообщениями сервера.

Я написал разработчикам письмо на тему что-либо поменять с выводом в понятное место (ну напр. добавить REAL-time log) или дать исходный код (утилиты, понятно, а не их основного коммерческого продукта), есть шанс что помощь придет "оттуда".
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056016
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я проверял на:

ping -t www.sql.ru
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056020
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот исходник в сборе.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056156
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneя проверял на:

ping -t www.sql.ru

Что я вам могу на это сказать...
Ping у меня тоже работает красиво с вашим исходником (собственно, текста в форуме было достаточно).
Следуя своей логике, я не поленился запустить в консоли (без всякого програмирования) команду
ping -t www.sql.ru > 1.txt
и открывая этот файл в процессе работы в другом окне far убеждался в том, что строчек в 1.txt становится все больше и больше, т.е. даже не используя ваш пример я бы просто читал 1.txt раз в 1сек, и получал бы оттуда все что надо.
А вот с этой коварной утилитой - весь вывод лишь в конце ее работы. Я так понимаю, смысл статьи, что вы предлагали почитать, что "вот-де есть такие коварные приложения типа рассматриваемого, которые -де так вот плохо себя ведут, как я описываю".
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056226
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
добавьте в цикл обработку пайпа hReadStdErrorDup по аналогии с hReadStdOutputDup
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056356
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
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.
start.hStdOutput = hWritePipe
    start.hStdError = hWritePipe

    
    Result = CreateProcessA( 0 &, cmdline, sa, sa,  1 &, _
        NORMAL_PRIORITY_CLASS,  0 &,  0 &, start, proc)

    If Result <>  0  Then
        
        Dim lPeekData As Long
        
        Do
            Call PeekNamedPipe(hReadStdOutputDup, ByVal  0 &,  0 &, ByVal  0 &, _
                lPeekData, ByVal  0 &)
            
            If lPeekData >  0  Then
                Buffer = Space$(lPeekData)
                bSuccess = ReadFile(hReadStdOutputDup, Buffer, Len(Buffer), L,  0 &)
                
                If bSuccess =  1  Then
                    
                    s = Left(Buffer, L)
                    sss = Space$(Len(s))
                    OemToChar s, sss
                    
                    OUT.SelStart = Len(OUT.Text)
                    OUT.SelText = sss
                    
                Else
                    ExecCmd = "ERROR: ReadFile failed!"
                    Exit Do
                End If
            Else
                bSuccess = WaitForSingleObject(proc.hProcess,  0 &)
                        
                If bSuccess =  0  Then
                    Exit Do
                End If
            End If
            
            Call PeekNamedPipe(hReadStdErrorDup, ByVal  0 &,  0 &, ByVal  0 &, _
                lPeekData, ByVal  0 &)
            
            If lPeekData >  0  Then
                Buffer = Space$(lPeekData)
                bSuccess = ReadFile(hReadStdErrorDup, Buffer, Len(Buffer), L,  0 &)
                
                If bSuccess =  1  Then
                    
                    s = Left(Buffer, L)
                    sss = Space$(Len(s))
                    OemToChar s, sss
                    
                    OUT.SelStart = Len(OUT.Text)
                    OUT.SelText = sss
                    
                Else
                    ExecCmd = "ERROR: ReadFile failed!"
                    Exit Do
                End If
            Else
                bSuccess = WaitForSingleObject(proc.hProcess,  0 &)
                        
                If bSuccess =  0  Then
                    Exit Do
                End If
            End If
            
            If bExit Then
                bExit = False
                TerminateProcess proc.hProcess, Result
                ExecCmd = vbCrLf & "Stopped."
                GoTo lb_out
            End If
            
            DoEvents
        Loop
        ExecCmd = vbCrLf & "Success."

???(возможно натупил) не хочет...
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056375
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тогда видно все-таки это:

Note Some console based applications do not use the standard handles for their input/output (IO) operations. The Win32 API does not support redirection of these processes.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056458
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneтогда видно все-таки это:

Note Some console based applications do not use the standard handles for their input/output (IO) operations. The Win32 API does not support redirection of these processes.

Я именно на это и обратил внимание, когда писал
Я писал...Я так понимаю, смысл статьи, что вы предлагали почитать, что "вот-де есть такие коварные приложения типа рассматриваемого, которые -де так вот плохо себя ведут, как я описываю".

Но ведь в консоль же она как-то из себя пишет? Нельзя эту консоль целиком прочесть как есть? Или это уже картинка просто после вывода?
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056473
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
видно в конце работы это приложение все что было вываливает в консоль, а до этого работает с ней в графическом режиме (скорее всего писали ее на C++)
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056520
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konst_Oneскорее всего писали ее на C++
Понятно, что не на VB. Если хотите, могу кинуть exe-шник (69кб), запускать его вам бесполезно (да и неправильно чужие exe-шники запускать) если только по F3 или каким hiew-вьюером глянуть, может больше моего в нем увидете.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056540
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
спс конечно за доверие, но как-то нет особого желания. думаю, что осается бодаться вам с разработчиками данной утилиты, чтобы они вам пошли навстречу в этом вопросе.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056586
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только что прислали ответ:
... is a "console mode" application ;
to collect in real time the logged line, you application needs to:
- run sendfax.exe and to "redirect standard output" (stdout)
- your application should then read from redirected stdout (character by character)
We do not have sample code for such system programming; however you should find some on the WEB.

А то что мы тут делали это не то же самое?
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056763
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Только что прислали ответ:
... is a "console mode" application ;
to collect in real time the logged line, you application needs to:
- run sendfax.exe and to "redirect standard output" (stdout)
- your application should then read from redirected stdout (character by character)
We do not have sample code for such system programming; however you should find some on the WEB.

А то что мы тут делали это не то же самое?В принципе, тоже самое. Во всяком случае они намекают что пайпов будет достаточно. А в твоих экспериментах пайпы не заработали?
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35056855
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Console is the most flexible mode.
Sendfax.exe outputs the result in real time ; command line redirection to file (using ">") may however produce the file only once operation is complete or enough data was collected (but should be "command line" = "shell" = ~"DOS" specific behavior).
If you VB app redirects the console output (stdout) when executing sendfax.exe, then your VB app can read each line as soon as they are produced by sendfax.exe (and write it in real-time to a file, …).
Note that you may be able in VB to redirect stdout directly to a file with some code that may look as follow (search Google for: +"redirect stdout" +createfile):
1) CreateFile
2) Redirect stdout to handle of file previously created (set proper handle in STARTUPINFO that will be passed to CreateProcess)
3) execute "sendfax" using CreateProcess
4) close handle.
There are no plans to change this utility.


Я уже и на C++ этот код попробовал (поиск привел именно к той статье, что вы мне указали, там где Note:) -результат тот же
Ощущение такое что они намекают на тот самый код, который вы привели, (или на что-то более тонкое???) "character by character", но код то этот не работает в данном конкретном случае и они это я так понимаю не проверяли.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35057337
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал так как они сказали что называется в лоб:
Код: 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.
#include <windows.h>
void main()
{
    HANDLE hFile;

    SECURITY_ATTRIBUTES sa;

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;    
    sa.lpSecurityDescriptor = NULL;

//) 1)CreateFile
    hFile = CreateFile(
                "stdout.txt",
                GENERIC_WRITE | GENERIC_READ, 
                FILE_SHARE_READ | FILE_SHARE_WRITE, 
                &sa,
                OPEN_ALWAYS,
                 0 ,
                NULL);
//2) Redirect stdout to handle of file previously created (set proper handle in STARTUPINFO that will be passed to CreateProcess)

    SetFilePointer(hFile,  0 , NULL, FILE_END);

    STARTUPINFO si = {sizeof(STARTUPINFO)};

    si.hStdOutput = hFile;
    si.dwFlags    = STARTF_USESTDHANDLES;

    PROCESS_INFORMATION pi;
//3) execute "sendfax" using CreateProcess
    CreateProcess(NULL, "c:\\111\\sendfax.exe 84951234567 c:\\fax.tif /convert=no /output=txt", NULL, NULL, TRUE , 0 ,  0 ,  0 , &si, &pi);
//4) close handle
    CloseHandle(hFile);
}
Те же грабли только в профиль.
ping -работает "как надо"
то что надо - работает как и во всех предыдущих рассмотрениях, т.е. полный вывод лишь в конце.

P.S. За C++ просьба не язвить. Я к нему прибегаю в крайних случаях. Ясно одно: если этот код на C++ не работает,то будучи переделанным на VB он также не заработает "как надо".
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35057774
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что-то они явно не договаривают, раз примера нет. пошли им свой, пусть скажут , что не так.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35058084
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня тут возникла простая трезвая мысль.
В любой консоли ручками можно сделать Выделить все -> Копировать(или Enter), потом пойти в блокнот и написать "вставить".Эффект по сути требуемый будет. Это ведь можно сделать программно? Единственное, используется буфер обмена и если таких консолей будет 4 (а информацию разумно считывать хотя бы 1 раз в секунду)+ я еще сижу работаю, то информация может перекреститься-потеряться и будет бардак. Т.е. идея копирования всего экрана в данном случае разумна(информации не бог весть сколько), но только не в буфер обмена. Надо подумать...
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35058663
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот, вполне рабочий вариант получился:
Код: 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.
Dim commandText As String
Dim dTaskID As Double
Dim fsuccess As Integer
Dim csScreenBuffer As CONSOLE_SCREEN_BUFFER_INFO
Dim ConsoleBoundary As SMALL_RECT
Dim XPos As Integer, YPos As Integer
Private Sub Command1_Click()
    'запуск консоли
     If AllocConsole() Then
       hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE)
       If hConsoleOut =  0  Then Err.Raise Number:= 502 , Description:="Couldn't allocate STDOUT"
     Else
       Err.Raise Number:= 502 , Description:="Couldn't allocate console"
     End If
    commandText = Text2.Text
    'таймер активирован
    Timer1.Enabled = True
    'запуск приложения и ожидание его завершения
    ShellAndContinue commandText
    'таймер дезактивирован
    Timer1.Enabled = False
    'еще раз читаем экран на случай если не успели считать крайние строки
    Timer1_Timer
    'расправляемся с ненужной более консолью
    CloseHandle hConsoleOut
    FreeConsole
End Sub

Private Sub Timer1_Timer()
    'раз в 0,5 сек читает экран консоли
    fsuccess = GetConsoleScreenBufferInfo(hConsoleOut, csScreenBuffer)
    'non-zero result is a success
    ConsoleBoundary = csScreenBuffer.srWindow
    Dim lineMessage As String *  80 
    readLength =  80 
    XPos =  0 
    YPos =  0 
    Text1.Text = ""
    'последовательное чтение всех видимых на экране строк
    For YPos =  0  To ConsoleBoundary.Bottom
        def = ReadConsoleOutputCharacter(hConsoleOut, lineMessage, readLength, YPos *  65536 , vbNull)
        If Trim(lineMessage) <> "" Then
            Text1.Text = Text1.Text & Trim(lineMessage) & vbCrLf
        End If
    Next YPos
End Sub
Плюс модуль конечно, пришлось из двух один собирать:
Код: 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.
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.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
Option Explicit
'Functions that support the application opening the command
'window where the subsequent execcmd will execute from,
'as well as close and free the command window.
'Also functions that support reading the console screen buffer

Public hConsoleIn As Long
Public hConsoleOut As Long

Global Const NORMAL_PRIORITY_CLASS = &H20&
Global Const INFINITE = - 1 &
Public Const STD_OUTPUT_HANDLE = - 11 &
Public Const STD_INPUT_HANDLE = - 10 &


Public Const GW_HWNDFIRST =  0 
Public Const GW_HWNDLAST =  1 
Public Const GW_HWNDNEXT =  2 
Public Const GW_HWNDPREV =  3 

Public Const GW_CHILD =  5 
Public Const GW_MAX =  5 


Public Const STILL_ACTIVE = &H103
Public Const PROCESS_QUERY_INFORMATION = &H400

Public Const GW_OWNER =  4 
Public Const GWL_STYLE = - 16 
Public Const WS_DISABLED = &H8000000
Public Const WS_CANCELMODE = &H1F
Public Const WM_CLOSE = &H10

Public glCurrentHwnd

Public Type STARTUPINFO
      cb As Long
      lpReserved As String
      lpDesktop As String
      lpTitle As String
      dwX As Long
      dwY As Long
      dwXSize As Long
      dwYSize As Long
      dwXCountChars As Long
      dwYCountChars As Long
      dwFillAttribute As Long
      dwFlags As Long
      wShowWindow As Integer
      cbReserved2 As Integer
      lpReserved2 As Long
      hStdInput As Long
      hStdOutput As Long
      hStdError As Long
End Type

Public Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type

Public Type COORD
        x As Integer
        y As Integer
End Type

Public Type SMALL_RECT
        Left As Integer
        Top As Integer
        Right As Integer
        Bottom As Integer
End Type

Public Type CONSOLE_SCREEN_BUFFER_INFO
        dwSize As COORD
        dwCursorPosition As COORD
        wAttributes As Integer
        srWindow As SMALL_RECT
        dwMaximumWindowSize As COORD
End Type

Declare Function AllocConsole Lib "kernel32" () As Long

Declare Function FreeConsole Lib "kernel32" () As Long

Declare Function GetStdHandle Lib "kernel32" (ByVal _
           nStdHandle As Long) As Long

Declare Function GetLastError Lib "kernel32" ()

Declare Function GetConsoleScreenBufferInfo Lib "kernel32" _
(ByVal hConsoleOutput As Long, _
lpConsoleScreenBufferInfo As CONSOLE_SCREEN_BUFFER_INFO) As Long

Declare Function SetConsoleCursorPosition Lib "kernel32" _
(ByVal hConsoleOutput As Long, ByVal CursorPosition As Long) As Long

Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
    hHandle As Long, ByVal dwMilliseconds As Long) As Long

Declare Function CreateProcessA Lib "kernel32" (ByVal _
    lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
    lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
    ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
    ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
    lpStartupInfo As STARTUPINFO, lpProcessInformation As _
    PROCESS_INFORMATION) As Long

Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long

Declare Function GetExitCodeProcess Lib "kernel32" _
    (ByVal hProcess As Long, lpExitCode As Long) As Long

Declare Function ReadConsoleOutputCharacter Lib "kernel32" Alias _
"ReadConsoleOutputCharacterA" _
    (ByVal hConsoleOutput As Long, ByVal lpCharacter As String, ByVal _
    nLength As Long, ByVal dwReadCoord As Long, _
    lpNumberOfCharsRead As Long) As Long


Declare Function OpenProcess Lib "kernel32" _
   (ByVal dwDesiredAccess As Long, ByVal bInheritHandle _
   As Long, ByVal dwProcessID As Long) As Long
Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) _
    As Long
Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, _
    ByVal wCmd As Long) As Long
Declare Function PostMessage Lib "user32" Alias _
    "PostMessageA" (ByVal hwnd As Long, ByVal wMsg _
    As Long, ByVal wParam _
    As Long, ByVal lParam As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias _
    "GetWindowLongA" (ByVal hwnd As Long, _
    ByVal nIndex As Long) As Long
Declare Function GetParent Lib "user32" (ByVal hwnd _
As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias _
    "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Declare Function GetWindowText Lib "user32" Alias _
    "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString _
    As String, ByVal cch As Long) As Long

Public Const SW_SHOWNOACTIVATE =  4 

Declare Function ShowWindow Lib "user32" (ByVal hwnd _
    As Long, ByVal nCmdShow As Long) As Long
Public Sub ShellAndContinue(ByVal AppToRun As String)
   ' On Error GoTo ErrorRoutineErr
    
    Dim hProcess As Long
    Dim RetVal As Long
    Dim Msg, Style, Title, Response 'msgbox variables
    
    'The next line launches AppToRun,
    'captures process ID
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,  1 , _
    Shell(AppToRun, vbHide))
    Do
        'Get the status of the process
        GetExitCodeProcess hProcess, RetVal
        DoEvents
    'Loop while the process is active
    Loop While RetVal = STILL_ACTIVE
    
ErrorRoutineResume:
    Exit Sub
'ErrorRoutineErr:
'    MsgBox Error.Description
End Sub

Public Function ExecCmd(cmdline$)
    Dim proc As PROCESS_INFORMATION
    Dim start As STARTUPINFO
    Dim ret&

    ' Initialize the STARTUPINFO structure:
    start.cb = Len(start)

    ' Start the shelled application:
    ret& = CreateProcessA(vbNullString, cmdline$,  0 &,  0 &,  1 &, _
        NORMAL_PRIORITY_CLASS,  0 &, vbNullString, start, proc)

    ' Wait for the shelled application to finish:
        ret& = WaitForSingleObject(proc.hProcess, INFINITE)
        Call GetExitCodeProcess(proc.hProcess, ret&)
        Call CloseHandle(proc.hThread)
        Call CloseHandle(proc.hProcess)
        ExecCmd = ret&
End Function

Теперь вот задался двумя вопросами:
1) Как запустить консоль невидимо от пользователя, ибо
Shell(AppToRun, vbHide ) в ShellAndContinue здесь не поможет, консоль и так уже стартовала vbNormal
2) Не возникнет ли у меня проблем, если мое приложение будет запускать несколько таких консолей одновременно? Уж больно Couldn't allocate console при отладке сильно много ругалось.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35058737
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как запустить невидимо, похоже понял:

После AllocConsole() надо добавить:
Код: plaintext
ShowWindow FindWindow("ConsoleWindowClass", App.Path & "\" & App.EXEName & ".exe"), vbHide
в модуль при этом добавить
Код: plaintext
1.
Declare Function FindWindow Lib "User32.dll" Alias "FindWindowA" _
(ByVal Classname As String, ByVal WindowName As String) As Long
Здесь App.Path & "\" & App.EXEName & ".exe" -по сути то что написано в заголовке консоли при ее запуске, однако способ какой-то кривой получился: во первых если запускать из корня нужна обработка этой фразы, во-вторых если я запускаю несколько экземпляров проги, то еще непонятно какую там консоль найдет FindWindow -"свою" или "чужую", хотя поверхностный эксперимент показал, что "свою".

Как запустить несколько консолей из одного приложения таким методом, пока не разобрался, поигрался,возникло предположение что никак.
Если это так, то надо писать что-то типа console.exe [proga.exe] [logfile-name.txt]
Т.е. console.exe запускает proga.exe и в файл logfile-name.txt в REAL-TIME сваливаются сообщения от proga.exe

А центральное приложение запускает эти самые console.exe через shellandcontinue , по таймеру заглядывает в logfile-name.txt, до завершения console.exe просто красиво отображает информацию-чего там происходит, а по выходу окончательно анализирует logfile-name.txt и протоколирует результаты работы.
Как-то уж очень навороченно получается...проще конечно из центрального приложения запускать несколько консолей и хранить результаты их работы в массиве переменных (textbox-ах), а не в файлах
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35058753
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1)Можно конечно себя обезопасить, сделав так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
   SetConsoleTitle "MyNewConsole77"
    'пауза
    ltime = Timer()
    Do
        dummy = DoEvents()
        If (Timer - ltime >  0 . 000000001 ) Or (Timer < ltime) Then
            Exit Do
        End If
    Loop
    ShowWindow FindWindow("ConsoleWindowClass", "MyNewConsole77"), vbHide
Но здесь 2 минуса: 1)без хоть минимальной паузы код не работает 2) Окно консоли таки мелькает на экране, чего без переименовывания совсем не заметно

2) http://msdn2.microsoft.com/en-us/library/ms681944(VS.85).aspx
A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console.
Иными словами, из одного приложения можно управлять не более чем одной консолью.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35058754
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забыл в код дописать, иначе не понятно
Код: plaintext
1.
Declare Function SetConsoleTitle Lib "kernel32" Alias _
    "SetConsoleTitleA" (ByVal lpConsoleTitle As String) As Long
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35059071
AndrF
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий771) Как запустить консоль невидимо от пользователя, ибо
Shell(AppToRun, vbHide ) в ShellAndContinue здесь не поможет, консоль и так уже стартовала vbNormal

Запускать используя CreateProcess задавая 6-м параметром DETACHED_PROCESS.

Честно говоря все не читал, но что-то долго мучаетесь... У CreateProcess есть три параметра - им достаточно передавать указатели возвращенные CreateFile. Вот и все - все работает. Использовал это дело еще лет 8..10 назад...
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35059263
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы не забывайте, что я сначала вызываю консоль через AllocConsole(), а только потом создаю в ней CreateProcess, а AllocConsole() параметров не имеет.
Если бы я сначала делал CreateProcess, а потом AttachConsole(), то возможно ваш совет и пременился бы с успехом, хотя с AttachConsole() еще разбираться надо.
А в моем случае боюсь тот вариант, что я сам нашел единственный.
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35061258
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дело закончилось тем, что от разработчиков пришел новый exe-шник от 14.01
Please find attached an update that should enable redirection to file (from command prompt or CreateProcess) to operate in real time.
Our tests showed it was working in real time from command prompt.

Наши тесты тоже как ни странно это показали. Он "как надо" работает со всеми приведенными тут кодами, и даже корректно поддерживает "proga.exe > 1.txt", что вообще делает возможным элементарное

1) ShellAndContinue ("proga.exe > 1.txt")
2) FSys.OpenTextFile ("1.txt", forReading.. по таймеру
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35063481
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
раскрутили наконец разработчиков тулзы, молодец
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35063580
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Дело закончилось тем, что от разработчиков пришел новый exe-шник от 14.01
...Он "как надо" работает со всеми приведенными тут кодами, и даже корректно поддерживает "proga.exe > 1.txt", что вообще делает возможным элементарноеСкорее всего, старый вариант забывал сливать буфера. А новый соотвественно сливает их каждый раз после новой строки...
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35068562
AndrF
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Вы не забывайте, что я сначала вызываю консоль через AllocConsole(), а только потом создаю в ней CreateProcess, а AllocConsole() параметров не имеет.
Если бы я сначала делал CreateProcess, а потом AttachConsole(), то возможно ваш совет и пременился бы с успехом, хотя с AttachConsole() еще разбираться надо.
А в моем случае боюсь тот вариант, что я сам нашел единственный.

А зачем, собственно, AllocConsole с сопутствующими танцами? Почему не просто CreateProcess?
...
Рейтинг: 0 / 0
Чтение результатов работы консольного приложения
    #35069219
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AndrFА зачем, собственно, AllocConsole с сопутствующими танцами? Почему не просто CreateProcess?
Вы эту тему внимательно читали, сколько всего намучено было.
Я свои проблемы решил , причем методом "proga.exe > 1.txt" без всякого програмирования.

Но коль пошла такая пьянка, то ответьте на след.вопрос

Будет ли работать следующий код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Private Sub Timer1_Timer()
    'раз в 0,5 сек читает экран консоли
    fsuccess = GetConsoleScreenBufferInfo(hConsoleOut, csScreenBuffer)
    'non-zero result is a success
    ConsoleBoundary = csScreenBuffer.srWindow
    Dim lineMessage As String *  80 
    readLength =  80 
    XPos =  0 
    YPos =  0 
    Text1.Text = ""
    'последовательное чтение всех видимых на экране строк
    For YPos =  0  To ConsoleBoundary.Bottom
        def = ReadConsoleOutputCharacter(hConsoleOut, lineMessage, readLength, YPos *  65536 , vbNull)
        If Trim(lineMessage) <> "" Then
            Text1.Text = Text1.Text & Trim(lineMessage) & vbCrLf
        End If
    Next YPos
End Sub
без AllocConsole как вы говорите (надо прочитать консоль целиком!)
Только сами ответьте на этот вопрос (желательно код, а не общие намеки), ответ будет мне интересен после такого объема изысканий.
...
Рейтинг: 0 / 0
42 сообщений из 42, показаны все 2 страниц
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Чтение результатов работы консольного приложения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]