如何使用.NET提升UAC COM组件

时间:2020-03-06 14:39:39  来源:igfitidea点击:

我找到了一篇有关如何通过调用来提升用C ++编写的COM对象的文章
CoCreateInstanceAsAdmin。但是我无法找到或者做的是一种将.NET(c#)应用程序的组件实现为COM对象,然后调用该对象执行需要UAC提升的任务的方法。 MSDN将其记录为管理COM对象模型。

我知道以管理员身份启动该应用程序(或者另一个应用程序)是可能且非常容易的,可以在一个单独的过程中执行任务(例如,参见Daniel Moth的帖子,但我正在寻找一种方法可以在同一未提升的.NET可执行文件中执行所有操作。当然,这样做会在一个新进程中生成COM对象,但是由于透明的编组,.NET COM对象的调用者不应该(很多)意识到这一点。

关于如何通过CoCreateInstanceAsAdminAPI从Cproject实例化用C#编写的COM对象的任何想法都将非常有帮助。因此,我对学习如何用C#编写COM对象非常感兴趣,然后可以通过C海拔高度的API从C中调用它。

不必介意提升的COM对象是否不在同一进程中运行。我只是不想启动整个提升的应用程序。我只想提高将执行代码的COM对象。如果我可以写一些东西:

// in a dedicated assembly, marked with the following attributes:
[assembly: ComVisible (true)]
[assembly: Guid ("....")]

public class ElevatedClass
{
    public void X() { /* do something */ }
}

然后通过CoCreateInstanceAsAdmin调用使我的主应用程序实例化ElevatedClass。但是也许我只是在做梦。

解决方案

高程的要素是过程。因此,如果我正确理解了问题,并且我们想要一种在处理过程中提升COM对象的方法,那么答案是我们不能做到。 CoCreateInstanceAsAdmin的重点是不要在过程中运行它。

查看Windows Vista UAC演示示例代码

(对于UnsafeNativeMethods.CoGetObject方法,我们还需要Vista Bridge示例)

这使Ccode可以显示几种不同的提升方式,包括COM对象

(不完整的代码示例获取上面的文件)

[return: MarshalAs(UnmanagedType.Interface)]
static internal object LaunchElevatedCOMObject(Guid Clsid, Guid InterfaceID)
   {
   string CLSID = Clsid.ToString("B"); // B formatting directive: returns {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} 
   string monikerName = "Elevation:Administrator!new:" + CLSID;

   NativeMethods.BIND_OPTS3 bo = new NativeMethods.BIND_OPTS3();
   bo.cbStruct = (uint)Marshal.SizeOf(bo);
   bo.hwnd = IntPtr.Zero;
   bo.dwClassContext = (int)NativeMethods.CLSCTX.CLSCTX_ALL;

   object retVal = UnsafeNativeMethods.CoGetObject(monikerName, ref bo, InterfaceID);

   return (retVal);
}

我认为CoCreateInstanceAsAdmin的唯一工作方式是如果我们提前注册了COM组件。如果我们希望应用程序在XCopy部署设置中工作,则可能会出现问题。

出于我自己在Gallio中的目的,我决定在清单上创建一个小的托管过程,以要求管理员特权。然后,当我需要执行提升操作时,我启动了托管过程的实例,并通过.Net远程处理指示它执行在Gallio的Inversion of Control容器中注册的特定命令。

这是一项相当不错的工作,但是Gallio已经拥有了一个进程外托管设备,因此在组合中增加高度并不是一件难事。此外,此机制确保Gallio可以执行特权提升,而无需在注册表中事先安装任何其他COM组件。