diff --git a/smartmontools/ChangeLog b/smartmontools/ChangeLog
index 214614814b7d268e9163ed547839fe81ec6c8365..ab753db4c4a61bbdc8b09245e8f506a94a0d3fc1 100644
--- a/smartmontools/ChangeLog
+++ b/smartmontools/ChangeLog
@@ -1,5 +1,17 @@
 $Id$
 
+2018-10-17  Christian Franke  <franke@computer.org>
+
+	os_win32/popen_win32.cpp, os_win32/popen.h: New popen()/pclose()
+	for Windows.  Unlike MSVCRT _popen(), it does not open a new console.
+	os_win32.cpp: Remove run_cmd(), use popen() instead.
+	os_win32/daemon_win32.cpp, os_win32/daemon_win32.h: Remove
+	daemon_spawn().
+	smartd.cpp: Remove _WIN32 specific usage of daemon_spawn(),
+	use generic code with popen() also on Windows.
+	Makefile.am, os_win32/vc14/smart*.vcxproj*: Add new files.
+
+
 2018-10-17  Rick Chen  <juihsiang.chen@gmail.com>
 
 	scsiprint.cpp: Add SCSI information to JSON output as below:
diff --git a/smartmontools/Makefile.am b/smartmontools/Makefile.am
index f2faf5c0aa5ffc5db9225921f15e53945e6e33f6..f63a90212ea372ed5fc57e3f56d84c8866f0dc6f 100644
--- a/smartmontools/Makefile.am
+++ b/smartmontools/Makefile.am
@@ -121,6 +121,10 @@ EXTRA_smartctl_SOURCES = \
 
 if OS_WIN32_MINGW
 
+smartctl_SOURCES += \
+        os_win32/popen_win32.cpp \
+        os_win32/popen.h
+
 smartctl_LDADD        += smartctl_res.o
 smartctl_DEPENDENCIES += smartctl_res.o
 
@@ -192,6 +196,8 @@ if OS_WIN32_MINGW
 smartd_SOURCES += \
         os_win32/daemon_win32.cpp \
         os_win32/daemon_win32.h \
+        os_win32/popen_win32.cpp \
+        os_win32/popen.h \
         os_win32/syslog_win32.cpp \
         os_win32/syslog.h
 
diff --git a/smartmontools/os_win32.cpp b/smartmontools/os_win32.cpp
index 8f22359c096cfda3b4ce15db3413bdcc1893510b..00d5ce3ad4199af7219e8fdb9e4c02432b97637b 100644
--- a/smartmontools/os_win32.cpp
+++ b/smartmontools/os_win32.cpp
@@ -28,6 +28,7 @@
 #include "dev_areca.h"
 
 #include "os_win32/wmiquery.h"
+#include "os_win32/popen.h"
 
 // TODO: Move from smartctl.h to other include file
 extern unsigned char failuretest_permissive;
@@ -2555,63 +2556,6 @@ static int get_clipboard(char * data, int datasize)
 }
 
 
