win32-api
FFI Definitions of Windows win32 api for node-ffi-napi
Migrate to v13
See migrate13
Initialization
npm run bootstrap
Packages
Package | Version |
---|---|
win32-api |
|
win32-def |
What can I do with this?
Calling win32 native functions come from user32.dll, kernel32.dll, comctl32.dll by Node.js via node-ffi-napi
Installing
npm install win32-api
Usage
DLL Wrapper
import {
user32FindWindowEx,
winspoolGetDefaultPrinter,
} from 'win32-api/fun'
// Retrieves the printer name of the default printer for the current user on the local computer
const printerName = await winspoolGetDefaultPrinter()
const child = spawn('notepad.exe')
const hWnd = await user32FindWindowEx(0, 0, 'Notepad', null)
Find window and set window title
// **Find calc's hWnd, need running a calculator program manually at first**
/**
* Exposed modules:
* Comctl32: Comctl32 from lib/comctl32/api
* Kernel32: kernel32 from lib/kernel32/api
* User32: user32 from lib/user32/api
*/
import { Kernel32, User32 } from 'win32-api/promise'
import ref from 'ref-napi'
const knl32 = Kernel32.load()
const user32 = User32.load()
// const user32 = load(['FindWindowExW']) // load only one api defined in lib/{dll}/api from user32.dll
const title = 'Calculator\0' // null-terminated string
// const title = '计算器\0' // null-terminated string 字符串必须以\0即null结尾!
const lpszWindow = Buffer.from(title, 'ucs2')
const hWnd = await user32.FindWindowExW(0, 0, null, lpszWindow)
assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0)
console.log('buf: ', hWnd)
// Change title of the Calculator
const res = await user32.SetWindowTextW(hWnd, Buffer.from('Node-Calculator\0', 'ucs2'))
if ( ! res) {
console.log('SetWindowTextW failed')
}
else {
console.log('window title changed')
}
Ref
import ref from 'ref-napi'
// so we can all agree that a buffer with the int value written
// to it could be represented as an "int *"
const buf = Buffer.alloc(4)
buf.writeInt32LE(12345, 0)
const hex = ref.hexAddress(buf)
console.log(typeof hex)
console.log(hex) // ← '7FA89D006FD8'
buf.type = ref.types.int // @ts-ignore
// now we can dereference to get the "meaningful" value
console.log(ref.deref(buf)) // ← 12345
// use of types and windef:
import ref from 'ref-napi'
import { DModel as M } from 'win32-api'
import { Kernel32, User32 } from 'win32-api/promise'
const knl32 = Kernel32.load()
const user32 = User32.load()
const lpszClass = Buffer.from('guard64\0', 'ucs2')
const hInstanceBuffer = ref.alloc(W.HANDLE_PVOID)
const hInstanceAddr = ref.address(hInstanceBuffer)
await knl32.GetModuleHandleExW(0, lpszClass, hInstanceAddr)
// <Buffer@0x00000094D3968EC0 00 00 a4 60 ff 7f 00 00, type: { indirection: 2, name: 'uint64*' }>
console.log(hInstanceBuffer)
console.log(hInstanceBuffer.readInt32LE(0)) // -> 1621360640 (60A40000)
console.log(hInstanceBuffer.readBigUInt64LE()) // -> 140734814748672n (7FFF60A40000)
Struct
// struct usage with ref-struct
import { retrieveStructFromPtrAddress, StructFactory } from 'win32-api'
import {
DModel as M,
DTypes as W,
DStruct as DS,
} from 'win32-api'
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx
const point = StructFactory<M.POINT>(DS.POINT)
point.x = 100
point.y = 200
console.log(point)
Struct
import { StructFactory } from 'win32-api'
import {
DModel as M,
DTypes as W,
DStruct as DS,
} from 'win32-api'
// https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew
const dd: M.DISPLAY_DEVICEW = StructFactory(DS.DISPLAY_DEVICEW)
dd.cb = dd.ref().byteLength
console.log(dd)
// https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test/user32/51.user32.EnumDisplayDevicesW.test.ts
Async Find window and set window title
// **Find calc's hWnd, need running a calculator program manually at first**
import * as ref from 'ref-napi'
import {
DModel as M,
DTypes as W,
DStruct as DS,
} from 'win32-api'
import { Kernel32, User32 } from 'win32-api/promise'
const knl32 = Kernel32.load()
const user32 = User32.load()
const lpszClass = Buffer.from('CalcFrame\0', 'ucs2')
// win10
const calcLpszWindow = Buffer.from('Calculator\0', 'ucs2')
// for win7/8
const calcLpszClass = Buffer.from('CalcFrame\0', 'ucs2')
const child = spawn('calc.exe')
const hWnd = await user32.FindWindowExW(0, 0, null, calcLpszWindow) // win10
const hWnd = await user32.FindWindowExW(0, 0, calcLpszClass , null) // win7/8
assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0, 'found no calc window')
const title = 'Node-Calculator'
const len = title.length
const ret = await user32.SetWindowTextW(hWnd, Buffer.from(title + '\0', 'ucs2'))
assert(ret, 'SetWindowTextW() failed')
const buf = Buffer.alloc(len * 2)
await user32.GetWindowTextW(hWnd, buf, len + 1)
const str = buf.toString('ucs2').replace(/\0+$/, '')
assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`)
child.kill() // seems not work under win10
Demo
Dependencies Troubleshooting
Compile successfully with
- Node.js v18, Python v3.9 and VS2019, VS2022
- Node.js v16, Python v3.9 and VS2019, VS2022
- Node.js v14, Python v3.7 and VS2019
If installation of node-gyp fails: Check out node-gyp and node-gyp-on-windows, windows-build-tools