Process start standard error

Start-Process Запускает один или несколько процессов на локальном компьютере. Синтаксис Описание Командлет Start-Process запускает один или несколько процессов на локальном компьютере. По умолчанию создает новый процесс, Start-Process который наследует все переменные среды, определенные в текущем процессе. Чтобы указать программу, которая выполняется в процессе, введите исполняемый файл или файл скрипта или файл, который можно открыть […]

Содержание

  1. Start-Process
  2. Синтаксис
  3. Описание
  4. Примеры
  5. Пример 1. Запуск процесса, использующего значения по умолчанию
  6. Пример 2. Печать текстового файла
  7. Пример 3. Запуск процесса сортировки элементов в новый файл
  8. Пример 4. Запуск процесса в развернутом окне
  9. Пример 5. Запуск PowerShell от имени администратора
  10. Пример 6. Использование разных команд для запуска процесса
  11. Пример 7. Указание аргументов для процесса
  12. Пример 8. Выполнение команды от имени администратора с помощью альтернативных учетных данных
  13. Пример 9. Создание отсоединяемого процесса в Linux
  14. Параметры
  15. -ArgumentList
  16. -Confirm
  17. -Credential
  18. -FilePath
  19. -LoadUserProfile
  20. -NoNewWindow
  21. -PassThru
  22. -RedirectStandardError
  23. -RedirectStandardInput
  24. -RedirectStandardOutput
  25. -UseNewEnvironment
  26. -WhatIf
  27. -WindowStyle
  28. -WorkingDirectory
  29. Входные данные
  30. Выходные данные
  31. Примечания

Start-Process

Запускает один или несколько процессов на локальном компьютере.

Синтаксис

Описание

Командлет Start-Process запускает один или несколько процессов на локальном компьютере. По умолчанию создает новый процесс, Start-Process который наследует все переменные среды, определенные в текущем процессе.

Чтобы указать программу, которая выполняется в процессе, введите исполняемый файл или файл скрипта или файл, который можно открыть с помощью программы на компьютере. Если указан неисполняемый файл, запускает программу, Start-Process связанную с файлом, аналогично командлету Invoke-Item .

Параметры можно использовать Start-Process для указания параметров, таких как загрузка профиля пользователя, запуск процесса в новом окне или использование альтернативных учетных данных.

Примеры

Пример 1. Запуск процесса, использующего значения по умолчанию

В этом примере запускается процесс, использующий Sort.exe файл в текущей папке. Команда использует все значения по умолчанию, включая стиль окна по умолчанию, рабочую папку и учетные данные.

Пример 2. Печать текстового файла

В этом примере запускается процесс печати C:PS-TestMyFile.txt файла.

Пример 3. Запуск процесса сортировки элементов в новый файл

В этом примере запускается процесс, который сортирует элементы в TestSort.txt файле и возвращает отсортированные элементы в файлах Sorted.txt . Все ошибки записываются в SortError.txt файл. Параметр UseNewEnvironment указывает, что процесс выполняется с собственными переменными среды.

В этом примере используется сплаттинг для передачи параметров командлету . Дополнительные сведения см. в разделе about_Splatting.

Пример 4. Запуск процесса в развернутом окне

В этом примере запускается Notepad.exe процесс. Окно разворачивается во весь экран и удерживается до завершения процесса.

Пример 5. Запуск PowerShell от имени администратора

Этот пример запускает PowerShell с помощью параметра Запуск от имени администратора .

Пример 6. Использование разных команд для запуска процесса

В этом примере показано, как найти команды, которые можно использовать при запуске процесса. Доступные команды определяются расширением имени файла, который запускается в процессе.

В примере используется для New-Object создания объекта System.Diagnostics.ProcessStartInfo для powershell.exe , файла, который выполняется в процессе PowerShell. Свойство Verbs объекта ProcessStartInfo показывает, что команды Open и RunAs можно использовать с powershell.exe или с любым процессом, выполняющим .exe файл.

Пример 7. Указание аргументов для процесса

Обе команды запускают интерпретатор команд Windows, выдавая dir команду в папке Program Files . Так как это имя папки содержит пробел, значение должно быть заключено в экранированные кавычки. Обратите внимание, что первая команда указывает строку как ArgumentList. Вторая команда представляет собой массив строк.

Пример 8. Выполнение команды от имени администратора с помощью альтернативных учетных данных