-// Run a command, write stdout to dataout
-// TODO: Combine with daemon_win32.cpp:daemon_spawn()
-
-static int run_cmd(const char * cmd, char * dataout, int outsize)
-{
-  // Create stdout pipe
-  SECURITY_ATTRIBUTES sa = {sizeof(sa), 0, TRUE};
-  HANDLE pipe_out_w, h;
-  if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize))
-    return -1;
-  HANDLE self = GetCurrentProcess();
-  HANDLE pipe_out_r;
-  if (!DuplicateHandle(self, h, self, &pipe_out_r,
-    GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
-    CloseHandle(pipe_out_w);
-    return -1;
-  }
-  HANDLE pipe_err_w;
-  if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
-    0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
-    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-    return -1;
-  }
-
-  // Create process
-  STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-  si.hStdInput  = INVALID_HANDLE_VALUE;
-  si.hStdOutput = pipe_out_w; si.hStdError  = pipe_err_w;
-  si.dwFlags = STARTF_USESTDHANDLES;
-  PROCESS_INFORMATION pi;
-  if (!CreateProcess(
-    NULL, const_cast<char *>(cmd),
-    NULL, NULL, TRUE/*inherit*/,
-    CREATE_NO_WINDOW/*do not create a new console window*/,
-    NULL, NULL, &si, &pi)) {
-    CloseHandle(pipe_err_w); CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-    return -1;
-  }
-  CloseHandle(pi.hThread);
-  CloseHandle(pipe_err_w); CloseHandle(pipe_out_w);
-
-  // Copy stdout to output buffer
-  int i = 0;
-  while (i < outsize) {
-    DWORD num_read;
-    if (!ReadFile(pipe_out_r, dataout+i, outsize-i, &num_read, NULL) || num_read == 0)
-      break;
-    i += num_read;
-  }
-  CloseHandle(pipe_out_r);
-  // Wait for process
-  WaitForSingleObject(pi.hProcess, INFINITE);
-  CloseHandle(pi.hProcess);
-  return i;
-}
-
-
 static const char * findstr(const char * str, const char * sub)
 {
   const char * s = strstr(str, sub);
@@ -2638,7 +2582,11 @@ bool win_tw_cli_device::open()
     snprintf(cmd, sizeof(cmd), "tw_cli /%s show all", name+n1);
     if (ata_debugmode > 1)
       pout("%s: Run: \"%s\"\n", name, cmd);
-    size = run_cmd(cmd, buffer, sizeof(buffer));
+    FILE * f = popen(cmd, "rb");
+    if (f) {
+      size = fread(buffer, 1, sizeof(buffer), f);
+      pclose(f);
+    }
   }
   else {
     return set_err(EINVAL);
diff --git a/smartmontools/os_win32/daemon_win32.cpp b/smartmontools/os_win32/daemon_win32.cpp
index 94cc5b05c5d092d1325116ca30cf22d6be4ae3fe..7cab81fbd62a455fca83829ec1b2a0f12a61b463 100644
--- a/smartmontools/os_win32/daemon_win32.cpp
+++ b/smartmontools/os_win32/daemon_win32.cpp
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://www.smartmontools.org
  *
- * Copyright (C) 2004-14 Christian Franke
+ * Copyright (C) 2004-18 Christian Franke
  *
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
@@ -457,120 +457,6 @@ int daemon_detach(const char * ident)
 }
 
 
-/////////////////////////////////////////////////////////////////////////////
-
-// Spawn a command and redirect <inpbuf >outbuf
-// return command's exitcode or -1 on error
-
-int daemon_spawn(const char * cmd,
-                 const char * inpbuf, int inpsize,
-                 char *       outbuf, int outsize )
-{
-  HANDLE self = GetCurrentProcess();
-
-  // Create stdin pipe with inheritable read side
-  SECURITY_ATTRIBUTES sa;
-  memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
-  sa.bInheritHandle = TRUE;
-  HANDLE pipe_inp_r, pipe_inp_w, h;
-  if (!CreatePipe(&pipe_inp_r, &h, &sa/*inherit*/, inpsize*2+13))
-    return -1;
-  if (!DuplicateHandle(self, h, self, &pipe_inp_w,
-    0, FALSE/*!inherit*/, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
-    CloseHandle(pipe_inp_r);
-    return -1;
-  }
-
-  // Create stdout pipe with inheritable write side
-  memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
-  sa.bInheritHandle = TRUE;
-  HANDLE pipe_out_w;
-  if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) {
-    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-    return -1;
-  }
-
-  HANDLE pipe_out_r;
-  if (!DuplicateHandle(self, h, self, &pipe_out_r,
-    GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
-    CloseHandle(pipe_out_w); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-    return -1;
-  }
-
-  // Create stderr handle as dup of stdout write side
-  HANDLE pipe_err_w;
-  if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
-    0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
-    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-    return -1;
-  }
-
-  // Create process with pipes as stdio
-  STARTUPINFO si;
-  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-  si.hStdInput  = pipe_inp_r;
-  si.hStdOutput = pipe_out_w;
-  si.hStdError  = pipe_err_w;
-  si.dwFlags = STARTF_USESTDHANDLES;
-  PROCESS_INFORMATION pi;
-  if (!CreateProcessA(
-    NULL, (char*)cmd,
-    NULL, NULL, TRUE/*inherit*/,
-    CREATE_NO_WINDOW, // DETACHED_PROCESS does not work
-    NULL, NULL, &si, &pi)) {
-    CloseHandle(pipe_err_w);
-    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-    return -1;
-  }
-  CloseHandle(pi.hThread);
-  // Close inherited handles
-  CloseHandle(pipe_inp_r);
-  CloseHandle(pipe_out_w);
-  CloseHandle(pipe_err_w);
-
-  // Copy inpbuf to stdin
-  // convert \n => \r\n
-  DWORD num_io;
-  int i;
-  for (i = 0; i < inpsize; ) {
-    int len = 0;
-    while (i+len < inpsize && inpbuf[i+len] != '\n')
-      len++;
-    if (len > 0)
-      WriteFile(pipe_inp_w, inpbuf+i, len, &num_io, NULL);
-    i += len;
-    if (i < inpsize) {
-      WriteFile(pipe_inp_w, "\r\n", 2, &num_io, NULL);
-      i++;
-    }
-  }
-  CloseHandle(pipe_inp_w);
-
-  // Copy stdout to output buffer until full, rest to /dev/null
-  // convert \r\n => \n
-  for (i = 0; ; ) {
-    char buf[256];
-    if (!ReadFile(pipe_out_r, buf, sizeof(buf), &num_io, NULL) || num_io == 0)
-      break;
-    for (int j = 0; i < outsize-1 && j < (int)num_io; j++) {
-      if (buf[j] != '\r')
-        outbuf[i++] = buf[j];
-    }
-  }
-  outbuf[i] = 0;
-  CloseHandle(pipe_out_r);
-
-  // Wait for process exitcode
-  DWORD exitcode = 42;
-  WaitForSingleObject(pi.hProcess, INFINITE);
-  GetExitCodeProcess(pi.hProcess, &exitcode);
-  CloseHandle(pi.hProcess);
-  return exitcode;
-}
-
-
 /////////////////////////////////////////////////////////////////////////////
 // Initd Functions
 
