将什么作为第一个参数传递给IActiveScriptProfilerControl.StartProfileling

本文关键字:IActiveScriptProfilerControl StartProfileling 参数传递 第一个 什么 | 更新日期: 2023-09-27 18:26:07

试图从C#代码中使用IActiveScriptProfilerControl::StartProfiling,我创建了这个接口定义:

[ComImport]
[Guid(@"784b5ff0-69b0-47d1-a7dc-2518f4230e90")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IActiveScriptProfilerControl
{
    void StartProfiling(
        ref Guid clsidProfilerObject, 
        ProfilerEventMask eventMask, 
        uint dwContext);
    // ...
}

我相信它被正确地翻译成了.NET.

最初的第一个参数定义为

[in] REFCLSID clsidProfilerObject

有了这些定义:

typedef GUID CLSID;
typedef CLSID *REFCLSID;

我还能够创建MicrosoftJQueryScriptEngine对象的实例并查询IActiveScriptProfilerControl

我目前失败的是如何告诉StartProfiling函数使用我的IActiveScriptProfilerCallback派生对象。

我的问题:

如何通过调用IActiveScriptProfilerControl::StartProfiling将我自己的探查器回调类与活动脚本探查器控制接口连接起来?

理想情况下,我很乐意这样做,而不需要注册我的类。

更新1:

我已经将接口定义的第一个参数更改为:

[ComImport]
[Guid(@"784b5ff0-69b0-47d1-a7dc-2518f4230e90")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IActiveScriptProfilerControl
{
    void StartProfiling(
        IActiveScriptProfilerCallback clsidProfilerObject, // <-- changed.
        ProfilerEventMask eventMask, 
        uint dwContext);
    // ...
}

并试图通过传递我的IActiveScriptProfilerCallback派生类的实例来调用此函数。

尽管如此,我还是得到了错误:

类未注册(HRESULT中的异常:0x80040154(REGDB_E_CLASSNOTREG))

将什么作为第一个参数传递给IActiveScriptProfilerControl.StartProfileling

(在搜索类似错误时从我未来的自己更新)

我已经通过监视注册表解决了这个问题,无论是在对程序集执行Regasm.exe调用时,还是在对StartProfiling赋值时监视探查器请求的键时。

HKEY_CLASSES_ROOT:需要这些密钥

REGEDIT4

[HKEY_CLASSES_ROOT''ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback]@="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"

[HKEY_CLASES_ROOT''ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerAllback''CLSID]@="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"

[HKEY_CLASSES''ROOT''CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}]@="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"

[HKEY_CLASES_ROOT''CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}''InprocServer32]@="mscoree.dll"ThreadingModel"="两者"Class"="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerAllback"Assembly"="ZetaProducer.SuperSlimScriptingEngineProfiler,Version=14.1.0.0,Culture=neutral,PublicKeyToken=null"RuntimeVersion"="v4.0.30119"CodeBase"="file:///C:/P/Zeta制片人/13/Zeta制片人Main/Bin/Applications/ZetaProducer.SuperSlimScriptingEngineProfiler.dll"

[HKEYCLASSES_ROOT''CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}''InprocServer32''14.1.0.0]"Class"="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerAllback"Assembly"="ZetaProducer.SuperSlimScriptingEngineProfiler,Version=14.1.0.0,Culture=neutral,PublicKeyToken=null"RuntimeVersion"="v4.0.30119"CodeBase"="file:///C:/P/Zeta制片人/13/Zeta制片人Main/Bin/Applications/ZetaProducer.SuperSlimScriptingEngineProfiler.dll"

[HKEYCLASSES_ROOT''CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}''ProgId]@="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"

[HKEYCLASSES_ROOT''CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}''已实现类别{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]

JScript的另一个建议是还添加:

[HKEYCURRENT_USER''Environment]
"JS_PROFILER"="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"

由于我希望我的程序在没有管理权限的情况下运行,所以我创建了一个类来创建上面的密钥unter HKEY_CURRENT_USER,它也可以工作。

以下是供参考的完整类文件:

