多进程向Windows终端服务器客户端文件追加写入的问题求助
多进程向Windows终端服务共享客户端驱动器文件追加记录的问题
问题概述
我需要运行一个多进程程序,向同一文件追加记录。在非Windows服务器上写入本地文件时,追加功能正常;但在Windows服务器上,通过终端服务器客户端路径(如\\tsclient\c\temp\myfile-append.txt)写入共享客户端驱动器的文件时,功能失效:
- 调用
CreateFile()时将dwDesiredAccess设为GENERIC_WRITE,进程2会覆盖进程1的所有数据,无法实现追加 - 替换为
FILE_APPEND_DATA时,文件能创建,但调用WriteFile()会返回ERROR_INVALID_PARAMETER(错误码87)
Windows服务器上的错误表现
使用FILE_APPEND_DATA时的WriteFile()错误输出:
process 1: Running on a Windows Server and Terminal Services are enabled CreateFile: \\tsclient\c\temp\myfile-write.txt WriteFile: TEST-6620 WriteFile: TEST-6620 WriteFile: TEST-6620 WriteFile: TEST-6620 CreateFile: \\tsclient\c\temp\myfile-append.txt WriteFile: TEST-6620 WriteFile returned ERROR_INVALID_PARAMETER errno:87 Press return to exit... process 2: Running on a Windows Server and Terminal Services are enabled CreateFile: \\tsclient\c\temp\myfile-write.txt WriteFile: TEST-9020 WriteFile: TEST-9020 WriteFile: TEST-9020 WriteFile: TEST-9020 CreateFile: \\tsclient\c\temp\myfile-append.txt WriteFile: TEST-9020 WriteFile returned ERROR_INVALID_PARAMETER errno:87 Press return to exit...
文件结果:
myfile-append已创建但为空myfile-write仅保留进程2的最后4条记录:
TEST-4424 TEST-4424 TEST-4424 TEST-4424
非Windows服务器上的正常表现
运行无错误,输出如下:
process 1 Terminal Services are not enabled so using local files CreateFile: myfile-write.txt WriteFile: TEST-8320 WriteFile: TEST-8320 WriteFile: TEST-8320 WriteFile: TEST-8320 CreateFile: myfile-append.txt WriteFile: TEST-8320 WriteFile: TEST-8320 WriteFile: TEST-8320 WriteFile: TEST-8320 Press return to exit... process 2 Terminal Services are not enabled so using local files CreateFile: myfile-write.txt WriteFile: TEST-11992 WriteFile: TEST-11992 WriteFile: TEST-11992 WriteFile: TEST-11992 CreateFile: myfile-append.txt WriteFile: TEST-11992 WriteFile: TEST-11992 WriteFile: TEST-11992 WriteFile: TEST-11992 Press return to exit...
文件结果:
myfile-append正确包含8条记录(每个进程各4条):
TEST-24820 TEST-16324 TEST-24820 TEST-16324 TEST-24820 TEST-16324 TEST-24820 TEST-16324
myfile-write仅保留进程2的最后4条记录:
TEST-16324 TEST-16324 TEST-16324 TEST-16324
需求
如何实现多进程程序在Windows服务器上,通过终端服务器客户端路径向共享客户端驱动器的文件追加记录?
附件代码
多进程运行批处理脚本
@echo off del \\tsclient\c\temp\myfile-append.txt del \\tsclient\c\temp\myfile-write.txt echo Starting process 1 START "process 1" ConsoleApplication1.exe timeout /t 1 echo Starting process 2 START "process 2" ConsoleApplication1.exe echo Press return after both processes have finished... timeout /t -1 echo myfile-append file, should have 8 records, 4 from each process: type \\tsclient\c\temp\myfile-append.txt echo myfile-write file, should have last 4 records written from process 2: type \\tsclient\c\temp\myfile-write.txt
ConsoleApplication1.cpp 源码
#define COUNT 4 #define SLEEP 2000 #include <Windows.h> #include <iostream> #include <stdlib.h> #include <fileapi.h> #include <errhandlingapi.h> wchar_t filename_local_write[512] = L"myfile-write.txt"; wchar_t filename_local_append[512] = L"myfile-append.txt"; wchar_t filename_ts_write[512] = L"\\\\tsclient\\c\\temp\\myfile-write.txt"; wchar_t filename_ts_append[512] = L"\\\\tsclient\\c\\temp\\myfile-append.txt"; wchar_t* filename_write; wchar_t* filename_append; void* myExit(int exitVal); int main() { int ii; char buf[512]; DWORD rval; SECURITY_ATTRIBUTES sa; HANDLE hFile = 0; DWORD pid; // 检测终端服务是否启用 OSVERSIONINFOEX osVersionInfo; ULONGLONG dwlConditionMask = VerSetConditionMask(0, VER_SUITENAME, VER_AND); ZeroMemory(&osVersionInfo, sizeof(osVersionInfo)); osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo); osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL; int tsEnabled = VerifyVersionInfo((POSVERSIONINFOEX)&osVersionInfo, VER_SUITENAME, dwlConditionMask); if (tsEnabled) { printf("Running on a Windows Server and Terminal Services are enabled\n"); filename_write = filename_ts_write; filename_append = filename_ts_append; } else { printf("Terminal Services are not enabled so using local files\n"); filename_write = filename_local_write; filename_append = filename_local_append; } // 使用进程ID标识写入的记录来源 pid = GetCurrentProcessId(); // 使用GENERIC_WRITE创建文件 memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = FALSE; printf("CreateFile: %ws\n", filename_write); hFile = CreateFileW( filename_write, // 文件路径 GENERIC_READ | GENERIC_WRITE, // 访问权限 FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享模式 &sa, // 安全属性 OPEN_ALWAYS, // 创建方式 FILE_ATTRIBUTE_NORMAL, // 文件属性 NULL); // 模板文件句柄 if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile returned INVALID_HANDLE_VALUE errno:%d\n", GetLastError()); myExit(1); } // 向GENERIC_WRITE创建的文件写入COUNT条记录 rval = 0; for (ii = 0; ii < COUNT; ii++) { sprintf_s(buf, "TEST-%d\n", pid); printf("WriteFile: %s", buf); if (!WriteFile(hFile, buf, strlen(buf), &rval, NULL)) { errno = GetLastError(); if (errno == ERROR_INVALID_PARAMETER) { printf("WriteFile returned ERROR_INVALID_PARAMETER errno:%d\n", errno); } else { printf("WriteFile ERROR: returned errno:%d\n", errno); } myExit(1); } Sleep(SLEEP); } // 关闭文件句柄 CloseHandle(hFile); // 使用FILE_APPEND_DATA创建文件 memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = FALSE; printf("CreateFile: %ws\n", filename_append); hFile = CreateFileW( filename_append, // 文件路径 GENERIC_READ | FILE_APPEND_DATA, // 访问权限 FILE_SHARE_READ | FILE_SHARE_WRITE, // 共享模式 &sa, // 安全属性 OPEN_ALWAYS, // 创建方式 FILE_ATTRIBUTE_NORMAL, // 文件属性 NULL); // 模板文件句柄 if (hFile == INVALID_HANDLE_VALUE) { printf("CreateFile returned INVALID_HANDLE_VALUE errno:%d\n", GetLastError()); myExit(1); } // 向FILE_APPEND_DATA创建的文件写入COUNT条记录 rval = 0; for (ii = 0; ii < COUNT; ii++) { sprintf_s(buf, "TEST-%d\n", pid); printf("WriteFile: %s", buf); if (!WriteFile(hFile, buf, strlen(buf), &rval, NULL)) { errno = GetLastError(); if (errno == ERROR_INVALID_PARAMETER) { printf("WriteFile returned ERROR_INVALID_PARAMETER errno:%d\n", errno); } else { printf("WriteFile ERROR: returned errno:%d\n", errno); } myExit(1); } Sleep(SLEEP); } // 关闭文件句柄 CloseHandle(hFile); myExit(0); } // main void *myExit(int exitVal) { printf("Press return to exit...\n"); int rval = getchar(); exit(exitVal); } // myExit
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

