npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

resedit

v2.0.3

Published

Node.js library editing Windows Resource data

Downloads

733,610

Readme

NPM version Build Status

resedit-js

resedit-js is a library that manipulates resouces contained by Windows Executable files. All implementations are written in JavaScript (TypeScript), so there are no further restrictions for running environment.

This library is not tested well for modifying and/or signing executables yet. Please be careful with the emitted binaries.

To use in command line, consider using resedit-js-cli.

The demo page: resedit demo

Install

npm install resedit

Migrate from v1.x to v2.x

  • If you use from ES module (.mjs) and load by using import, no need for migration.
  • If you use from ES module (.mjs) and load by using require (Node.js: via createRequire), replace with import statement: import * as ResEdit from 'resedit'.
  • If you use from CommonJS module (.cjs) and load by using require, choose followings:
    • Convert CommonJS module to ES module and replace require call with import statement
    • Use resedit/cjs module and call load function (see below)
  • If you use TypeScript,
    • For "module": "ES2015" or higher, no need for migration.
    • For "module": "CommonJS", import resedit/cjs and call load function

The sample of using resedit/cjs in CommonJS module is:

const { load } = require('resedit/cjs');
load().then((ResEdit) => {
  // ResEdit will be the namespace object of resedit library
  // (for example ResEdit.Data.IconFile is available)
});

Similarly, the sample of using resedit/cjs in TypeScript CommonJS module is:

// You can use `ResEdit` for type references (cannot be used for value references)
import { type ResEdit, load } from 'resedit/cjs';
load().then((RE: typeof ResEdit) => {
  // RE will be the namespace object of resedit library
  // (for example RE.Data.IconFile is available)
});

Supported formats

  • Windows Executables (PE Format, such as .exe and .dll), both 32-bit and 64-bit, are supported.
    • Executables for 16-bit Windows is not supported.
  • .res file is not supported now.
  • PNG-based icon data is supported on require('resedit').Resource.IconGroupEntry class.

Parsing signed executables

  • Parsing signed executables (by using Authenticode or etc.) is not allowed by default and an exception will be thrown if NtExecutable.from receives a signed binary.
  • To parse signed, { ignoreCert: true } object must be passed to the second argument of NtExecutable.from.
  • Although the base executable data is signed, NtExecutable.generate will generate unsigned executable binary. If you want to re-sign it, you must use generate-function with signing (see below) or any other signing tool such as Microsoft signtool.

Signing executables with resedit-js

resedit-js provides basic signing process generateExecutableWithSign function, which is based on Authenticode specification and related RFCs.

To keep resedit-js generic library, the followings are required to use signing process.

  • Encryption / calculating hash (digest) process (e.g. Node.js built-in crypto module)
    • A private key data is implicitly required to encrypt data.
  • DER-format certificate binary (such as *.cer file data or *.p7b file data with DER-format), which is paired with the private key used by encryption process.
  • (optional) Generating timestamp data, especially communicating with TSA server (e.g. HTTP/HTTPS API)

These requirements are represented as SignerObject. The caller of generateExecutableWithSign function must implement this object to sign executables.

An example code is here: signTest.mjs

Note that resedit-js only provides basic signing process, and provides as beta version. For example adding more attributes/informations to certificates are not supported now.

Some digest algorithms, such as SHA3 algorithms, might not be supported by current Windows.

Notes

  • It is not strongly recommended that the destination executable file is equal to the source executable file (which is not an intermediate data).

Examples

For more APIs, please see dist directory of the package. And, some test codes may help you for usages.

import * as PELibrary from 'pe-library';
import * as ResEdit from 'resedit';
import * as fs from 'fs';

// load and parse data
const data = fs.readFileSync('MyApp.exe');
// (the Node.js Buffer instance can be specified directly to NtExecutable.from)
const exe = PELibrary.NtExecutable.from(data);
const res = PELibrary.NtExecutableResource.from(exe);

// rewrite resources
// - You can use helper classes as followings:
//   - ResEdit.Resource.IconGroupEntry: access icon resource data
//   - ResEdit.Resource.StringTable: access string resource data
//   - ResEdit.Resource.VersionInfo: access version info data

// -- replace icons

// load icon data from file
// (you can use ResEdit.Data.IconFile to parse icon data)
const iconFile = ResEdit.Data.IconFile.from(fs.readFileSync('MyIcon.ico'));

ResEdit.Resource.IconGroupEntry.replaceIconsForResource(
  // destEntries
  res.entries,
  // iconGroupID
  // - This ID is originally defined in base executable file
  //   (the ID list can be retrieved by `ResEdit.Resource.IconGroupEntry.fromEntries(res.entries).map((entry) => entry.id)`)
  101,
  // lang ('lang: 1033' means 'en-US')
  1033,
  // icons (map IconFileItem to IconItem/RawIconItem)
  iconFile.icons.map((item) => item.data)
);

// -- replace version

const viList = ResEdit.Resource.VersionInfo.fromEntries(res.entries);
const vi = viList[0];
// setFileVersion will set `vi.fixedInfo.fileVersionMS`/`fileVersionLS` and 'FileVersion' string value
// ('1033' means 'en-US')
vi.setFileVersion(1, 0, 0, 0, 1033);
// ('lang: 1033' means 'en-US', 'codepage: 1200' is the default codepage)
vi.setStringValues(
  { lang: 1033, codepage: 1200 },
  {
    FileDescription: 'My application',
    ProductName: 'My product',
  }
);
vi.outputToResourceEntries(res.entries);

// write to another binary
res.outputResource(exe);
const newBinary = exe.generate();
fs.writeFileSync('MyApp_modified.exe', Buffer.from(newBinary));

License

MIT License