Как UAC поднять COM-компонент с помощью .NET

Я нашел статью о том, как поднять COM-объект, написанный на С++, путем вызова CoCreateInstanceAsAdmin. Но то, что я не смог найти или сделать, - это способ реализовать компонент моего приложения .NET(С#) в качестве COM-объекта, а затем вызвать этот объект для выполнения задач, требующих повышения UAC. MSDN документирует это как административную COM-модель объекта.

Я знаю, что можно и довольно просто запустить приложение (или другое приложение) в качестве администратора для выполнения задач в отдельном процессе (см., например, сообщение от Daniel Moth, но то, что я ищу, - это способ сделать все из одного и того же невыполненного исполняемого файла .NET. Это, конечно же, вызовет COM-объект в новый процесс, но благодаря прозрачной сортировке вызывающий объект .NET COM не должен (слишком много) знать об этом.

Любые идеи относительно того, как я могу создать объект COM, написанный на С#, из проекта С#, через API CoCreateInstanceAsAdmin, будут очень полезны. Поэтому мне действительно интересно узнать, как написать COM-объект в С#, который затем я могу вызвать из С# через API-интерфейсы COM-уровня.

Не обращайте внимания, если повышенный COM-объект не запускается в том же процессе. Я просто не хочу запускать все приложение повышенным; Я бы просто хотел, чтобы объект COM, который будет выполнять код, будет повышен. Если бы я мог написать что-то по строкам:

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

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

а затем мое основное приложение просто инициирует ElevatedClass через вызов CoCreateInstanceAsAdmin. Но, возможно, я просто мечтаю.

Ответ 1

Посмотрите Образец кода демо-версии Windows Vista UAC

(Вам также понадобится Vista Bridge для метода UnsafeNativeMethods.CoGetObject)

Что дает вам код С#, который показывает несколько различных способов повышения, включая объект 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);
}

Ответ 2

Элементы возвышения - это процессы. Итак, если я правильно понял ваш вопрос и вам нужен способ поднять COM-объект в ваш процесс, то ответ вы не можете. Весь смысл CoCreateInstanceAsAdmin - НЕ запускать его в вашем процессе.

Ответ 3

Я думаю, что единственный способ, которым работает CoCreateInstanceAsAdmin, - это то, что вы заранее зарегистрировали компонент COM. Это может быть проблемой, если вы планируете использовать приложение в настройке XCopy.

В моих собственных целях в Gallio я решил создать небольшой процесс хостинга на стороне с манифестом, требующим привилегий администратора. Затем, когда мне нужно выполнить повышенное действие, я разворачиваю экземпляр процесса хостинга и инструктирую его через .Net, чтобы выполнить определенную команду, зарегистрированную в контейнере Gallio Inversion of Control.

Это справедливая работа, но у Галлио уже был выход из процесса хостинга, поэтому добавление высоты в микс было не слишком сложным. Более того, этот механизм гарантирует, что Gallio сможет выполнять повышение привилегий, не требуя предварительной установки каких-либо других COM-компонентов в реестре.