如何在 C 语言的 windows 的 %appdata% 路径中创建目录并创建文件
Posted
技术标签:
【中文标题】如何在 C 语言的 windows 的 %appdata% 路径中创建目录并创建文件【英文标题】:How can I create a directory and make a file in %appdata% path of windows in C language 【发布时间】:2022-01-24 03:26:01 【问题描述】:我成功创建了一个目录或文件夹,并且我还设法在该目录中创建了一个文件,但是如果我不知道他们的用户名或用户文件夹名称是什么,如何在用户的 appdata 本地创建目录和文件?谢谢!
我使用了代码块
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
int check;
char* dirname = "C:/Pyromagne";
check = mkdir(dirname);
FILE* fp;
fp = fopen("C:/Pyromagne/test.pyr", "w+");
fputs("Pyromagne\n", fp);
fputs("qwertyuiop", fp);
fclose(fp);
FILE* ffpp;
char user[25];
char pass[25];
char uuser[25];
ffpp = fopen("C:/Pyromagne/test.pyr", "r");
strcpy(uuser, fgets(user, 255, (FILE*)ffpp));
printf("%s\n", uuser);
strcpy(uuser, fgets(user, 255, (FILE*)ffpp));
printf("%s\n", uuser);
fclose(ffpp);
【问题讨论】:
你可以试试getenv("APPDATA")
,这会给你“users/name/appdata/roaming”。你真的应该使用SHGetKnownFolderPath
支持Unicode,特别是对于非英语系统。但我不知道如何在 gcc 中使用 C。
@BarmakShemirani 没那么难:#include <Shlobj.h> PWSTR path; HRESULT hRes = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &path); if (SUCCEEDED(hRes)) /* use path as needed... */ CoTaskMemFree(path);
并确保也链接到 Shell32.lib
。
@RemyLebeau 在 Visual Studio 中很容易,但 MinGW 有一些奇怪的地方。它甚至不会在 c++ 中编译,它在 c 中编译,我链接到 libshell32.a
(MinGW 的版本)但得到 "undefined reference" 错误。我可以运行ShellExecute
,它也是shell32.lib 函数,它甚至不需要显式链接命令。
@BarmakShemirani - Remy 的代码应该可以在 C 中使用 GCC 编译(至少对我有用,在 Windows 下在 gcc 中编译),但您需要为文件夹 ID 添加 libuuid.a。
@BarmakShemirani getenv("APPDATA")
和 SHGetKnownFolderPath
这两个有什么区别?为了使用getenv("APPDATA")
函数,我需要哪些库?
【参考方案1】:
SHGetKnownFolderPath
获取 AppData、Documents 等的 Unicode 路径
KNOWNFOLDERID
对于"C:\Users\MyName\AppData\Local"
是FOLDERID_LocalAppData
此函数需要 CoTaskMemFree
、KNOWNFOLDERID
和 SHGetKnownFolderPath
的附加库
gcc file.c libole32.a libuuid.a libshell32.a
使用 MinGW,64 位,gcc 版本 4.8.3,SHGetKnownFolderPath
似乎不在libshell32.a
中。命令行nm libshell32.a
也没有列出这个函数。所以在MinGW中,我们必须手动加载这个函数,如下:
#define _WIN32_WINNT 0x0600
#include <stdio.h>
#include <Windows.h>
#include <shlobj.h>
//add libraries for libole32.a and libuuid.a
HRESULT MySHGetKnownFolderPath
(const KNOWNFOLDERID* const id, DWORD flags, HANDLE token, PWSTR* str)
typedef HRESULT(WINAPI* lpf)(const KNOWNFOLDERID* const, DWORD, HANDLE, PWSTR*);
HMODULE lib = LoadLibraryW(L"shell32.dll");
if (!lib) return E_FAIL;
lpf fnc = (lpf)GetProcAddress(lib, "SHGetKnownFolderPath");
HRESULT result = fnc ? fnc(id, flags, token, str) : E_FAIL;
FreeLibrary(lib);
return result;
int main(void)
wchar_t* temp;
if SUCCEEDED(MySHGetKnownFolderPath(&FOLDERID_LocalAppData, 0, NULL, &temp))
wchar_t path[1024];
swprintf(path, 1024, L"%s\\_add_new_dir", temp);
CoTaskMemFree(temp); //free this memory as soon as possible
wprintf(L"path: %s\n", path); //CreateDirectoryW(path, NULL);
return 0;
此外,您可以使用getenv
或_wgetenv
(Unicode 版本)
#include <stdio.h>
#include <Windows.h>
int main(void)
wprintf(L"%s\n", _wgetenv(L"LOCALAPPDATA"));
wprintf(L"%s\n", _wgetenv(L"APPDATA"));
wprintf(L"%s\n", _wgetenv(L"USERPROFILE"));
wchar_t buf[1024];
swprintf(buf, 1024, L"%s\\_add_new_dir", _wgetenv(L"LOCALAPPDATA"));
wprintf(L"buf: %s\n", buf); //CreateDirectoryW(buf, NULL);
return 0;
要在 Code::Blocks 中添加库,点击菜单 -> 设置 -> 编译器,它应该会弹出这个窗口:
然后点击“添加”按钮,找到MinGW安装文件夹,库应该在
C:\My_MinGW_folder\mingw\lib\libole32.a
or
C:\My_MinGW_folder\mingw\lib32\libole32.a (for 32-bit program)
您可以通过查看该函数的文档来确定您需要哪些库。例如SHGetKnownFolderPath
说它需要“shell32.lib”(对于 Visual Studio)MinGW 使用“libshell32.a”代替。
【讨论】:
我在哪里可以获得这些库? @Pyromagne 查看更新后的答案。注意_wgetenv
方法不需要额外的库
您好 Barmak,关于 mingw,我需要先安装它才能使用该库,还是只下载这些库?
我应该安装什么? MinGW 还是 MinGW-w64?
你能运行这个程序MessageBoxW(0, L"test", 0, 0);
吗?还是我为_wgetenv
发布的代码?如果是这样,您已经安装了 GCC 编译器和 MinGW 库,它将位于不同的文件夹中,可能在 c:\ 或 c:\users\myname 下的某个位置。对于 GCC,运行这个程序:void *p; printf("sizeof pointer: %d\n", sizeof(p));
如果它打印 8
,那么你使用的是 64 位版本。如果它打印 4,则您使用的是 32 位版本。对于 Windows 开发,我会推荐 Visual Studio。【参考方案2】:
在MSYS2/UCRT下,我最近(和昨天一样...)使用SHGetFolderPathA()
在C代码中获取用户的配置文件目录。
在使用最新 MSYS2/UCRT 安装附带的任何 GCC 版本进行编译后,到目前为止,它已在 Windows Server 2016 AWS 安装上进行有限单元测试。 (系统目前已关闭,我正在休假,所以我无法查看详细信息)
这可能适用于您的环境:
char buffer[ MAX_PATH ] = 0 ;
HRESULT result = SHGetFolderPathA( NULL, CSIDL_APPDATA, NULL, 0, buffer );
if ( result != S_OK )
//handle error
有点跑题了,我已经成长为更喜欢 MSYS2/UCRT 而不是替代方案。
【讨论】:
理想情况下,您应该使用 W 函数和 Unicode,否则如果用户的用户名中包含仅 Unicode 字符,则配置文件相关路径可能会失败... 你到底用什么IDE?以上是关于如何在 C 语言的 windows 的 %appdata% 路径中创建目录并创建文件的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Windows 10 上安装 framework-res.apk