问题描述
尝试使用 IActiveScriptProfilerControl ::根据我的C#代码中的StartProfiling
,我创建了以下接口定义:
Trying to use IActiveScriptProfilerControl::StartProfiling
from my C# code, I've created this interface definition:
[ComImport]
[Guid(@"784b5ff0-69b0-47d1-a7dc-2518f4230e90")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IActiveScriptProfilerControl
{
void StartProfiling(
ref Guid clsidProfilerObject,
ProfilerEventMask eventMask,
uint dwContext);
// ...
}
我相信可以正确地将其翻译成.NET.
Which I believe is correctly translated to .NET.
原始的第一个参数定义为
The original first parameter is defined as
[in] REFCLSID clsidProfilerObject
具有以下定义:
typedef GUID CLSID;
typedef CLSID *REFCLSID;
我还能够创建Microsoft的 JQueryScriptEngine
对象的实例,并查询 IActiveScriptProfilerControl
.
I'm also able to create an instance of Microsofts JQueryScriptEngine
object and query for the IActiveScriptProfilerControl
.
我目前无法解决的是如何告诉 StartProfiling
函数使用我的 IActiveScriptProfilerCallback
派生对象.
What I'm currently failing at is how to tell the StartProfiling
function to use my IActiveScriptProfilerCallback
-derived object.
我的问题:
如何通过调用 IActiveScriptProfilerControl :: StartProfiling
将我自己的探查器回调类与活动脚本探查器控制接口连接起来?
How to connect my own profiler callback class with the active script profiler control interface through a call to IActiveScriptProfilerControl::StartProfiling
?
理想情况下,我很愿意在没有 的情况下执行此操作,而无需 RegAsm 我的课程.
Ideally, I would love to do this without the need to RegAsm my class.
更新1:
我已将接口定义的第一个参数更改为:
I've changed the first parameter of interface definition to:
[ComImport]
[Guid(@"784b5ff0-69b0-47d1-a7dc-2518f4230e90")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IActiveScriptProfilerControl
{
void StartProfiling(
IActiveScriptProfilerCallback clsidProfilerObject, // <-- changed.
ProfilerEventMask eventMask,
uint dwContext);
// ...
}
,并尝试通过传递我的 IActiveScriptProfilerCallback
派生类的实例来调用此函数.
and tried to call this function by passing an instance of my IActiveScriptProfilerCallback
-derived class.
仍然出现错误:
推荐答案
(从我未来的自我更新中寻找类似的错误时来到这里)
(Update from my future self that came here while searching for a similar error)
我已经通过监控注册表来解决了这个问题,在执行 Regasm.exe时调用我的程序集,以及在评估 StartProfiling
时监视事件探查器要求的键时.
I've managed to solve this by monitoring the registry, both when doing a Regasm.exe call on my assembly, as well as when monitoring what keys the profiler requests when valling StartProfiling
.
HKEY_CLASSES_ROOT
需要这些键:
[HKEY_CLASSES_ROOT \ ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback]@ ="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
[HKEY_CLASSES_ROOT\ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback] @="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
[HKEY_CLASSES_ROOT \ ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback \ CLSID]@ ="{1C406FBA-59EF-4FB2-938C-C1DA182D5914}"
[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}] @="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
[HKEY_CLASSES_ROOT \ CLSID {1C406FBA-59EF-4FB2-938C-C1DA182D5914} \ InprocServer32]@ ="mscoree.dll""ThreadingModel" =两者""Class" ="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback""Assembly" ="ZetaProducer.SuperSlimScriptingEngineProfiler,版本= 14.1.0.0,文化=中性,PublicKeyToken =空""RuntimeVersion" ="v4.0.30319""CodeBase" ="file:///C:/P/Zeta制作人/13/Zeta制作人Main/Bin/Applications/ZetaProducer.SuperSlimScriptingEngineProfiler.dll"
[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 \ 14.1.0.0]"Class" ="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback""Assembly" ="ZetaProducer.SuperSlimScriptingEngineProfiler,版本= 14.1.0.0,文化=中性,PublicKeyToken =空""RuntimeVersion" ="v4.0.30319""CodeBase" ="file:///C:/P/Zeta制作人/13/Zeta制作人Main/Bin/Applications/ZetaProducer.SuperSlimScriptingEngineProfiler.dll"
[HKEY_CLASSES_ROOT\CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}\InprocServer32\14.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}\ProgId] @="ZetaProducer.SuperSlimScriptingEngineProfiler.SlimScriptEngineProfilerCallback"
[HKEY_CLASSES_ROOT \ CLSID {1C406FBA-59EF-4FB2-938C-C1DA182D5914} \实现的类别{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]]
[HKEY_CLASSES_ROOT\CLSID{1C406FBA-59EF-4FB2-938C-C1DA182D5914}\Implemented Categories{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
另一个建议对于JScript也要添加:
Another suggestion for JScript is to also add:
由于我希望我的程序可以在没有管理特权的情况下运行,因此我创建了一个类来创建上述键,直到 HKEY_CURRENT_USER
,也可以使用.
Since I wanted my program to run without administrative privileges, I've create a class to create the above keys unter HKEY_CURRENT_USER
, wich also works.
以下是完整的类文件,仅供参考:
Following is the full class file for reference purposes:
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://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.
// 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中运行时,我的开发机器上再次出现初始错误:
I've once again got the initial error on my development machine when running directly from within Visual Studio 2017:
经过一番尝试和错误后,我发现这是由于以下事实,我将我的Visual Studio配置为始终以管理员.
After some try and error, I figured out that this was due to the fact, that I configured my Visual Studio to always run as an administrator.
从此上下文中开始时,似乎有点出问题了.我仍然不知道到底是什么.
When starting from within this context, somehow something seems to go wrong. I still don't know what exactly.
解决方案是直接从Windows File Explorer(而不是从Visual Studio中)直接启动我的可执行文件.
Solution for this was to simply start my executable directly from Windows File Explorer and not from within Visual Studio.
另一种可能的解决方案(我没有尝试过)应该是不要以管理员身份运行Visual Studio.
Another possible solution (which I didn't try) should be to not run Visual Studio as an administrator.
这篇关于作为第一个参数传递给IActiveScriptProfilerControl.StartProfiling的内容是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!