{"id":22873722,"url":"https://github.com/nullean/proc","last_synced_at":"2026-01-30T20:08:27.218Z","repository":{"id":56253049,"uuid":"121227368","full_name":"nullean/proc","owner":"nullean","description":"Dependency free reactive abstraction for `System.Diagnostics.Process`, exposes handy static one-liner methods for the one offs","archived":false,"fork":false,"pushed_at":"2024-01-16T13:56:22.000Z","size":218,"stargazers_count":27,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-05-28T12:52:27.622Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nullean.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-12T09:38:08.000Z","updated_at":"2024-04-17T23:36:01.000Z","dependencies_parsed_at":"2024-01-15T23:03:25.250Z","dependency_job_id":"a73d5127-8eea-4cd1-8e5c-33c56575fe47","html_url":"https://github.com/nullean/proc","commit_stats":{"total_commits":91,"total_committers":4,"mean_commits":22.75,"dds":"0.48351648351648346","last_synced_commit":"53bdb390e8f2ed8947877483c02fb3e7e2bc99f4"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullean%2Fproc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullean%2Fproc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullean%2Fproc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullean%2Fproc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nullean","download_url":"https://codeload.github.com/nullean/proc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252750349,"owners_count":21798685,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-13T14:29:58.820Z","updated_at":"2026-01-30T20:08:27.185Z","avatar_url":"https://github.com/nullean.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Proc\n\n\u003ca href=\"https://www.nuget.org/packages/Proc/\"\u003e\u003cimg src=\"https://img.shields.io/nuget/v/Proc?color=blue\u0026style=plastic\" /\u003e\u003c/a\u003e\n\n\u003cimg src=\"https://github.com/nullean/proc/raw/master/build/nuget-icon.png\" align=\"right\"\n     title=\"Logo \" width=\"220\" height=\"220\"\u003e\n\nA dependency free `System.Diagnostics.Process` supercharger. \n\n1. `Proc.Exec()` for the quick one-liners\n2. `Proc.Start()` for the quick one-liners \n   - Use if you want to capture the console output as well as print these message in real time.\n   - Proc.Start() also allows you to script StandardIn and react to messages\n3. Wraps `System.Diagnostics.Process` as an `IObservable` \n    * `ProcessObservable` stream based wrapper\n    * `EventBasedObservableProcess` event based wrapper\n4. Built in support to send `SIGINT` to any process before doing a hard `SIGKILL` (`Process.Kill()`)\n    * Has to be set using `SendControlCFirst = true` on `StartArguments`\n    \n## Proc.Exec\n\nExecute a process and blocks using a default timeout of 4 minutes. This method uses the same console session\nas and as such will print the binaries console output. Throws a `ProcExecException` if the command fails to execute.\nSee also `ExecArguments` for more options\n\n```csharp\nProc.Exec(\"ipconfig\", \"/all\");\n```\n\n## Proc.Start\n\nstart a process and block using the default timeout of 4 minutes\n```csharp\nvar result = Proc.Start(\"ipconfig\", \"/all\");\n```\n\nProvide a custom timeout and an `IConsoleOutWriter` that can output to console \nwhile this line is blocking. The following example writes `stderr` in red.\n\n```csharp\nvar result = Proc.Start(\"ipconfig\", TimeSpan.FromSeconds(10), new ConsoleOutColorWriter());\n```\n\nMore options can be passed by passing `StartArguments` instead to control how the process should start.\n\n```csharp\nvar args = new StartArguments(\"ipconfig\", \"/all\")\n{\n  WorkingDirectory = ..\n}\nProc.Start(args, TimeSpan.FromSeconds(10));\n```\n\nThe static  `Proc.Start` has a timeout of `4 minutes` if not specified.\n\n`result` has the following properties\n\n* `Completed` true if the program completed before the timeout\n* `ConsoleOut` a list the console out message as `LineOut` \n   instances where `Error` on each indicating whether it was written on `stderr` or not\n* `ExitCode` \n\n**NOTE** `ConsoleOut` will always be set regardless of whether an `IConsoleOutWriter` is provided\n\n## ObservableProcess\n\nThe heart of it all this is an `IObservable\u003cCharactersOut\u003e`. It listens on the output buffers directly and does not wait on \nnewlines to emit.\n\nTo create an observable process manually follow the following pattern:\n\n```csharp\nusing (var p = new ObservableProcess(args))\n{\n\tp.Subscribe(c =\u003e Console.Write(c.Characters));\n\tp.WaitForCompletion(TimeSpan.FromSeconds(2));\n}\n```\n\nThe observable is `cold` untill subscribed and is not intended to be reused or subscribed to multiple times. If you need to \nshare a subscription look into RX's `Publish`.\n\nThe `WaitForCompletion()` call blocks so that `p` is not disposed which would attempt to shutdown the started process.\n\nThe default for doing a shutdown is through `Process.Kill` this is a hard `SIGKILL` on the process.\n\nThe cool thing about `Proc` is that it supports `SIGINT` interoptions as well to allow for processes to be cleanly shutdown. \n\n```csharp\nvar args = new StartArguments(\"elasticsearch.bat\")\n{\n\tSendControlCFirst = true\n};\n```\n\nThis will attempt to send a `Control+C` into the running process console on windows first before falling back to `Process.Kill`. \nLinux and OSX support for this flag is still in the works so thats why this behaviour is opt in.\n\n\nDealing with `byte[]` characters might not be what you want to program against, so `ObservableProcess` allows the following as well.\n\n\n```csharp\nusing (var p = new ObservableProcess(args))\n{\n\tp.SubscribeLines(c =\u003e Console.WriteLine(c.Line));\n\tp.WaitForCompletion(TimeSpan.FromSeconds(2));\n}\n```\n\nInstead of proxying `byte[]` as they are received on the socket this buffers and only emits on lines. \n\nIn some cases it can be very useful to introduce your own word boundaries\n\n```csharp\npublic class MyProcObservable : ObservableProcess\n{\n\tpublic MyProcObservable(string binary, params string[] arguments) : base(binary, arguments) { }\n\n\tpublic MyProcObservable(StartArguments startArguments) : base(startArguments) { }\n\n\tprotected override bool BufferBoundary(char[] stdOut, char[] stdErr)\n\t{\n\t\treturn base.BufferBoundary(stdOut, stdErr);\n\t}\n}\n```\n\nreturning true inside `BufferBoundary` will yield the line to `SubscribeLine()`. This could be usefull e.g if your process \nprompts without a new line:\n\n\u003e Continue [Y/N]: \u003cno newline here\u003e\n\nA more concrete example of this is when you call a `bat` file on windows and send a `SIGINT` signal it will *always* prompt:\n\n\u003e Terminate batch job (Y/N)?\n\nWhich would not yield to `SubscribeLines` and block any waithandles unnecessary. `ObservableProcess` handles this edgecase\ntherefor OOTB and automatically replies with `Y` on `stdin` in this case.\n\nAlso note that `ObservableProcess` will yield whatever is in the buffer before OnCompleted().\n\n\n# EventBasedObservable\n\n`ObservableProcess`'s sibbling that utilizes `OutputDataReceived` and `ErrorDataReceived` and can only emit lines.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnullean%2Fproc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnullean%2Fproc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnullean%2Fproc/lists"}