{"id":16554564,"url":"https://github.com/tyrrrz/ressy","last_synced_at":"2025-04-04T22:08:21.049Z","repository":{"id":45073537,"uuid":"383193456","full_name":"Tyrrrz/Ressy","owner":"Tyrrrz","description":"Resource editor for PE files","archived":false,"fork":false,"pushed_at":"2025-03-03T19:46:12.000Z","size":335,"stargazers_count":60,"open_issues_count":2,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-28T21:08:48.045Z","etag":null,"topics":["assembly","binary","dotnet","dotnet-core","dotnet-standard","native-resources","parser","pe","portable-executable","resources","win32"],"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/Tyrrrz.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"License.txt","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},"funding":{"github":"Tyrrrz","patreon":"Tyrrrz","custom":["tyrrrz.me/donate"]}},"created_at":"2021-07-05T15:53:59.000Z","updated_at":"2025-03-27T14:26:43.000Z","dependencies_parsed_at":"2023-02-08T20:15:27.732Z","dependency_job_id":"07dfd38f-8619-49e1-a72f-ac522277b746","html_url":"https://github.com/Tyrrrz/Ressy","commit_stats":{"total_commits":160,"total_committers":2,"mean_commits":80.0,"dds":0.03749999999999998,"last_synced_commit":"c13f97cc01156abaca0594545abbd74e772a3cf4"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tyrrrz%2FRessy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tyrrrz%2FRessy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tyrrrz%2FRessy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tyrrrz%2FRessy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tyrrrz","download_url":"https://codeload.github.com/Tyrrrz/Ressy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247256115,"owners_count":20909240,"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":["assembly","binary","dotnet","dotnet-core","dotnet-standard","native-resources","parser","pe","portable-executable","resources","win32"],"created_at":"2024-10-11T19:51:48.158Z","updated_at":"2025-04-04T22:08:21.027Z","avatar_url":"https://github.com/Tyrrrz.png","language":"C#","funding_links":["https://github.com/sponsors/Tyrrrz","https://patreon.com/Tyrrrz","tyrrrz.me/donate"],"categories":[],"sub_categories":[],"readme":"# Ressy\n\n[![Status](https://img.shields.io/badge/status-maintenance-ffd700.svg)](https://github.com/Tyrrrz/.github/blob/master/docs/project-status.md)\n[![Made in Ukraine](https://img.shields.io/badge/made_in-ukraine-ffd700.svg?labelColor=0057b7)](https://tyrrrz.me/ukraine)\n[![Build](https://img.shields.io/github/actions/workflow/status/Tyrrrz/Ressy/main.yml?branch=master)](https://github.com/Tyrrrz/Ressy/actions)\n[![Coverage](https://img.shields.io/codecov/c/github/Tyrrrz/Ressy/master)](https://codecov.io/gh/Tyrrrz/Ressy)\n[![Version](https://img.shields.io/nuget/v/Ressy.svg)](https://nuget.org/packages/Ressy)\n[![Downloads](https://img.shields.io/nuget/dt/Ressy.svg)](https://nuget.org/packages/Ressy)\n[![Discord](https://img.shields.io/discord/869237470565392384?label=discord)](https://discord.gg/2SUWKFnHSm)\n[![Fuck Russia](https://img.shields.io/badge/fuck-russia-e4181c.svg?labelColor=000000)](https://twitter.com/tyrrrz/status/1495972128977571848)\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003ctd width=\"99999\" align=\"center\"\u003eDevelopment of this project is entirely funded by the community. \u003cb\u003e\u003ca href=\"https://tyrrrz.me/donate\"\u003eConsider donating to support!\u003c/a\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"favicon.png\" alt=\"Icon\" /\u003e\n\u003c/p\u003e\n\n**Ressy** is a library for managing native resources stored in portable executable images (i.e. EXE and DLL files).\nIt offers a high-level abstraction model for working with the [resource functions](https://docs.microsoft.com/en-us/windows/win32/menurc/resources-functions) provided by the Windows API.\n\n## Terms of use\u003csup\u003e[[?]](https://github.com/Tyrrrz/.github/blob/master/docs/why-so-political.md)\u003c/sup\u003e\n\nBy using this project or its source code, for any purpose and in any shape or form, you grant your **implicit agreement** to all the following statements:\n\n- You **condemn Russia and its military aggression against Ukraine**\n- You **recognize that Russia is an occupant that unlawfully invaded a sovereign state**\n- You **support Ukraine's territorial integrity, including its claims over temporarily occupied territories of Crimea and Donbas**\n- You **reject false narratives perpetuated by Russian state propaganda**\n\nTo learn more about the war and how you can help, [click here](https://tyrrrz.me/ukraine). Glory to Ukraine! 🇺🇦\n\n## Install\n\n- 📦 [NuGet](https://nuget.org/packages/Ressy): `dotnet add package Ressy`\n\n\u003e **Warning**:\n\u003e This library relies on the Windows API and, as such, works only on Windows.\n\n## Usage\n\n**Ressy**'s functionality is provided entirely through the `PortableExecutable` class.\nYou can create an instance of this class by passing a string that specifies the path to a PE file:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\n// ...\n```\n\n### Reading resources\n\n#### Enumerate resource identifiers\n\nTo get the list of resources in a PE file, use the `GetResourceIdentifiers()` method:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nvar identifiers = portableExecutable.GetResourceIdentifiers();\n```\n\nReturned list should contain something similiar to this:\n\n```txt\n- Type: 16 (RT_VERSION), Name: 1, Language: 1033\n- Type: 24 (RT_MANIFEST), Name: 1, Language: 1033\n- Type: 3 (RT_ICON), Name: 1, Language: 1033\n- Type: 3 (RT_ICON), Name: 2, Language: 1033\n- Type: 3 (RT_ICON), Name: 3, Language: 1033\n- Type: 14 (RT_GROUP_ICON), Name: 2, Language: 1033\n- Type: 4 (RT_MENU), Name: 1, Language: 1033\n- Type: 5 (RT_DIALOG), Name: 1, Language: 1033\n- Type: 5 (RT_DIALOG), Name: 2, Language: 1033\n- Type: 5 (RT_DIALOG), Name: 3, Language: 1033\n- Type: \"MUI\", Name: 1, Language: 1033\n- ...\n```\n\n#### Retrieve resource data\n\nTo resolve a specific resource, call the `GetResource(...)` method.\nThis returns an instance of the `Resource` class that contains the resource data:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nvar resource = portableExecutable.GetResource(new ResourceIdentifier(\n    ResourceType.Manifest,\n    ResourceName.FromCode(1),\n    new Language(1033)\n));\n\nvar resourceData = resource.Data; // byte[]\nvar resourceString = resource.ReadAsString(Encoding.UTF8); // string\n```\n\nIf you aren't sure that the requested resource actually exists in the PE file, you can use the `TryGetResource(...)` method instead.\nIt returns `null` in case the resource is missing:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nvar resource = portableExecutable.TryGetResource(new ResourceIdentifier(\n    ResourceType.Manifest,\n    ResourceName.FromCode(100),\n    new Language(1033)\n)); // resource is null\n```\n\n### Modifying resources\n\n#### Set resource data\n\nTo add or overwrite a resource, call the `SetResource(...)` method:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.SetResource(\n    new ResourceIdentifier(\n        ResourceType.Manifest,\n        ResourceName.FromCode(1),\n        new Language(1033)\n    ),\n    [0x01, 0x02, 0x03]\n);\n```\n\n#### Remove resources\n\nTo remove a resource, call the `RemoveResource(...)` method:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.RemoveResource(\n    new ResourceIdentifier(\n        ResourceType.Manifest,\n        ResourceName.FromCode(1),\n        new Language(1033)\n    )\n);\n```\n\nTo remove all resources in a PE file, call the `ClearResources()` method:\n\n```csharp\nusing Ressy;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.ClearResources();\n```\n\n### High-level operations\n\n**Ressy** provides extensions for `PortableExecutable` that enable you to directly read and manipulate known resource types, such as icons, manifests, versions, etc.\n\n#### Manifest resources\n\nA manifest resource (type `24`) contains XML data that identifies and describes native assemblies that the application should bind to at run-time.\nIt may also contain other information, such as application settings, requested execution level, and more.\n\nTo learn more about application manifests, see [this article](https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests).\n\n##### Retrieve the manifest\n\nTo read the manifest resource as an XML text string, call the `GetManifest()` extension method:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Manifests;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nvar manifest = portableExecutable.GetManifest();\n// -or-\n// var manifest = portableExecutable.TryGetManifest();\n```\n\n\u003e **Note**:\n\u003e If there are multiple manifest resources, this method retrieves the first one it finds, giving preference to resources with lower ordinal name (ID) and in the neutral language.\n\n##### Set the manifest\n\nTo add or overwrite a manifest resource, call the `SetManifest(...)` extension method:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Manifests;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.SetManifest(\"\u003cassembly\u003e...\u003c/assembly\u003e\");\n```\n\n##### Remove the manifest\n\nTo remove all manifest resources, call the `RemoveManifest()` extension method:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Manifests;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.RemoveManifest();\n```\n\n#### Icon resources\n\nIcon resources (type `3`) and icon group resources (type `14`) are used to visually identify an application within the operating system.\nEach portable executable file may contain multiple icon resources (usually in different sizes or color configurations), which are grouped together by the corresponding icon group resource.\n\n##### Set the icon\n\nTo add or overwrite icon resources based on an ICO file, call the `SetIcon(...)` extension method:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Icons;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.SetIcon(\"new_icon.ico\");\n```\n\n\u003e **Warning**:\n\u003e Calling this method does not remove the existing icon and icon group resources, except for those that are overwritten directly.\n\u003e If you want to clean out redundant icon resources, call the `RemoveIcon()` method first.\n\nAdditionally, you can also set the icon by passing a stream that contains ICO-formatted data:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Icons;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nusing var iconFileStream = File.OpenRead(\"new_icon.ico\");\nportableExecutable.SetIcon(iconFileStream);\n```\n\n##### Remove the icon\n\nTo remove all icon and icon group resources, call the `RemoveIcon()` extension method:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Icons;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.RemoveIcon();\n```\n\n#### Version info resources\n\nA version info resource (type `16`) contains file version numbers, compatibility flags, and arbitrary string attributes.\nSome of these attributes (such as, for example, `ProductName` and `Copyright`) are recognized by the operating system and may be displayed in certain places.\n\n##### Retrieve version info\n\nTo get the version info resource, call the `GetVersionInfo()` extension method.\nThis returns a `VersionInfo` object that represents the deserialized binary data stored in the resource:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Versions;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nvar versionInfo = portableExecutable.GetVersionInfo();\n// -or-\n// var versionInfo = portableExecutable.TryGetVersionInfo();\n```\n\nReturned object should contain data similar to this:\n\n```jsonc\n// Formatted as JSON in this example for better readability\n{\n  \"FileVersion\": \"10.0.19041.1\",\n  \"ProductVersion\": \"10.0.19041.1\",\n  \"FileFlags\": \"None\",\n  \"FileOperatingSystem\": \"Windows32, WindowsNT\",\n  \"FileType\": \"Application\",\n  \"FileSubType\": \"Unknown\",\n  \"AttributeTables\": [\n    {\n      \"Language\": {\n        \"Id\": 1033\n      },\n      \"CodePage\": {\n        \"Id\": 1200\n      },\n      \"Attributes\": {\n        \"CompanyName\": \"Microsoft Corporation\",\n        \"FileDescription\": \"Notepad\",\n        \"FileVersion\": \"10.0.19041.1 (WinBuild.160101.0800)\",\n        \"InternalName\": \"Notepad\",\n        \"LegalCopyright\": \"© Microsoft Corporation. All rights reserved.\",\n        \"OriginalFilename\": \"NOTEPAD.EXE.MUI\",\n        \"ProductName\": \"Microsoft® Windows® Operating System\",\n        \"ProductVersion\": \"10.0.19041.1\"\n      }\n    }\n  ]\n}\n```\n\n\u003e **Note**:\n\u003e If there are multiple version info resources, this method retrieves the first one it finds, giving preference to resources with lower ordinal name (ID) and in the neutral language.\n\nWhen working with version info resources that include multiple attribute tables (bound to different language and code page pairs), you can use the `GetAttribute(...)` method to query a specific attribute.\nThis method searches through all attribute tables (giving preference to tables in the neutral language) and returns the first matching value it finds:\n\n```csharp\n// ...\n\nvar companyName = versionInfo.GetAttribute(VersionAttributeName.CompanyName); // Microsoft Corporation\n// -or-\n// var companyName = versionInfo.TryGetAttribute(VersionAttributeName.CompanyName);\n```\n\n##### Set version info\n\nTo add or overwrite a version info resource, call the `SetVersionInfo(...)` extension method.\nYou can use the `VersionInfoBuilder` class to drastically simplify the creation of a new `VersionInfo` instance:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Versions;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nvar versionInfo = new VersionInfoBuilder()\n    .SetFileVersion(new Version(1, 2, 3, 4))\n    .SetProductVersion(new Version(1, 2, 3, 4))\n    .SetFileType(FileType.Application)\n    .SetAttribute(VersionAttributeName.FileDescription, \"My new description\")\n    .SetAttribute(VersionAttributeName.CompanyName, \"My new company\")\n    .SetAttribute(\"Custom Attribute\", \"My new value\")\n    .Build();\n\nportableExecutable.SetVersionInfo(versionInfo);\n```\n\nYou can also use an alternative overload of this method, which lets you selectively modify only a subset of properties in a version info resource, leaving the rest intact.\nProperties that are not provided are pulled from the existing version info resource or resolved to their default values in case the resource does not exist:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Versions;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.SetVersionInfo(v =\u003e v\n    .SetFileVersion(new Version(1, 2, 3, 4))\n    .SetAttribute(\"Custom Attribute\", \"My new value\")\n);\n```\n\n\u003e **Note**:\n\u003e When using the `SetAttribute(...)` method on `VersionInfoBuilder`, you can optionally specify the language and code page of the table that you want to add the attribute to.\n\u003e If you choose to omit these parameters, **Ressy** will set the attribute in all attribute tables.\n\u003e In case there are no existing attribute tables, this method creates a new one bound to the neutral language and the Unicode code page.\n\n##### Remove version info\n\nTo remove all version info resources, call the `RemoveVersionInfo()` extension method:\n\n```csharp\nusing Ressy;\nusing Ressy.HighLevel.Versions;\n\nvar portableExecutable = new PortableExecutable(\"some_app.exe\");\n\nportableExecutable.RemoveVersionInfo();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyrrrz%2Fressy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftyrrrz%2Fressy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftyrrrz%2Fressy/lists"}