You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多进程向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:33:10