为什么我的代码在 Windows 7 下无法在“C:\Program Files”中创建目录?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4583200/
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 15:53:39  来源:igfitidea点击:

Why does my code fail to create a directory in "C:\Program Files" under Windows 7?

c++windowsvisual-c++windows-7uac

提问by sunil.nishad87

I am using Windows 7 and I have to run one program in that windows but that program working in Windows XP. This is a Visual C++ program and I am using Visual Studio 2008 for this. When I am running my application, it does not throw any errors, but it does not create a directory in "c:\program files\". So can anyone help me to create directory and exe file?

我使用的是 Windows 7,我必须在该窗口中运行一个程序,但该程序可在 Windows XP 中运行。这是一个 Visual C++ 程序,我为此使用 Visual Studio 2008。当我运行我的应用程序时,它不会抛出任何错误,但它不会在“c:\program files\”中创建目录。那么谁能帮我创建目录和exe文件?

This is the code I am using:

这是我正在使用的代码:

char szAppPath[MAX_PATH];
char szFileName[MAX_PATH];
DWORD dwResult;
WIN32_FIND_DATA FindFileData;
HANDLE hFind;

dwResult = ExpandEnvironmentStrings( NULL, szAppPath, MAX_PATH);  // "%ProgramFiles%"


// do same for NSim directory
strcat(szAppPath,"\NSim");
hFind = FindFirstFile(szAppPath, &FindFileData);

if (hFind == INVALID_HANDLE_VALUE) 
{
    //Directory Does't Exists create New
    if(!CreateDirectory(szAppPath,NULL))  //Throw Error
    {
        MessageBox("Unable to Create N-SIM directory","NSim Installer");
        return ;
    }
} 
else  
{
    //check if is directory or not
    if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
    {
        MessageBox("Can't Create N-SIM directory\n Another file with same name exists","NSim Installer");
        return ;
    }

    FindClose(hFind);
}

//***************************************N-SIM Application****************************
strcpy(szFileName, szAppPath);
HRSRC hRes;

if( bRegister == FALSE)
{
    strcat(szFileName,"\NSim.exe"); //make same name of the Client & Server in program file
    hRes = FindResource(NULL, MAKEINTRESOURCE(IDR_LANSIMSERVER),RT_RCDATA);

    if(flagUpgrade ==0)
    {
        CString trial = installationDate();   //----- Detemine Expiry Date -----

        setRegistry(trial);
    }
}

回答by Cody Gray

It's a file permissions issue, plain and simple.Programs can't just go rooting around system directories in Windows 7. That's why it works "properly" in Windows XP, but not in newer versions.

这是一个文件权限问题,简单明了。程序不能只是在 Windows 7 中的系统目录中扎根。这就是它在 Windows XP 中“正常”运行但在较新版本中不能运行的原因。

I can't tell for sure, but it looks like you're trying to write an installer. If so, why are you reinventing the wheel? There are tons of great setup utilities available—Visual Studio provides a setup project that you can customize to your needs, or look into Inno Setup, my personal favorite. A Google search will turn up plenty of other options that have already solved this problem for you, and innumerable others.

我不能肯定,但看起来您正在尝试编写安装程序。如果是这样,你为什么要重新发明轮子?有大量出色的设置实用程序可用 — Visual Studio 提供了一个设置项目,您可以根据自己的需要对其进行自定义,或者查看我个人最喜欢的Inno Setup。谷歌搜索会出现许多其他选项,这些选项已经为您解决了这个问题,还有无数其他选项。

If this isn'tan installer, and you're just trying to store application and/or user data in the Program Files folder, I highly recommend that you look elsewhere. You weren't supposed to shove data into the app folder under earlier versions of Windows, and Windows 7 just cuts you off at the knees if you do this. Your best bet is to follow the recommendations that existed from the beginning: Investigate the user and common Application Data folders carefully. Use the SHGetKnownFolderPath functionto retrieve the full path to a known folder using its KNOWNFOLDERID. A couple of suggestions:

