Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Unloading file AuCpp.dll from other processes
#1
The Au library uses a dll file AuCpp.dll. If your program uses the Au library, sometimes it may want to delete or replace the dll, for example when installing new version. But it may fail because the dll may be loaded into some seemingly unrelated processes.

Class elm and some other Au library functions load the dll into the target process to make "find UI element" faster or/and enable some features.

There are 2 versions of AuCpp.dll files: 64-bit dll for 64-bit processes and 32-bit dll for 32-bit processes.

If need to delete the dll, you can:
- With elm functions use flag NotInProc. Then the dll will not be loaded into the target process. But will be slower etc.
- Or unload the dll from other processes. This script shows how.
 
Code:
Copy      Help
// script "Unload AuCpp.dll from other processes.cs"
//AuCpp.dll exports function Cpp_Unload. It unloads AuCpp.dll from other processes. You can use it in any program (C#, C++, etc).
//Or, to avoid loading AuCpp.dll into your process, use Cpp_Unload code converted to C#.
//Or, if you use C++, copy the function from GitHub to your C++ program.


#if !true //use function Cpp_Unload of AuCpp.dll
api.Cpp_Unload(1);

unsafe class api : NativeApi {
    /// <param name="flags">1 - wait less.</param>
    [DllImport("AuCpp.dll", CallingConvention = CallingConvention.Cdecl)]
    internal static extern void Cpp_Unload(uint flags);
}
#else //use Cpp_Unload code converted to C#
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;

UnloadAuCppDll(!true);

void UnloadAuCppDll(bool waitLess) {
    int less = waitLess ? 5 : 1;
    List<nint> a = new();
    
    //close elm agent windows
    for (nint w = 0; (w = api.FindWindowEx(api.HWND_MESSAGE, w, "AuCpp_IPA_1", null)) != 0;) a.Add(w);
    int n = a.Count;
    if (n > 0) {
        for (int i = 0; i < n; i++) api.SendMessageTimeout(a[i], api.WM_CLOSE, 0, 0, api.SMTO_ABORTIFHUNG, 5000 / less, out _);
        a.Clear();
        Thread.Sleep(n * 50);
    }

    
    //unload from processes where loaded by the clipboard hook
    api.SendMessageTimeout(api.HWND_BROADCAST, 0, 0, 0, api.SMTO_ABORTIFHUNG, 1000 / less, out _);
    for (nint w = 0; (w = api.FindWindowEx(api.HWND_MESSAGE, w, null, null)) != 0;) a.Add(w);
    foreach (var w in a) api.SendMessageTimeout(w, 0, 0, 0, api.SMTO_ABORTIFHUNG, 1000 / less, out _);
    Thread.Sleep(500 / less);
}


unsafe class api {
    [
DllImport("user32.dll", EntryPoint = "FindWindowExW")]
    internal static extern nint FindWindowEx(nint hWndParent, nint hWndChildAfter, string lpszClass, string lpszWindow);
    
    [
DllImport("user32.dll", EntryPoint = "SendMessageTimeoutW")]
    internal static extern nint SendMessageTimeout(nint hWnd, int Msg, nint wParam, nint lParam, uint fuFlags, int uTimeout, out nint lpdwResult);
    
    internal const nint HWND_MESSAGE = -3;
    internal const nint HWND_BROADCAST = 0xFFFF;
    internal const uint SMTO_ABORTIFHUNG = 0x2;
    internal const int WM_CLOSE = 0x10;
}

#endif

In LA 1.2 and later the dll also exports function UnloadAuCppDll. It can be called by rundll32.exe. Example in cmd:
 
Code:
Copy      Help
rundll32.exe "C:\path\to\AuCpp.dll",UnloadAuCppDll 0

See also: Pascal code for Inno Setup

Notes:
- Cannot unload from hung or suspended processes.
- Cannot unload from admin processes if this process isn't admin.
- Cannot unload if some process still uses COM objects of that process (eg UI elements).
- May need to wait more.
- Test with AuCpp.dll of your program. Not with AuCpp.dll of LibreAutomate while it is running.


Forum Jump:


Users browsing this thread: 1 Guest(s)