我的程序取决于根据登录的用户而变化的信息。例如AppData的位置。我的程序还需要管理权限。如果我以管理员身份运行程序,程序会认为管理员是当前登录的用户。
我的“解决方案”:创建第二个程序作为控制台运行。它作为标准用户运行,将信息放入变量以正确识别当前用户。然后它将主程序从Resources保存到磁盘,启动它,然后通过Arguments传递这些变量。
问题:我必须先构建程序两次才能测试它。这非常烦人。
虽然我的解决方案有效,但我已经厌倦了。有没有其他方法可以让当前(活动)登录用户?我尝试过 SystemInformation.UserName.ToString 和 My.User.Name.ToString 。两者都给错了用户。
编辑: System.Security.Principal.WindowsIdentity.GetCurrent()。名称不起作用。
建议的解决方案:我不会在我的主程序之前运行程序来收集信息,而是尝试在我的主程序运行的同时运行该程序。我的主程序将等待信息被发回,然后恢复。这样,我不必一直双重构建。
答案 0 :(得分:1)
这个答案可能会引起争议,因为它并没有严格回答标题中的问题。但是问题仍然是正确的答案。明确提出的问题是所谓的XY problem。您遇到了问题,找到了可能的解决方案,然后在实施该解决方案时遇到问题,因此您已经寻求帮助。问题在于,你脑海中想出的解决方案并不正确。
我的程序取决于根据登录用户而变化的信息。例如AppData的位置。
这很正常。但是,您不会通过检测登录的用户来解决此问题。无论如何,这对您没有任何好处。假设您知道用户的名称:您现在如何使用它来找出AppData文件夹?我假设您将尝试根据您对Windows默认安装中文件夹位置的了解手动撰写路径:C:\Users\<the user name>\AppData\
。但是你只是犯了错误。如果用户已将其配置文件目录映射到其他位置,会发生什么?如果用户名与Users目录中的目录名称不匹配(例如,如果管理员帐户已重命名),该怎么办?
这个问题的真正解决方案完全简单。您只需向Windows询问AppData文件夹的路径即可。让操作系统完成其工作,跟踪登录用户。
通常,在Windows中,您可以调用SHGetKnownFolderPath
函数或其道德等效函数。在.NET Framework中,该功能由Environment.GetFolderPath
method包装。简单,保证是正确的。
您需要指定SpecialFolder.CommonApplicationData
(所有用户的AppData文件夹),SpecialFolder.ApplicationData
(当前用户的漫游AppData文件夹)或SpecialFolder.LocalApplicationData
(非漫游)当前用户的AppData文件夹。)
我的程序还需要管理权限。如果我以管理员身份运行程序,程序会认为管理员是当前登录的用户。
因为它是。如果您以管理员身份运行程序,则出于所有意图和目的,程序将以管理员身份运行。这意味着返回Administrator作为当前用户的名称,返回管理员的AppData文件夹,依此类推。这是非常合乎逻辑的,它使程序能够执行特定于管理员的事情。
但除此之外,拥有一个需要管理权限的整个应用程序是不好的做法(除了最不寻常的情况之外)。通常,真正需要管理权限的应用程序只执行一个或两个操作。例如,我写了一点实用工具。它的基本功能都不需要管理权限,但它具有安装自身的功能,以便在启动时为所有用户启动。显然,这需要管理权限,但这只是一次性的专业功能。您不希望整个应用仅需要针对该专用功能的管理权限。如果当前用户无法获得管理员权限,该怎么办?他们应该仍然可以使用该软件,只需禁用管理员专用功能或无法访问。
这适用于Windows的流程提升模型。暂时无法提升当前流程。您必须启动一个新的提升进程,执行需要管理权限的任何操作,然后退出该进程。我已经写了关于如何做到这一点的详细说明here。当然,它们都在C#中,但很容易翻译成VB.NET。
我可以通过其他方式获取当前(活动)登录用户吗?我已经尝试过SystemInformation.UserName.ToString和My.User.Name.ToString。两者都给错了用户。
就像我上面所说的那样,信息不是&#34;错误&#34;。你自己说过:他们正在回归现在的(活跃的)&#34;用户:管理员。您请求将应用程序运行的那个。
根据我上面提出的解决方案,您的应用程序正常运行,不会以管理员身份运行。这样可以提高安全性,并确保您获得适用于当前登录用户的信息。当您需要执行需要管理员权限的操作时,您将关闭第二个提升的进程,执行工作,然后退出该进程。升级过程将作为管理员,用于所有意图和目的,这几乎总是你想要的。
对于它的价值,我经常会看到像你这样的人尝试编写安装程序的问题(不要这样做,只需使用已有的许多优秀安装程序之一)。显然,他们的安装程序需要管理员权限,因此他们将其设置为在启动时请求提升。到现在为止还挺好。除了他们想要在安装期间将数据写入特定用户的AppData文件夹。现在他们遇到了问题,因为(1)他们无法获得该路径,并且(2)甚至可能 其他已登录用户。该解决方案以及Windows徽标指南正式推荐的解决方案是在首次运行时执行此类初始化。换句话说,第一次安装的应用程序由普通用户运行。然后你得到你期望的AppData文件夹。
答案 1 :(得分:0)
我相信Environment.UserName
会获取当前登录的用户(而不是&#39;运行为&#39;用户)。也可以按如下方式查询WMI:
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem");
ManagementObjectCollection collection = searcher.Get();
string username = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];
这来自this SO question。
答案 2 :(得分:0)
此处找到的解决方案Detect Current Logged on User with VB.Net 和 getting username in vb.net
我还需要编写应用程序直接转到我已经拥有url的本地路径。 c:\ users \ username \ appdata \ packages和&#34; environment.username&#34;适合我。我刚刚声明了一个变量来保存它
答案 3 :(得分:0)
我的供稿中弹出了一个经常被问到的问题,我想尝试一下“回答”自己的问题。
背景故事是我试图创建一个注册表调整实用程序(部分作为自学VB的一种方式)。当时我对编程非常陌生。我会选中一个框并立即将其应用。其中一些调整是HKEY_CURRENT_USER
。至少对于Windows 10,如果您在本地Administrators组中并且进行了提升,则它仍具有运行用户身份。也许UAC在Windows 7上的表现有所不同,也许我在运行两个帐户(用户和管理员)。我相信我正在尝试解决一个边缘案件。
无论哪种方式,如果用户将其他用户提升(或运行),显然它将以该用户身份列出进程。您可以通过以下几种方式来检测交互式用户:
HKEY_USER
可能适用(以避免重定向)。query /user
:此命令不容易解析。但是,它不受海拔高度的影响(它始终了解交互式用户)。interactive user
:基于https://serverfault.com/questions/188115/what-is-windows-interactive-user,系统会自动为用户分配特殊身份。我还没有弄清楚,但是也许有一种方法可以枚举它们以确定用户是否是交互式的。以上所有内容不一定都可以防弹,也不一定适合所有人。您可能需要一起使用多个以确保正确使用,尤其是在您的需求至关重要的情况下。上面的内容还假设您具有实施每个单独的知识。 (例如,我如何使用C#从“事件日志”中读取信息。)有足够的指南和线程,尤其是关于SO的指南和线程将对此进行解释。我认为没有必要对此进行重新讨论,尤其是考虑到我的问题与系统管理员的关系比什么都重要。