You can use this quick&dirty piece of software listed below to redirect std i/o of a program to a tcp connection.
Assuming the executable file is named tcpcmd.exe. Following command line tcpcmd 12345 "sqlite3 -batch" will run "sqlite3 -batch" and listen on tcp port 12345 (for security reasons it listens only on loopback interface (127.0.0.1)). (You may need to link with ws2_32.lib) ------------------------------------------------------------------------- #include <WinSock2.h> #include <stdio.h> #define BUFFER_SIZE 1024 #define OV_ENTRIES 2 enum TransferState { TS_NULL, TS_READING, TS_READY, TS_WRITING }; WSADATA g_WsaData; PROCESS_INFORMATION g_Process; SOCKET g_sockLst, g_sockClient; HANDLE g_hInWr, g_hInRd, g_hOutWr, g_hOutRd; HANDLE g_hIOCP; wchar_t* g_zCommand; int g_nPort; int g_bConnected = 0; enum TransferState g_eInState = TS_NULL, g_eOutState = TS_NULL; OVERLAPPED g_ovIn, g_ovOut; WSABUF g_wbIn, g_wbOut; DWORD g_flgWsaIn; DWORD g_nIn, g_nOut; char g_bufIn[BUFFER_SIZE], g_bufOut[BUFFER_SIZE]; void printError(const wchar_t* zFunc, DWORD nErr); int parseArgs(int argc, wchar_t* argv[]); int openPort(); int acceptClient(); void closeClient(); int runCommandProcess(); int main_loop(); int wmain(int argc, wchar_t* argv[]) { int rc = parseArgs(argc, argv); if (rc) return rc; rc = WSAStartup(MAKEWORD(2, 2), &g_WsaData); if (rc) { printError(L"WSAStartup", rc); return rc; } rc = openPort(); if (!rc) { rc = runCommandProcess(); if (!rc) { while (main_loop() == 0); TerminateProcess(g_Process.hProcess, 0); } closeClient(); closesocket(g_sockLst); } WSACleanup(); return rc; } int main_loop() { int rc; DWORD dwProcExit; ULONG i; ULONG nOvEntries = 0; OVERLAPPED_ENTRY ovEntries[OV_ENTRIES]; rc = GetExitCodeProcess(g_Process.hProcess, &dwProcExit); if (!rc) { printError(L"GetExitCodeProcess", GetLastError()); return 1; } if (dwProcExit != STILL_ACTIVE) return 1; switch (g_eInState) { case TS_NULL: rc = acceptClient(); if (rc) break; memset(&g_ovIn, 0, sizeof(g_ovIn)); g_wbIn.buf = g_bufIn; g_wbIn.len = BUFFER_SIZE; g_nIn = 0; g_flgWsaIn = 0; rc = WSARecv(g_sockClient, &g_wbIn, 1, NULL, &g_flgWsaIn, &g_ovIn, NULL); if (rc) { DWORD err = WSAGetLastError(); if (err != ERROR_IO_PENDING) { printError(L"WSARecv", err); closeClient(); return 0; } } g_eInState = TS_READING; break; case TS_READY: memset(&g_ovIn, 0, sizeof(g_ovIn)); rc = WriteFile(g_hInWr, g_bufIn, g_nIn, NULL, &g_ovIn); if (!rc) { DWORD err = GetLastError(); if (err != ERROR_IO_PENDING) { printError(L"WriteFile", err); return 1; } } g_eInState = TS_WRITING; break; default: break; } switch (g_eOutState) { case TS_NULL: memset(&g_ovOut, 0, sizeof(g_ovOut)); rc = ReadFile(g_hOutRd, g_bufOut, BUFFER_SIZE, NULL, &g_ovOut); if (!rc) { DWORD err = GetLastError(); if (err != ERROR_IO_PENDING) { printError(L"ReadFile", err); return 1; } } g_eOutState = TS_READING; break; case TS_READY: rc = acceptClient(); if (rc) break; memset(&g_ovOut, 0, sizeof(g_ovOut)); g_wbOut.buf = g_bufOut; g_wbOut.len = g_nOut; rc = WSASend(g_sockClient, &g_wbOut, 1, NULL, 0, &g_ovOut, NULL); if (rc) { DWORD err = WSAGetLastError(); if (err != ERROR_IO_PENDING) { printError(L"WSASend", err); closeClient(); return 0; } } g_eOutState = TS_WRITING; break; default: break; } memset(&ovEntries, 0, sizeof(ovEntries)); rc = GetQueuedCompletionStatusEx(g_hIOCP, ovEntries, 2, &nOvEntries, 10000, TRUE); if (!rc) return 0; for (i = 0; i < nOvEntries; ++i) { LPOVERLAPPED_ENTRY pOvEn = &ovEntries[i]; if (pOvEn->lpOverlapped == &g_ovIn) { switch (g_eInState) { case TS_READING: g_nIn = pOvEn->dwNumberOfBytesTransferred; if (g_nIn) g_eInState = TS_READY; else { g_eInState = TS_NULL; closeClient(); } break; case TS_WRITING: if (g_nIn <= pOvEn->dwNumberOfBytesTransferred) g_eInState = TS_NULL; else { g_nIn -= pOvEn->dwNumberOfBytesTransferred; memmove(g_bufIn, (g_bufIn + pOvEn->dwNumberOfBytesTransferred), g_nIn); g_eInState = TS_READY; } break; default: break; } } else if (pOvEn->lpOverlapped == &g_ovOut) { switch (g_eOutState) { case TS_READING: g_nOut = pOvEn->dwNumberOfBytesTransferred; if (g_nOut) g_eOutState = TS_READY; else g_eOutState = TS_NULL; break; case TS_WRITING: if (g_nOut <= pOvEn->dwNumberOfBytesTransferred) g_eOutState = TS_NULL; else { g_nOut -= pOvEn->dwNumberOfBytesTransferred; memmove(g_bufOut, (g_bufOut + pOvEn->dwNumberOfBytesTransferred), g_nOut); g_eOutState = TS_READY; } break; default: break; } } } return 0; } int openPort() { int rc; struct sockaddr_in saddrLst; g_sockLst = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (g_sockLst == INVALID_SOCKET) { printError(L"socket", WSAGetLastError()); return 1; } memset(&saddrLst, 0, sizeof(saddrLst)); saddrLst.sin_family = AF_INET; saddrLst.sin_port = htons(g_nPort); saddrLst.sin_addr.s_addr = htonl(INADDR_LOOPBACK); rc = bind(g_sockLst, (struct sockaddr*)&saddrLst, sizeof(saddrLst)); if (rc) { printError(L"bind", WSAGetLastError()); closesocket(g_sockLst); return rc; } rc = listen(g_sockLst, 1); if (rc) { printError(L"listen", WSAGetLastError()); closesocket(g_sockLst); return rc; } return rc; } int acceptClient() { HANDLE hIOCP; if (g_bConnected) return 0; g_sockClient = accept(g_sockLst, NULL, NULL); if (g_sockClient == INVALID_SOCKET) { printError(L"accept", WSAGetLastError()); return 1; } hIOCP = CreateIoCompletionPort((HANDLE)g_sockClient, g_hIOCP, 0, 0); if (!hIOCP) { printError(L"CreateIoCompletionPort", GetLastError()); closesocket(g_sockClient); return 1; } g_bConnected = 1; return 0; } void closeClient() { if (g_bConnected) closesocket(g_sockClient); g_bConnected = 0; } int createPipe(PHANDLE phServer, PHANDLE phClient, int dir) { DWORD dwOpenMode = (dir ? PIPE_ACCESS_INBOUND : PIPE_ACCESS_OUTBOUND) | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED; DWORD dwFileAccess = (dir ? GENERIC_WRITE : GENERIC_READ); DWORD dwFileShare = (dir ? FILE_SHARE_READ : FILE_SHARE_WRITE) | FILE_SHARE_DELETE; SECURITY_ATTRIBUTES sec_attr; wchar_t name[256]; swprintf(name, 255, L"\\\\.\\pipe\\ChildStdPipe%d_P%u_T%u", dir, GetCurrentProcessId(), GetCurrentThreadId()); *phServer = CreateNamedPipeW(name, dwOpenMode, PIPE_REJECT_REMOTE_CLIENTS, 1, 0, 0, 0, NULL); if (*phServer == INVALID_HANDLE_VALUE) { printError(L"CreateNamedPipeW", GetLastError()); return 1; } memset(&sec_attr, 0, sizeof(sec_attr)); sec_attr.bInheritHandle = TRUE; *phClient = CreateFileW(name, dwFileAccess, dwFileShare, &sec_attr, OPEN_EXISTING, 0, NULL); if (*phClient == INVALID_HANDLE_VALUE) { printError(L"CreateFileW", GetLastError()); CloseHandle(*phServer); return 1; } return 0; } int runCommandProcess() { int rc; STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(startup_info)); rc = createPipe(&g_hInWr, &g_hInRd, 0); if (rc) return rc; rc = createPipe(&g_hOutRd, &g_hOutWr, 1); if (rc) return rc; g_hIOCP = CreateIoCompletionPort(g_hInWr, NULL, 0, 0); if (!g_hIOCP) { printError(L"CreateIoCompletionPort", GetLastError()); return 1; } g_hIOCP = CreateIoCompletionPort(g_hOutRd, g_hIOCP, 0, 0); if (!g_hIOCP) { printError(L"CreateIoCompletionPort", GetLastError()); return 1; } startup_info.cb = sizeof(startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; startup_info.hStdInput = g_hInRd; startup_info.hStdOutput = g_hOutWr; startup_info.hStdError = g_hOutWr; rc = CreateProcessW(NULL, g_zCommand, NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &startup_info, &g_Process); if (!rc) { printError(L"CreateProcess", GetLastError()); return 1; } return 0; } void printError(const wchar_t* zFunc, DWORD nErr) { static const DWORD fmtFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; LPWSTR zErr = NULL; FormatMessageW(fmtFlags, NULL, nErr, 0, (LPWSTR)&zErr, 0, NULL); fwprintf(stderr, L"%ls error (%u): %ls\n", zFunc, nErr, zErr); LocalFree((HLOCAL)zErr); } int parseArgs(int argc, wchar_t* argv[]) { static const wchar_t* const zUsage = L"Usage %ls <port> <command>"; if (argc != 3) { fwprintf(stderr, zUsage, argv[0]); return 1; } g_nPort = wcstol(argv[1], NULL, 0); if (g_nPort < 1 || g_nPort > 65535) { fwprintf(stderr, L"Invalid port number %d\n", g_nPort); fwprintf(stderr, zUsage, argv[0]); return 1; } g_zCommand = argv[2]; return 0; } ------------------------------------------------------------------------- 2018-06-08 19:26 GMT+02:00, lhelger...@surplushunter.net <lhelger...@surplushunter.net>: > > Hello - > > I've been following for a while, a lot of very intelligent > people here, and not a lot of fuss!!! Very nice, my compliments to > all!! > > I'm just learning SQLite and using it to collect alarm values from a > monitoring system. The monitoring system can't access the SQLite file > directly, so I've been using sqlite3.exe as the intermediate. > > Since I'm > making many access to the database the monitoring program is constantly > launching sqlite3.exe with new commands or files of commands, very wasteful > of resources. (Windows 7) > > Is there a platform/program that can be run as a > SQLite "front end" that could be launched once and take commands from > another program and pass back results, or is there a way to do that with > sqlite3.exe? I've looked around the web and not found anything, so > far. > > Any guidance is greatly appreciated, thanks for your time!! > > Leland > > _______________________________________________ > sqlite-users mailing list > sqlite-users@mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users > _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users