技术开发 频道

VS2010与Win7共舞:UAC与数据重定向

  禁用UAC Virtualization

  凡事都没有绝对。如果因为一些特殊的要求(众所周知,客户的要求千奇百怪,无奇不有),我们一定要向“Program Files”目录写入数据,这时该怎么办呢?面对这种极其特殊的情况,我们可以在应用程序的Manifest禁用UAC Virtualization,取消其对数据写操作的重定向。在项目属性中,我们设置启用UAC(Enable User Account Control),并且在UAC Execution Level中设置请求管理员权限。这样,应用程序在启动的时候,就会向用户请求管理员权限,当应用程序获得管理员执行权限后,当然可以向任意目录写入数据,UAC Virtualization也就不会起作用了。

  图2  通过Manifest禁用UAC Virtualization

  对于64位应用程序,本身是不具备UAC Virtualization机制的,所以根本不存在禁用的问题。当我们在64位应用程序中尝试向“Program Files”等敏感目录写入数据时,就会遇到一个“拒绝访问”的错误:

// 测试文件夹是否存在
BOOL IsDirectoryExists(TCHAR *dirName)
{
    WIN32_FILE_ATTRIBUTE_DATA dataDirAttrData;
    
if (!::GetFileAttributesEx(dirName, GetFileExInfoStandard, &dataDirAttrData))
    {
        DWORD lastError
= ::GetLastError();
        
if (lastError == ERROR_PATH_NOT_FOUND || lastError == ERROR_FILE_NOT_FOUND || lastError == ERROR_NOT_READY)
            
return FALSE;
    }

    
return (dataDirAttrData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}

//
    
// 获取文件夹路径
    
//if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramData,
    
//           0, NULL, &pszPath)))
    
// 错误的做法:
    if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramFiles,
        
0, NULL, &pszPath)))
    {
        
// 提示错误
        MessageBox(hwndDlg, _T("SHGetKnownFolderPath无法获取文件路径"),
            _T(
"Error"), MB_OK | MB_ICONERROR);
        
return FALSE;
    }

//
      
// 检查文件夹是否存在
    if (::IsDirectoryExists(dataFilePath))
    {
        
// 如果文件夹不存在,则创建文件夹
        if (!::CreateDirectory(dataFilePath, NULL))
        {
            DWORD dwErrorCode
= ::GetLastError();
            LPCWSTR lpBuffer;
            
// 获取错误信息
            FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER   |
                   FORMAT_MESSAGE_IGNORE_INSERTS  
|
                 FORMAT_MESSAGE_FROM_SYSTEM,
                 NULL,
                 dwErrorCode,
//  错误代码
                 LANG_NEUTRAL,
                 (LPTSTR)
&lpBuffer,
                
0 ,
                 NULL );
            
            
// 显示错误对话框
            MessageBox(hwndDlg, lpBuffer, _T("创建文件夹错误"), MB_OK | MB_ICONERROR);
            LocalFree((HLOCAL)lpBuffer);
            
            
return FALSE;
        }
    }

  当这段代码执行到创建文件夹的时候,会遇到一个“拒绝访问”错误:

  图3  创建文件夹的“拒绝访问”错误

  为了避免这个错误,同样的,我们可以通过在项目属性中设置,使得Manifest中嵌入UAC相关的信息,在应用程序启动的时候请求管理员权限,就像我们在运行其他大多数需要管理器权限的应用程序一样。当应用程序获得管理员权限后,这个错误就不存在了。但是这里必须要指出,这种做法是不太安全的,能够避免尽量避免。

系列文章索引:

        VS2010与Win7共舞:ETW自定义程序日志

  VS与Win7共舞:性能计数器进行性能分析

  VS2010与Windows7共舞:对库进行编程

  VS与Windows 7共舞:库(Library) 

  VS2010与Win7共舞:响应Ribbon控件消息 

  VS与Win7共舞:用XML文件定义Ribbon界面

  VS 2010与Windows7共舞:又见Ribbon

  VS2010与Win7共舞 :任务栏状态提示

  VS2010与Win7共舞 :任务栏缩略图

  VS2010与Windows 7共舞:Jumplist

0
相关文章