nwinread 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -0
- package/CHANGES.md +120 -0
- package/LICENSE +21 -0
- package/README.md +135 -0
- package/binding.gyp +27 -0
- package/build/binding.sln +19 -0
- package/build/eventlog.vcxproj +148 -0
- package/build/eventlog.vcxproj.filters +55 -0
- package/index.js +17 -0
- package/native/eventlog.cc +298 -0
- package/package.json +22 -0
- package/test.js +34 -0
package/.gitattributes
ADDED
package/CHANGES.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Resumen de Correcciones - nwinread
|
|
2
|
+
|
|
3
|
+
## Limpieza de Archivos (8 de febrero de 2026)
|
|
4
|
+
|
|
5
|
+
### Archivos Eliminados
|
|
6
|
+
- `native/eventlog_new.cc` - Archivo temporal de desarrollo
|
|
7
|
+
- `native/eventlog_simple.cc` - Archivo temporal de desarrollo
|
|
8
|
+
- `native/binding.gyp` - Duplicado innecesario
|
|
9
|
+
- `native/build/` - Carpeta de build duplicada
|
|
10
|
+
- `native/node_modules/` - Dependencias duplicadas
|
|
11
|
+
|
|
12
|
+
### Archivos Agregados
|
|
13
|
+
- `.gitignore` - Para mantener el repositorio limpio
|
|
14
|
+
|
|
15
|
+
### Estructura Final Limpia
|
|
16
|
+
```
|
|
17
|
+
nwinread/
|
|
18
|
+
├── binding.gyp # Configuración de build
|
|
19
|
+
├── index.js # API principal
|
|
20
|
+
├── package.json # Configuración del proyecto
|
|
21
|
+
├── README.md # Documentación
|
|
22
|
+
├── test.js # Pruebas
|
|
23
|
+
├── CHANGES.md # Este archivo
|
|
24
|
+
├── .gitignore # Archivos a ignorar en git
|
|
25
|
+
├── native/
|
|
26
|
+
│ └── eventlog.cc # Código fuente C++
|
|
27
|
+
└── build/ # Resultado de compilación
|
|
28
|
+
└── Release/
|
|
29
|
+
└── eventlog.node
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Problemas Encontrados y Solucionados
|
|
33
|
+
|
|
34
|
+
### 1. **Inconsistencia en nombres de funciones**
|
|
35
|
+
- **Problema**: En `index.js` se llamaba `native.readEvents()` pero en C++ se exportaba como `read`
|
|
36
|
+
- **Solución**: Corregido para usar `native.read()` con parámetros individuales
|
|
37
|
+
|
|
38
|
+
### 2. **Problemas de compilación con node-addon-api**
|
|
39
|
+
- **Problema**: Errores de sintaxis con la versión 8.x de node-addon-api
|
|
40
|
+
- **Solución**: Migrado a Node-API puro (node_api.h) que es más estable
|
|
41
|
+
|
|
42
|
+
### 3. **Configuración de binding.gyp**
|
|
43
|
+
- **Problema**: Configuración incorrecta para Windows y librerías
|
|
44
|
+
- **Solución**: Simplificado para usar Node-API puro y linking correcto a wevtapi.lib
|
|
45
|
+
|
|
46
|
+
### 4. **Manejo de errores mejorado**
|
|
47
|
+
- **Problema**: Manejo básico de errores sin validación
|
|
48
|
+
- **Solución**: Agregado validación exhaustiva de parámetros y manejo de errores de Windows API
|
|
49
|
+
|
|
50
|
+
### 5. **Scripts de build**
|
|
51
|
+
- **Problema**: Faltaban scripts convenientes para build
|
|
52
|
+
- **Solución**: Agregados scripts `build`, `rebuild`, `clean`, y `test` en package.json
|
|
53
|
+
|
|
54
|
+
## Archivos Modificados/Creados
|
|
55
|
+
|
|
56
|
+
### `package.json`
|
|
57
|
+
- Agregados scripts de build y prueba
|
|
58
|
+
- Removida dependencia de node-addon-api
|
|
59
|
+
- Agregada descripción del proyecto
|
|
60
|
+
|
|
61
|
+
### `index.js`
|
|
62
|
+
- Corregida llamada a función nativa
|
|
63
|
+
- Mejorada API con parámetros explícitos
|
|
64
|
+
- Agregada documentación de parámetros
|
|
65
|
+
|
|
66
|
+
### `native/eventlog.cc`
|
|
67
|
+
- Reescrito completamente usando Node-API puro
|
|
68
|
+
- Agregado manejo robusto de errores
|
|
69
|
+
- Mejorada validación de parámetros
|
|
70
|
+
- Mejor conversión de strings UTF-8/UTF-16
|
|
71
|
+
|
|
72
|
+
### `binding.gyp`
|
|
73
|
+
- Simplificado para Node-API puro
|
|
74
|
+
- Configuración correcta para Windows
|
|
75
|
+
- Linking apropiado a wevtapi.lib
|
|
76
|
+
|
|
77
|
+
### `test.js`
|
|
78
|
+
- Creado archivo de prueba funcional
|
|
79
|
+
- Prueba lectura del log de Sistema
|
|
80
|
+
- Validación de resultados
|
|
81
|
+
|
|
82
|
+
### `README.md`
|
|
83
|
+
- Documentación completa actualizada
|
|
84
|
+
- Instrucciones de instalación y uso
|
|
85
|
+
- Ejemplos de código
|
|
86
|
+
- Solución de problemas comunes
|
|
87
|
+
|
|
88
|
+
## Estado Final
|
|
89
|
+
|
|
90
|
+
✅ **Compilación**: Exitosa sin errores
|
|
91
|
+
✅ **Funcionalidad**: Módulo lee eventos de Windows correctamente
|
|
92
|
+
✅ **Pruebas**: Pasan exitosamente
|
|
93
|
+
✅ **API**: Interfaz limpia y bien documentada
|
|
94
|
+
|
|
95
|
+
## Funcionalidades Implementadas
|
|
96
|
+
|
|
97
|
+
- Lectura de eventos desde cualquier canal de Windows Event Log
|
|
98
|
+
- Soporte para 3 modos de lectura (principio, final, watermark)
|
|
99
|
+
- Validación robusta de parámetros
|
|
100
|
+
- Manejo apropiado de errores de Windows API
|
|
101
|
+
- Conversión correcta de codificación UTF-8/UTF-16
|
|
102
|
+
- Extracción de Event Record IDs del XML
|
|
103
|
+
- Limitación configurable del número de eventos
|
|
104
|
+
|
|
105
|
+
## Uso del Módulo
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
const nwinread = require('nwinread');
|
|
109
|
+
|
|
110
|
+
const result = nwinread.readEvents(
|
|
111
|
+
'System', // Canal
|
|
112
|
+
nwinread.START_MODE.END, // Modo
|
|
113
|
+
0, // Watermark
|
|
114
|
+
10 // Máximo eventos
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
console.log(`Encontrados ${result.records.length} eventos`);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
El proyecto ahora está completamente funcional y listo para producción.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Solzimer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# nwinread - Windows Event Log Reader
|
|
2
|
+
|
|
3
|
+
A native Node.js module for reading Windows event logs using the Windows Event Log API.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Windows Vista/7/8/10/11 or Windows Server 2008/2012/2016/2019/2022
|
|
8
|
+
- Node.js (version 14 or higher)
|
|
9
|
+
- Visual Studio Build Tools or Visual Studio Community
|
|
10
|
+
- Python (for node-gyp)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install
|
|
16
|
+
npm run build
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Manual step-by-step installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Install dependencies
|
|
23
|
+
npm install node-addon-api
|
|
24
|
+
npm install -g node-gyp
|
|
25
|
+
|
|
26
|
+
# Configure and compile the native module
|
|
27
|
+
node-gyp configure
|
|
28
|
+
node-gyp build
|
|
29
|
+
|
|
30
|
+
# Or use the package.json script
|
|
31
|
+
npm run build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
const nwinread = require('nwinread');
|
|
38
|
+
|
|
39
|
+
// Read events from the end of the log (all events)
|
|
40
|
+
const result = nwinread.readEvents(
|
|
41
|
+
'System', // Channel (System, Application, Security, etc.)
|
|
42
|
+
nwinread.START_MODE.END, // Read mode
|
|
43
|
+
0, // Watermark (for WATERMARK mode)
|
|
44
|
+
10 // Maximum number of events
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Read events with specific ID filter
|
|
48
|
+
const filteredResult = nwinread.readEvents(
|
|
49
|
+
'System', // Channel
|
|
50
|
+
nwinread.START_MODE.BEGINNING, // Read mode
|
|
51
|
+
0, // Watermark
|
|
52
|
+
20, // Maximum number of events
|
|
53
|
+
[7045, 7034, 7036] // Event IDs filter (optional)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
console.log(`Found ${result.records.length} events`);
|
|
57
|
+
console.log(`Last Record ID: ${result.lastRecordId}`);
|
|
58
|
+
|
|
59
|
+
console.log(`Filtered events: ${filteredResult.records.length}`);
|
|
60
|
+
|
|
61
|
+
// Process events
|
|
62
|
+
result.records.forEach((event, index) => {
|
|
63
|
+
console.log(`Event ${index + 1}:`);
|
|
64
|
+
console.log(` Record ID: ${event.recordId}`);
|
|
65
|
+
console.log(` XML: ${event.xml.substring(0, 100)}...`);
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Read modes
|
|
70
|
+
|
|
71
|
+
- `START_MODE.BEGINNING` (0): Read from the beginning of the log
|
|
72
|
+
- `START_MODE.END` (1): Read from the end of the log
|
|
73
|
+
- `START_MODE.WATERMARK` (2): Read from a specific Record ID
|
|
74
|
+
|
|
75
|
+
## API
|
|
76
|
+
|
|
77
|
+
### readEvents(channel, mode, watermark, maxEvents, eventIds)
|
|
78
|
+
|
|
79
|
+
- **channel** (string): Event channel name (e.g.: 'System', 'Application', 'Security')
|
|
80
|
+
- **mode** (number): Read mode (use START_MODE constants)
|
|
81
|
+
- **watermark** (number): Record ID to start from (only for WATERMARK mode)
|
|
82
|
+
- **maxEvents** (number): Maximum number of events to read (1-10000)
|
|
83
|
+
- **eventIds** (array|null, optional): Array of Event IDs to filter. If `null`, `undefined`, or empty array, no filter is applied
|
|
84
|
+
|
|
85
|
+
**Returns:** Object with properties:
|
|
86
|
+
- `records`: Array of events with `xml` and `recordId` properties
|
|
87
|
+
- `lastRecordId`: ID of the last processed record
|
|
88
|
+
|
|
89
|
+
### Event ID filtering examples
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// No filter - all events
|
|
93
|
+
const allEvents = nwinread.readEvents('System', nwinread.START_MODE.BEGINNING, 0, 10);
|
|
94
|
+
|
|
95
|
+
// Filter only Windows service events
|
|
96
|
+
const serviceEvents = nwinread.readEvents('System', nwinread.START_MODE.BEGINNING, 0, 10, [7034, 7035, 7036, 7040, 7045]);
|
|
97
|
+
|
|
98
|
+
// Filter specific critical events
|
|
99
|
+
const criticalEvents = nwinread.readEvents('System', nwinread.START_MODE.BEGINNING, 0, 10, [1000, 1001, 1002]);
|
|
100
|
+
|
|
101
|
+
// Empty array = no filter (equivalent to null)
|
|
102
|
+
const noFilter = nwinread.readEvents('System', nwinread.START_MODE.BEGINNING, 0, 10, []);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Common Event IDs
|
|
106
|
+
|
|
107
|
+
- **7034**: Service crashed
|
|
108
|
+
- **7035**: Service start/stop control sent
|
|
109
|
+
- **7036**: Service started/stopped
|
|
110
|
+
- **7040**: Service startup type changed
|
|
111
|
+
- **7045**: New service installed
|
|
112
|
+
- **1000**: Application error
|
|
113
|
+
- **1001**: Application hang
|
|
114
|
+
- **4624**: Successful account logon (Security log)
|
|
115
|
+
- **4625**: Failed account logon (Security log)
|
|
116
|
+
|
|
117
|
+
## Testing
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm test
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Troubleshooting
|
|
124
|
+
|
|
125
|
+
1. **Compilation error**: Make sure you have Visual Studio Build Tools installed
|
|
126
|
+
2. **Permission error**: Some logs require administrator privileges
|
|
127
|
+
3. **Channel not found**: Verify that the channel name is correct
|
|
128
|
+
|
|
129
|
+
## Common channels
|
|
130
|
+
|
|
131
|
+
- `System`: System events
|
|
132
|
+
- `Application`: Application events
|
|
133
|
+
- `Security`: Security events (requires admin permissions)
|
|
134
|
+
- `Setup`: Installation events
|
|
135
|
+
- `Microsoft-Windows-PowerShell/Operational`: PowerShell events
|
package/binding.gyp
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"targets": [
|
|
3
|
+
{
|
|
4
|
+
"target_name": "eventlog",
|
|
5
|
+
"sources": [ "native/eventlog.cc" ],
|
|
6
|
+
"defines": [
|
|
7
|
+
"UNICODE",
|
|
8
|
+
"_UNICODE",
|
|
9
|
+
"WIN32_LEAN_AND_MEAN",
|
|
10
|
+
"_WIN32_WINNT=0x0600"
|
|
11
|
+
],
|
|
12
|
+
"conditions": [
|
|
13
|
+
['OS=="win"', {
|
|
14
|
+
"link_settings": {
|
|
15
|
+
"libraries": [ "-lwevtapi.lib" ]
|
|
16
|
+
},
|
|
17
|
+
"msvs_settings": {
|
|
18
|
+
"VCCLCompilerTool": {
|
|
19
|
+
"ExceptionHandling": 1,
|
|
20
|
+
"AdditionalOptions": [ "/utf-8" ]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}]
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
2
|
+
# Visual Studio 2015
|
|
3
|
+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eventlog", "eventlog.vcxproj", "{3EC5C0A2-29FB-8AA2-6EDD-875B8159EA7D}"
|
|
4
|
+
EndProject
|
|
5
|
+
Global
|
|
6
|
+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
7
|
+
Debug|x64 = Debug|x64
|
|
8
|
+
Release|x64 = Release|x64
|
|
9
|
+
EndGlobalSection
|
|
10
|
+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
11
|
+
{3EC5C0A2-29FB-8AA2-6EDD-875B8159EA7D}.Debug|x64.ActiveCfg = Debug|x64
|
|
12
|
+
{3EC5C0A2-29FB-8AA2-6EDD-875B8159EA7D}.Debug|x64.Build.0 = Debug|x64
|
|
13
|
+
{3EC5C0A2-29FB-8AA2-6EDD-875B8159EA7D}.Release|x64.ActiveCfg = Release|x64
|
|
14
|
+
{3EC5C0A2-29FB-8AA2-6EDD-875B8159EA7D}.Release|x64.Build.0 = Release|x64
|
|
15
|
+
EndGlobalSection
|
|
16
|
+
GlobalSection(SolutionProperties) = preSolution
|
|
17
|
+
HideSolutionNode = FALSE
|
|
18
|
+
EndGlobalSection
|
|
19
|
+
EndGlobal
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
3
|
+
<ItemGroup Label="ProjectConfigurations">
|
|
4
|
+
<ProjectConfiguration Include="Debug|x64">
|
|
5
|
+
<Configuration>Debug</Configuration>
|
|
6
|
+
<Platform>x64</Platform>
|
|
7
|
+
</ProjectConfiguration>
|
|
8
|
+
<ProjectConfiguration Include="Release|x64">
|
|
9
|
+
<Configuration>Release</Configuration>
|
|
10
|
+
<Platform>x64</Platform>
|
|
11
|
+
</ProjectConfiguration>
|
|
12
|
+
</ItemGroup>
|
|
13
|
+
<PropertyGroup Label="Globals">
|
|
14
|
+
<ProjectGuid>{3EC5C0A2-29FB-8AA2-6EDD-875B8159EA7D}</ProjectGuid>
|
|
15
|
+
<Keyword>Win32Proj</Keyword>
|
|
16
|
+
<RootNamespace>eventlog</RootNamespace>
|
|
17
|
+
<IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename>
|
|
18
|
+
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
|
19
|
+
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
|
|
20
|
+
</PropertyGroup>
|
|
21
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
|
|
22
|
+
<PropertyGroup Label="Configuration">
|
|
23
|
+
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
24
|
+
</PropertyGroup>
|
|
25
|
+
<PropertyGroup Label="Locals">
|
|
26
|
+
<PlatformToolset>v143</PlatformToolset>
|
|
27
|
+
</PropertyGroup>
|
|
28
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
|
|
29
|
+
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props"/>
|
|
30
|
+
<ImportGroup Label="ExtensionSettings"/>
|
|
31
|
+
<ImportGroup Label="PropertySheets">
|
|
32
|
+
<Import Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"/>
|
|
33
|
+
</ImportGroup>
|
|
34
|
+
<PropertyGroup Label="UserMacros"/>
|
|
35
|
+
<PropertyGroup>
|
|
36
|
+
<ExecutablePath>$(ExecutablePath);$(MSBuildProjectDirectory)\..\bin\;$(MSBuildProjectDirectory)\..\bin\</ExecutablePath>
|
|
37
|
+
<IgnoreImportLibrary>true</IgnoreImportLibrary>
|
|
38
|
+
<IntDir>$(Configuration)\obj\$(ProjectName)\</IntDir>
|
|
39
|
+
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
|
40
|
+
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
|
|
41
|
+
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
|
42
|
+
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.node</TargetExt>
|
|
43
|
+
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.node</TargetExt>
|
|
44
|
+
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.node</TargetExt>
|
|
45
|
+
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.node</TargetExt>
|
|
46
|
+
<TargetName>$(ProjectName)</TargetName>
|
|
47
|
+
<TargetPath>$(OutDir)\$(ProjectName).node</TargetPath>
|
|
48
|
+
</PropertyGroup>
|
|
49
|
+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
50
|
+
<ClCompile>
|
|
51
|
+
<AdditionalIncludeDirectories>C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\include\node;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\src;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\config;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\openssl\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\uv\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\zlib;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\v8\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
52
|
+
<AdditionalOptions>/Zc:__cplusplus -std:c++20 /Zm2000 /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
|
53
|
+
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
|
54
|
+
<BufferSecurityCheck>true</BufferSecurityCheck>
|
|
55
|
+
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
56
|
+
<DisableSpecificWarnings>4351;4355;4800;4251;4275;4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
57
|
+
<ExceptionHandling>Sync</ExceptionHandling>
|
|
58
|
+
<MinimalRebuild>false</MinimalRebuild>
|
|
59
|
+
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
|
60
|
+
<OmitFramePointers>false</OmitFramePointers>
|
|
61
|
+
<Optimization>Disabled</Optimization>
|
|
62
|
+
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
63
|
+
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=eventlog;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;_GLIBCXX_USE_CXX11_ABI=1;_FILE_OFFSET_BITS=64;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;NOMINMAX;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";DEBUG;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
64
|
+
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
|
65
|
+
<StringPooling>true</StringPooling>
|
|
66
|
+
<SuppressStartupBanner>true</SuppressStartupBanner>
|
|
67
|
+
<TreatWarningAsError>false</TreatWarningAsError>
|
|
68
|
+
<WarningLevel>Level3</WarningLevel>
|
|
69
|
+
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
70
|
+
</ClCompile>
|
|
71
|
+
<Lib>
|
|
72
|
+
<AdditionalOptions>/LTCG:INCREMENTAL %(AdditionalOptions)</AdditionalOptions>
|
|
73
|
+
</Lib>
|
|
74
|
+
<Link>
|
|
75
|
+
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;delayimp.lib;"C:\\Users\\solzi\\AppData\\Local\\node-gyp\\Cache\\22.17.0\\x64\\node.lib";wevtapi.lib</AdditionalDependencies>
|
|
76
|
+
<AdditionalOptions>/LTCG:INCREMENTAL /ignore:4199 %(AdditionalOptions)</AdditionalOptions>
|
|
77
|
+
<DelayLoadDLLs>node.exe;%(DelayLoadDLLs)</DelayLoadDLLs>
|
|
78
|
+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
79
|
+
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
80
|
+
<OptimizeReferences>true</OptimizeReferences>
|
|
81
|
+
<OutputFile>$(OutDir)$(ProjectName).node</OutputFile>
|
|
82
|
+
<SuppressStartupBanner>true</SuppressStartupBanner>
|
|
83
|
+
<TargetExt>.node</TargetExt>
|
|
84
|
+
<TargetMachine>MachineX64</TargetMachine>
|
|
85
|
+
</Link>
|
|
86
|
+
<ResourceCompile>
|
|
87
|
+
<AdditionalIncludeDirectories>C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\include\node;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\src;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\config;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\openssl\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\uv\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\zlib;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\v8\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
88
|
+
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=eventlog;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;_GLIBCXX_USE_CXX11_ABI=1;_FILE_OFFSET_BITS=64;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;NOMINMAX;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";DEBUG;_DEBUG;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
89
|
+
</ResourceCompile>
|
|
90
|
+
</ItemDefinitionGroup>
|
|
91
|
+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
92
|
+
<ClCompile>
|
|
93
|
+
<AdditionalIncludeDirectories>C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\include\node;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\src;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\config;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\openssl\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\uv\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\zlib;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\v8\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
94
|
+
<AdditionalOptions>/Zc:__cplusplus -std:c++20 /Zm2000 /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
|
95
|
+
<BufferSecurityCheck>true</BufferSecurityCheck>
|
|
96
|
+
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
|
97
|
+
<DisableSpecificWarnings>4351;4355;4800;4251;4275;4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
|
98
|
+
<ExceptionHandling>Sync</ExceptionHandling>
|
|
99
|
+
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
|
100
|
+
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
101
|
+
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
|
102
|
+
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
103
|
+
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
|
104
|
+
<OmitFramePointers>true</OmitFramePointers>
|
|
105
|
+
<Optimization>Full</Optimization>
|
|
106
|
+
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
|
107
|
+
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=eventlog;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;_GLIBCXX_USE_CXX11_ABI=1;_FILE_OFFSET_BITS=64;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;NOMINMAX;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
108
|
+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
|
109
|
+
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
|
110
|
+
<StringPooling>true</StringPooling>
|
|
111
|
+
<SuppressStartupBanner>true</SuppressStartupBanner>
|
|
112
|
+
<TreatWarningAsError>false</TreatWarningAsError>
|
|
113
|
+
<WarningLevel>Level3</WarningLevel>
|
|
114
|
+
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
115
|
+
</ClCompile>
|
|
116
|
+
<Lib>
|
|
117
|
+
<AdditionalOptions>/LTCG:INCREMENTAL %(AdditionalOptions)</AdditionalOptions>
|
|
118
|
+
</Lib>
|
|
119
|
+
<Link>
|
|
120
|
+
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;delayimp.lib;"C:\\Users\\solzi\\AppData\\Local\\node-gyp\\Cache\\22.17.0\\x64\\node.lib";wevtapi.lib</AdditionalDependencies>
|
|
121
|
+
<AdditionalOptions>/LTCG:INCREMENTAL /ignore:4199 %(AdditionalOptions)</AdditionalOptions>
|
|
122
|
+
<DelayLoadDLLs>node.exe;%(DelayLoadDLLs)</DelayLoadDLLs>
|
|
123
|
+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
124
|
+
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
125
|
+
<OptimizeReferences>true</OptimizeReferences>
|
|
126
|
+
<OutputFile>$(OutDir)$(ProjectName).node</OutputFile>
|
|
127
|
+
<SuppressStartupBanner>true</SuppressStartupBanner>
|
|
128
|
+
<TargetExt>.node</TargetExt>
|
|
129
|
+
<TargetMachine>MachineX64</TargetMachine>
|
|
130
|
+
</Link>
|
|
131
|
+
<ResourceCompile>
|
|
132
|
+
<AdditionalIncludeDirectories>C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\include\node;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\src;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\config;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\openssl\openssl\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\uv\include;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\zlib;C:\Users\solzi\AppData\Local\node-gyp\Cache\22.17.0\deps\v8\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
133
|
+
<PreprocessorDefinitions>NODE_GYP_MODULE_NAME=eventlog;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;_GLIBCXX_USE_CXX11_ABI=1;_FILE_OFFSET_BITS=64;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;NOMINMAX;OPENSSL_NO_PINSHARED;OPENSSL_THREADS;UNICODE;_UNICODE;WIN32_LEAN_AND_MEAN;_WIN32_WINNT=0x0600;BUILDING_NODE_EXTENSION;HOST_BINARY="node.exe";%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
134
|
+
</ResourceCompile>
|
|
135
|
+
</ItemDefinitionGroup>
|
|
136
|
+
<ItemGroup>
|
|
137
|
+
<None Include="..\binding.gyp"/>
|
|
138
|
+
</ItemGroup>
|
|
139
|
+
<ItemGroup>
|
|
140
|
+
<ClCompile Include="..\native\eventlog.cc">
|
|
141
|
+
<ObjectFileName>$(IntDir)\native\eventlog.obj</ObjectFileName>
|
|
142
|
+
</ClCompile>
|
|
143
|
+
<ClCompile Include="C:\Users\solzi\AppData\Roaming\nvm\v22.17.0\node_modules\node-gyp\src\win_delay_load_hook.cc"/>
|
|
144
|
+
</ItemGroup>
|
|
145
|
+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
|
|
146
|
+
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets"/>
|
|
147
|
+
<ImportGroup Label="ExtensionTargets"/>
|
|
148
|
+
</Project>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
3
|
+
<ItemGroup>
|
|
4
|
+
<Filter Include="..">
|
|
5
|
+
<UniqueIdentifier>{13ED4249-1F9C-5F0F-2651-29A73F3A7059}</UniqueIdentifier>
|
|
6
|
+
</Filter>
|
|
7
|
+
<Filter Include="..\native">
|
|
8
|
+
<UniqueIdentifier>{751DE1B9-2CA6-B33D-2A40-92CBD5B002F3}</UniqueIdentifier>
|
|
9
|
+
</Filter>
|
|
10
|
+
<Filter Include="C:">
|
|
11
|
+
<UniqueIdentifier>{F87FD356-0FEB-9BC5-D1FA-368C81420008}</UniqueIdentifier>
|
|
12
|
+
</Filter>
|
|
13
|
+
<Filter Include="C:\Users">
|
|
14
|
+
<UniqueIdentifier>{707347A1-1ABA-A9B2-9AF4-DE122F5D7F08}</UniqueIdentifier>
|
|
15
|
+
</Filter>
|
|
16
|
+
<Filter Include="C:\Users\solzi">
|
|
17
|
+
<UniqueIdentifier>{36F44239-C2BD-2609-082B-8716CC7F3439}</UniqueIdentifier>
|
|
18
|
+
</Filter>
|
|
19
|
+
<Filter Include="C:\Users\solzi\AppData">
|
|
20
|
+
<UniqueIdentifier>{DABCEBCE-33D1-4D68-EC67-0BC19A2A0901}</UniqueIdentifier>
|
|
21
|
+
</Filter>
|
|
22
|
+
<Filter Include="C:\Users\solzi\AppData\Roaming">
|
|
23
|
+
<UniqueIdentifier>{06897101-0A2C-F34A-36C2-4D0BE8BF5EB9}</UniqueIdentifier>
|
|
24
|
+
</Filter>
|
|
25
|
+
<Filter Include="C:\Users\solzi\AppData\Roaming\nvm">
|
|
26
|
+
<UniqueIdentifier>{C6BD613B-358D-2DCD-8B8A-73765EB3E8E4}</UniqueIdentifier>
|
|
27
|
+
</Filter>
|
|
28
|
+
<Filter Include="C:\Users\solzi\AppData\Roaming\nvm\v22.17.0">
|
|
29
|
+
<UniqueIdentifier>{EEBCB736-7B17-79B2-FBF2-41E78D86FD71}</UniqueIdentifier>
|
|
30
|
+
</Filter>
|
|
31
|
+
<Filter Include="C:\Users\solzi\AppData\Roaming\nvm\v22.17.0\node_modules">
|
|
32
|
+
<UniqueIdentifier>{126A39EA-1D28-5689-C126-0DA0AB5837A0}</UniqueIdentifier>
|
|
33
|
+
</Filter>
|
|
34
|
+
<Filter Include="C:\Users\solzi\AppData\Roaming\nvm\v22.17.0\node_modules\node-gyp">
|
|
35
|
+
<UniqueIdentifier>{49558BB4-6D34-CA91-A65D-85A65792DC11}</UniqueIdentifier>
|
|
36
|
+
</Filter>
|
|
37
|
+
<Filter Include="C:\Users\solzi\AppData\Roaming\nvm\v22.17.0\node_modules\node-gyp\src">
|
|
38
|
+
<UniqueIdentifier>{F1003AD6-4B6D-45DF-3F56-5CAC869BF55E}</UniqueIdentifier>
|
|
39
|
+
</Filter>
|
|
40
|
+
<Filter Include="..">
|
|
41
|
+
<UniqueIdentifier>{13ED4249-1F9C-5F0F-2651-29A73F3A7059}</UniqueIdentifier>
|
|
42
|
+
</Filter>
|
|
43
|
+
</ItemGroup>
|
|
44
|
+
<ItemGroup>
|
|
45
|
+
<ClCompile Include="..\native\eventlog.cc">
|
|
46
|
+
<Filter>..\native</Filter>
|
|
47
|
+
</ClCompile>
|
|
48
|
+
<ClCompile Include="C:\Users\solzi\AppData\Roaming\nvm\v22.17.0\node_modules\node-gyp\src\win_delay_load_hook.cc">
|
|
49
|
+
<Filter>C:\Users\solzi\AppData\Roaming\nvm\v22.17.0\node_modules\node-gyp\src</Filter>
|
|
50
|
+
</ClCompile>
|
|
51
|
+
<None Include="..\binding.gyp">
|
|
52
|
+
<Filter>..</Filter>
|
|
53
|
+
</None>
|
|
54
|
+
</ItemGroup>
|
|
55
|
+
</Project>
|
package/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const native = require('./build/Release/eventlog.node');
|
|
2
|
+
|
|
3
|
+
const START_MODE = {
|
|
4
|
+
BEGINNING: 0,
|
|
5
|
+
END: 1,
|
|
6
|
+
WATERMARK: 2
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
START_MODE,
|
|
11
|
+
|
|
12
|
+
readEvents(channel, mode = START_MODE.BEGINNING, watermark = 0, maxEvents = 100, eventIds = null) {
|
|
13
|
+
// Si eventIds es null, undefined, o un array vacío, no se aplica filtro
|
|
14
|
+
const filterIds = (eventIds && eventIds.length > 0) ? eventIds : null;
|
|
15
|
+
return native.read(channel, mode, watermark, maxEvents, filterIds);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
#include <node_api.h>
|
|
2
|
+
#include <windows.h>
|
|
3
|
+
#include <winevt.h>
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <cassert>
|
|
7
|
+
|
|
8
|
+
#pragma comment(lib, "wevtapi.lib")
|
|
9
|
+
|
|
10
|
+
enum ReadMode {
|
|
11
|
+
FROM_BEGINNING = 0,
|
|
12
|
+
FROM_END = 1,
|
|
13
|
+
FROM_WATERMARK = 2
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Convierte UTF-8 a wide string
|
|
17
|
+
std::wstring Utf8ToWide(const std::string& str) {
|
|
18
|
+
if (str.empty()) return std::wstring();
|
|
19
|
+
|
|
20
|
+
int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
|
|
21
|
+
if (size == 0) return std::wstring();
|
|
22
|
+
|
|
23
|
+
std::wstring w(size, 0);
|
|
24
|
+
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &w[0], size);
|
|
25
|
+
return w;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Convierte wide string a UTF-8
|
|
29
|
+
std::string WideToUtf8(const std::wstring& wstr) {
|
|
30
|
+
if (wstr.empty()) return std::string();
|
|
31
|
+
|
|
32
|
+
int size = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
|
|
33
|
+
if (size == 0) return std::string();
|
|
34
|
+
|
|
35
|
+
std::string str(size, 0);
|
|
36
|
+
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], size, NULL, NULL);
|
|
37
|
+
return str;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
napi_value ReadEventLog(napi_env env, napi_callback_info info) {
|
|
41
|
+
napi_status status;
|
|
42
|
+
size_t argc = 5;
|
|
43
|
+
napi_value args[5];
|
|
44
|
+
|
|
45
|
+
// Obtener argumentos
|
|
46
|
+
status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
|
47
|
+
assert(status == napi_ok);
|
|
48
|
+
|
|
49
|
+
if (argc < 4) {
|
|
50
|
+
napi_throw_type_error(env, nullptr, "Expected 4-5 arguments: (channel, mode, watermark, maxEvents, eventIds?)");
|
|
51
|
+
return nullptr;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Extraer channel
|
|
55
|
+
size_t channel_len;
|
|
56
|
+
status = napi_get_value_string_utf8(env, args[0], nullptr, 0, &channel_len);
|
|
57
|
+
assert(status == napi_ok);
|
|
58
|
+
|
|
59
|
+
std::string channel(channel_len, '\0');
|
|
60
|
+
status = napi_get_value_string_utf8(env, args[0], &channel[0], channel_len + 1, &channel_len);
|
|
61
|
+
assert(status == napi_ok);
|
|
62
|
+
|
|
63
|
+
// Extraer otros argumentos
|
|
64
|
+
int32_t mode;
|
|
65
|
+
int64_t watermark;
|
|
66
|
+
int32_t maxEvents;
|
|
67
|
+
|
|
68
|
+
status = napi_get_value_int32(env, args[1], &mode);
|
|
69
|
+
assert(status == napi_ok);
|
|
70
|
+
|
|
71
|
+
status = napi_get_value_int64(env, args[2], &watermark);
|
|
72
|
+
assert(status == napi_ok);
|
|
73
|
+
|
|
74
|
+
status = napi_get_value_int32(env, args[3], &maxEvents);
|
|
75
|
+
assert(status == napi_ok);
|
|
76
|
+
|
|
77
|
+
// Procesar eventIds (parámetro opcional)
|
|
78
|
+
std::vector<int32_t> eventIds;
|
|
79
|
+
if (argc >= 5) {
|
|
80
|
+
napi_valuetype valueType;
|
|
81
|
+
status = napi_typeof(env, args[4], &valueType);
|
|
82
|
+
|
|
83
|
+
if (valueType != napi_null && valueType != napi_undefined) {
|
|
84
|
+
bool isArray;
|
|
85
|
+
status = napi_is_array(env, args[4], &isArray);
|
|
86
|
+
assert(status == napi_ok);
|
|
87
|
+
|
|
88
|
+
if (isArray) {
|
|
89
|
+
uint32_t arrayLength;
|
|
90
|
+
status = napi_get_array_length(env, args[4], &arrayLength);
|
|
91
|
+
assert(status == napi_ok);
|
|
92
|
+
|
|
93
|
+
for (uint32_t i = 0; i < arrayLength; i++) {
|
|
94
|
+
napi_value element;
|
|
95
|
+
status = napi_get_element(env, args[4], i, &element);
|
|
96
|
+
assert(status == napi_ok);
|
|
97
|
+
|
|
98
|
+
int32_t eventId;
|
|
99
|
+
status = napi_get_value_int32(env, element, &eventId);
|
|
100
|
+
if (status == napi_ok && eventId > 0) {
|
|
101
|
+
eventIds.push_back(eventId);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Validar parámetros
|
|
109
|
+
if (channel.empty()) {
|
|
110
|
+
napi_throw_type_error(env, nullptr, "Channel name cannot be empty");
|
|
111
|
+
return nullptr;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (mode < 0 || mode > 2) {
|
|
115
|
+
napi_throw_type_error(env, nullptr, "Invalid mode. Must be 0, 1, or 2");
|
|
116
|
+
return nullptr;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (maxEvents <= 0 || maxEvents > 10000) {
|
|
120
|
+
napi_throw_type_error(env, nullptr, "maxEvents must be between 1 and 10000");
|
|
121
|
+
return nullptr;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
DWORD flags = EvtQueryChannelPath;
|
|
125
|
+
if (mode == FROM_END) {
|
|
126
|
+
flags |= EvtQueryReverseDirection;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
std::wstring query;
|
|
130
|
+
|
|
131
|
+
// Construir filtro de Event IDs si se proporcionaron
|
|
132
|
+
std::wstring eventIdFilter;
|
|
133
|
+
if (!eventIds.empty()) {
|
|
134
|
+
eventIdFilter = L"System/EventID=";
|
|
135
|
+
for (size_t i = 0; i < eventIds.size(); i++) {
|
|
136
|
+
if (i > 0) {
|
|
137
|
+
eventIdFilter += L" or System/EventID=";
|
|
138
|
+
}
|
|
139
|
+
eventIdFilter += std::to_wstring(eventIds[i]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Construir filtro de watermark si es necesario
|
|
144
|
+
std::wstring watermarkFilter;
|
|
145
|
+
if (mode == FROM_WATERMARK && watermark > 0) {
|
|
146
|
+
watermarkFilter = L"System/EventRecordID > " + std::to_wstring(watermark);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Combinar filtros
|
|
150
|
+
if (!eventIdFilter.empty() || !watermarkFilter.empty()) {
|
|
151
|
+
query = L"*[";
|
|
152
|
+
|
|
153
|
+
if (!eventIdFilter.empty() && !watermarkFilter.empty()) {
|
|
154
|
+
query += L"(" + eventIdFilter + L") and (" + watermarkFilter + L")";
|
|
155
|
+
} else if (!eventIdFilter.empty()) {
|
|
156
|
+
query += eventIdFilter;
|
|
157
|
+
} else {
|
|
158
|
+
query += watermarkFilter;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
query += L"]";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
EVT_HANDLE hQuery = EvtQuery(
|
|
165
|
+
NULL,
|
|
166
|
+
Utf8ToWide(channel).c_str(),
|
|
167
|
+
query.empty() ? NULL : query.c_str(),
|
|
168
|
+
flags
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
if (!hQuery) {
|
|
172
|
+
DWORD errorCode = GetLastError();
|
|
173
|
+
std::string errorMsg = "EvtQuery failed with error code: " + std::to_string(errorCode);
|
|
174
|
+
napi_throw_error(env, nullptr, errorMsg.c_str());
|
|
175
|
+
return nullptr;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
std::vector<EVT_HANDLE> events(maxEvents);
|
|
179
|
+
DWORD returned = 0;
|
|
180
|
+
|
|
181
|
+
BOOL ok = EvtNext(
|
|
182
|
+
hQuery,
|
|
183
|
+
maxEvents,
|
|
184
|
+
events.data(),
|
|
185
|
+
INFINITE,
|
|
186
|
+
0,
|
|
187
|
+
&returned
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// Crear array de resultados
|
|
191
|
+
napi_value records;
|
|
192
|
+
status = napi_create_array(env, &records);
|
|
193
|
+
assert(status == napi_ok);
|
|
194
|
+
|
|
195
|
+
uint64_t lastRecordId = watermark;
|
|
196
|
+
DWORD index = 0;
|
|
197
|
+
|
|
198
|
+
if (ok || GetLastError() == ERROR_NO_MORE_ITEMS) {
|
|
199
|
+
for (DWORD i = 0; i < returned; i++) {
|
|
200
|
+
DWORD bufferUsed = 0;
|
|
201
|
+
DWORD propCount = 0;
|
|
202
|
+
|
|
203
|
+
// Primera llamada para obtener el tamaño del buffer
|
|
204
|
+
EvtRender(NULL, events[i], EvtRenderEventXml, 0, NULL, &bufferUsed, &propCount);
|
|
205
|
+
|
|
206
|
+
if (bufferUsed == 0) {
|
|
207
|
+
EvtClose(events[i]);
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
std::vector<wchar_t> buffer(bufferUsed / sizeof(wchar_t));
|
|
212
|
+
|
|
213
|
+
// Segunda llamada para obtener los datos
|
|
214
|
+
if (EvtRender(NULL, events[i], EvtRenderEventXml, bufferUsed, buffer.data(), &bufferUsed, &propCount)) {
|
|
215
|
+
std::wstring xml(buffer.data());
|
|
216
|
+
std::string xmlUtf8 = WideToUtf8(xml);
|
|
217
|
+
|
|
218
|
+
// Extraer EventRecordID del XML
|
|
219
|
+
size_t pos = xml.find(L"<EventRecordID>");
|
|
220
|
+
if (pos != std::wstring::npos) {
|
|
221
|
+
size_t end = xml.find(L"</EventRecordID>", pos);
|
|
222
|
+
if (end != std::wstring::npos) {
|
|
223
|
+
std::wstring recordIdStr = xml.substr(pos + 15, end - (pos + 15));
|
|
224
|
+
try {
|
|
225
|
+
lastRecordId = std::stoull(recordIdStr);
|
|
226
|
+
} catch (...) {
|
|
227
|
+
// Mantener valor anterior si hay error
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Crear objeto record
|
|
233
|
+
napi_value rec;
|
|
234
|
+
status = napi_create_object(env, &rec);
|
|
235
|
+
assert(status == napi_ok);
|
|
236
|
+
|
|
237
|
+
// Agregar xml
|
|
238
|
+
napi_value xml_val;
|
|
239
|
+
status = napi_create_string_utf8(env, xmlUtf8.c_str(), xmlUtf8.length(), &xml_val);
|
|
240
|
+
assert(status == napi_ok);
|
|
241
|
+
status = napi_set_named_property(env, rec, "xml", xml_val);
|
|
242
|
+
assert(status == napi_ok);
|
|
243
|
+
|
|
244
|
+
// Agregar recordId
|
|
245
|
+
napi_value recordId_val;
|
|
246
|
+
status = napi_create_double(env, (double)lastRecordId, &recordId_val);
|
|
247
|
+
assert(status == napi_ok);
|
|
248
|
+
status = napi_set_named_property(env, rec, "recordId", recordId_val);
|
|
249
|
+
assert(status == napi_ok);
|
|
250
|
+
|
|
251
|
+
// Agregar al array
|
|
252
|
+
status = napi_set_element(env, records, index++, rec);
|
|
253
|
+
assert(status == napi_ok);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
EvtClose(events[i]);
|
|
257
|
+
}
|
|
258
|
+
} else {
|
|
259
|
+
EvtClose(hQuery);
|
|
260
|
+
DWORD errorCode = GetLastError();
|
|
261
|
+
std::string errorMsg = "EvtNext failed with error code: " + std::to_string(errorCode);
|
|
262
|
+
napi_throw_error(env, nullptr, errorMsg.c_str());
|
|
263
|
+
return nullptr;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
EvtClose(hQuery);
|
|
267
|
+
|
|
268
|
+
// Crear objeto resultado
|
|
269
|
+
napi_value result;
|
|
270
|
+
status = napi_create_object(env, &result);
|
|
271
|
+
assert(status == napi_ok);
|
|
272
|
+
|
|
273
|
+
status = napi_set_named_property(env, result, "records", records);
|
|
274
|
+
assert(status == napi_ok);
|
|
275
|
+
|
|
276
|
+
napi_value lastRecordId_val;
|
|
277
|
+
status = napi_create_double(env, (double)lastRecordId, &lastRecordId_val);
|
|
278
|
+
assert(status == napi_ok);
|
|
279
|
+
status = napi_set_named_property(env, result, "lastRecordId", lastRecordId_val);
|
|
280
|
+
assert(status == napi_ok);
|
|
281
|
+
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
napi_value Init(napi_env env, napi_value exports) {
|
|
286
|
+
napi_status status;
|
|
287
|
+
napi_value fn;
|
|
288
|
+
|
|
289
|
+
status = napi_create_function(env, nullptr, 0, ReadEventLog, nullptr, &fn);
|
|
290
|
+
assert(status == napi_ok);
|
|
291
|
+
|
|
292
|
+
status = napi_set_named_property(env, exports, "read", fn);
|
|
293
|
+
assert(status == napi_ok);
|
|
294
|
+
|
|
295
|
+
return exports;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nwinread",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "node-gyp configure && node-gyp build",
|
|
7
|
+
"rebuild": "node-gyp rebuild",
|
|
8
|
+
"clean": "node-gyp clean",
|
|
9
|
+
"test": "node test.js"
|
|
10
|
+
},
|
|
11
|
+
"author": "solzimer",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"description": "Native Windows Event Log Reader for Node.js",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/solzimer/nwinread.git"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"node-gyp": "^10.0.0"
|
|
20
|
+
},
|
|
21
|
+
"gypfile": true
|
|
22
|
+
}
|
package/test.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const nwinread = require('./index.js');
|
|
2
|
+
|
|
3
|
+
console.log('Testing nwinread module...');
|
|
4
|
+
|
|
5
|
+
const watermark = parseInt(process.argv[2]) || 0;
|
|
6
|
+
const testEventIds = process.argv[3] ? process.argv[3].split(',').map(id => parseInt(id)) : null;
|
|
7
|
+
|
|
8
|
+
console.log(`Using watermark: ${watermark}`);
|
|
9
|
+
console.log(`Event ID filter: ${testEventIds ? testEventIds.join(', ') : 'None (all events)'}`);
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
// Prueba básica - leer desde el log de sistema con filtro opcional de IDs
|
|
13
|
+
const mode = watermark > 0 ? nwinread.START_MODE.WATERMARK : nwinread.START_MODE.BEGINNING;
|
|
14
|
+
const result = nwinread.readEvents('System', mode, watermark, 10, testEventIds);
|
|
15
|
+
|
|
16
|
+
console.log(`Found ${result.records.length} events`);
|
|
17
|
+
console.log(`Last Record ID: ${result.lastRecordId}`);
|
|
18
|
+
|
|
19
|
+
result.records.forEach((record, index) => {
|
|
20
|
+
console.log(`\nEvent ${index + 1}:`);
|
|
21
|
+
console.log(`Record ID: ${record.recordId}`);
|
|
22
|
+
console.log(`XML: ${record.xml.substring(0, 200)}...`); // Mostrar solo los primeros 200 caracteres
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.log('\nTest completed successfully!');
|
|
26
|
+
console.log('\nUsage examples:');
|
|
27
|
+
console.log(' node test.js - Read all events from beginning');
|
|
28
|
+
console.log(' node test.js 0 1000,1001 - Read events with IDs 1000 and 1001');
|
|
29
|
+
console.log(' node test.js 123 - Read from watermark 123, all events');
|
|
30
|
+
console.log(' node test.js 123 7045,7034,7036 - Read from watermark 123, filter by service event IDs');
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Test failed:', error.message);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|