В Windows можно запустить Start-Process -Verb RunAs , чтобы запустить процесс с повышенными разрешениями. Это повышает уровень контекста текущего пользователя. Параметр Credential позволяет указать альтернативное имя пользователя и пароль, что позволяет запустить процесс в другом пользовательском содержимом. Однако параметры Credential и Verb нельзя использовать вместе.

Чтобы запустить процесс с повышенными правами, используя альтернативные учетные данные, необходимо сначала запустить PowerShell с помощью альтернативных учетных данных, а затем использовать Start-Process для запуска процесса с повышенными правами.

Пример начинается cmd.exe с повышенных разрешений из сеанса PowerShell, который выполняется с альтернативными учетными данными.

Пример 9. Создание отсоединяемого процесса в Linux

В Windows создает независимый процесс, Start-Process который продолжает выполняться независимо от запускаемой оболочки. На платформах, отличных от Windows, только что запущенный процесс присоединяется к запущенной оболочке. Если запущенная оболочка закрыта, дочерний процесс завершается.

Чтобы избежать завершения дочернего процесса на unix-подобных платформах, можно объединить Start-Process с nohup . В следующем примере запускается фоновый экземпляр PowerShell в Linux, который остается активным даже после закрытия сеанса запуска. Команда nohup собирает выходные данные в файле nohup.out в текущем каталоге.

В этом примере Start-Process выполняет команду Linux nohup , которая запускается pwsh как отсоединяемый процесс. Дополнительные сведения см. в статье nohup в Википедии.

Параметры

-ArgumentList

Указывает параметры или значения параметров, которые будут использоваться при запуске этого командлета процесса. Аргументы могут приниматься как одна строка с аргументами, разделенными пробелами, или как массив строк, разделенных запятыми. Командлет объединяет массив в одну строку, при этом каждый элемент массива отделяется одним пробелом.

Внешние кавычки строк PowerShell не включаются при передаче значений ArgumentList в новый процесс. Если параметры или значения параметров содержат пробелы или кавычки, их необходимо заключить в экранированные двойные кавычки. Дополнительные сведения см. в разделе about_Quoting_Rules.

Для получения наилучших результатов используйте одно значение ArgumentList , содержащее все аргументы и все необходимые символы кавычек.

Type: String [ ]
Aliases: Args
Position: 1
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-Confirm

Запрос подтверждения перед выполнением командлета.

Type: SwitchParameter
Aliases: cf
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-Credential

Указывает учетную запись пользователя с разрешением на выполнение этого действия. По умолчанию командлет использует учетные данные текущего пользователя.

Введите имя пользователя, например User01 или Domain01User01, или введите объект PSCredential , созданный командлетом Get-Credential . Если ввести имя пользователя, вам будет предложено ввести пароль.

Учетные данные хранятся в объекте PSCredential , а пароль хранится как SecureString.

Дополнительные сведения о защите данных SecureString см. в разделе Как безопасно secure is SecureString?.

Type: PSCredential
Aliases: RunAs
Position: Named
Default value: Current user
Accept pipeline input: False
Accept wildcard characters: False

-FilePath

Указывает необязательный путь и имя файла программы, которая запускается в процессе. Введите имя исполняемого файла или документа, например .txt файла или .doc , связанного с программой на компьютере. Это обязательный параметр.

Если указано только имя файла, не соответствующее системной команде, используйте параметр WorkingDirectory , чтобы указать путь.

Type: String
Aliases: PSPath, Path
Position:
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-LoadUserProfile

Указывает, что этот командлет загружает профиль пользователя Windows, хранящийся в HKEY_USERS разделе реестра для текущего пользователя. Параметр не применяется к системам, отличным от Windows.

Этот параметр не влияет на профили PowerShell. Дополнительные сведения см. в разделе about_Profiles.

Type: SwitchParameter
Aliases: Lup
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-NoNewWindow

Предотвращает запуск процесса в новом окне. По умолчанию в Windows PowerShell открывает новое окно. В системах, отличных от Windows, вы никогда не получаете новое окно.

Параметры NoNewWindow и WindowStyle нельзя использовать в одной команде.

Параметр не применяется к системам, отличным от Windows.

Type: SwitchParameter
Aliases: nnw
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-PassThru

Возвращает объект процесса для каждого запущенного командлетом процесса По умолчанию этот командлет не создает никаких выходных данных.

Type: SwitchParameter
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-RedirectStandardError

