Войти

Показать полную графическую версию : [решено] запуск приложения с параметром /?


RUVATA
24-08-2010, 14:13
Всем доброго времени суток :)
при помощи
System.Diagnostics.Process.Start
можно запускать\останавливать и управлять процессами...

все ОК, но вот как-бы help по параметрам посмотреть...
параметр /? предоставляет справку в cmd если они у проги имеются...

Visual Studio 2010 //// vb.NET
консольное приложение

мне на определенном этапе необходимо, чтобы открылась вот эта самая справка...

архиватор 7zip прописан в сист.PATH как "7z"

н\п


System.Diagnostics.Process.Start("7z","/?")


видно как поверх консоли VS открывается еще одна в ней отображается справка и закрывается (доля секунды)...
как бы задержать вот эту справку?

Admiral
25-08-2010, 12:57
RUVATA если допустимо что б текст справки выводился не поверх консоли VS, а прямо в ней, то можно и не задерживать вывод.
Для осуществления вывода в консоль VS необходимо будет задействовать средства Win32:
CreatePipe -> Accessing CreateProcess from C# and VB.NET (http://blogs.msdn.com/b/thottams/archive/2006/08/11/696013.aspx) -> ReadFile (http://msdn.microsoft.com/ru-ru/library/system.runtime.interopservices.handleref.aspx)

RUVATA
25-08-2010, 13:53
у меня проблема, или код примера не верен, или какие-то свойства проекта не позволяют так испоьзовать dll


<DllImport("kernel32.dll")> _

Function CreateProcess( _

ByVal lpApplicationName As String, _

ByVal lpCommandLine As String, _

ByVal lpProcessAttributes As IntPtr, _

ByVal lpThreadAttributes As IntPtr, _

ByVal bInheritHandles As Boolean, _

ByVal dwCreationFlags As UInteger, _

ByVal lpEnvironment As IntPtr, _

ByVal lpCurrentDirectory As String, _

ByRef lpStartupInfo As STARTUPINFO, _

ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean

End Function


Че-т никак не пойму... в чем беда


<DllImport("KERNEL32.DLL", EntryPoint:="MoveFileW", SetLastError:=True,
CharSet:=CharSet.Unicode, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)>
Public Function MoveFile(
ByVal src As String,
ByVal dst As String) As Boolean
End Function


... без проблем

Admiral
25-08-2010, 13:58
RUVATA, можно воспользовался VB6м вариантом (см. в программе Api Viewer 2004 (http://www.activevb.de/rubriken/apiviewer/index-apiviewereng.html), не забывая что при переходе (VB6 -> VB.NET) Long заменяется на Integer)
Declare Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" ( _
ByVal lpApplicationName As String, _
ByVal lpCommandLine As String, _
ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
ByVal bInheritHandles As Integer, _
ByVal dwCreationFlags As Integer, _
ByRef lpEnvironment As Integer, _
ByVal lpCurrentDriectory As String, _
ByRef lpStartupInfo As STARTUPINFO, _
ByRef lpProcessInformation As PROCESS_INFORMATION) As Integer

RUVATA
25-08-2010, 14:02
так... я все поправил код работает... и смысл?
Accessing CreateProcess from C# and VB.NET »
он тупо открывает блокнот... ну по крайней мере выглядит так

Admiral
25-08-2010, 14:07
RUVATA это не готовый по вопросу пример, а пример лишь использования CreateProcess в VB.NET
Для осуществления поставленной задачи нужно последовательно использовать сразу три Win32:
CreatePipe CreateProcess ReadFile

RUVATA
25-08-2010, 14:57
ну... как бы... я все равно не понял о чем этот пример, функция CreateProcess это API-шный аналог NET-овского Process.Start ? Зачем?

мамочка... :o

а вот есть еще такая "фитча" Console.Set(In/Out) занимается перенаправлением ввода\вывода в консоль там никак не замудрить...

проблемма то как раз в том, чтобы найти вывод от "7z" Запущенного Process.Start, и перенаправить его в Console...

не верится что такая "хрень" требует аш 3 функции API... кстати про
# CreateProcess
# ReadFile »

я вроде понял... а
CreatePipe »
э-т что за приблуда

сам сейчас копаюсь в закаулках vb.NET все что касает перенаправления ввода\вывода...
есть способы клонировать поток, направить поток, но уже от запущенного процесса...
а в моем случае его надо перенаправить перед его запуском - вот тут тупняк

Admiral
25-08-2010, 15:10
RUVATA кстати там автор поста и спрашивает, зачем вам Win32 вариант. Ответ прост, в своё время был не обнаружен в .NET 1.0 и началось.

CreatePipe как раз и создаёт перед запуском среду для перенаправления потока, вызванного по CreateProcess. Останется только считать его посредством ReadFile
Возможно есть чисто .NET решения, однако при наличии WIN32 тратится на поиски может и не рационально.

Вот пример использования всех трёх функций воедино.

Public Structure SECURITY_ATTRIBUTES
Public nLength As Integer
Public lpSecurityDescriptor As Integer
Public bInheritHandle As Integer
End Structure

Declare Function CreatePipe Lib "kernel32.dll" ( _
ByRef phReadPipe As Integer, _
ByRef phWritePipe As Integer, _
ByRef lpPipeAttributes As SECURITY_ATTRIBUTES, _
ByVal nSize As Integer) As Integer

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

Const STARTF_USESTDHANDLES As Integer = &amp;H100
Const STARTF_USESHOWWINDOW As Integer = &amp;H1
Const SW_HIDE As Integer = 0

Public Structure PROCESS_INFORMATION
Public hProcess As Integer
Public hThread As Integer
Public dwProcessId As Integer
Public dwThreadId As Integer
End Structure

Declare Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" ( _
ByVal lpApplicationName As String, _
ByVal lpCommandLine As String, _
ByRef lpProcessAttributes As SECURITY_ATTRIBUTES, _
ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, _
ByVal bInheritHandles As Integer, _
ByVal dwCreationFlags As Integer, _
ByRef lpEnvironment As Integer, _
ByVal lpCurrentDriectory As String, _
ByRef lpStartupInfo As STARTUPINFO, _
ByRef lpProcessInformation As PROCESS_INFORMATION) As Integer

Const NORMAL_PRIORITY_CLASS As Integer = &amp;H20

Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Integer) As Integer

