更新(23/02/13):フックを個別にテストしました。動作します。printf
問題は、コンソールを.dllに関連付けない限り、.dllで使用できないことでした。
代わりに、すべてをに置き換えてprintf
、fprintf
出力をログファイルに書き込みました。
更新(22/02/13):変数clazz
を正しい方法で初期化しました。
デスクトップウィンドウが。の場合、Javaアプリケーションでメソッドを呼び出したいcreated/activated/destroyed
。
2つのネイティブ関数を使用して単純なJavaクラスを作成しました。
public class Hook {
public Hook(){}
public void setstatus(){
System.out.println("status set");
}
public native void starthook();
public native void stophook();
}
そしてCIで次のように書いています:
#include "Hook.h"
#include <windows.h>
#include <jni.h>
#include <stdio.h>
#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
FILE *pFile=NULL;
//do mid, clazz and jvm have to be shared ?
//jmethodID mid=NULL;
//jclass clazz=NULL;
//static JavaVM *jvm = NULL;
#pragma data_seg()
HINSTANCE g_hInstance = NULL;
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){
switch (ul_reason_for_call){
case DLL_PROCESS_ATTACH:
g_hInstance = (HINSTANCE) hModule;
break;
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break;
case DLL_PROCESS_DETACH: break;
}
return TRUE;
}
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam){
if (nCode < 0)
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
/*
JNIEnv *env;
int res =(*jvm)->AttachCurrentThread(jvm,(void **)&env, NULL);
if(res<0){
fprintf(pFile,"AttachCurrentThread failed\n");
return 0;
}
*/
HWND hWnd = (HWND)wParam;
if (!hWnd){
fprintf(pFile,"hWnd==NULL\n");
//(*jvm)->DetachCurrentThread(jvm);
return 0;
}
if (nCode == HCBT_ACTIVATE){
// is printed
fprintf(pFile,"activated\n");
// isn't called
//(*env)->CallVoidMethod(env, clazz, mid);
// Nothing is logged
//if((*env)->ExceptionOccurred(env))
// (*env)->ExceptionDescribe(env);
}
else if (nCode == HCBT_DESTROYWND){
fprintf(pFile,"destroyed\n");
}
else if (nCode == HCBT_CREATEWND){
fprintf(pFile,"created\n");
}
//(*jvm)->DetachCurrentThread(jvm);
return 0;
}
JNIEXPORT void JNICALL Java_Hook_starthook(JNIEnv *e, jobject o){
/*
if(jvm==NULL)
if(((*e)->GetJavaVM(e,&jvm))<0){
printf("GetJavaVM failed\n");
return;
}
jclass localRef = (*e)->GetObjectClass(e, o);
clazz = (*e)->NewGlobalRef(e,localRef);
if(clazz==NULL){
printf("GetObjectClass failed\n");
return;
}
mid = (*e)->GetMethodID(e, clazz, "setstatus", "()V");
if(mid==0){
printf("GetMethodID failed\n");
return;
}
*/
pFile = fopen("C:/workspace/CBTHook/log.txt","a");
g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) CBTProc, g_hInstance, 0);
printf("Hook started\n");
}
JNIEXPORT void JNICALL Java_Hook_stophook(JNIEnv *e, jobject o){
if (g_hHook){
UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
//(*e)->DeleteGlobalRef(e,clazz);
}
if(pFile)
fclose(pFile);
}
printf("Hook stopped\n");
}
動作しますが、関数内から関数をCBTHook
呼び出すことができません。setstatus
callback
(*env)->CallVoidMethod(env, clazz, mid);
何もせず、例外はスローされません。
私は何をしなければなりませんか?
さらに、グローバル変数を共有する必要があります:mid
、、?のすべての変数clazz
jvm
#pragma data_seg("SHARED")
セグメントは「共有」されます。これは、特定のプロセスに固有ではないことを意味します。
そして、これが必要な場合、他のスレッドをアタッチ/デタッチする正しい方法は何でしょうか?