Указывает файл. Этот командлет отправляет все ошибки, созданные процессом, в указанный файл. Введите путь и имя файла. По умолчанию все ошибки отображаются в консоли.

Type: String
Aliases: RSE
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-RedirectStandardInput

Указывает файл. Этот командлет считывает входные данные из указанного файла. Введите путь и имя входного файла. По умолчанию процесс получает входные данные с клавиатуры.

Type: String
Aliases: RSI
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-RedirectStandardOutput

Указывает файл. Этот командлет отправляет выходные данные, созданные процессом, в указанный файл. Введите путь и имя файла. По умолчанию выходные данные отображаются в консоли.

Type: String
Aliases: RSO
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-UseNewEnvironment

Указывает, что этот командлет использует новые переменные среды, указанные для процесса. По умолчанию запущенный процесс выполняется с переменными среды, унаследованными от родительского процесса.

В Windows при использовании UseNewEnvironment новый процесс начинает содержать только переменные среды по умолчанию, определенные для области компьютера . Это имеет побочный эффект, что $env:USERNAME для задано значение SYSTEM. Ни одна из переменных из области user не включается.

Type: SwitchParameter
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

Указывает команду, используемую при запуске этого командлета. Доступные команды определяются расширением имени файла, который выполняется в процессе.

В приведенной ниже таблице показаны команды, доступные для некоторых распространенных типов файлов.

Тип файла Команды
.cmd Edit , Open , Print , RunAs , RunAsUser
EXE Open , RunAs , RunAsUser
.txt Open , Print , PrintTo
.wav Open , Play

Чтобы найти команды, которые можно использовать с файлом, который выполняется в процессе, используйте New-Object командлет для создания объекта System.Diagnostics.ProcessStartInfo для файла. Доступные команды находятся в свойстве Verbs объекта ProcessStartInfo . Дополнительные сведения см. в примерах.

Параметр не применяется к системам, отличным от Windows.

Type: String
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

Указывает, что этот командлет ожидает завершения указанного процесса и его потомков, прежде чем принимать дополнительные входные данные. Этот параметр подавляет командную строку или сохраняет окно до завершения процессов.

Type: SwitchParameter
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-WhatIf

Показывает, что произойдет при запуске командлета. Командлет не выполняется.

Этот параметр появился в PowerShell 6.0.

Type: SwitchParameter
Aliases: wi
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-WindowStyle

Указывает состояние окна, используемого для нового процесса. Значение по умолчанию — Normal . Допустимые значения для этого параметра:

Параметры WindowStyle и NoNewWindow нельзя использовать в одной команде.

Параметр не применяется к системам, отличным от Windows. При использовании в системах, отличных от Windows, вы никогда не получаете новое окно.

Type: ProcessWindowStyle
Accepted values: Normal, Hidden, Minimized, Maximized
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

-WorkingDirectory

Указывает расположение, в котором должен начаться новый процесс.

Если этот параметр не указан, командлет по умолчанию использует полное расположение, указанное в параметре FilePath . Если значение параметра FilePath не является полным, по умолчанию используется текущий рабочий каталог вызывающего процесса.

Подстановочные знаки не поддерживаются. Путь не должен содержать символы, которые будут интерпретироваться как подстановочные знаки.

Type: String
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False

Входные данные

None

Вы не можете передать объекты в этот командлет.

Выходные данные

None

По умолчанию этот командлет не возвращает выходные данные.

При использовании параметра PassThru этот командлет возвращает объект Process .

Примечания

PowerShell включает следующие псевдонимы для Start-Process :

Собственные команды — это исполняемые файлы, установленные в операционной системе. Эти исполняемые файлы можно запускать из любой оболочки командной строки, например PowerShell. Обычно команда выполняется точно так же, как в bash или cmd.exe . Командлет Start-Process можно использовать для выполнения любых собственных команд, но его следует использовать только в том случае, если необходимо управлять выполнением команды.

Start-Process полезно для запуска программ графического пользовательского интерфейса на платформах, отличных от Windows. Например, выполните команду Start-Proces gedit , чтобы запустить графический текстовый редактор, распространенный в средах рабочего стола GNOME.

По умолчанию Start-Process запускает процесс асинхронно. Элемент управления мгновенно возвращается в PowerShell, даже если новый процесс все еще выполняется.

  • В локальной системе запущенный процесс находится в независимом от вызывающего процесса.
  • В удаленной системе новый процесс завершается после завершения удаленного сеанса сразу после Start-Process выполнения команды . Таким образом, вы не можете использовать Start-Process в удаленном сеансе, ожидая, что запущенный процесс выживет сеанс.

