ClickOnce不支持请求执行级别“requireAdministrator”。

110

我正在编写一个需要访问注册表的应用程序。在添加其他功能之前,比如描述或名称,我没有触碰任何构建设置,只是想让它能工作。

突然出现了一个错误,但我没有在这个应用程序中使用 ClickOnce。我所做的就是包含一个请求这些权限的清单文件。ClickOnce不支持请求执行级别为'requireAdministrator'的操作。

我的问题是这个错误无法消失,我无法编译我的程序。有什么建议吗?(附注:我即将上床睡觉,明天下午再查看此事)。


6
我不想说废话,但是您在清单中请求了 requireAdministrator 权限,并且 ClickOnce 抱怨它不支持 requireAdministrator。问题非常明显。 ClickOnce 在您的清单中看到了需要提升权限(这成为您的应用程序的一部分)。我不确定您还需要什么信息... - Ken White
6
管理员权限和点击一次的要求结合起来,阻止了您编译项目,而不仅仅是运行它,这一点可能并不完全明显或逻辑上合理 - 但确实如此。 - 500 - Internal Server Error
@500-服务器内部错误,逻辑应该告诉你,由于“需要管理员”导致编译失败,因为与“需要管理员不支持”有关,这表明它们之间存在因果关系,个人认为。 :-) - Ken White
@KenWhite:是的 - 没有争议 :) - 500 - Internal Server Error
1
问题不在于我想使用ClickOnce和管理员权限,而在于我想使用管理员权限,并且之前已经编译了大约10次,但这次ClickOnce却说它不兼容。 - LMS
11
@KenWhite,问题并不像您所描述的那样清晰明了。这个问题发生在您点击“发布”按钮时(至少在我这里是这样)。我添加了清单并选择了“requireAdministrator”,之后程序运行得非常完美。只有当我点击“发布”时才开始出现这个错误,并且一直清除不了,除非我进入设置中禁用“ClickOnce”。因此解决方案不是“requireAdministrator”不被支持,而是不能启用“ClickOnce”,如果您已经设置了“requireAdministrator”,则无法单击“发布”。 - Gavin Coates
11个回答

167

编辑: 这条评论也提供了一个很好的答案。

每当您单击“发布”时,似乎都会启用Click once,无论您是否想要启用它! 如果您正在使用“requireAdministrator”,则似乎无法使用ClickOnce,因此无法“发布”您的项目。


原始内容:

事实证明,在“安全性”选项卡下,“启用ClickOnce安全性设置”被勾选了。 尽管我没有勾选它。 无论如何,取消该复选框后就可以停止ClickOnce给我带来的错误。 这花费了一些时间才找到……


