{"id":22025114,"url":"https://github.com/refvalue/svchostify","last_synced_at":"2026-04-19T19:31:39.686Z","repository":{"id":265448088,"uuid":"895978326","full_name":"refvalue/SvcHostify","owner":"refvalue","description":"Hosting your C#/Java/C++ project as a DLL service easily, NOT ONLY svchost.exe!","archived":false,"fork":false,"pushed_at":"2025-02-20T14:06:59.000Z","size":142,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-23T10:45:54.819Z","etag":null,"topics":["cpp","csharp","dll","java","svchost","windows","windowsservices"],"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/refvalue.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":"2024-11-29T09:54:43.000Z","updated_at":"2025-02-20T14:07:02.000Z","dependencies_parsed_at":"2025-02-20T15:22:49.385Z","dependency_job_id":"cdc81ffb-c61c-4c20-a193-62c824743673","html_url":"https://github.com/refvalue/SvcHostify","commit_stats":null,"previous_names":["refvalue/svchostify"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refvalue%2FSvcHostify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refvalue%2FSvcHostify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refvalue%2FSvcHostify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/refvalue%2FSvcHostify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/refvalue","download_url":"https://codeload.github.com/refvalue/SvcHostify/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245090862,"owners_count":20559296,"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":["cpp","csharp","dll","java","svchost","windows","windowsservices"],"created_at":"2024-11-30T07:14:08.469Z","updated_at":"2026-04-19T19:31:39.608Z","avatar_url":"https://github.com/refvalue.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SvcHostify: Hosting Your Own Codebase as A DLL Service Easily\n\n\n\n## Motivation\n\n`svchost.exe` is a critical system process for hosting DLLs as Windows Services, but some of its internal workings are undocumented. Creating custom `svchost` DLL services, especially when using languages like Java or C#, can be cumbersome. This is mainly due to the need for exporting C-style functions to interact with `svchost.exe`, which complicates the development process. To address this challenge, I created the \"svchostify\" project, which simplifies the creation of `svchost` DLL services, making it easier for developers to work with `svchost.exe` and supporting a wider range of programming languages.\n\n\n\n## SvcHost Mode - For Personal Use\n\nMicrosoft states that `svchost.exe` is reserved for use by the operating system’s own services, so hosting as a SvcHost service is intended for academic and research purposes only, and might be used in personal environments. It is not recommended for use in production systems.\n\n\n\n## Standalone Mode - For Production Use (NEW in [v0.1.1]())\n\nThis project provides a production-friendly mode, which allows it to run as a standalone service loaded by `rundll32.exe`, the operating system's DLL loader. This mode can be distributed without requiring any third-party executables. NVIDIA, for instance, uses this method to create its services.\n\n![standalone.png](standalone.png)\n\n**NOTE: This mode is set by default started in v0.1.1.**\n\n\n\n## Prerequisites\n\nThe latest [Visual C++ Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) is required for everything to function properly, only for x64 Windows.\n\n\n\n## Downloading the Hosting DLL\n\nThis project provides a C++ dynamic library that enables hosting a DLL service, which can be registered to be loaded by `svchost.exe`. The latest compiled release can be found on the [Release](../../releases/) page. The default name for the prebuilt DLL is typically `svchostify.dll`. You can download and extract it to any location on your disk that you prefer.\n\n\n\n## Command-Line Overview\n\nThe `svchostify.dll` is a self-executable library, meaning it can be directly loaded by `rundll32.exe`—the Windows tool used to run DLLs—by locating the C-style function entry specified by the user.\n\n```powershell\nrundll32 svchostify.dll invoke \u003cOPTIONS\u003e\n```\n\nAvailable options and arguments are listed below:\n\n| Parameter             | Description                                                  |\n| --------------------- | ------------------------------------------------------------ |\n| `--install`, `-i`     | Installs the service.                                        |\n| `--uninstall`, `-u`   | Uninstalls the service.                                      |\n| `--config-file`, `-c` | Specifies a configuration file that the installation or uninstallation is based on. |\n| `--help`, `-h`        | Displays details of the command line arguments.              |\n\nTo install or uninstall a service, use:\n\n```powershell\nrundll32 svchostify.dll invoke -i -c \u003cCONFIG_FILE\u003e\nrundll32 svchostify.dll invoke -u -c \u003cCONFIG_FILE\u003e\n```\n\n**NOTE: The configuration payload, along with the service metadata, will be written to the Windows Registry simultaneously, eliminating the need for a config file after installation.**\n\n\n\n## JSON Configuration\n\nThe hosting service reads a JSON file for its internal configuration and the key-value pairs and objects are defined as follows:\n\n| Field Name                             | Type              | Description                                                  | Possible Values                                 | Default          | Required |\n| -------------------------------------- | ----------------- | ------------------------------------------------------------ | ----------------------------------------------- | ---------------- | -------- |\n| `workType`                             | `string`          | The type of the service.                                     | `com`, `pure_c`, `jvm`, `executable`            |                  | Yes      |\n| `name`                                 | `string`          | The name of the service.                                     | Any                                             |                  | Yes      |\n| `displayName`                          | `string`          | The display name of the service.                             | Any                                             |                  | Yes      |\n| `context`                              | `string`          | Arbitrary content according to the work type: a coclass `{GUID}` for `com`, a DLL path for `pure_c`, a `CLASSPATH` for `jvm`, an EXE path for `executable`. | Any                                             |                  | Yes      |\n| `accountType`                          | `string`          | The account type under which the service runs.               | `localSystem`, `networkService`, `localService` |                  | Yes      |\n| `standalone` \u003cbr /\u003e**(NEW in v0.1.1)** | `boolean`         | Indicates whether to run as a standalone service (hosted in `rundll32.exe`) instead of `svchost.exe` | `true`, `false`                                 | `true`           | No       |\n| `postQuitMessage`                      | `boolean`         | Indicates whether to post a quit message before the service exits when the type is `executable`. | `true`, `false`                                 | `false`          | No       |\n| `description`                          | `string`          | A description of the service.                                | Any                                             | `null`           | No       |\n| `jdkDirectory`                         | `string`          | The JDK Directory.                                           | Any valid directory path                        | `null`           | No       |\n| `workingDirectory`                     | `string`          | The initial working directory.                               | Any valid directory path                        | The DLL location | No       |\n| `arguments`                            | `array of string` | The startup arguments for the service.                       | `List of string`                                | `null`           | No       |\n| `dllDirectories`                       | `array of string` | Additional directories for loading DLLs.                     | List of directories                             | The DLL location | No       |\n| `logger`                               | `object`          | Logger configuration object.                                 | See below                                       | See below        | No       |\n\n#### Logger Configuration Object\n\n| Field Name | Type     | Description                                                  | Possible Values                | Default             | Required |\n| ---------- | -------- | ------------------------------------------------------------ | ------------------------------ | ------------------- | -------- |\n| `basePath` | `string` | The base path of the logging file.                           | Any valid directory path       | logs/svchostify.log | Yes      |\n| `maxSize`  | `string` | The maximum size of one single log file. The pattern is `\\d+\\s*(KiB\\|MiB\\|GiB\\|TiB)?`. | Any valid values like `10 MiB` | 50 MiB              | No       |\n| `maxFiles` | `number` | The maximum count of log files.                              | Any positive integer           | 5                   | No       |\n\n**Note: The complete JSON schema can be found [here](svchostify.schema.json).**\n\n\n\n## JSON Samples\n\n### Hosting a JAR package\n\n```json\n{\n  \"workerType\": \"jvm\",\n  \"name\": \"ABC_SomeTestSvc_Java\",\n  \"displayName\": \"ABC Test Java Service\",\n  \"context\": \"E:/Projects/SvcHostify/samples/svchost.jar\",\n  \"accountType\": \"networkService\",\n  \"standalone\": true,\n  \"description\": \"A Test Java Service for SvcHost.\",\n  \"jdkDirectory\": \"D:/jdk-21\",\n  \"workingDirectory\": \"D:/\",\n  \"arguments\": [\n    \"Hello\",\n    \"World\"\n  ],\n  \"logger\": {\n    \"basePath\": \"logs/logger_java.log\",\n    \"maxSize\": \"10 MiB\",\n    \"maxFiles\": 10\n  }\n}\n```\n\nThe sample project is [located here](samples/java/).\n\n\n\n### Hosting a C# DLL implemented as an in-process COM server\n\n```json\n{\n  \"workerType\": \"com\",\n  \"name\": \"ABC_MyTestSvc_CSharp\",\n  \"displayName\": \"ABC Test CSharp Service\",\n  \"context\": \"{47D7093F-69E2-D17D-422D-49BE836EF3A5}\",\n  \"accountType\": \"localSystem\",\n  \"standalone\": true,\n  \"description\": \"Test CSharp (Hosted as a COM server) Service for SvcHost.\",\n  \"workingDirectory\": \"D:/\",\n  \"arguments\": [\n    \"Hello\",\n    \"World\"\n  ],\n  \"logger\": {\n    \"basePath\": \"logs/logger_csharp.log\",\n    \"maxSize\": \"10 MiB\",\n    \"maxFiles\": 10\n  }\n}\n```\n\nThe sample project can be [checked here](samples/csharp/).\n\n\n\n### Hosting a C++ DLL by calling exported pure C functions\n\n```json\n{\n  \"workerType\": \"pureC\",\n  \"name\": \"ABC_MyTestSvc_CPP\",\n  \"displayName\": \"ABC Test C++ Service\",\n  \"context\": \"refvalue-test-service.dll\",\n  \"accountType\": \"localSystem\",\n  \"standalone\": true,\n  \"description\": \"Test C++ Service for SvcHost.\",\n  \"workingDirectory\": \"D:/\",\n  \"arguments\": [\n    \"Hello\",\n    \"World\"\n  ],\n  \"logger\": {\n    \"basePath\": \"logs/logger_cpp.log\",\n    \"maxSize\": \"10 MiB\",\n    \"maxFiles\": 10\n  }\n}\n```\n\nThe sample project is provided for [review here](samples/cpp/).\n\n\n\n## Calling Conventions\n\n| Programming Language | Calling Method                                               |\n| -------------------- | ------------------------------------------------------------ |\n| Java                 | Implements `org.refvalue.SvcHostify` class with `static` methods `void run(String[] args)` and `void onStop()` |\n| C#                   | Implements the COM interface `ISvcHostify` and its methods `void Run(string[] args)` and `void OnStop()` |\n| C/C++                | Exports `extern \"C\"` functions `void refvalue_svchostify_run(std::size_t argc, const char* argv[])` and `void refvalue_svchostify_on_stop()` |\n\nSome quick samples are provided in the `samples` directory. Feel free to [take a look](samples/)!\n\n\n\n## Prototypes\n\n### Java\n\n```java\npackage org.refvalue;\n\nimport java.io.PrintStream;\nimport java.io.UnsupportedEncodingException;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\npublic final class SvcHostify {\n    private static final AtomicBoolean running = new AtomicBoolean(false);\n\n    static {\n        try {\n            // Uses UTF-8 encoding all the way.\n            System.setOut(new PrintStream(System.out, true, \"UTF-8\"));\n        } catch (UnsupportedEncodingException e) {\n            e.printStackTrace();\n        }\n    }\n\n    /**\n     * The main routine of the service.\n     * \n     * @param args The input arguments.\n     */\n    public static void run(String[] args) {\n        // The main loop of your service.\n        for (int i = 0; running.getAcquire(); i++) {\n            System.out.println(String.format(\"Hello service counter: %d\", i));\n\n            try {\n                Thread.sleep(100);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n        }\n\n        System.out.println(\"Service has stopped from Java.\");\n    }\n\n    /**\n     * This function will be called by the SvcHostify routine in another thread and\n     * you can, for example, send a signal to your 'run' routine to stop gracefully.\n     */\n    public static void onStop() {\n        System.out.println(\"Requesting a stop.\");\n\n        running.setRelease(false);\n    }\n}\n```\n\n\n\n### C#\n\n```csharp\nusing System.Runtime.InteropServices;\n\nnamespace Refvalue.Samples.SvcHost\n{\n    [ComVisible(true)]\n    [Guid(\"47D7093F-69E2-D17D-422D-49BE836EF3A5\")]\n    [ClassInterface(ClassInterfaceType.None)]\n    public class TestService : ISvcHostify\n    {\n        private int _running = 0;\n\n        /// \u003csummary\u003e\n        /// The service entry point.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"args\"\u003eThe input arguments\u003c/param\u003e\n        public void Run(string[] args)\n        {\n            Interlocked.Exchange(ref _running, 1);\n\n            for (int i = 0; Interlocked.CompareExchange(ref _running, 1, 1) == 1; i++)\n            {\n                Console.WriteLine($\"Hello service counter: {i}\");\n                Thread.Sleep(100);\n            }\n\n            Console.WriteLine(\"Service has stopped from CSharp.\");\n        }\n\n        /// \u003csummary\u003e\n        /// This function will be called by the SvcHostify routine in another thread and\n        /// you can, for example, send a signal to your 'Run' routine to stop gracefully.\n        /// \u003c/summary\u003e\n        public void OnStop()\n        {\n            Console.WriteLine(\"Requesting a stop.\");\n\n            Interlocked.Exchange(ref _running, 0);\n        }\n    }\n}\n```\n\n\n\n### C++\n\n```cpp\n#include \u003catomic\u003e\n#include \u003ccstddef\u003e\n#include \u003ccstdio\u003e\n#include \u003cexception\u003e\n#include \u003ciostream\u003e\n#include \u003cthread\u003e\n\nnamespace {\n    class test_service {\n    public:\n        test_service() : running_{false} {}\n\n        /**\n         * @brief The service entry point.\n         * @param argc The count of the arguments.\n         * @param argv The input arguments.\n         */\n        void run(std::size_t argc, const char* argv[]) {\n            using std::chrono_literals::operator\"\"ms;\n\n            running_.store(true, std::memory_order::release);\n\n            for (std::size_t i = 0; running_.load(std::memory_order::acquire); i++) {\n                std::cout \u003c\u003c \"Hello service counter: \" \u003c\u003c i \u003c\u003c '\\n';\n                std::this_thread::sleep_for(100ms);\n            }\n        }\n\n        /**\n         * This function will be called by the SvcHostify routine in another thread and,\n         * you can, for example, send a signal to your 'run' routine to stop gracefully.\n         */\n        void on_stop() {\n            printf(\"Requesting a stop.\\n\");\n\n            running_.store(false, std::memory_order::release);\n        }\n\n    private:\n        std::atomic_bool running_;\n    };\n\n    test_service service;\n} // namespace\n\nextern \"C\" {\n__declspec(dllexport) void refvalue_svchostify_run(std::size_t argc, const char* argv[]) try {\n    service.run(argc, argv);\n} catch (std::exception\u0026 ex) {\n    std::cout \u003c\u003c ex.what() \u003c\u003c '\\n';\n}\n\n__declspec(dllexport) void refvalue_svchostify_on_stop() try { service.on_stop(); } catch (std::exception\u0026 ex) {\n    std::cout \u003c\u003c ex.what() \u003c\u003c '\\n';\n}\n}\n```\n\n\n\n## Logging Redirection\n\nThis system automatically redirects all output sent to `stdout` and `stderr` streams to a log file. It captures logs from various sources, including:\n\n- **Java**: `System.out.println`\n- **C#**: `Console.WriteLine`\n- **C++**: `std::cout`, `spdlog`, `printf`and other standard output methods\n\nThe log file is continuously updated, with a new entry added every time the output exceeds 4 KB, ensuring that log data is refreshed at regular intervals. This redirection simplifies logging by consolidating output from multiple languages and libraries into a single, centralized log file for easier monitoring and troubleshooting.\n\n\n\n## Exception Handling in Your Code\n\nThe hosting system automatically handles JNI exceptions as well as COM exceptions generated by the .NET Runtime. Throwing exceptions from Java code and the C# coclass implementation are **expected** behaviors. It's **NOT RECOMMENDED** to throw exceptions within the `pure_c` routines.\n\n\n\n## LICENSE\n\nThis project is licensed under the MIT License.\n\nYou are free to use, modify, and distribute the software, including for commercial purposes, under the terms of the MIT License.\nSee the [LICENSE](LICENSE) file for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frefvalue%2Fsvchostify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frefvalue%2Fsvchostify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frefvalue%2Fsvchostify/lists"}