Если вам нужно использовать Start-Process в удаленном сеансе, вызовите его с помощью параметра Wait . Вы также можете использовать другие методы для создания нового процесса в удаленной системе.

При использовании параметра Wait ожидает выхода Start-Process дерева процесса (процесса и всех его потомков) перед возвратом управления. Это отличается от поведения командлета Wait-Process , который ожидает только завершения указанных процессов.

В Windows наиболее распространенным вариантом Start-Process использования является использование параметра Wait для блокировки хода выполнения до завершения нового процесса. В системе, отличной от Windows, это редко требуется, так как поведение по умолчанию для приложений командной строки эквивалентно Start-Process -Wait .

Источник

  • Remove From My Forums
  • Question

  • Hi, I’m having a problem running programs with Process.Start(). I want to create a tool for running windows tools/programs such as cmd, powershell, task manager, ect… The problem is that some of the programs run a 32-bit and I want them to run in 64-bit,
    and two of them don’t do anything. One even gives me an error. Most of the programs I try to run open just fine in 64-bit like I want.

    These programs run in 32-bit.

    Process.Start(@"C:WindowsSystem32WindowsPowerShellv1.0powershell.exe")
    Process.Start(@"C:WindowsSystem32WindowsPowerShellv1.0powershell_ise.exe")
    Process.Start(@"C:WindowsSystem32taskmgr.exe")
    Process.Start(@"C:WindowsSystem32msinfo32.exe")
    Process.Start("regedit.exe")
    Process.Start("cleanmgr.exe")
    
    

    I don’t care so much about having all these running in 64-bit, but I do want powershell.exe, powershell_ise.exe, and taskmgr.exe to run in 64-bit. I tried to specify the path to the 64-bit version of the program, but they still run in 32-bit. I even tried
    to compile my program to run in 64-bit, but these programs still run in 32-bit. Also some other programs run in 64-bit no problem.

    These run in 64-bit.

    Process.Start("cmd.exe")
    Process.Start("Control.exe")
    

    These programs don’t do anything

    Process.Start(@"C:WindowsSystem32msconfig.exe")//Gives me a file not found error.
    
    Process.Start(@"C:WindowsSystem32dfrgui.exe")//I don't get any errors, but nothing happens when I try to run it.

    Can someone help me out here?

Answers

  • Hi LavaCreeperKing,

    Thank you for posting here.

    When using Process.Start() to start a program, whether the started program is 32-bit or 64-bit depends on the current project.

    The command prompt launched from a 32-bit program will be a 32-bit command prompt, and a command prompt launched from a 64-bit application will be a 64-bit command prompt.

    In the default setting of Visual Studio, the program runs in 32-bit mode.

    It seems that msconfig.exe and dfrgui.exe can only run in 64-bit, so if you uncheck Prefer 32-bit, this program will run in 64-bit and the previous error will disappear.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click «Mark as Answer» the responses that resolved your issue, and to click «Unmark as Answer» if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to
    MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by

      Thursday, October 8, 2020 9:12 PM

In the code given in the question, I think that reading the ExitCode property of the initiation variable should work.

$process = Start-Process -FilePath ping -ArgumentList localhost -NoNewWindow -PassThru -Wait
$process.ExitCode

Note that (as in your example) you need to add the -PassThru and -Wait parameters (this caught me out for a while).

That’s how Start-Process was designed for some reason. Here’s a way to get it without sending to file:

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "ping.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "localhost"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
Write-Host "stdout: $stdout"
Write-Host "stderr: $stderr"
Write-Host "exit code: " + $p.ExitCode

IMPORTANT:

We have been using the function as provided above by LPG.

However, this contains a bug you might encounter when you start a process that generates a lot of output. Due to this you might end up with a deadlock when using this function. Instead use the adapted version below:

Function Execute-Command ($commandTitle, $commandPath, $commandArguments)
{
  Try {
    $pinfo = New-Object System.Diagnostics.ProcessStartInfo
    $pinfo.FileName = $commandPath
    $pinfo.RedirectStandardError = $true
    $pinfo.RedirectStandardOutput = $true
    $pinfo.UseShellExecute = $false
    $pinfo.Arguments = $commandArguments
    $p = New-Object System.Diagnostics.Process
    $p.StartInfo = $pinfo
    $p.Start() | Out-Null
    [pscustomobject]@{
        commandTitle = $commandTitle
        stdout = $p.StandardOutput.ReadToEnd()
        stderr = $p.StandardError.ReadToEnd()
        ExitCode = $p.ExitCode
    }
    $p.WaitForExit()
  }
  Catch {
     exit
  }
}

