【问题标题】:Why does my code fail to create a directory in "C:\Program Files" under Windows 7?为什么我的代码无法在 Windows 7 下的“C:\Program Files”中创建目录?
【发布时间】:2011-01-03 09:01:22
【问题描述】:

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

这是我正在使用的代码:

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);
    }
}

【问题讨论】:

  • 字符串转义很差。而不是C:\NSimC:\\NSim
  • 显然在重新格式化时,İsmail 'cartman' Dönmez “修复”了字符串转义问题...
  • 我已经在我的程序中使用了它,但它仍然没有创建文件夹。请提供另一种解决方案
  • @goreSplatter:字符串在原始源代码中已正确转义,但由于文本未格式化为源代码,因此未显示。 Ismail 修复的只是代码格式——我检查了,因为我同意你的观点,这样的东西不应该被“编辑”。
  • @Cody 感谢您指出这一点。由于我还差一点rep,所以我看不到源...

标签: c++ windows visual-c++ windows-7 uac


【解决方案1】:

这是一个文件权限问题,简单明了。程序不能仅仅围绕 Windows 7 中的系统目录进行操作。这就是为什么它在 Windows XP 中“正常”工作,但在较新版本中不能正常工作的原因.

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

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

  • FOLDERID_ProgramData(所有用户共享的程序数据目录)
  • FOLDERID_LocalAppData(每用户程序数据目录,非漫游)
  • FOLDERID_RoamingAppData(每用户程序数据目录,漫游)

或者,您可以尝试以管理员身份运行应用程序。您可能想查看creating a manifest,它表明应用程序需要管理员级别的权限才能执行。

【讨论】:

  • 嗨,我拥有所有权限。你能告诉一些其他的逻辑吗?
  • @sunil:你是怎么确认的? UAC 强制执行权限的方式的差异最有可能解释您的代码在 Windows XP 上按预期工作,但在更高版本的 Windows 上则不然。
  • 是的,我已确认。此代码在 windowsxp 上运行,但不在 windows7 操作系统中运行。我可以用其他代码代替这段代码吗?
  • @sunil:在发表评论之前,您真的阅读了我的回答吗?我提供了至少 3 条不同的建议,说明你可以做什么。
  • @sunil:阅读 documentation 和 Inno Setup 中包含的帮助文件。还包括一些示例安装程序脚本。该网站有一个knowledge base 包含补充信息。快速谷歌搜索显示this quick-start guide。使用起来确实不是很困难。不要束手无策。
【解决方案2】:

[编辑]为了便于阅读,我编辑了问题中的代码,并删除了注释掉的代码(以查看树木的木材)。现在很明显 nothing 在调用 strcat() 之前初始化了 szAppPath,并且以 NULL 作为第一个参数调用 ExpandEnvironmentStringsundefined (当然没有用)。在未初始化的字符串上调用 strcat() 不太可能获得预期的结果。这可能是由于没有发布真实代码,甚至是其他人(包括我的)编辑的人工制品。


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 ;
}

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

【讨论】:

【解决方案3】:

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

【讨论】:

  • 并且,尽量避免使用您自己的程序作为其他程序的安装程序。即使您有自定义 UI 和自定义这个和那个,许多安装程序制造商也可以选择在安装过程中插入您自己的 dll 并从您的 dll 调用函数。
  • 你能告诉我这个过程吗?
  • 您还想在安装程序中添加什么(除了复制文件)?
  • 我的exe文件也没有显示在桌面和启动菜单中。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

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

    否则,请使用适当的安装程序,按照 Microsoft 的方式进行操作。

    【讨论】:

      猜你喜欢
      • 2017-11-27
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多