注册无管理员权限的COM [英] Registering a COM without Admin rights

查看:265
本文介绍了注册无管理员权限的COM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想把一个.net程序集注册为COM。



事实上,我知道的是,而不是 HKEY_CLASSES_ROOT 我想要在 HKEY_CURRENT_USER / Software / Classes 中写入条目,以便不需要UAC / Admin权限。



找到两个问题的解决方案,我都在努力:



1)程序化方式 ,具有以下代码:

  IntPtr键; 
var openKeyresult = RegOpenKeyEx(HKEY_CURRENT_USER,SOFTWARE\\Classes,0,(int)RegistrySecurity.KEY_WOW64_64KEY,out key);
var overrideKeyResult = RegOverridePredefKey(HKEY_CLASSES_ROOT,key);
var registerResult = Registrar.RegisterAssembly(GetAssembly(),AssemblyRegistrationFlags.SetCodeBase);

在这种方法中, overrideKeyResult 对应于ERROR_INVALID_HANDLE,因此, RegisterAssembly 抛出一个访问被拒绝异常,因为它试图写入 HKEY_CLASSES_ROOT



注意:每次我运行 RegOpenKeyEx 键值不同, p>

2)使用regasm



/ regfile 标志,然后在生成的 .reg 文件中替换 code> HKEY_CLASSES_ROOT 出现 HKEY_CURRENT_USER / Software / Classes



认为应该工作,但是当我无法卸载我的Outlook AddIn时,如何取消注册这样的程序集?



,因为我看不到以同样的方式因为:



var openKeyresult = RegOpenKeyEx(HKEY_CURRENT_USER,SOFTWARE\\Classes,0,(int)RegistrySecurity.KEY_WOW64_64KEY, out key);

解决方案

为了什么是值得的,我写了一组C#实用程序在用户注册表中注册/取消注册.NET类型(当然应该标记为ComVisible)而不要求regasm,也不要求UAC提示:

  public static class ComUtilities 
{
private const string ClsidRegistryKey = @Software\Classes \CLSID;

public static void RegisterComObjectInCurrentUser(Type type)
{
if(type == null)
throw new ArgumentNullException(type);

RegisterComObjectInCurrentUser(type,new Uri(type.Assembly.Location).ToString());
}

//此函数在HKEY_CURRENT_USER中注册一个.NET COM对象,以避免UAC提示
public static void RegisterComObjectInCurrentUser(type type,string assemblyPath)
{
if(type == null)
throw new ArgumentNullException(type);

(RegistryKey key = EnsureSubKey(Registry.CurrentUser,Path.Combine(Path.Combine(ClsidRegistryKey,type.GUID.ToString(B)),InprocServer32)))
{
key.SetValue(null,mscoree.dll);
key.SetValue(Assembly,type.Assembly.FullName);
key.SeValue(Class,type.FullName);
if(assemblyPath!= null)
{
key.SetValue(CodeBase,assemblyPath);
}
key.SetValue(RuntimeVersion,v4.0.30319);
key.SetValue(ThreadingModel,Both);
}

使用(RegistryKey key = EnsureSubKey(Registry.CurrentUser,Path.Combine(ClsidRegistryKey,type.GUID.ToString(B)))
{
// cf http://stackoverflow.com/questions/2070999/is-the-implemented-categories-key-needed-when-registering-a-managed-com-compon
using(RegistryKey cats = EnsureSubKey (key,@Implemented Categories \ {62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}))
{
//不做任何特殊处理
}

var att = GetAttribute< ProgIdAttribute>(type);
if(att!= null&&!string.IsNullOrEmpty(att.Value))
{
using(RegistryKey progid = EnsureSubKey(key,@ProgId))
{
progid.SetValue(null,att.Value);
}
}
}
}

public static void UnregisterComObject(Type type)
{
using(RegistryKey key =注册表.CurrentUser.OpenSubKey(ClsidRegistryKey,true))
{
if(key == null)
return;

key.DeleteSubKeyTree(type.GUID.ToString(B),false);
}
}

private static RegistryKey EnsureSubKey(RegistryKey root,string name)
{
RegistryKey key = root.OpenSubKey(name,true);
if(key!= null)
return key;

string parentName = Path.GetDirectoryName(name);
if(string.IsNullOrEmpty(parentName))
return root.CreateSubKey(name);

使用(RegistryKey parentKey = EnsureSubKey(root,parentName))
{
return parentKey.CreateSubKey(Path.GetFileName(name));
}
}

private static T GetAttribute< T>(ICustomAttributeProvider provider)其中T:属性
{
object [] o = provider.GetCustomAttributes (typeof(T),true);
if(o == null || o.Length == 0)
return null;

return(T)o [0];
}
}


I want to register a .net assembly as COM.

In fact what that means as far as I know is, that instead of HKEY_CLASSES_ROOT I want the entries to be written in HKEY_CURRENT_USER/Software/Classes, so that UAC/Admin rights are not needed.

Found two solutions of that problem, with both I'm struggling:

1) Programmatically way, with following code:

        IntPtr key;
        var openKeyresult = RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\Classes", 0, (int)RegistrySecurity.KEY_WOW64_64KEY, out key);
        var overrideKeyResult = RegOverridePredefKey(HKEY_CLASSES_ROOT, key);
        var registerResult = Registrar.RegisterAssembly(GetAssembly(), AssemblyRegistrationFlags.SetCodeBase);