Further information on this issue can be found at MSDN:

A deadlock condition can result if the parent process calls p.WaitForExit before p.StandardError.ReadToEnd and the child process writes enough text to fill the redirected stream. The parent process would wait indefinitely for the child process to exit. The child process would wait indefinitely for the parent to read from the full StandardError stream.

Tags:

Powershell

Start Process

Related

The following code works on .NET Framework but throws on .NET Core 3:

Process.Start("https://github.com");

System.ComponentModel.Win32Exception
  HResult=0x80004005
  Message=The system cannot find the file specified.
  Source=System.Diagnostics.Process
  StackTrace:
   at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start(String fileName)
   at NetCoreProcessStartBug.MainWindow.ButtonBase_OnClick(Object sender, RoutedEventArgs e) in c:devNetCoreProcessStartBugNetCoreProcessStartBugMainWindow.xaml.cs:line 31
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.RouteItem.InvokeHandler(RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.EventRoute.InvokeHandlers(Object source, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.Controls.Primitives.ButtonBase.OnClick()
   at System.Windows.Controls.Button.OnClick()
   at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.RouteItem.InvokeHandler(RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.EventRoute.ReInvokeHandlers(Object source, RoutedEventArgs args)
   at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
   at System.Windows.UIElement.CrackMouseButtonEventAndReRaiseEvent(DependencyObject sender, MouseButtonEventArgs e)
   at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
   at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.RouteItem.InvokeHandler(RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.EventRoute.InvokeHandlers(Object source, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
   at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
   at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
   at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.TranslateAndDispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at NetCoreProcessStartBug.App.Main()

GitHub repro: https://github.com/onovotny/NetCoreProcessStartBug

A while back I was working on a small Proof of concept where I needed to use console based client to connect to a server and use it to send and receive messages to other clients.As you must be aware of that all windows process are attached with a standard error ,input and output streams.Input stream by default point to keyboard and in case of a console application both standard error and output stream point to console.That means any program related output and exceptions are by default displayed in console window.That was problematic for me as couple of third party dlls and framework which I was using had extensive logging on errors and both the output and error were getting terribly mixed up.Most of these errors were not fatal errors and were not supposed to close the application e.g. whenever client and server TCP connection was lost an exception was raised and used to come in red font on console window.

Solution was to redirect error stream to something other than console and let only valid output be displayed on console.

Redirection in case of a child process

By child process I just mean one process spawning another process.It is quite simple in case you want to start a child process and want its output or errors to be redirected i.e. you have a console application (or any kind of application for that matter) and you start another process from it and redirect its error to a file.

var childProcess = new Process();
childProcess.StartInfo.FileName = "ChildProcess.exe";
childProcess.StartInfo.UseShellExecute = false;
childProcess.StartInfo.RedirectStandardError = true;
childProcess.Start();
using (StreamReader reader = childProcess.StandardError)
{
    string result = reader.ReadToEnd();
   //WRITE TO A FILE OR TO ANY OTHER TARGET
}
childProcess.WaitForExit();

You need to make sure that UseShellExecute = false as it makes sure that process is started as a child process.In case it is true, process would be started using windows shell and would be assigned its own standard error and output (we would deal with this in the next section).In such cases reading from StandardError stream throws exception.

This whole thing was not useful for me as I wanted to redirect the error stream of my top level console process (i.e. there was only one process and no parent spawning child).

Redirection in case of a top level process

By top level process I mean a process started by windows shell (i.e. the ones we start by double clicking a .exe file).Console.SetErorr method in Console class seems to do something similar.Basically it takes a TextWriter and makes that new standard error.At first look it seems we got our solution but that is not the case.It just writes anything written specifically to Console.Error stream (e.g. using Console.Error.Write) to the redirected stream but any exceptions coming from your code or third party dlls will still go to Console.

After struggling a little I realized that there is NO direct way of doing this using .NET framework libraries (In case any of you know a way,  let me know ).So how do we do this ?

Answer is to do this via PInvoke to SetStdHandle windows kernel32.dll method.So in case you want to totally redirect all your errors use something like below.

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern int SetStdHandle(int device, IntPtr handle);

public static void RedirectStandardErrorToFile(FileStream fileStream)
{
    StreamWriter errStream = new StreamWriter(fileStream);
    errStream.AutoFlush = true;
    Console.SetError(errStream);
    var status = SetStdHandle(-12, fileStream.SafeFileHandle.DangerousGetHandle()); // set stderr
}

SetStdHandle first parameter specifies which stream to redirect i.e. –12 is for stderr and –11 for stdout.Notice that we also use same stream in Console.SetError.

Also all this applies in case you want to redirect standard output or both.

One disadvantage of using this is that you application is now tied to windows platform i.e. you cannot use it with for example with mono on Linux.

Also, If you are someone extensively working on .NET console applications or are interested to know more than just the basics than there is an excellent pluralsight course on building console application in .NET which you might want to look into.

stdout, stdin, and stderr are standard streams, which interconnect input and output communication channels between a program and its environment when the program executes.

Streams generally mean the flow of data. You can think of streams as a conveyor belt in a factory connected to different machines (programs in our case). Different machines can be arranged, directed, and connected with a belt (pipe) in a way to produce a particular result.

Just as we can have physical I/O devices connected (input via mouse, output via monitor), standard streams abstract this, giving us the power of composability in our code.

Testimage

Just like the way we can compose powerful Linux commands from small commands, we can make use of Node.js standard streams to achieve the same in Node.js.

Node.js stdin, stdout, and stdin

When we run a Node.js program, a process is started for that program execution.

The GNU documentation defines a process as “the primitive units for allocation of system resources. Each process has its own address space and (usually) one thread of control. A process executes a program; you can have multiple processes executing the same program, but each process has its own copy of the program within its own address space and executes it independently of the other copies.”

Every process is initialized with three open file descriptors called stdinstdout, and stderr.

Those three file descriptors are collectively called the standard streams.

A set of the three standard streams is started for a process and we can access them via the process object in Node.js.

The standards streams are treated as if there are files. An easy way to access any file is by using the unique file descriptor associated with it. In the case of these standards streams, there are unique values assigned to each of them.

  • process.stdin(0): The standard input stream, which is a source of input for the program
  • process.stdout(1): The standard output stream, which is a source of output from the program
  • process.stderr(2): The standard error stream, which is used for error messages and diagnostics issued by the program

Simple use of stdin and stdout

Let’s write a simple application that receives data via the terminal and prints a processed output into the terminal.

We’d create a JavaScript file (index.js) and write the code below:

 // index.js
process.stdin.on("data", data => {
    data = data.toString().toUpperCase()
    process.stdout.write(data + "n")
})

Running the above program creates an event listener to listen for data input, processes the input, and prints the output to the terminal.

Simple Result

We can stop the running process in our terminal by pressing ctrl + c.

Making use of readline to create interactive terminal scripts

readline is a Node.js module that provides an interface for reading data from a Readable stream (such as process.stdin) one line at a time.

First, we would create a new JavaScript file called index.js, import the readline module into our program, then create a function, ask, that receives a string as an argument and creates a prompt with the string in our terminal:

// index.js
const readline = require("readline")

function ask(question) {
    // asks a question and expect an answer
}

Then we will create an interface using readline that connects stdin to stdout:

// index.js
const readline = require("readline")

const rl = readline.createInterface({
    input: process.stdin, 
    output: process.stdout,
})

function ask(question) {
    // asks a question and expectings an answer
}

We will complete the ask function to expect answers and repeat the whole process recursively:

 // index.js
const readline = require("readline")

const rl = readline.createInterface({
    input: process.stdin, 
    output: process.stdout,
})

function ask(question) {
    rl.question(question, (answer) => {
        rl.write(`The answer received:  ${answer}n`)

        ask(question)
    })
}

ask("What is your name: ")

Running the above program would create a terminal interface that keeps looping until we end the Node.js process by pressing ctrl + c in the terminal.

The ctrl + c sends a signal to our running Node.js program called SIGKILL, which tells Node.js to stop our program execution. We can also, programmatically, inform Node.js to stop executing our application by calling process.exit(exitCode).

So we will update our ask function to check if the answer from input “q.” If the input is “q” then it should exit the application:

// index.js
const readline = require("readline")

const rl = readline.createInterface({
    input: process.stdin, 
    output: process.stdout,
})

function ask(question) {
    rl.question(question, (answer) => {
        if(answer === "q") {
            process.exit(1)
        }
        rl.write(`The answer received:  ${answer}n`)

        ask(question)
    })
}

ask("What is your name: ") 

What is stderr?

When we write applications or programs, errors may occur due to so many reasons. stderr is the default file descriptor where a process can write error messages.

Consider this code below:

// index.js
process.stderr.write("error! some error occurredn")

Running this application with node index.js would write the error message to our terminal similarly to how stdout would output it.

It is pretty straightforward to understand why stdin and stdout exist. However, stderr seems pretty odd.


More great articles from LogRocket:

  • Don’t miss a moment with The Replay, a curated newsletter from LogRocket
  • Learn how LogRocket’s Galileo cuts through the noise to proactively resolve issues in your app
  • Use React’s useEffect to optimize your application’s performance
  • Switch between multiple versions of Node
  • Discover how to animate your React app with AnimXYZ
  • Explore Tauri, a new framework for building binaries
  • Compare NestJS vs. Express.js

In the UNIX/Linux-based ecosystem, there was a period where stderr did not exist. All outputs of UNIX commands could be piped via stdout, including both expected results of the command and errors or diagnostic messages.

This is not considered a best practice as the error can also pass through the pipe which the command attached at the end of the pipe may not understand.

Hence, stderr was created to direct error or diagnostic messages via a different file descriptor, which is 2.

N.B., in Linux, when you pipe commands together, only the expecting result is piped together. The error or diagnostic error message is piped via the stderr file descriptor and is by default printed to the terminal.

Let us play around with this by writing two Node.js programs called logger.js and printer.js.

The logger.js is mocking a logging program, but in our case, the logs are predefined already.

Then the printer.js would read data from the stdin and write them to a file.

First, we will create the logger.js below:

const logObject = [
    {
        type: "normal",
        message: "SUCCESS: 2 + 2 is 4"
    },
    {
        type: "normal",
        message: "SUCCESS 5 + 5 is 10"
    },
    {
        type: "error",
        message: "ERROR! 3 + 3 is not 4"
    },
    {
        type: "normal",
        message: "SUCESS 10 - 4 is 6"
    }
]

function logger() {
    logObject.forEach(log => {
        setTimeout(() => {
            if (log.type === "normal") process.stdout.write(log.message)
            else process.stderr.write(log.message + 'n')
        }, 500)
    })
}

logger()

Next, we will create another Node.js file that creates or opens a text file, logs.txt, read inputs provided by stdout, and writes them to a file:

const fs = require("fs")

fs.open("./logs.txt", "w", (err, fd) => {
    if (err) throw Error(err.message)
    process.stdin.on("data", data => {
        fs.write(fd, data.toString() + "n", (err) => {
            if (err) throw Error(err.message)
        })
    })
})

To run this application, we can pipe these two programs in our terminal by running:

$ node logger.js | node printer.js

N.B., if you are running the above command with Git Bash in Windows, you may come across the error stdout is not a tty. This is likely an issue with Git Bash. You can run the command using Window Powershell or make the script executable by including a shebang (#!/bin/env node) at the top of the file and running the command above as ./logger.js | ./printer.js.

After execution, we can confirm that only the success logs that passed by stdout made it to the logs.txt:

// logs.txt
SUCCESS: 2 + 2 is 4
SUCCESS 5 + 5 is 10
SUCcESS 10 - 4 is 6

And that the error logs were printed to the terminal. This is the default behavior of stderr but we can also change this through redirection and pipelines.

Wrapping up

Now we understand what the standard steams are and how we can make use of them in our Node.js application. We also know how standard streams can help us to build simple programs that can be channeled to formulate more complex programs.

For instance, printer.js doesn’t necessarily need to be aware of what logger.js does. All printer.js do is receive data from a stdout and write the date to a file.

printer.js can be reused and composed with other programs, even with Linux commands, provided they share the same execution environment.

200’s only Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, try LogRocket. LogRocket Network Request Monitoringhttps://logrocket.com/signup/

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.

Понравилась статья? Поделить с друзьями:
  • Process initialization failed windows 10 как исправить
  • Process finished with exit code 1073740791 0xc0000409 как исправить
  • Process exited with error code 11234
  • Process error missing file try reinstalling to fix this
  • Procedure error occurred xiaomi mi tool v2