windows 常见的可写应用程序文件放在哪里?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/147016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:19:56  来源:igfitidea点击:

Where to put common writable application files?

c++windowswinapiuacapplication-data

提问by dennisV

I thought that CSIDL_COMMON_APPDATA\company\productshould be the place to put files that are common for all users of the application and that the application can modify, however, on Vista this is a read-only location, unless modified by the installer (as per MSDN - http://msdn.microsoft.com/en-us/library/ms995853.aspx), so... what's best? Modify the location's security settings to allow writing or use CSIDL_COMMON_DOCUMENTS\company\productinstead? Maybe there's a third option?

我认为这CSIDL_COMMON_APPDATA\company\product应该是放置应用程序所有用户通用的文件并且应用程序可以修改的地方,但是,在 Vista 上,这是一个只读位置,除非安装程序修改(根据 MSDN - http: //msdn.microsoft.com/en-us/library/ms995853.aspx),那么……什么是最好的?修改位置的安全设置以允许写入或使用CSIDL_COMMON_DOCUMENTS\company\product?也许还有第三种选择?

Also, is there an "official" Microsoft recommendation on this somewhere?

另外,是否有“官方”微软对此的建议?

回答by 1800 INFORMATION

Modify just the security on a specific sub-directory of the AppData directory (this is from the link you provided):

仅修改 AppData 目录的特定子目录上的安全性(来自您提供的链接):

CSIDL_COMMON_APPDATA This folder should be used for application data that is not user specific. For example, an application may store a spell check dictionary, a database of clip-art or a log file in the CSIDL_COMMON_APPDATA folder. This information will not roam and is available to anyone using the computer. By default, this location is read-only for normal (non-admin, non-power) Users. If an application requires normal Users to have write access to an application specific subdirectory of CSIDL_COMMON_APPDATA, then the application must explicitly modify the security on that sub-directory during application setup.The modified security must be documented in the Vendor Questionnaire.

CSIDL_COMMON_APPDATA 此文件夹应用于非用户特定的应用程序数据。例如,应用程序可以在 CSIDL_COMMON_APPDATA 文件夹中存储拼写检查字典、剪贴画数据库或日志文件。此信息不会漫游,任何使用计算机的人都可以使用。默认情况下,此位置对于普通(非管理员、非电源)用户是只读的。如果应用程序要求普通用户对 CSIDL_COMMON_APPDATA 的应用程序特定子目录具有写访问权限,则应用程序必须在应用程序设置期间显式修改该子目录上的安全性。修改后的证券必须记录在供应商问卷中。

回答by Wyatt O'Day

Here's a simple example showing how to create files and folders with Read/Write permission for all users in the Common App Data folder (CSIDL_COMMON_APPDATA). Any user can run this code to give all other users permission to write to the files & folders:

这是一个简单的示例,展示了如何在 Common App Data 文件夹 (CSIDL_COMMON_APPDATA) 中为所有用户创建具有读/写权限的文件和文件夹。任何用户都可以运行此代码以授予所有其他用户写入文件和文件夹的权限:

#include <windows.h>

#include <shlobj.h>
#pragma comment(lib, "shell32.lib")

// for PathAppend
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
#pragma comment(lib, "advapi32.lib")    

#include <iostream>
#include <fstream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwRes, dwDisposition;
    PSID pEveryoneSID = NULL;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
    SECURITY_ATTRIBUTES sa;

    // Create a well-known SID for the Everyone group.
    if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
                     SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0,
                     &pEveryoneSID))
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone access to files & folders you create.
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = 0xFFFFFFFF;
    ea.grfAccessMode = SET_ACCESS;

    // both folders & files will inherit this ACE
    ea.grfInheritance= CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName  = (LPTSTR) pEveryoneSID;

    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes)
    {
        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize a security descriptor.
    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (NULL == pSD)
    {
        _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
        goto Cleanup;
    }

    if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
    {
        _tprintf(_T("InitializeSecurityDescriptor Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Add the ACL to the security descriptor.
    if (!SetSecurityDescriptorDacl(pSD,
            TRUE,     // bDaclPresent flag
            pACL,
            FALSE))   // not a default DACL
    {
        _tprintf(_T("SetSecurityDescriptorDacl Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize a security attributes structure.
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;



    TCHAR szPath[MAX_PATH];

    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) 
    {
        PathAppend(szPath, TEXT("Your Shared Folder"));

        if (!CreateDirectory(szPath, &sa)
            && GetLastError() != ERROR_ALREADY_EXISTS) 
        {
            goto Cleanup;
        }

        PathAppend(szPath, TEXT("textitup.txt"));

        HANDLE hFile = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, 0, 0);
        if (hFile == INVALID_HANDLE_VALUE)
            goto Cleanup;
        else
            CloseHandle(hFile);

        //TODO: do the writing
        ofstream fsOut;
        fsOut.exceptions(ios::eofbit | ios::failbit | ios::badbit);
        fsOut.open(szPath, ios::out | ios::binary | ios::trunc);

        fsOut << "Hello world!\n";
        fsOut.close();
    }

Cleanup:

    if (pEveryoneSID) 
        FreeSid(pEveryoneSID);
    if (pACL) 
        LocalFree(pACL);
    if (pSD) 
        LocalFree(pSD);

    return 0;
}

回答by TheSoftwareJedi

I think this postmay answer some questions, but it seems a difficult problem for many.

我认为这篇文章可能会回答一些问题,但对许多人来说似乎是一个难题。

Apparently, CSIDL_COMMON_DOCUMENTS provides a common workaround

显然,CSIDL_COMMON_DOCUMENTS 提供了一个通用的解决方法

回答by Christoffer Lette

Guidelines for Vista/UAC can be found here. Search that page for "CSIDL" and you'll find some "official" answers.

可在此处找到 Vista/UAC 指南。在该页面上搜索“ CSIDL”,您会找到一些“官方”答案。