引入<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
相关产品推荐
相关产品推荐

