Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] запуск приложения с параметром /? (http://forum.oszone.net/showthread.php?t=183726)

RUVATA 24-08-2010 14:13 1480739

запуск приложения с параметром /?
 
Всем доброго времени суток :)
при помощи
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 1481298

RUVATA если допустимо что б текст справки выводился не поверх консоли VS, а прямо в ней, то можно и не задерживать вывод.
Для осуществления вывода в консоль VS необходимо будет задействовать средства Win32:
CreatePipe -> Accessing CreateProcess from C# and VB.NET -> ReadFile

RUVATA 25-08-2010 13:53 1481348

у меня проблема, или код примера не верен, или какие-то свойства проекта не позволяют так испоьзовать 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 1481354

RUVATA, можно воспользовался VB6м вариантом (см. в программе Api Viewer 2004, не забывая что при переходе (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 1481356

так... я все поправил код работает... и смысл?
Цитата:

Цитата Admiral
Accessing CreateProcess from C# and VB.NET »

он тупо открывает блокнот... ну по крайней мере выглядит так

Admiral 25-08-2010 14:07 1481360

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

RUVATA 25-08-2010 14:57 1481410

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

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

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

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

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

Цитата Admiral
# CreateProcess
# ReadFile »

я вроде понял... а
Цитата:

Цитата Admiral
CreatePipe »

э-т что за приблуда

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

Admiral 25-08-2010 15:10 1481419

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 1481454

:o
без комментариев...
у меня весь проект едва-ли половина описанного решения...

RUVATA 25-08-2010 16:38 1481516

А ТЕПЕРЬ описываю ПРАВИЛЬНЫЙ СПОСОБ перенаправления ввода\вывода любого процесса
в стандартные потоки используемые в консоли 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 1485627

RUVATA, отлично, если этот код то что нужно.

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


Время: 02:59.

Время: 02:59.
© OSzone.net 2001-