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

引入<windows.h>检测文件只读属性时与自定义typedef冲突的解决方案咨询

引入<windows.h>检测文件只读属性时与自定义typedef冲突的解决方案咨询

我完全理解你的困扰——<windows.h>里的海量类型定义和自定义typedef冲突确实很烦人,而且你又不想动已经写好的大量代码。这里有几个实用的解决方案,按推荐程度排序:

方案1:将Windows API调用隔离到单独模块(最干净易维护)

核心思路是把和Windows相关的代码单独放在一个.c文件里,只在这个文件中包含<windows.h>,其他代码通过头文件调用封装好的函数,完全避免冲突。

步骤1:创建属性检测的头文件(file_attrs.h)

#ifndef FILE_ATTRS_H
#define FILE_ATTRS_H

// 返回值说明:
// 0 = 文件不是只读
// 1 = 文件是只读
// -1 = 获取文件属性失败
int isFileReadOnly(const char* filename);

#endif

步骤2:实现属性检测的.c文件(file_attrs.c)

#include "file_attrs.h"
#include <windows.h>

int isFileReadOnly(const char* filename) {
    DWORD fileAttr = GetFileAttributesA(filename);
    if (fileAttr == INVALID_FILE_ATTRIBUTES) {
        // 获取属性失败,可能文件不存在或权限问题
        return -1;
    }
    return (fileAttr & FILE_ATTRIBUTE_READONLY) ? 1 : 0;
}

步骤3:在原函数中调用封装好的函数

修改你的protectWriteFile,在检测到文件存在后加入只读判断:

int protectWriteFile(CCHAR* fn, CCHAR* ex) {
    char exten[EXTEN_LEN] = { 0 };
    int suffixLen = getSuffix(fn, EXTEN_LEN, '.', '\0', exten);
    if (suffixLen <= 0) return -1;
    if (strcmp(ex, exten) != 0) return -2;
    if (!fileExists(fn)) return 0;

    // 调用隔离的只读检测函数
    int readOnlyStatus = isFileReadOnly(fn);
    if (readOnlyStatus == -1) return -3; // 获取属性失败
    if (readOnlyStatus == 1) return -4;  // 文件只读

    return 1;
}

方案2:动态加载Windows API(完全不编译包含<windows.h>)

如果不想新增文件,也可以通过动态加载kernel32.dll的方式调用GetFileAttributesA,不需要包含<windows.h>,直接手动定义所需的常量和函数指针:

// 在你的函数外部定义必要的Windows常量和函数指针(避免和现有typedef冲突)
#define INVALID_FILE_ATTRIBUTES ((unsigned long)-1)
#define FILE_ATTRIBUTE_READONLY 0x00000001
typedef unsigned long (WINAPI *GetFileAttributesAFunc)(const char* lpFileName);

// 封装动态加载的检测函数
int isFileReadOnly(const char* filename) {
    void* hKernel32 = LoadLibraryA("kernel32.dll");
    if (!hKernel32) return -1;

    GetFileAttributesAFunc pGetAttr = (GetFileAttributesAFunc)GetProcAddress(hKernel32, "GetFileAttributesA");
    if (!pGetAttr) {
        FreeLibrary(hKernel32);
        return -1;
    }

    unsigned long attr = pGetAttr(filename);
    int result = -1;
    if (attr != INVALID_FILE_ATTRIBUTES) {
        result = (attr & FILE_ATTRIBUTE_READONLY) ? 1 : 0;
    }

    FreeLibrary(hKernel32);
    return result;
}

之后在protectWriteFile中调用这个函数即可,和方案1的逻辑一致。

方案3:调整编译宏避免冲突(不推荐,稳定性差)

如果你非要在原文件中包含<windows.h>,可以尝试在包含前定义特定宏来减少冲突,比如:

// 在包含<windows.h>前加入这些宏
#define WIN32_LEAN_AND_MEAN
#define NO_STRICT
#include <windows.h>

但这个方案风险较高,不同VS版本的<windows.h>宏定义可能有差异,而且可能还是会有未覆盖的冲突点,只作为最后备选。

最后更新调用逻辑

记得在调用处新增对只读错误的处理:

int protectResult = protectWriteFile(logFn, "log");
if (protectResult < 0) {
    switch (protectResult) {
        case -1:
            printf("*** ERROR: No valid file extension found ***\n");
            break;
        case -2:
            printf("*** ERROR: Invalid file extension - must be \"log\" ***\n");
            break;
        case -3:
            printf("*** ERROR: Failed to retrieve file attributes ***\n");
            break;
        case -4:
            printf("*** ERROR: The specified file is read-only and cannot be overwritten ***\n");
            break;
    }
    return 1;
}

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 11:49:32