3
啊,我认为从你收到的错误消息中这很明显 ;) - 500 - Internal Server Error
4
让我困惑的是我没有启用ClickOnce。 - LMS
33
似乎每次单击“发布”时,ClickOnce都会被启用,无论您是否希望如此!如果您正在使用“requireAdministrator”,则似乎无法使用ClickOnce,因此无法“发布”您的项目。 - Gavin Coates
1
@GavinCoates所说的是正确的。原因是ClickOnce应用程序始终安装在其“AppData”文件夹中,每个用户都有一个。权限提升将导致用户上下文的切换,在该上下文中,甚至未安装ClickOnce应用程序。 - bertl
请查看我在下方的评论(https://dev59.com/C2gu5IYBdhLWcg3w3ara#46456301)。这个“已接受”的响应是正确的,但关键是选择“部分信任...”。 - CodeBreaker
显示剩余7条评论

57

我知道这是一个旧问题,但我两年后来到这里:

您可以从项目属性的安全选项卡中禁用ClicKOnce以帮助解决问题;请参见下面的截图:

输入图像描述


11
当您发布应用程序时,此复选框将再次被选中。 - dikkini
@dikkini,没错!如何禁用它?有人知道答案吗? - saidfagan
@ saidfagan 对于这种情况没有答案或解决方案。我使用工具ULMerge来合并exe和dll文件。 - dikkini
这对我有效,无论我是否需要一直禁用复选框。 - Professor Zoom

22
如果您曾经使用过发布向导或“立即发布”,那么单击一次复选框将自动被选择...

20

我知道这可能有点老了,但我在寻找答案时偶然发现了它。在我的情况下,我正在使用发布功能,并且需要继续使用它。我还需要访问管理员权限。因此,出于这个原因,以上任何答案都对我无效。

最终,我在应用程序的开头添加了一个方法,检查它是否作为管理员运行,如果不是,则以管理员身份重新启动自己。要实现此目的,您需要添加以下引用。

using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;

那么,您需要将此放置在主方法方便访问的地方。我正在使用WPF,因此我将其添加到MainWindow.xaml.cs中,但您可以在代码的早期任何地方添加它。只需记住,如果需要,在这些方法中添加“static”关键字。

private void AdminRelauncher()
{
    if (!IsRunAsAdmin())
    {
        ProcessStartInfo proc = new ProcessStartInfo();
        proc.UseShellExecute = true;
        proc.WorkingDirectory = Environment.CurrentDirectory;
        proc.FileName = Assembly.GetEntryAssembly().CodeBase;

        proc.Verb = "runas";

        try
        {
            Process.Start(proc);
            Application.Current.Shutdown();
        }
        catch(Exception ex)
        {
            Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
        }
    }
}

private bool IsRunAsAdmin()
{
    try
    {
        WindowsIdentity id = WindowsIdentity.GetCurrent();
        WindowsPrincipal principal = new WindowsPrincipal(id);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
    catch (Exception)
    {
        return false;
    }
}

最后,在程序的开头添加对该方法的引用。在我的情况下,我将其添加到了 MainWindow 中,但在 Main 中添加也可以。

public MainWindow()
{
    InitializeComponent();
    AdminRelauncher(); //This is the only important line here, add it to a place it gets run early on.
}

希望这能帮到您!

对于.NET Core和.NET 5+

如果您在20年代遇到了这个问题,那么以下是如何更改使其与.NET Core和.NET 5+兼容。

唯一需要更改的功能是AdminRelauncher,它应该像这样改变。

private static void AdminRelauncher()
{
    if (!IsRunAsAdmin())
    {
        ProcessStartInfo proc = new ProcessStartInfo();
        proc.UseShellExecute = true;
        proc.WorkingDirectory = Environment.CurrentDirectory;
        proc.FileName = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe");

        proc.Verb = "runas";

        try
        {
            Process.Start(proc);
            Environment.Exit(0);
        }
        catch (Exception ex)
        {
            Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
        }
    }
}

唯一的重大变化就是,如有人指出应用程序并不总是可用。所以Environment.Exit(0)可以替换它,并且文件名需要将 .exe 替换为 .dll。这在 .NET 6 中已经过测试。


3
非常正确。由于我到那个时间点不需要调试器,所以我绕过了它,但我想你可以以管理员身份运行VS,然后程序也会以管理员模式启动,跳过重新启动。我将测试一下以确保。 - Tyler C
1
对于任何偶然发现这篇文章的人,上面提到的确实可行。 - Tyler C
当前上下文中不存在名称为'Application'的变量。错误 - vee
1
对于Winform项目,只需删除Application.Current.Shutdown();并使用return退出Main()即可正常工作。 - Ge Rong
1
对于新的 .net core winform 应用程序,您需要:proc.FileName = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe"); (因为 1. codebase 已过时,2. 程序集是 "xyz.dll" 而不是 "xyz.exe") - user2845090
显示剩余3条评论

6
这个操作可以通过选择“启用 ClickOnce 安全设置”(因为在发布期间无法取消选择),然后选择“这是部分信任应用程序”来实现。下拉菜单中将自动选择“本地 Intranet”,这是完全可以的。保存更改,发布应用程序,完成。 :-)Security Settings Snippet

6

对于那些未选中“启用ClickOnce安全设置”的人,无法工作,请尝试我找到的方法。

首先,将您的app.manifest文件中的requestedExecutionLevel项保留不变:

<requestedExecutionLevel level="asInvoker" uiAccess="false" />

然后你需要像这样编辑Program.cs文件:

using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
using System.Windows.Forms;

请将主方法重构为:

    static void Main()
        {
            var wi = WindowsIdentity.GetCurrent();
            var wp = new WindowsPrincipal(wi);

            bool runAsAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);

            if (!runAsAdmin)
            {
                // It is not possible to launch a ClickOnce app as administrator directly,
                // so instead we launch the app as administrator in a new process.
                var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase);

                // The following properties run the new process as administrator
                processInfo.UseShellExecute = true;
                processInfo.Verb = "runas";

                // Start the new process
                try
                {
                    Process.Start(processInfo);
                }
                catch (Exception)
                {
                    // The user did not allow the application to run as administrator
                    MessageBox.Show("Sorry, but I don't seem to be able to start " + 
                       "this program with administrator rights!");
                }

                // Shut down the current process
                Application.Exit();
            }
            else
            {
                // We are running as administrator
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }

