将什么作为第一个参数传递给 IActiveScriptProfilerControl.StartProfiling?
What to pass as the first parameter to IActiveScriptProfilerControl.StartProfiling?
尝试在我的 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;
我还能够创建 Microsoft JQueryScriptEngine
对象的实例并查询 IActiveScriptProfilerControl
。
我目前失败的是如何告诉 StartProfiling
函数使用我的 IActiveScriptProfilerCallback
派生对象。
我的问题:
如何通过调用 IActiveScriptProfilerControl::StartProfiling
将我自己的分析器回调 class 连接到活动脚本分析器控制界面?
理想情况下,我很乐意这样做 而无需 RegAsm 我的 class.
更新 1:
我已经将接口定义的第一个参数更改为:
[ComImport]
[Guid(@"784b5ff0-69b0-47d1-a7dc-2518f4230e90")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IActiveScriptProfilerControl
{
void StartProfiling(
IActiveScriptProfilerCallback clsidProfilerObject, // <-- changed.
ProfilerEventMask eventMask,
uint dwContext);
// ...
}
并尝试通过传递我的 IActiveScriptProfilerCallback
派生的 class.
的实例来调用此函数
仍然,我得到错误:
Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
(搜索类似错误时来到这里的未来自我的更新)
我已经设法通过 monitoring the registry, both when doing a Regasm.exe 调用我的程序集来解决这个问题,以及在监控 StartProfiling
.
时分析器请求的键时
HKEY_CLASSES_ROOT
需要这些密钥:
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=14.1.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.1.0.0]
"Class"="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
"Assembly"="ZetaProducer.SuperSlimScriptingEngineProfiler,
Version=14.1.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}]
Another suggestion 对于 JScript 也是添加:
[HKEY_CURRENT_USER\Environment]
"JS_PROFILER"="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"
因为我希望我的程序 运行 没有管理权限,所以我创建了一个 class 来在 HKEY_CURRENT_USER
下创建上述键,这也有效。
以下是完整的 class 文件以供参考:
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.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.
//
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.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://docs.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.
//
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.
//
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 中 运行ning 时,我的开发机器上再次出现初始错误:
Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
经过反复尝试,我发现这是因为我 configured my Visual Studio to always run as an administrator.
当从这个上下文开始时,不知何故似乎出了问题。我还是不知道具体是什么。
解决方案是直接从 Windows 文件资源管理器而不是从 Visual Studio.
中直接启动我的可执行文件
另一种可能的解决方案(我没有尝试过)应该是不 运行 Visual Studio 作为管理员。
尝试在我的 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;
我还能够创建 Microsoft JQueryScriptEngine
对象的实例并查询 IActiveScriptProfilerControl
。
我目前失败的是如何告诉 StartProfiling
函数使用我的 IActiveScriptProfilerCallback
派生对象。
我的问题:
如何通过调用 IActiveScriptProfilerControl::StartProfiling
将我自己的分析器回调 class 连接到活动脚本分析器控制界面?
理想情况下,我很乐意这样做 而无需 RegAsm 我的 class.
更新 1:
我已经将接口定义的第一个参数更改为:
[ComImport]
[Guid(@"784b5ff0-69b0-47d1-a7dc-2518f4230e90")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IActiveScriptProfilerControl
{
void StartProfiling(
IActiveScriptProfilerCallback clsidProfilerObject, // <-- changed.
ProfilerEventMask eventMask,
uint dwContext);
// ...
}
并尝试通过传递我的 IActiveScriptProfilerCallback
派生的 class.
仍然,我得到错误:
Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
(搜索类似错误时来到这里的未来自我的更新)
我已经设法通过 monitoring the registry, both when doing a Regasm.exe 调用我的程序集来解决这个问题,以及在监控 StartProfiling
.
HKEY_CLASSES_ROOT
需要这些密钥:
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=14.1.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.1.0.0] "Class"="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback" "Assembly"="ZetaProducer.SuperSlimScriptingEngineProfiler, Version=14.1.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}]
Another suggestion 对于 JScript 也是添加:
[HKEY_CURRENT_USER\Environment]
"JS_PROFILER"="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"
因为我希望我的程序 运行 没有管理权限,所以我创建了一个 class 来在 HKEY_CURRENT_USER
下创建上述键,这也有效。
以下是完整的 class 文件以供参考:
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.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.
//
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.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://docs.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.
//
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.
//
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 中 运行ning 时,我的开发机器上再次出现初始错误:
Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
经过反复尝试,我发现这是因为我 configured my Visual Studio to always run as an administrator.
当从这个上下文开始时,不知何故似乎出了问题。我还是不知道具体是什么。
解决方案是直接从 Windows 文件资源管理器而不是从 Visual Studio.
中直接启动我的可执行文件另一种可能的解决方案(我没有尝试过)应该是不 运行 Visual Studio 作为管理员。