Jump to content

DllCall function pauses script


 Share

Go to solution Solved by Nine,

Recommended Posts

Hello,

I've been looking into offloading a couple functions outside of the main script as they are blocking. Such as FileCopy, PlaySound and anything else that has to parse large number of folders. So I've looked into C++ and dll files with the help of this topic among others. However I can't quite figure out how to work with these files. As of right now when I'm calling the file the script pauses until the function within the dll finishes running. I'm not sure if this has to do with the fact that AutoIt is waiting for a return.

Is there a way to not need a return from let's say function number 1, but wait for return from function number 2 somewhere in the loop?

In the future I will need to do both. Have the function execute without having any return and have another one return value while still not pausing main script in AutoIt. Does any of this have to do with DllCallbackRegister or is the pausing due to MessageBox function in C++ hanging main script because it was executed under it?

$dll = DllOpen("A:\DLL functions\functions\Debug\functions.dll")
If Random(1, 2, 1) = 1 Then
    DllCall($dll, "none:cdecl", "PlaySound", "str", "A:\test.wav")
Else
    $aReturn = DllCall($dll, "int:cdecl", "Test", "int", 2, "int", 3)
    ConsoleWrite('Return: ' & $aReturn[0])
EndIf
DllClose($dll)

My C++ code looks like this (first time trying C++):
Header:

#ifndef _DLL_TUTORIAL_H_
#define _DLL_TUTORIAL_H_
#include <iostream>

#define DECLDIR __declspec(dllexport)

extern "C"
{
	// Functions
	DECLDIR int Test(int a, int b);
	DECLDIR void PlaySound(const char* c);
}

#endif

CPP file:
 

#include <iostream>
#include <Windows.h>
#include <pch.h>
#include "Header.h"
#include <iostream>
#include <string>

extern "C"
{
    DECLDIR int Test(int a, int b) //Function 1
    {
        int sum = a + b;
        //std::string text = "Result is: " + std::to_string(sum);
        //MessageBox(0, TEXT(text.c_str()), TEXT("Title"), 0);
        return sum;
    }

    DECLDIR void PlaySound(const char* c) //Function 2
    {
        //std::cout << "DLL Called!" << std::endl;
        std::string text = "Passed from AutoIt - ";
        text += c;
        MessageBox(0, TEXT(text.c_str()), TEXT("Title"), 0);
        return;
        //------------------------------------------------------------
        //PlaySound()
    }
}

 

functions.dll

Link to comment
Share on other sites

  • Solution

DllCall will always wait for completion of a function.  But there is a number of overlapped functions that windows has created allowing asynchronous processing.  The approach is basically that you define a callback function that is called under defined circumstances (see ReadDirectoryChangesW for example).

You can also start secondary processes (with Run for example) to execute tasks in background while the main script continues.  If you need a more complex communication between processes you can use IPC (see WCD IPC in my signature)

FYI, SoundPlay has a nowait flag (see AutoIt help file)

Link to comment
Share on other sites

Simply let the dll func create a separate thread to execute the function asynchronously. (see for example here and here).

Link to comment
Share on other sites

@Nine I'll look into the overlapped functions, thanks. As for the other approach it's something that I'm already doing. I was just wondering if this way it would be much more efficient.

As for the SoundPlay function it was an example I wanted to start with as that function specifically just "broke" at one point. It simply ran and didn't give an error (sound never played), but instead of looking into it I just replaced it with _SoundPlay. What was the cause I have no idea, perhaps caching of the sounds or something.

@RTFC I will check these as well.

 

Link to comment
Share on other sites

I have some C# dot net code that I run using 

that I have spawn up a separate monitor for some things, and update variables in C#, then retrieve them in AutoIt periodically. Here's how the separate monitor in C# is launched:

    public bool LaunchMonitor()
    {
        ShouldRun = true;
        new Thread(delegate()
        {
            Monitor();
        }).Start();

        return true;
    }

From AutoIt it's just:

#include "..\DotNet\Includes\DotNetAll.au3"
Local $fFile = FileOpen(@ScriptDir & "\Program.cs")
Local $oNetCode = DotNet_LoadCScode( _
        FileRead($fFile), _
        "System.dll | System.Management.dll | " & _
        "", Default, Default, "/unsafe /optimize /platform:x64")
FileClose($fFile)
Local $oNetClass = DotNet_CreateObject($oNetCode, "MonitorMain")

$oNetClass.InitializeVars()
$oNetClass.LaunchMonitor()

 

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...