为没有凭据的不同用户获取特殊文件夹

时间:2016-06-04 13:22:30

标签: c# wpf winapi .net-4.0

我正在编写一个卸载程序,作为该过程的一部分,我想为所有本地用户清理缓存,临时文件等。该应用程序将提升以使其正常工作。

我要查找的文件位于AppData\Local等特殊文件夹中,因此我需要这些路径。对于当前登录的用户,这与Environment.GetFolderPath无关。但是,这不适合不同的用户。

根据referencesource.microsoft.com,GetFolderPath最终会调用SHGetFolderPath,后者又会SHGetKnownFolderPath。这两个Win32 API都有一个可选的hToken参数,可以让我指定一个帐户令牌。

事实上,这将有效:

private static string GetFolderPath(Guid knownfolderid, string user, string domain, string password)
{
    const int LOGON32_PROVIDER_DEFAULT = 0;
    const int LOGON32_LOGON_INTERACTIVE = 2;

    SafeTokenHandle safeTokenHandle;

    if (!LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle))
        throw new System.Security.Authentication.InvalidCredentialException();

    IntPtr pPath;
    SHGetKnownFolderPath(knownfolderid,
                         0,
                         safeTokenHandle.DangerousGetHandle(),
                         out pPath);
    string result = System.Runtime.InteropServices.Marshal.PtrToStringUni(pPath);
    System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pPath);

    return result;
}

...但它对我的用途来说是不切实际的 - 当然 - 我不希望卸载某些内容的管理员必须知道并提供每个用户名和密码。

所以:

  • 有没有办法获取适当的访问令牌需要知道用户的凭据?
  • 失败了,有没有不同的方法来实现我的目标?当然,从注册表seems unsafe读取信息,硬编码文件夹名称也是如此。

1 个答案:

答案 0 :(得分:1)

假设修改应用程序以支持卸载程序为时已晚,您可以在安装时在ProgramData中创建一个文件夹,然后每次启动应用程序时都可以为当前用户编写一个文件包含目录和/或文件的路径。 (您甚至可以在更新时对其进行改进,但对于在安装更新和卸载产品之间没有登录的用户来说,它不会起作用。)

您需要对安全性保持谨慎。非管理员用户应该只有"创建文件"访问该文件夹,该文件夹应设置为不可继承。这样他们就无法看到或操纵彼此的文件。您可能还希望为CREATOR OWNER分配可继承的完全访问权限。

您还需要验证保存的路径信息,而不是盲目信任它,否则恶意用户可能会使您的卸载程序删除错误的文件。我建议您检查您要删除的文件或文件夹是否属于拥有包含已保存路径信息的文件的同一个人,如果没有,请致电寻求帮助。为了更加安全,您的应用程序还可以标记它创建的文件,这些文件应该在卸载时删除,可能使用备用数据流。