Update So there is some lock put if there is an export in the go file which is causing the problem.
To fix I was inspired by this guy https://gist.github.com/NaniteFactory/7a82b68e822b7d2de44037d6e7511734#file-dllmain-go dllmain.go: ``` package main /* #include "dllmain.h" */ import "C" ``` dllmain.h: ``` #include <windows.h> // Declare the function defined in Go that you want to call on DLL load extern void RunMe(); BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // Call the Go function when the DLL is loaded RunMe(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } ``` main.go: ``` package main import "C" import ( "syscall" "golang.org/x/sys/windows" ) //export RunMe func RunMe() { windows.MessageBox(windows.HWND(0), syscall.StringToUTF16Ptr("RunMe"), syscall.StringToUTF16Ptr("RunMe"), windows.MB_OK) } func main() { } ``` Compile: ``` GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build -a -o ~/Desktop/dropamd64.dll -buildmode=c-shared ``` I get a dll but: *rundll32.exe Z:\dropamd64.dll -----> Nothing happens* *rundll32.exe Z:\dropamd64.dll,RunMe ------> Nothing happens* *msiexec.exe /y * *Z:\dropamd64.dll ------->Nothin happens* Le dimanche 10 novembre 2024 à 21:09:36 UTC+1, rudeus greyrat a écrit : > Thanks for your response. It seems logic to do what you say (aka lets make > DllMain in C if Go does not let us control it) > > So I did a main.c: > ``` > #include <windows.h> > > extern void RunMe(); > > BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID > lpReserved) { > switch (ul_reason_for_call) { > case DLL_PROCESS_ATTACH: > RunMe(); > break; > case DLL_THREAD_ATTACH: > case DLL_THREAD_DETACH: > case DLL_PROCESS_DETACH: > break; > } > return TRUE; > } > ``` > > Then a main.go that use main.c > ``` > package main > > //#include "main.c" > > import "C" > import ( > "syscall" > > "golang.org/x/sys/windows" > ) > > //export RunMe > func RunMe() { > windows.MessageBox(windows.HWND(0), syscall.StringToUTF16Ptr("RunMe"), > syscall.StringToUTF16Ptr("RunMe"), windows.MB_OK) > } > > func main() {} > ``` > > Then I compile by cd into the directory containing the main.go and main.c > and running: > ``` > GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go build > -a -o ~/Desktop/dropamd64.dll -buildmode=c-shared > ``` > > However I get an error from x86_64-w64-mingw32-gcc that DllMain is defined > multiple time. I am not sure the issue is from DllMain though, because If I > change DllMain to TestRudeus I get also the error TestRudeus is defined > multiple time... > > Le dimanche 10 novembre 2024 à 17:15:52 UTC+1, Jason E. Aten a écrit : > >> I'll add that the one way I've found to address the "Go runtime cannot >> shut itself down" problem >> is to compile to wasm. WebAssembly hosts >> like the browser -- and running the wasm on a background web worker -- >> provide very nice ways of killing >> a web worker thread. I believe (but have not tried it), that wasm >> runtimes like wazero >> and wasmtime also provide means to pause and kill threads. >> https://github.com/tetratelabs/wazero/issues/421 may be relevant. >> >> Runtimes like wazero compile the wasm to native code. These >> days they can, very impressively, execute at native or near native speed. >> Moreover, if you use tinygo (llvm under the covers) you can actually >> get wasm code to go faster (sometimes _much_ faster) than the native go >> compiler, even though you are going through a wasm layer. >> >> Since it would be vastly more portable than writing a DLL, you might >> explore the wasm approach if the wasm runtimes provide for what you >> are trying to do on Windows (which they well may not, but its worth >> exploring). >> >> On Sunday, November 10, 2024 at 3:14:52 PM UTC Jason E. Aten wrote: >> >>> Use CGO in your .go file, and then there, or in an adjacent C file, >>> actually do write a DllMain function; >>> https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain >>> >>> When fdwReason == DLL_PROCESS_ATTACH, then you know this is the first >>> load of the DLL >>> into this process. I think your subject line acknowledges that you known >>> this. >>> >>> Note that the APIENTRY annotation on the DllMain is required, in order >>> to get the >>> right calling convention. >>> >>> Be aware that the go runtime has a major problem when used inside a DLL: >>> it >>> provides no way to shut itself down. This means that you can never unload >>> a DLL that you have loaded, even though Windows processes routinely do >>> unload DLLs. >>> >>> On XP or later you can use GetModuleHandleEx with the >>> GET_MODULE_HANDLE_EX_FLAG_PIN flag to prevent unloading of the DLL. >>> This means that your process won't crash on unload, but also that the >>> DLL will not actually be unloaded. In order to update the DLL, you must >>> kill the >>> process. >>> >>> On Sunday, November 10, 2024 at 1:54:16 PM UTC rudeus greyrat wrote: >>> >>>> I am trying to write DLL in go. I want it to execute some stuff when >>>> the DLL is attached to a process. >>>> >>>> I thought init() will be the equivalent of onattach but It seems I am >>>> wrong. >>>> >>>> I created this as a proof of concept: >>>> ``` >>>> package main >>>> >>>> import "C" >>>> import ( >>>> "syscall" >>>> >>>> "golang.org/x/sys/windows" >>>> ) >>>> >>>> //export RunMe >>>> func RunMe() { >>>> >>>> windows.MessageBox(windows.HWND(0), >>>> syscall.StringToUTF16Ptr("RunMe"), syscall.StringToUTF16Ptr("RunMe"), >>>> windows.MB_OK) >>>> } >>>> >>>> func init() { >>>> windows.MessageBox(windows.HWND(0), syscall.StringToUTF16Ptr("DLL >>>> Loaded"), syscall.StringToUTF16Ptr("DLL Load"), windows.MB_OK) >>>> } >>>> >>>> func main() {} >>>> ``` >>>> >>>> I compile on Linux with: >>>> ``` >>>> GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc go >>>> build -a -o ~/Desktop/dropamd64.dll -buildmode=c-shared >>>> cmd/dll64bit/main.go >>>> ``` >>>> >>>> I transfer on my Windows machine then here is the amazing result: >>>> *rundll32.exe Z:\dropamd64.dll -----> Nothing happens* >>>> *rundll32.exe Z:\dropamd64.dll,RunMe ------> Runs RunMe() and init() >>>> and I get 2 MessageBox* >>>> >>>> My question is, how to get a DLL that runs stuff only when process is >>>> attached ? >>>> >>>> There not a lot of official Golang doc about DLL (some few people write >>>> here and there some tutorials that are not always right and correct ...) >>>> So >>>> if you have some trustworthy doc please share. >>>> >>>> >>>> >>>> >>>> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/e1416660-0963-4ef6-8a11-27a0dd580e32n%40googlegroups.com.