in this approach, overrideKeyResult is 6 which corresponds to ERROR_INVALID_HANDLE, thus, the RegisterAssembly throw a "access denied" exception because it tries to write to HKEY_CLASSES_ROOT.

on a side note: each time I run the RegOpenKeyEx the key value is different, is that ok?

2) with regasm

by using regasm.exe with the /regfile flag, and then replacing in the generated .reg file all HKEY_CLASSES_ROOT occurences with HKEY_CURRENT_USER/Software/Classes

this I think should work, but how do I unregister such assembly when I wan't to uninstall my Outlook AddIn?

as I see I can't make it in the same way as register because:

var openKeyresult = RegOpenKeyEx(HKEY_CURRENT_USER, "SOFTWARE\\Classes", 0, (int)RegistrySecurity.KEY_WOW64_64KEY, out key);

解决方案

For what it's worth, I've written a set of C# utilities that register/unregister a .NET type (should be marked as ComVisible of course) in user's registry without requiring regasm, nor UAC prompts:

public static class ComUtilities
{
    private const string ClsidRegistryKey = @"Software\Classes\CLSID";

    public static void RegisterComObjectInCurrentUser(Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        RegisterComObjectInCurrentUser(type, new Uri(type.Assembly.Location).ToString());
    }

    // this functions registers a .NET COM object in HKEY_CURRENT_USER to avoid UAC prompts
    public static void RegisterComObjectInCurrentUser(Type type, string assemblyPath)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        using (RegistryKey key = EnsureSubKey(Registry.CurrentUser, Path.Combine(Path.Combine(ClsidRegistryKey, type.GUID.ToString("B")), "InprocServer32")))
        {
            key.SetValue(null, "mscoree.dll");
            key.SetValue("Assembly", type.Assembly.FullName);
            key.SetValue("Class", type.FullName);
            if (assemblyPath != null)
            {
                key.SetValue("CodeBase", assemblyPath);
            }
            key.SetValue("RuntimeVersion", "v4.0.30319");
            key.SetValue("ThreadingModel", "Both");
        }

        using (RegistryKey key = EnsureSubKey(Registry.CurrentUser, Path.Combine(ClsidRegistryKey, type.GUID.ToString("B"))))
        {
            // cf http://stackoverflow.com/questions/2070999/is-the-implemented-categories-key-needed-when-registering-a-managed-com-compon
            using (RegistryKey cats = EnsureSubKey(key, @"Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}"))
            {
                // do nothing special
            }

            var att = GetAttribute<ProgIdAttribute>(type);
            if (att != null && !string.IsNullOrEmpty(att.Value))
            {
                using (RegistryKey progid = EnsureSubKey(key, @"ProgId"))
                {
                    progid.SetValue(null, att.Value);
                }
            }
        }
    }

    public static void UnregisterComObject(Type type)
    {
        using (RegistryKey key = Registry.CurrentUser.OpenSubKey(ClsidRegistryKey, true))
        {
            if (key == null)
                return;

            key.DeleteSubKeyTree(type.GUID.ToString("B"), false);
        }
    }

    private static RegistryKey EnsureSubKey(RegistryKey root, string name)
    {
        RegistryKey key = root.OpenSubKey(name, true);
        if (key != null)
            return key;

        string parentName = Path.GetDirectoryName(name);
        if (string.IsNullOrEmpty(parentName))
            return root.CreateSubKey(name);

        using (RegistryKey parentKey = EnsureSubKey(root, parentName))
        {
            return parentKey.CreateSubKey(Path.GetFileName(name));
        }
    }

    private static T GetAttribute<T>(ICustomAttributeProvider provider) where T : Attribute
    {
        object[] o = provider.GetCustomAttributes(typeof(T), true);
        if (o == null || o.Length == 0)
            return null;

        return (T)o[0];
    }
}

这篇关于注册无管理员权限的COM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