且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在c#中以编程方式注册COM DLL,无需管理员优先权....

更新时间:2023-01-15 09:29:10

你可以尝试运行regsvr32,但我怀疑你会发现你会遇到同样的问题。鉴于非管理员通常仅限于访问注册表,我怀疑您会发现您需要您的用户以管理员身份登录才能安装您的程序,因为您使用了COM。没有理由为你的C#dll使用COM,除非你需要它们与其他语言一起使用。
You could try to run regsvr32, but I suspect you'll find you'll have the same issue. Given that a non admin is often limited in access to the registry, I suspect you will find you need your user to log in as admin to install your program because you used COM. There is no reason to use COM for your C# dlls, unless you need them to work with other languages.


由用户SYSTEM启动的服务
可以执行这样的操作其非SYSTEM客户的任务...:)
A service started by user SYSTEM
could perform such tasks for its "non SYSTEM" clients... :)


我的简单解决方案有一些限制。不要调用 [ComRegisterFunction] 标记的方法。也适用于任何CPU组件。

My simple solution works with some restrictions. Do not calls methods marked by [ComRegisterFunction]. Also works only for "Any CPU" assemlies.
Assembly assembly = Assembly.LoadFile("drive:\\my.dll");
Type[] Types = assembly.GetExportedTypes();

foreach (Type type in Types)
{
    ComVisibleAttribute[] attributes = (ComVisibleAttribute[])type.GetCustomAttributes(typeof(ComVisibleAttribute), false);

    if (attributes.Length > 0 && attributes[0].Value)
    {
        Register(type);
    }

}




static void Register(Type type)
{
    string ProgID = type.FullName;
    string Version = type.Assembly.GetName().Version.ToString();
    string GUIDstr = "{" + type.GUID.ToString() + "}";
    string keyPath = @"Software\Classes\";


    RegistryKey regularx86View = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry32);

    RegistryKey regularx64View = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
 
    RegistryKey[] keys = {regularx86View.OpenSubKey(keyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl),
                    regularx64View.OpenSubKey(keyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl)};

            
    ProgIdAttribute[] attributes = (ProgIdAttribute[])type.GetCustomAttributes(typeof(ProgIdAttribute), false);

    if (attributes.Length > 0)
        ProgID = attributes[0].Value;

    foreach(RegistryKey RootKey in keys)
    {
        //[HKEY_CURRENT_USER\Software\Classes\Prog.ID]
        //@="Namespace.Class"
                
        RegistryKey keyProgID = RootKey.CreateSubKey(ProgID);
        keyProgID.SetValue(null, type.FullName);

        //[HKEY_CURRENT_USER\Software\Classes\Prog.ID\CLSID]
        //@="{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
        keyProgID.CreateSubKey(@"CLSID").SetValue(null, GUIDstr);


        //[HKEY_CURRENT_USER\Software\Classes\CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}]
        //@="Namespace.Class
        //
        RegistryKey keyCLSID = RootKey.OpenSubKey(@"CLSID", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl).CreateSubKey(GUIDstr);
        keyCLSID.SetValue(null, type.FullName);


        //[HKEY_CURRENT_USER\Software\Classes\CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\ProgId]
        //@="Prog.ID"
        keyCLSID.CreateSubKey("ProgId").SetValue(null, ProgID);


        //[HKEY_CURRENT_USER\Software\Classes\CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\InprocServer32]
        //@="mscoree.dll"
        //"ThreadingModel"="Both"
        //"Class"="Namespace.Class"
        //"Assembly"="AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=71c72075855a359a"
        //"RuntimeVersion"="v4.0.30319"
        //"CodeBase"="file:///Drive:/Full/Image/Path/file.dll"
        RegistryKey InprocServer32 = keyCLSID.CreateSubKey("InprocServer32");
        SetInprocServer(InprocServer32, type, false);

        //[HKEY_CURRENT_USER\Software\Classes\CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\InprocServer32\1.0.0.0]
        //"Class"="Namespace.Class"
        //"Assembly"="AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=71c72075855a359a"
        //"RuntimeVersion"="v4.0.30319"
        //"CodeBase"="file:///Drive:/Full/Image/Path/file.dll"
        SetInprocServer(InprocServer32.CreateSubKey("Version"), type, true);

        //[HKEY_CURRENT_USER\Software\Classes\CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
        keyCLSID.CreateSubKey(@"Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}");

        keyCLSID.Close();
    }

}




static void SetInprocServer(RegistryKey key, Type type, bool versionNode)
{

    if (!versionNode)
    {
        key.SetValue(null, "mscoree.dll");
        key.SetValue("ThreadingModel", "Both");
    }

    key.SetValue("Class", type.FullName);
    key.SetValue("Assembly", type.Assembly.FullName);
    key.SetValue("RuntimeVersion", type.Assembly.ImageRuntimeVersion);
    key.SetValue("CodeBase", type.Assembly.CodeBase);
}