它可以在Windows 10和Visual Studio 2019上运行!


2

我有同样的问题,通过取消勾选“启用ClickOnce安全设置”来解决。

在Visual Studio中找到此选项,请右键单击您的项目==>属性==>选择安全性==>启用ClickOnce安全设置(此选项已经被选中,因此我取消了它并解决了我的问题)。


2

以下是VB.NET的代码片段

If Not New WindowsPrincipal(WindowsIdentity.GetCurrent).IsInRole(WindowsBuiltInRole.Administrator) Then
            Process.Start(New ProcessStartInfo With { _
                                                     .UseShellExecute = True, _
                                                     .WorkingDirectory = Environment.CurrentDirectory, _
                                                     .FileName = Assembly.GetEntryAssembly.CodeBase, _
                                                     .Verb = "runas"})

编辑:但是如果您以这种方式部署,则一些杀毒软件将阻止您的代码。


1
对于那些遇到这种情况的人,我想贡献一下我的经验。是的,如果你取消勾选“启用 ClickOnce 安全性设置”选项,当你进行“生成 > 发布”操作时,它会自动重新勾选。
对我来说,我不需要“发布”——这是一个简单的、便携式的 .exe 文件,为我的用户创建计划任务,并且我需要确保它在作为管理员登录时也能提升权限。
所以我只需从“\bin\Release”中获取最新的 .exe 文件,并将其部署到客户端系统上。
效果和预期一样好——即使在启用 UAC 并将其设置为最高级别的系统上运行,.exe 文件也有“盾牌”标志,当我运行它时,即使以管理员身份登录,它也会提升权限并弹出 UAC 提示。
现在我的小任务调度程序可以创建任务而不会收到“访问被拒绝”的错误提示(之前只能通过右键单击 .exe 文件并选择“以管理员身份运行”来解决)。

1
我曾经遇到过完全相同的问题,但以上所有答案都没有起作用。我希望他们能重新设计 ClickOnce 安全设置。在大多数情况下,这是绝对必要且很好的功能,特别是对于在线发布的应用程序,但是我希望有更好的选项或解决方案,仅适用于本地发布。 - SkiSharp

0

打开你的 app.Manifest 文件,你会看到这个:

 <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />

注释里面有说明,但只需删除“requireAdministrator”并插入以下内容即可解决我的问题:

 <requestedExecutionLevel  level="asInvoker" uiAccess="false" />

3
OP说他们的应用程序需要访问注册表,所以这不是一个选择。 - LeeCambl
需要“requireAdministrator”权限才能写入注册表,因此这是一个要求。 - SkiSharp
ClickOnce 不支持请求执行级别 asInvoke - SkiSharp
有些DLL不允许您设置"asInvoke"。 - evry1falls

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接