namespace ZetaProducer.SuperSlimScriptingEngineProfiler.Helper
{
    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Security.AccessControl;
    using System.Security.Principal;
    using Zeta.VoyagerLibrary.Common.IO;
    public static class ProfilerComRegistration
    {
        public const string ClsidString = @"1C406FBA-59EF-4FB2-938C-C1DA182D5914";
        public static readonly Guid Clsid = new Guid(ClsidString);
        /*
        REGEDIT4
        [HKEY_CLASSES_ROOT'ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback]
        @="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
        [HKEY_CLASSES_ROOT'ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback'CLSID]
        @="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"
        [HKEY_CLASSES_ROOT'CLSID'{1C406FBA-59EF-4FB2-938C-C1DA182D5914}]
        @="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
        [HKEY_CLASSES_ROOT'CLSID'{1C406FBA-59EF-4FB2-938C-C1DA182D5914}'InprocServer32]
        @="mscoree.dll"
        "ThreadingModel"="Both"
        "Class"="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
        "Assembly"="ZetaProducer.SuperSlimScriptingEngineProfiler, Version=15.0.0.0, Culture=neutral, PublicKeyToken=null"
        "RuntimeVersion"="v4.0.30319"
        "CodeBase"="file:///C:/P/Zeta Producer/13/Zeta Producer Main/Bin/Applications/ZetaProducer.SuperSlimScriptingEngineProfiler.dll"
        [HKEY_CLASSES_ROOT'CLSID'{1C406FBA-59EF-4FB2-938C-C1DA182D5914}'InprocServer32'15.0.0.0]
        "Class"="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
        "Assembly"="ZetaProducer.SuperSlimScriptingEngineProfiler, Version=15.0.0.0, Culture=neutral, PublicKeyToken=null"
        "RuntimeVersion"="v4.0.30319"
        "CodeBase"="file:///C:/P/Zeta Producer/13/Zeta Producer Main/Bin/Applications/ZetaProducer.SuperSlimScriptingEngineProfiler.dll"
        [HKEY_CLASSES_ROOT'CLSID'{1C406FBA-59EF-4FB2-938C-C1DA182D5914}'ProgId]
        @="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
        [HKEY_CLASSES_ROOT'CLSID'{1C406FBA-59EF-4FB2-938C-C1DA182D5914}'Implemented Categories'{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
        */
        /*
        Siehe http://www.hexacorn.com/blog/2014/04/27/beyond-good-ol-run-key-part-11/:
        [HKEY_CURRENT_USER'Environment]
        "JS_PROFILER"="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"
         */
        public static void Register()
        {
            // Achtung vor dem Wow6432Node-Schlüssel.
            // https://stackoverflow.com/questions/2039186/reading-the-registry-and-wow6432node-key
            var views = new[]
            {
                RegistryView.Registry32,
                RegistryView.Registry64
            };
            foreach (var registryView in views)
            {
                var key = checkCreateKey(
                    registryView,
                    @"Software'Classes'ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback");
                if (key != null)
                {
                    key.SetValue(null,
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback",
                        RegistryValueKind.String);
                    key.Close();
                }
                key = checkCreateKey(
                    registryView,
                    @"Software'Classes'ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback'CLSID");
                if (key != null)
                {
                    key.SetValue(null, $@"{{{ClsidString}}}", RegistryValueKind.String);
                    key.Close();
                }
                key = checkCreateKey(
                    registryView,
                    $@"Software'Classes'CLSID'{{{ClsidString}}}");
                if (key != null)
                {
                    key.SetValue(null,
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback",
                        RegistryValueKind.String);
                    key.Close();
                }
                key = checkCreateKey(
                    registryView,
                    $@"Software'Classes'CLSID'{{{ClsidString}}}'InprocServer32");
                if (key != null)
                {
                    key.SetValue(null, @"mscoree.dll", RegistryValueKind.String);
                    key.SetValue(@"ThreadingModel", @"Both", RegistryValueKind.String);
                    key.SetValue(@"Class",
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback",
                        RegistryValueKind.String);
                    key.SetValue(@"Assembly",
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler, Version=15.0.0.0, Culture=neutral, PublicKeyToken=null",
                        RegistryValueKind.String);
                    key.SetValue(@"RuntimeVersion", @"v4.0.30319", RegistryValueKind.String);
                    key.SetValue(@"CodeBase", getFileUrl(), RegistryValueKind.String);
                    key.Close();
                }
                key = checkCreateKey(
                    registryView,
                    $@"Software'Classes'CLSID'{{{ClsidString}}}'InprocServer32'15.0.0.0");
                if (key != null)
                {
                    key.SetValue(@"Class",
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback",
                        RegistryValueKind.String);
                    key.SetValue(@"Assembly",
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler, Version=15.0.0.0, Culture=neutral, PublicKeyToken=null",
                        RegistryValueKind.String);
                    key.SetValue(@"RuntimeVersion", @"v4.0.30319", RegistryValueKind.String);
                    key.SetValue(@"CodeBase", getFileUrl(), RegistryValueKind.String);
                    key.Close();
                }
                key = checkCreateKey(
                    registryView,
                    $@"Software'Classes'CLSID'{{{ClsidString}}}'ProgId");
                if (key != null)
                {
                    key.SetValue(null,
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback",
                        RegistryValueKind.String);
                    key.Close();
                }
                // Aus der Dokumentation https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/scripting-articles/cc843609(v=vs.94):
                //
                // The JavaScript language runtime checks the JS_PROFILER environment variable on creation
                // to determine whether profiling should be enabled. If this variable is set to the CLSID
                // of the profiler, the language runtime creates an instance of the profiler COM object,
                // using the value of the variable to determine which profiler to create.
                // Ein Beispiel habe ich hier gefunden:
                // http://www.hexacorn.com/blog/2014/04/27/beyond-good-ol-run-key-part-11/
                key = checkCreateKey(registryView, @"Environment");
                if (key != null)
                {
                    key.SetValue(@"JS_PROFILER", $@"{{{ClsidString}}}", RegistryValueKind.String);
                    key.Close();
                }
            }
        }
        private static string getFileUrl()
        {
            // ReSharper disable once AssignNullToNotNullAttribute
            var filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
                @"ZetaProducer.SuperSlimScriptingEngineProfiler.dll");
            return PathHelper.ConvertFilePathToFileUrl(filePath);
        }
        public static void Unregister()
        {
            // Achtung vor dem Wow6432Node-Schlüssel.
            // https://stackoverflow.com/questions/2039186/reading-the-registry-and-wow6432node-key
            var views = new[]
            {
                RegistryView.Registry32,
                RegistryView.Registry64
            };
            foreach (var registryView in views)
            {
                var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, registryView);
                var key = baseKey.OpenSubKey(@"Software'Classes", true);
                if (key != null &&
                    new List<string>(key.GetSubKeyNames()).Contains(
                        @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"))
                {
                    try
                    {
                        key.DeleteSubKeyTree(
                            @"ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback", false);
                    }
                    catch (AccessViolationException)
                    {
                    }
                    key.Close();
                }
                key = baseKey.OpenSubKey(@"Software'Classes'CLSID", true);
                if (key != null &&
                    new List<string>(key.GetSubKeyNames()).Contains($@"{{{ClsidString}}}"))
                {
                    try
                    {
                        key.DeleteSubKeyTree($@"{{{ClsidString}}}", false);
                    }
                    catch (AccessViolationException)
                    {
                    }
                    key.Close();
                }
                key = baseKey.OpenSubKey(@"Environment", true);
                if (key != null)
                {
                    key.DeleteValue(@"JS_PROFILER", false);
                    key.Close();
                }
            }
        }
        private static RegistryKey checkCreateKey(RegistryView registryView, string keyPath)
        {
            // Achtung vor dem Wow6432Node-Schlüssel.
            // https://stackoverflow.com/questions/2039186/reading-the-registry-and-wow6432node-key
            var rs = new RegistrySecurity();
            // Jeder.
            var user = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
            rs.AddAccessRule(
                new RegistryAccessRule(
                    user,
                    RegistryRights.FullControl,
                    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                    PropagationFlags.None,
                    AccessControlType.Allow));
            var key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, registryView)
                .CreateSubKey(
                    keyPath,
                    RegistryKeyPermissionCheck.ReadWriteSubTree,
                    rs);
            return key;
        }
    }
}

2018年7月更新

当我直接从Visual Studio 2017中运行时,我的开发机器上再次出现初始错误:

类未注册(HRESULT中的异常:0x80040154(REGDB_E_CLASSNOTREG))

经过一番尝试和错误,我发现这是由于我将Visual Studio配置为始终以管理员身份运行。

当从这种背景下开始时,不知何故,似乎出了问题。我仍然不知道具体是什么。

解决方案是直接从Windows文件资源管理器启动我的可执行文件,而不是从Visual Studio中启动。

另一个可能的解决方案(我没有尝试)应该是不以管理员身份运行Visual Studio。

相关文章:
  • 没有找到相关文章