diff --git a/smartmontools/os_win32/daemon_win32.h b/smartmontools/os_win32/daemon_win32.h
index 7cbc42ccc1e5429edb9c8038c05537f02feb6f4e..a41b1fdb8d7fd27016caa21a41d4d3db6ab8ef29 100644
--- a/smartmontools/os_win32/daemon_win32.h
+++ b/smartmontools/os_win32/daemon_win32.h
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://www.smartmontools.org
  *
- * Copyright (C) 2004-12 Christian Franke
+ * Copyright (C) 2004-18 Christian Franke
  *
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
@@ -52,9 +52,4 @@ int daemon_enable_console(const char * title);
 // Detach from console
 int daemon_detach(const char * ident);
 
-// Spawn a process and redirect stdio
-int daemon_spawn(const char * cmd,
-                 const char * inpbuf, int inpsize,
-                 char *       outbuf, int outsize );
-
 #endif // DAEMON_WIN32_H
diff --git a/smartmontools/os_win32/popen.h b/smartmontools/os_win32/popen.h
new file mode 100644
index 0000000000000000000000000000000000000000..a0c0c91b895239d93f421787e1c0f81f45033b33
--- /dev/null
+++ b/smartmontools/os_win32/popen.h
@@ -0,0 +1,55 @@
+/*
+ * os_win32/popen.h
+ *
+ * Home page of code is: https://www.smartmontools.org
+ *
+ * Copyright (C) 2018 Christian Franke
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef POPEN_H
+#define POPEN_H
+
+#define POPEN_H_CVSID "$Id$"
+
+#include <stdio.h>
+
+// MinGW <stdio.h> defines these to _popen/_pclose
+#undef popen
+#undef pclose
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// popen(3) reimplementation for Windows
+//
+// The _popen() from MSVCRT is not useful as it always opens a new
+// console window if parent process has none.
+//
+// Differences to popen(3):
+// - Only modes "r[bt]" are supported
+// - stdin and stderr from parent are not inherited to child process
+//   but redirected to null device
+// - Only one child process can be run at a time
+
+FILE * popen(const char * command, const char * mode);
+
+int pclose(FILE * f);
+
+#ifdef __cplusplus
+}
+#endif
+
+// wait(3) macros from <sys/wait.h>
+#ifndef WIFEXITED
+#define WIFEXITED(status)   (((status) & 0xff) == 0x00)
+#define WIFSIGNALED(status) (((status) & 0xff) != 0x00)
+#define WIFSTOPPED(status)  (0)
+#define WEXITSTATUS(status) ((status) >> 8)
+#define WTERMSIG(status)    ((status) & 0xff)
+#define WSTOPSIG(status)    (0)
+#endif // WIFEXITED
+
+#endif // POPEN_H
diff --git a/smartmontools/os_win32/popen_win32.cpp b/smartmontools/os_win32/popen_win32.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..717fa7d9345da7926214ceeadfe4c3b488c47103
--- /dev/null
+++ b/smartmontools/os_win32/popen_win32.cpp
@@ -0,0 +1,176 @@
+/*
+ * os_win32/popen_win32.cpp
+ *
+ * Home page of code is: https://www.smartmontools.org
+ *
+ * Copyright (C) 2018 Christian Franke
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "popen.h"
+
+const char * popen_win32_cpp_cvsid = "$Id$"
+  POPEN_H_CVSID;
+
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h> // _open_osfhandle()
+#include <signal.h> // SIGSEGV
+#include <stdlib.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+static FILE * s_popen_file;
+static HANDLE s_popen_process;
+
+extern "C"
+FILE * popen(const char * command, const char * mode)
+{
+  // Fail if previous run is still in progress
+  if (s_popen_file) {
+    errno = EEXIST;
+    return (FILE *)0;
+  }
+
+  // mode "w" is not implemented
+  if (!(mode[0] == 'r' && (!mode[1] || !mode[2]))) {
+    errno = EINVAL;
+    return (FILE *)0;
+  }
+
+  // Set flags for text or binary mode
+  // Note: _open_osfhandle() ignores _fmode and defaults to O_BINARY
+  int oflags; const char * fomode;
+  switch (mode[1]) {
+    case 0:
+    case 't':
+      oflags = O_RDONLY|O_TEXT;
+      fomode = "rt";
+      break;
+    case 'b':
+      oflags = O_RDONLY|O_BINARY;
+      fomode = "rb";
+      break;
+    default:
+      errno = EINVAL;
+      return (FILE *)0;
+  }
+
+  // Create stdout pipe with inheritable write end
+  HANDLE pipe_out_r, pipe_out_w;
+  if (!CreatePipe(&pipe_out_r, &pipe_out_w, (SECURITY_ATTRIBUTES *)0, 1024)) {
+    errno = EMFILE;
+    return (FILE *)0;
+  }
+  if (!SetHandleInformation(pipe_out_w, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
+    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
+    errno = EMFILE;
+    return (FILE *)0;
+  }
+
+  // Connect pipe read end to new FD
+  int fd = _open_osfhandle((intptr_t)pipe_out_r, oflags);
+  if (fd < 0) {
+    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
+    return (FILE *)0;
+  }
+
+  // Connect FD to new FILE
+  FILE * f = fdopen(fd, fomode);
+  if (!f) {
+    int err = errno;
+    close(fd); // CloseHandle(pipe_out_r)
+    CloseHandle(pipe_out_w);
+    errno = err;
+    return (FILE *)0;
+  }
+
+  // Build command line "cmd /c COMMAND"
+  int cmdlen = strlen(command);
+  char * shellcmd = (char *)malloc(7 + cmdlen + 1);
+  if (!shellcmd) {
+    fclose(f); // CloseHandle(pipe_out_r)
+    CloseHandle(pipe_out_w);
+    errno = ENOMEM;
+    return (FILE *)0;
+  }
+  memcpy(shellcmd, "cmd /c ", 7);
+  memcpy(shellcmd + 7, command, cmdlen + 1);
+
+  // Redirect stdin stderr to null device
+  // Don't inherit parent's stdin, script may hang if parent has no console.
+  SECURITY_ATTRIBUTES sa_inherit = { sizeof(sa_inherit), (SECURITY_DESCRIPTOR *)0, TRUE };
+  HANDLE null_in  = CreateFile("nul", GENERIC_READ , 0, &sa_inherit, OPEN_EXISTING, 0, (HANDLE)0);
+  HANDLE null_err = CreateFile("nul", GENERIC_WRITE, 0, &sa_inherit, OPEN_EXISTING, 0, (HANDLE)0);
+
+  // Set stdio handles
+  STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+  si.hStdInput  = null_in;
+  si.hStdOutput = pipe_out_w;
+  si.hStdError  = null_err;
+  si.dwFlags = STARTF_USESTDHANDLES;
+
+  // Create process
+  PROCESS_INFORMATION pi;
+  BOOL ok = CreateProcessA(
+    getenv("COMSPEC"), // "C:\WINDOWS\system32\cmd.exe" or nullptr
+    shellcmd, // "cmd /c COMMAND" ("cmd" searched in PATH if COMSPEC not set)
+    (SECURITY_ATTRIBUTES *)0, (SECURITY_ATTRIBUTES *)0,
+    TRUE, // inherit
+    CREATE_NO_WINDOW, // DETACHED_PROCESS would open new console(s)
+    (void *)0, (char *)0, &si, &pi
+  );
+  free(shellcmd);
+
+  // Close inherited handles
+  CloseHandle(null_err);
+  CloseHandle(null_in);
+  CloseHandle(pipe_out_w);
+
+  if (!ok) {
+    fclose(f); // CloseHandle(pipe_out_r)
+    errno = ENOENT;
+    return (FILE *)0;
+  }
+
+  // Store process and FILE for pclose()
+  CloseHandle(pi.hThread);
+  s_popen_process = pi.hProcess;
+  s_popen_file = f;
+
+  return f;
+}
+
+extern "C"
+int pclose(FILE * f)
+{
+  if (f != s_popen_file) {
+    errno = EBADF;
+    return -1;
+  }
+
+  fclose(f);
+  s_popen_file = 0;
+
+  // Wait for process exitcode
+  DWORD exitcode = 42;
+  bool ok = (   WaitForSingleObject(s_popen_process, INFINITE) == WAIT_OBJECT_0
+             && GetExitCodeProcess(s_popen_process, &exitcode));
+
+  CloseHandle(s_popen_process);
+  s_popen_process = 0;
+
+  if (!ok) {
+    errno = ECHILD;
+    return -1;
+  }
+
+  // Modify exitcode for wait(3) macros
+  if (exitcode >> 23)
+    return ((exitcode << 9) >> 1) | SIGSEGV;
+  else
+    return exitcode << 8;
+}
diff --git a/smartmontools/os_win32/vc14/smartctl.vcxproj b/smartmontools/os_win32/vc14/smartctl.vcxproj
index 33a532478bb27bdf34f9841ec6b96e3580477c00..d42cacd015325fdf4620d8c9ee04e23a7379f26c 100644
--- a/smartmontools/os_win32/vc14/smartctl.vcxproj
+++ b/smartmontools/os_win32/vc14/smartctl.vcxproj
@@ -166,6 +166,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
+    <ClCompile Include="..\popen_win32.cpp" />
     <ClCompile Include="..\syslog_win32.cpp">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -290,6 +291,7 @@
     <ClInclude Include="..\..\json.h" />
     <ClInclude Include="..\..\nvmecmds.h" />
     <ClInclude Include="..\..\nvmeprint.h" />
+    <ClInclude Include="..\popen.h" />
     <ClInclude Include="config.h" />
     <ClInclude Include="svnversion.h" />
     <CustomBuildStep Include="..\daemon_win32.h">
diff --git a/smartmontools/os_win32/vc14/smartctl.vcxproj.filters b/smartmontools/os_win32/vc14/smartctl.vcxproj.filters
index 72e6f9fada82d24ccb52069f9d89ee622a4617e9..a2405bf15de3b551bb9299cd20a6574d36c804b9 100644
--- a/smartmontools/os_win32/vc14/smartctl.vcxproj.filters
+++ b/smartmontools/os_win32/vc14/smartctl.vcxproj.filters
@@ -69,6 +69,9 @@
     <ClCompile Include="..\..\nvmeprint.cpp" />
     <ClCompile Include="..\..\dev_intelliprop.cpp" />
     <ClCompile Include="..\..\json.cpp" />
+    <ClCompile Include="..\popen_win32.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\wmiquery.h">
@@ -115,6 +118,9 @@
     <ClInclude Include="..\..\getopt\bits\getopt_ext.h">
       <Filter>getopt</Filter>
     </ClInclude>
+    <ClInclude Include="..\popen.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\installer.nsi">
diff --git a/smartmontools/os_win32/vc14/smartd.vcxproj b/smartmontools/os_win32/vc14/smartd.vcxproj
index ca4cf688ab0198c5e9a93320fb5e86a8d6cc24a3..2b02af72ba3803886297e52ff43b4fd02c29593a 100644
--- a/smartmontools/os_win32/vc14/smartd.vcxproj
+++ b/smartmontools/os_win32/vc14/smartd.vcxproj
@@ -170,6 +170,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClCompile>
     <ClCompile Include="..\daemon_win32.cpp" />
+    <ClCompile Include="..\popen_win32.cpp" />
     <ClCompile Include="..\syslog_win32.cpp" />
     <ClCompile Include="..\wmiquery.cpp" />
     <ClCompile Include="..\..\regex\regcomp.c">
@@ -309,6 +310,7 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
     </ClInclude>
     <ClInclude Include="..\daemon_win32.h" />
+    <ClInclude Include="..\popen.h" />
     <ClInclude Include="..\syslog.h" />
     <ClInclude Include="..\wmiquery.h" />
     <ClInclude Include="..\..\regex\regex.h" />
diff --git a/smartmontools/os_win32/vc14/smartd.vcxproj.filters b/smartmontools/os_win32/vc14/smartd.vcxproj.filters
index 84e604f2ac1d32b69ba690eec1a6fe9eccf8601a..ce761a736c14216b0b36f51241b2cc79cc210652 100644
--- a/smartmontools/os_win32/vc14/smartd.vcxproj.filters
+++ b/smartmontools/os_win32/vc14/smartd.vcxproj.filters
@@ -68,6 +68,9 @@
     <ClCompile Include="..\..\nvmecmds.cpp" />
     <ClCompile Include="..\..\nvmeprint.cpp" />
     <ClCompile Include="..\..\dev_intelliprop.cpp" />
+    <ClCompile Include="..\popen_win32.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\daemon_win32.h">
@@ -116,6 +119,9 @@
     <ClInclude Include="..\..\getopt\bits\getopt_ext.h">
       <Filter>getopt</Filter>
     </ClInclude>
+    <ClInclude Include="..\popen.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\installer.nsi">
diff --git a/smartmontools/smartd.cpp b/smartmontools/smartd.cpp
index 416dc43bc9e9ba70861730d9006c543cb37ad913..26757a8d1cee3c8d3d650c7d350fd72ff616d4f1 100644
--- a/smartmontools/smartd.cpp
+++ b/smartmontools/smartd.cpp
@@ -42,6 +42,7 @@
 #endif
 
 #ifdef _WIN32
+#include "os_win32/popen.h" // popen/pclose()
 #ifdef _MSC_VER
 #pragma warning(disable:4761) // "conversion supplied"
 typedef unsigned short mode_t;
@@ -73,7 +74,7 @@ typedef int pid_t;
 
 #ifdef _WIN32
 // fork()/signal()/initd simulation for native Windows
-#include "daemon_win32.h" // daemon_main/detach/signal()
+#include "os_win32/daemon_win32.h" // daemon_main/detach/signal()
 #define strsignal daemon_strsignal
 #define sleep     daemon_sleep
 // SIGQUIT does not exist, CONTROL-Break signals SIGBREAK.
@@ -1192,7 +1193,6 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
   const char * newadd = (!address.empty()? address.c_str() : "<nomailer>");
   const char * newwarn = (which? "Warning via" : "Test of");
 
-#ifndef _WIN32
   char command[2048];
   snprintf(command, sizeof(command), "%s 2>&1", warning_script.c_str());
   
@@ -1265,29 +1265,6 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
       
     }
   }
-  
-#else // _WIN32
-  {
-    char command[2048];
-    snprintf(command, sizeof(command), "cmd /c \"%s\"", warning_script.c_str());
-
-    char stdoutbuf[800]; // < buffer in syslog_win32::vsyslog()
-    int rc;
-    // run command
-    PrintOut(LOG_INFO,"%s %s to %s ...\n",
-             (which?"Sending warning via":"Executing test of"), executable, newadd);
-    rc = daemon_spawn(command, "", 0, stdoutbuf, sizeof(stdoutbuf));
-    if (rc >= 0 && stdoutbuf[0])
-      PrintOut(LOG_CRIT,"%s %s to %s produced unexpected output (%d bytes) to STDOUT/STDERR:\n%s\n",
-        newwarn, executable, newadd, (int)strlen(stdoutbuf), stdoutbuf);
-    if (rc != 0)
-      PrintOut(LOG_CRIT,"%s %s to %s: failed, exit status %d\n",
-        newwarn, executable, newadd, rc);
-    else
-      PrintOut(LOG_INFO,"%s %s to %s: successful\n", newwarn, executable, newadd);
-  }
-
-#endif // _WIN32
 
   // increment mail sent counter
   mail->logged++;