Как 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-компонентов в реестре.