Const MAX_PATH As Integer = 260

Public Structure OVERLAPPED
Public ternal As Integer
Public ternalHigh As Integer
Public offset As Integer
Public OffsetHigh As Integer
Public hEvent As Integer
End Structure

Declare Function ReadFile Lib "kernel32.dll" ( _
ByVal hFile As Integer, _
ByVal lpBuffer As System.Text.StringBuilder, _
ByVal nNumberOfBytesToRead As Integer, _
ByRef lpNumberOfBytesRead As Integer, _
ByRef lpOverlapped As OVERLAPPED) As Boolean

Shared Function CmdAnswer2Buff(ByRef Command As String) As String
Dim hReadPipe As IntPtr = Nothing
Dim hWritePipe As IntPtr = Nothing

Dim sa As SECURITY_ATTRIBUTES
sa.nLength = System.Runtime.InteropServices.Marshal.SizeOf(sa)
sa.lpSecurityDescriptor = Nothing
sa.bInheritHandle = True

If CreatePipe(hReadPipe, hWritePipe, sa, 0) = 0 Then
MsgBox("Вызов функции CreatePipe() не прошёл успешно.", MsgBoxStyle.Critical, "Ошибка.")
Return Nothing
End If

Dim cif As STARTUPINFO = New STARTUPINFO()
cif.cb = System.Runtime.InteropServices.Marshal.SizeOf(cif)
cif.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
cif.wShowWindow = SW_HIDE
cif.hStdOutput = hWritePipe
cif.hStdError = hWritePipe
Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION()

If CreateProcess(Nothing, Command, Nothing, Nothing, True, NORMAL_PRIORITY_CLASS, Nothing, Nothing, cif, pi) = 0 Then
MsgBox("Путь или команда не верна", MsgBoxStyle.Critical, Command)
Return Nothing
End If

CloseHandle(hWritePipe)
CloseHandle(pi.hProcess)
CloseHandle(pi.hThread)

Dim ret As Boolean = True
Dim BufferA As System.Text.StringBuilder = New System.Text.StringBuilder(MAX_PATH)

Dim NumberOfBytesRead As Integer
Dim Buffer As String = Nothing
Do
ret = ReadFile(hReadPipe, BufferA, MAX_PATH - 1, NumberOfBytesRead, Nothing)
If NumberOfBytesRead &gt; 0 Then Buffer = Buffer &amp; BufferA.ToString
Loop While ret

CloseHandle(hReadPipe)
Return Buffer
End Function


Использовать так Console.WriteLine(CmdAnswer2Buff("7z /?"))

RUVATA
25-08-2010, 15:39
:o
без комментариев...
у меня весь проект едва-ли половина описанного решения...

RUVATA
25-08-2010, 16:38
А ТЕПЕРЬ описываю ПРАВИЛЬНЫЙ СПОСОБ перенаправления ввода\вывода любого процесса
в стандартные потоки используемые в консоли VS консольного приложения на vb.NET



Dim MyProcess As New Process

'
MyProcess.StartInfo.FileName = "7z"
' StartInfo.FileName - если приложение не описанно в sys.переменной PATH,
' то указывать полное имя к программе... н\п "C:\Program Files\7-Zip\7z.exe"
MyProcess.StartInfo.UseShellExecute = False
' это праметр определяет оболочку которая необходима для запуска процесса
' это приблуда для кроссплатформенности - ЗАБЫЛИ тупо всегда назначаем "False"
' тобишь открываем Wind-ой
MyProcess.StartInfo.RedirectStandardInput = True
' перенаправление потока ВВОД, и дискриптора 2 на стандартный поток реального времени
MyProcess.StartInfo.RedirectStandardOutput = False
' перенаправление потока ВЫВОД нам ни в коем случае не нужно... так что назначаем "False"
' и не забываем что речь идет о процессе у него все зеркально пользователю... т.е. то что пользователю ВЫВОД
' то процессу ВВОД
MyProcess.Start()
' запуск процесса.
Console.ReadKey()
' остановка на получении NextKey в консоли... для того чтоб она не закрылась




Сравним с решением при помощи API; :wow:

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

Admiral
31-08-2010, 14:16
RUVATA, отлично, если этот код то что нужно.

По подсветке код прошу сюда http://forum.oszone.net/thread-122281.html




© OSzone.net 2001-2012