如果这不是安装程序,而您只是想将应用程序和/或用户数据存储在 Program Files 文件夹中,我强烈建议您查看其他地方。在早期版本的 Windows 下,您不应该将数据推送到应用程序文件夹中,如果您这样做,Windows 7 只会让您失望。最好的办法是遵循从一开始就存在的建议:仔细调查用户和通用应用程序数据文件夹。使用SHGetKnownFolderPath 函数通过其KNOWNFOLDERID检索已知文件夹的完整路径。几个建议:

  • FOLDERID_ProgramData(a shared program data directory for all users)
  • FOLDERID_LocalAppData(a per-user program data directory, non-roaming)
  • FOLDERID_RoamingAppData(a per-user program data directory, roaming)
  • FOLDERID_ProgramData(所有用户共享的程序数据目录)
  • FOLDERID_LocalAppData(每个用户的程序数据目录,非漫游)
  • FOLDERID_RoamingAppData(每个用户的程序数据目录,漫游)

Alternatively, you can try running the application as an Administrator. You might want to look into creating a manifestthat indicates the application requires administrator-level permissions to execute.

或者,您可以尝试以管理员身份运行该应用程序。您可能需要考虑创建一个清单,指示应用程序需要管理员级别的权限才能执行。

回答by Clifford



[edit]I edited the code in the question for readability and removed the commented out code (to see the wood for the trees). It is now obvious that nothinginitialises szAppPath before calling strcat(), and calling ExpandEnvironmentStringswith NULL as the first argument is undefined(and certainly useless). Calling strcat()on an unitialised string is not likely to have the desired result. This may be an artefact of not posting the real code, or even of other peoples edits (including mine).

[编辑]我编辑了问题中的代码以提高可读性并删除了注释掉的代码(以查看树木的木材)。现在很明显,在调用 strcat() 之前没有初始化 szAppPath,并且调用ExpandEnvironmentStringsNULL 作为第一个参数是未定义的(当然也没有用)。调用strcat()一个未初始化的字符串不太可能得到想要的结果。这可能是没有发布真实代码的人工制品,甚至是其他人的编辑(包括我的)。



CreateDirectorysets the system error code on error; if you want to know what went wrong, check it! Any answer you get here will be an educated guess.

CreateDirectory在出错时设置系统错误代码;如果您想知道出了什么问题,请检查它!您在这里得到的任何答案都将是有根据的猜测。

if(!CreateDirectory(szAppPath,NULL))  //Throw Error
{
    DWORD errorcode = GetLastError(); 
    LPVOID lpMsgBuf;

    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL, errorcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL );

    MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK); 
    return ;
}

If you just want to get the error code and look it up manually, then a complete directory of codes is available on MSDN, here, I would guessthat ERROR_ACCESS_DENIED (5)is most probable. A more elaborate example of error code display is given here.

如果您只想获取错误代码并手动查找,那么MSDN上提供了完整的代码目录,我ERROR_ACCESS_DENIED (5)是最有可能的。此处给出更详细的错误代码显示示例。

回答by Sarwar Erfan

windows7? Ok, the problem is not with your program. Its with the file system permissions in Windows 7. User programs cannot create files there.

Windows 7的?好的,问题不在于您的程序。它具有 Windows 7 中的文件系统权限。用户程序无法在那里创建文件。

回答by denfon

I think the problem is lack of privileges. You can debug your project to see whether the CreateDirectoryfunction sets an error as ERROR_ACCESS_DENIED, if it does, you should make your program run with an administrator privilege. Add manifest in your project to do so.

我认为问题在于缺乏特权。您可以调试您的项目以查看该CreateDirectory函数是否将错误设置为ERROR_ACCESS_DENIED,如果是,您应该让您的程序以管理员权限运行。在您的项目中添加清单以执行此操作。

回答by CashCow

It is intended to protect your computer against attack. Well maybe. Or Microsoft deciding to tell you what you are and not allowed to do on your own computer.

它旨在保护您的计算机免受攻击。也许会。或者 Microsoft 决定告诉您您可以在自己的计算机上做什么和不允许做什么。

In any case you can change your UAC settings if you really have to write there in that way although that obviously exposes you to risk.

在任何情况下,如果您真的必须以这种方式编写,您都可以更改您的 UAC 设置,尽管这显然会使您面临风险。

Otherwise play nice and do things the Microsoft way, using a proper installer.

否则,使用适当的安装程序,以 Microsoft 的方式做好事并做事。