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.

Reply via email to