我有一个使用 native 插件的应用程序。对于这些插件,我有自己的二进制格式。每个插件都在运行时使用类似于将 DLL 映射到进程空间的方法加载。这意味着,每个插件都有自己的 ImageBase,.text 或 .data 等部分的处理方式与传统 DLL 相同。唯一不同的是插件的二进制格式(它不是 PE 文件)和将插件映射到进程空间的加载程序代码。
现在我知道通过此命令行进行跟踪时的 ETW:
xperf -on latency -stackwalk profile -buffersize 1024 -minbuffers 300 -start tracea1 -on Microsoft-Windows-Win32k:::'stack'
将发出可用于在跟踪捕获期间重建流程环境的事件。也就是说,它会发出“添加进程”、“向进程添加线程”、“向进程添加DLL模块”等事件,以便像xperfview这样的工具可以构建状态的虚拟环境系统中的进程和构建信息,如当前进程树。例如,这些事件是 ImageLoad提供有关在跟踪之前或期间加载的每个 DLL 的信息的事件。
当然,对于我的插件,不会生成这些 ImageLoad 事件,因为它们在技术上不是 DLL(也就是说,不是由与 DLL 相同的函数加载的,尽管它们的功能是相同的) .这就是为什么像 xperfview 这样的工具不知道它们在进程空间中的存在。
我想做的是在我的插件加载器代码中编写我自己的 EventWrites,并发出这些带有必要信息的 ImageLoad 事件,以便 xperfview,和类似的工具,可以将我的插件解释为普通的 DLL。我会填写必要的信息,如 ImageBase、ProcessId、ImageSize 等。
为此,我知道我需要注册事件 MSNT_SystemTrace 提供程序,它是 ImageLoad 事件的所有者,使用这种结构构建事件:
<Data Name="ImageBase">0x7FEFDBD0000</Data>
<Data Name="ImageSize">0x12D000</Data>
<Data Name="ProcessId"> 548</Data>
...
<Data Name="Reserved0"> 0</Data>
<Data Name="DefaultBase">0x7FEFDBD0000</Data>
并发出事件。
问题是我在尝试注册另一个 MSNT_SystemTrace 时收到 ERROR_ACCESS_DENIED,这是合乎逻辑的,因为此提供程序已经存在。
但这迫使我问一个问题,我正在尝试做的事情甚至得到 ETW 的支持吗?
最佳答案
我想我找到了解决方案。
虽然我不知道如何通过现有提供程序实时发出事件,但 Windows 8 公开了一个允许修改 ETL 跟踪日志的接口(interface),因此可以更改 ProviderId事件为不同的值。有问题的接口(interface)是 ITraceRelogger。您需要这些指南:
EXTERN_GUID(CLSID_TraceRelogger, 0x7b40792d, 0x05ff, 0x44c4, 0x90, 0x58, 0xf4, 0x40, 0xc7, 0x1f, 0x17, 0xd4);
DEFINE_GUID(IID_ITraceRelogger, 0xF754AD43, 0x3BCC, 0x4286, 0x80, 0x09,0x9C, 0x5D, 0xA2, 0x14, 0xE8, 0x4E); // {F754AD43-3BCC-4286-8009-9C5DA214E84E}
DEFINE_GUID(IID_ITraceEventCallback, 0x3ED25501, 0x593F, 0x43E9, 0x8F, 0x38,0x3A, 0xB4, 0x6F, 0x5A, 0x4A, 0x52); // {3ED25501-593F-43E9-8F38-3AB46F5A4A52}
和来自 Windows 8 SDK 的 relogger.h 文件 (c:\Program Files (x86)\Windows Kits\8.0\Include\um\relogger.h)。原来的relogger.h 似乎不知何故被破坏了,因为它引用了一些外部符号,但似乎没有 LIB 文件来补充它。不过,我相信您会设法解决这个问题!
要使用它,只需通过以下方式创建一个实例:
ITraceRelogger *relog = NULL;
hres = CoCreateInstance(CLSID_TraceRelogger, 0, CLSCTX_INPROC_SERVER, IID_ITraceRelogger2, (LPVOID *)& relog);
添加input.etl 和output.etl 文件:
#include <windows.h>
#include <cguid.h>
#include <atlbase.h>
#include <comdef.h>
...
CComBSTR input = "input.etl";
CComBSTR output = "output.etl";
...
hres = relog->AddLogfileTraceStream(input, NULL, & trace);
...
hres = relog->SetOutputFilename(output);
然后,您需要注册一个回调,它将处理事件修改。事件回调的实现示例放在这个答案的末尾。下面是有关如何将其与当前 ITraceRelogger 一起使用的代码:
EventCallback *ec = new EventCallback();
hres = relog->RegisterCallback(ec);
...
hres = relog->ProcessTrace();
警告:如果您没有注册任何回调,ProcessTrace() 将返回一个错误。
这是一个工作回调的例子:
class EventCallback: public ITraceEventCallback {
private:
DWORD ref_count;
DWORD64 evno;
public:
EventCallback() {
ref_count = 0;
evno = 0;
}
STDMETHODIMP QueryInterface(const IID& iid, void **obj) {
if(iid == IID_IUnknown) {
*obj = dynamic_cast<IUnknown *>(this);
} else if(iid == IID_ITraceEventCallback) {
*obj = dynamic_cast<ITraceEventCallback *>(this);
} else {
*obj = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
STDMETHODIMP_ (ULONG) AddRef(void) {
return InterlockedIncrement(& ref_count);
}
STDMETHODIMP_ (ULONG) Release() {
ULONG ucount = InterlockedDecrement(& ref_count);
if(ucount == 0) {
delete this;
}
return ucount;
}
HRESULT STDMETHODCALLTYPE OnBeginProcessTrace(ITraceEvent *HeaderEvent, ITraceRelogger *Relogger) {
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnEvent(ITraceEvent *Event, ITraceRelogger *Relogger) {
// Your main method.
evno++;
Relogger->Inject(Event);
}
HRESULT STDMETHODCALLTYPE OnFinalizeProcessTrace(ITraceRelogger *Relogger) {
return S_OK;
}
};
Relogger->Inject 会将当前的 Event 复制到输出文件。您可以使用 MSDN for ITraceRelogger 检查可用的方法,这些方法将允许您更改所需的事件属性。我感兴趣的方法是 SetProviderId()。
此外,请记住 MSDN 声明,ITraceRelogger 在 Windows 7 中可用。这不是我所经历的——我无法在 Windows 7 中实例化此类,因此 MSDN 可能有错误有关此主题的信息。
关于windows - ETW:通过现有提供程序发出事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19535855/
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search