Improve installer (Windows.plugin) (#21911)
thiagoftsm committed
Mar 11, 2026 at 23:06 UTC
6d6e52238d3ce5b18ba7b6da874e3c60fea806c5
9 files changed
+259
-13
.github/workflows/build.yml
+1
-1
@@ -389,7 +389,7 @@ jobs:
389
signing-account-name: Netdata
390
certificate-profile-name: Netdata
391
files-folder: ${{ github.workspace }}\build
392
- files-folder-filter: exe,dll,sys
392
+ files-folder-filter: exe,dll,sys,inf
393
files-folder-recurse: true
394
file-digest: SHA256
395
timestamp-rfc3161: "http://timestamp.acs.microsoft.com"
CMakeLists.txt
+10
-4
@@ -2021,8 +2021,8 @@ set(WINDOWS_PLUGIN_FILES
2021
)
2022
2023
set(WINDOWS_PLUGIN_DRIVER
2024
- src/collectors/windows.plugin/netdata_win_driver.c
2025
- src/collectors/windows.plugin/netdata_win_driver.h
2024
+ src/collectors/windows.plugin/driver/netdata_driver.c
2025
+ src/collectors/windows.plugin/driver/netdata_driver.h
2026
)
2027
2028
set(PROC_PLUGIN_FILES
@@ -3069,6 +3069,7 @@ if(OS_WINDOWS)
3069
configure_file(packaging/windows/eula.rtf eula.rtf COPYONLY)
3070
configure_file(packaging/windows/Top.bmp Top.bmp COPYONLY)
3071
configure_file(packaging/windows/BackGround.bmp BackGround.bmp COPYONLY)
3072
+ configure_file(src/collectors/windows.plugin/driver/netdata_driver.inf netdata_driver.inf COPYONLY)
3073
endif()
3074
3075
add_executable(netdata
@@ -3089,12 +3090,13 @@ if(OS_WINDOWS)
3090
target_compile_options(NetdataClaim PUBLIC -mwindows)
3091
3092
set(NETDATA_DRIVER_FILE "${CMAKE_BINARY_DIR}/netdata_driver.sys")
3093
+ set(NETDATA_DRIVER_FILE_INF "${CMAKE_BINARY_DIR}/netdata_driver.inf")
3094
3095
add_library(netdata_driver SHARED ${WINDOWS_PLUGIN_DRIVER})
3096
set_target_properties(netdata_driver PROPERTIES LIBRARY_OUTPUT_NAME "netdata_driver")
3097
set_target_properties(netdata_driver PROPERTIES PREFIX "")
3098
set_target_properties(netdata_driver PROPERTIES SUFFIX ".sys")
3097
- target_include_directories(netdata_driver PRIVATE BEFORE "/mingw64/include/ddk" "${CMAKE_SOURCE_DIR}/src/collectors/windows.plugin")
3099
+ target_include_directories(netdata_driver PRIVATE BEFORE "/mingw64/include/ddk" "${CMAKE_SOURCE_DIR}/src/collectors/windows.plugin" "${CMAKE_SOURCE_DIR}/src/collectors/windows.plugin/driver")
3100
target_compile_options(netdata_driver PRIVATE
3101
-Wall
3102
-Wextra
@@ -3114,7 +3116,11 @@ if(OS_WINDOWS)
3116
target_link_libraries(netdata_driver kernel32 ntoskrnl)
3117
3118
install(FILES "${NETDATA_DRIVER_FILE}"
3117
- COMPONENT netdata_win_driver
3119
+ COMPONENT netdata_driver
3120
+ DESTINATION "${BINDIR}")
3121
+
3122
+ install(FILES "${NETDATA_DRIVER_FILE_INF}"
3123
+ COMPONENT netdata_driver_inf
3124
DESTINATION "${BINDIR}")
3125
endif()
3126
packaging/windows/generate-driver-catalog.ps1
new
+95
@@ -0,0 +1,95 @@
1
+# Generate the Netdata driver catalog file required by WiX packaging.
2
+#
3
+# Requires INF and SYS files already staged in the target directory.
4
+
5
+#Requires -Version 4.0
6
+
7
+param(
8
+ [Parameter(Mandatory = $true)]
9
+ [string]$DriverDirectory,
10
+
11
+ [Parameter()]
12
+ [string]$OsTargets = "10_GE_X64,10_25H2_X64,Server2025_X64,10_NI_X64,10_CO_X64,ServerFE_X64,10_VB_X64,10_19H1_X64,10_RS5_X64,ServerRS5_X64,10_RS4_X64,10_RS3_X64,10_RS2_X64,10_AU_X64,10_X64,Server10_X64"
13
+)
14
+
15
+$ErrorActionPreference = "Stop"
16
+
17
+function Find-Inf2Cat {
18
+ $command = Get-Command Inf2Cat.exe -ErrorAction SilentlyContinue
19
+ if ($null -ne $command) {
20
+ return $command.Source
21
+ }
22
+
23
+ $kitRoots = @(
24
+ (Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\bin"),
25
+ (Join-Path $env:ProgramFiles "Windows Kits\10\bin")
26
+ )
27
+
28
+ $candidates = @()
29
+ foreach ($root in $kitRoots) {
30
+ if (Test-Path $root) {
31
+ # Prefer the typical WDK/SDK layout: Windows Kits\10\bin\<version>\x64\Inf2Cat.exe
32
+ $patternX64 = Join-Path $root '*\x64\Inf2Cat.exe'
33
+ $found = Get-ChildItem -Path $patternX64 -File -ErrorAction SilentlyContinue
34
+ if (-not $found) {
35
+ # Fallback: any versioned subfolder directly under bin containing Inf2Cat.exe
36
+ $patternAnyArch = Join-Path $root '*\Inf2Cat.exe'
37
+ $found = Get-ChildItem -Path $patternAnyArch -File -ErrorAction SilentlyContinue
38
+ if ($found) {
39
+ $candidates += $found
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ if ($candidates.Count -eq 0) {
46
+ throw "Inf2Cat.exe not found. Install Windows Driver Kit (WDK) or Windows SDK tools with Inf2Cat."
47
+ }
48
+
49
+ $x64Candidates = $candidates | Where-Object { $_.FullName -match '\\x64\\Inf2Cat\.exe$' }
50
+ if ($x64Candidates.Count -gt 0) {
51
+ $candidates = $x64Candidates
52
+ }
53
+
54
+ $latest = $candidates |
55
+ Sort-Object -Property {
56
+ $match = [regex]::Match($_.FullName, '\\10\\bin\\(?<ver>\d+\.\d+\.\d+\.\d+)\\')
57
+ if ($match.Success) {
58
+ [version]$match.Groups['ver'].Value
59
+ } else {
60
+ [version]"0.0.0.0"
61
+ }
62
+ } -Descending |
63
+ Select-Object -First 1
64
+
65
+ return $latest.FullName
66
+}
67
+
68
+$driverDir = (Resolve-Path -LiteralPath $DriverDirectory).Path
69
+$driverInf = Join-Path $driverDir "netdata_driver.inf"
70
+$driverSys = Join-Path $driverDir "netdata_driver.sys"
71
+$driverCat = Join-Path $driverDir "netdata_driver.cat"
72
+
73
+if (-not (Test-Path $driverInf)) {
74
+ throw "Missing driver INF: $driverInf"
75
+}
76
+
77
+if (-not (Test-Path $driverSys)) {
78
+ throw "Missing driver SYS: $driverSys"
79
+}
80
+
81
+$inf2cat = Find-Inf2Cat
82
+Write-Host "Using Inf2Cat: $inf2cat"
83
+Write-Host "Generating driver catalog in: $driverDir"
84
+
85
+& $inf2cat "/driver:$driverDir" "/os:$OsTargets"
86
+
87
+if ($LastExitCode -ne 0) {
88
+ throw "Inf2Cat failed with exit code $LastExitCode"
89
+}
90
+
91
+if (-not (Test-Path $driverCat)) {
92
+ throw "Catalog generation failed, missing output: $driverCat"
93
+}
94
+
95
+Write-Host "Generated driver catalog: $driverCat"
packaging/windows/netdata.wxs.in
+15
-1
@@ -171,7 +171,18 @@
171
</Package>
172
173
<Fragment>
174
+ <UI>
175
+ <ProgressText Action="NDKillProcess" Message="Stopping Netdata service before update..." />
176
+ <ProgressText Action="NDStopDriverSrv" Message="Stopping Netdata driver service..." />
177
+ <ProgressText Action="NDRemoveDriverSrv" Message="Removing Netdata driver service..." />
178
+ </UI>
179
+
180
<StandardDirectory Id="System64Folder">
181
+ <Directory Id="DRIVERDIR" Name="drivers" />
182
+ </StandardDirectory>
183
+
184
+ <StandardDirectory Id="WindowsFolder">
185
+ <Directory Id="INFDIR" Name="INF" />
186
</StandardDirectory>
187
188
<!-- All the files except for the ones we need to handle specially -->
@@ -181,6 +192,7 @@
192
<Exclude Files="C:\msys64\opt\netdata\usr\bin\wevt_netdata_manifest.xml" />
193
<Exclude Files="C:\msys64\opt\netdata\usr\bin\wevt_netdata.dll" />
194
<Exclude Files="C:\msys64\opt\netdata\usr\bin\netdata_driver.sys" />
195
+ <Exclude Files="C:\msys64\opt\netdata\usr\bin\netdata_driver.inf" />
196
</Files>
197
</ComponentGroup>
198
@@ -254,7 +266,9 @@
266
267
<!-- Install netdata driver file -->
268
<FeatureGroup Id="NetdataDriver">
257
- <File Id="NetdataDrv" Name="netdata_driver.sys" Directory="System64Folder" Source="C:\msys64\opt\netdata\usr\bin\netdata_driver.sys" Condition="NDDRVINST=1">
269
+ <File Id="NetdataDrv" Name="netdata_driver.sys" Directory="DRIVERDIR" Source="C:\msys64\opt\netdata\usr\bin\netdata_driver.sys" Condition="NDDRVINST=1">
270
+ </File>
271
+ <File Id="NetdataDrvInf" Name="netdata_driver.inf" Directory="INFDIR" Source="C:\msys64\opt\netdata\usr\bin\netdata_driver.inf" Condition="NDDRVINST=1">
272
</File>
273
</FeatureGroup>
274
packaging/windows/package-windows.sh
+7
@@ -50,3 +50,10 @@ if [ ! -f "/opt/netdata/etc/profile" ]; then
50
fi
51
${GITHUB_ACTIONS+echo "::endgroup::"}
52
53
+# TODO: We will have a PR to adjust CAB file creation and sign. This is only adding necessary structure
54
+#${GITHUB_ACTIONS+echo "::group::CAB file"}
55
+#mkdir "${build}/driver"
56
+#cp "${build}/usr/bin/netdata_driver.*" "${build}/driver"
57
+#powershell.exe -ExecutionPolicy Bypass -File "${repo_root}/packaging/windows/generate-driver-catalog.ps1"
58
+#${GITHUB_ACTIONS+echo "::endgroup::"}
59
+
src/collectors/windows.plugin/GetHardwareInfo.c
+86
-7
@@ -3,10 +3,10 @@
3
#include "windows_plugin.h"
4
#include "windows-internals.h"
5
6
-#include "netdata_win_driver.h"
6
+#include "driver/netdata_driver.h"
7
8
static const char *srv_name = "NetdataDriver";
9
-static const char *drv_path = "%SystemRoot%\\system32\\netdata_driver.sys";
9
+static const char *drv_path = "%SystemRoot%\\system32\\drivers\\netdata_driver.sys";
10
11
struct cpu_data {
12
RRDDIM *rd_cpu_temp;
@@ -99,6 +99,32 @@ int netdata_install_driver()
99
100
if (unlikely(!service)) {
101
if (GetLastError() == ERROR_SERVICE_EXISTS) {
102
+ SC_HANDLE existing = OpenServiceA(scm, srv_name, SERVICE_CHANGE_CONFIG);
103
+ if (!existing) {
104
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot open existing service. Error= %lu \n", GetLastError());
105
+ CloseServiceHandle(scm);
106
+ return -1;
107
+ }
108
+
109
+ if (!ChangeServiceConfigA(
110
+ existing,
111
+ SERVICE_KERNEL_DRIVER,
112
+ SERVICE_DEMAND_START,
113
+ SERVICE_ERROR_NORMAL,
114
+ expanded_path,
115
+ NULL,
116
+ NULL,
117
+ NULL,
118
+ NULL,
119
+ NULL,
120
+ NULL)) {
121
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot reconfigure existing service. Error= %lu \n", GetLastError());
122
+ CloseServiceHandle(existing);
123
+ CloseServiceHandle(scm);
124
+ return -1;
125
+ }
126
+
127
+ CloseServiceHandle(existing);
128
CloseServiceHandle(scm);
129
return 0;
130
}
@@ -114,6 +140,16 @@ int netdata_install_driver()
140
return 0;
141
}
142
143
+static inline void log_invalid_image_hash_error(void)
144
+{
145
+ nd_log(
146
+ NDLS_COLLECTORS,
147
+ NDLP_ERR,
148
+ "Driver failed to start: ERROR_INVALID_IMAGE_HASH (577). "
149
+ "This usually indicates a driver signature verification failure. "
150
+ "The driver binary may be corrupted, unsigned, or signed with an untrusted certificate.\n");
151
+}
152
+
153
int netdata_start_driver()
154
{
155
SC_HANDLE scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
@@ -124,22 +160,65 @@ int netdata_start_driver()
160
161
SC_HANDLE service = OpenServiceA(scm, srv_name, SERVICE_START | SERVICE_QUERY_STATUS);
162
if (unlikely(!service)) {
163
+ DWORD open_err = GetLastError();
164
CloseServiceHandle(scm);
128
- nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot open Service. Error= %lu \n", GetLastError());
129
- return -1;
165
+ scm = NULL;
166
+
167
+ // Service missing: attempt self-healing install then retry
168
+ if (open_err == ERROR_SERVICE_DOES_NOT_EXIST) {
169
+ nd_log(NDLS_COLLECTORS, NDLP_INFO, "Service not found, attempting to install driver and retry start\n");
170
+
171
+ if (netdata_install_driver() != 0) {
172
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Failed to install driver during self-healing\n");
173
+ return -1;
174
+ }
175
+
176
+ scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
177
+ if (unlikely(!scm)) {
178
+ nd_log(
179
+ NDLS_COLLECTORS,
180
+ NDLP_ERR,
181
+ "Cannot open Service Manager after install. Error= %lu \n",
182
+ GetLastError());
183
+ return -1;
184
+ }
185
+
186
+ service = OpenServiceA(scm, srv_name, SERVICE_START | SERVICE_QUERY_STATUS);
187
+ if (unlikely(!service)) {
188
+ nd_log(
189
+ NDLS_COLLECTORS,
190
+ NDLP_ERR,
191
+ "Cannot open Service after install. Error= %lu \n",
192
+ GetLastError());
193
+ CloseServiceHandle(scm);
194
+ return -1;
195
+ }
196
+ // fall through to StartServiceA with the newly opened handle
197
+ } else {
198
+ nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot open Service. Error= %lu \n", open_err);
199
+ return -1;
200
+ }
201
}
202
203
int ret = 0;
204
if (!StartServiceA(service, 0, NULL)) {
205
DWORD err = GetLastError();
135
- if (err != ERROR_SERVICE_ALREADY_RUNNING) {
206
+
207
+ if (err == ERROR_SERVICE_ALREADY_RUNNING) {
208
+ ret = 0;
209
+ } else if (err == ERROR_INVALID_IMAGE_HASH) {
210
+ log_invalid_image_hash_error();
211
+ ret = -1;
212
+ } else {
213
nd_log(NDLS_COLLECTORS, NDLP_ERR, "Cannot start Service. Error= %lu \n", err);
214
ret = -1;
215
}
216
}
217
141
- CloseServiceHandle(service);
142
- CloseServiceHandle(scm);
218
+ if (service)
219
+ CloseServiceHandle(service);
220
+ if (scm)
221
+ CloseServiceHandle(scm);
222
return ret;
223
}
224
src/collectors/windows.plugin/driver/netdata_driver.c
renamed
src/collectors/windows.plugin/driver/netdata_driver.h
renamed
src/collectors/windows.plugin/driver/netdata_driver.inf
new
+45
@@ -0,0 +1,45 @@
1
+;
2
+; Netdata Driver INF File
3
+;
4
+
5
+[Version]
6
+Signature="$Windows NT$"
7
+Class=System
8
+ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
9
+Provider=%Provider%
10
+DriverVer=03/07/2026,1.0.0.0
11
+CatalogFile=netdata_driver.cat
12
+
13
+[DestinationDirs]
14
+DefaultDestDir = 12
15
+
16
+[DefaultInstall.NTamd64]
17
+CopyFiles = DriverCopyFiles
18
+
19
+[DefaultInstall.NTamd64.Services]
20
+AddService = NetdataDriver,,DriverServiceInstall
21
+
22
+[DefaultUninstall.NTamd64]
23
+LegacyUninstall=1
24
+DelFiles = DriverCopyFiles
25
+
26
+[DriverCopyFiles]
27
+netdata_driver.sys
28
+
29
+[SourceDisksFiles]
30
+netdata_driver.sys = 1
31
+
32
+[SourceDisksNames]
33
+1 = %DiskName%,,,""
34
+
35
+[DriverServiceInstall]
36
+DisplayName = %DeviceDesc%
37
+ServiceType = 1
38
+StartType = 3
39
+ErrorControl = 1
40
+ServiceBinary = %12%\netdata_driver.sys
41
+
42
+[Strings]
43
+Provider = "Netdata"
44
+DeviceDesc = "Netdata Driver"
45
+DiskName = "Netdata Driver Disk"