Jump to content

All Activity

This stream auto-updates

  1. Past hour
  2. This is it!!! I found why it stopped by itself !
  3. Today
  4. You are not using the latest version edited above. It has been corrected like I said in my previous post. It is working now...
  5. @arcker HELP needed ! I am running your ServiceExample_v4.au3. But after 2 to 10 min the service stops, and I do not know why ! Here is your script a bit modified: #NoTrayIcon #RequireAdmin #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Run_After=copy "%out%" "\\myserver\c$\Batch\autoit" #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** Opt("mustdeclarevars", 1) ;~ https://www.autoitscript.com/forum/topic/80201-_service_udf-v4-build-your-own-service-with-autoit-code/ ;~ #AutoIt3Wrapper_Version=beta ;~ Opt("MustDeclareVars", 1) ; just for self control FPRIVATE "TYPE=PICT;ALT=smile.gif" dont to forget declare vars Global $MainLog = @ScriptDir & "\test_service.log" Global $sDescription = 'test' Global Const $sServiceName = 'a_test' ;~ FileDelete($MainLog) ;~ If $bServiceRunning Then Exit ;~ logprint("program started" & $cmdlineraw) #include <Winapi.au3> ;just For constants #include "services.au3" #include <File.au3> ;~ #include <Timers.au3> ; i used it for timers func ;~ If $bAU3ServiceDebug Then logprint("script started") If $cmdline[0] > 0 Then Switch $cmdline[1] Case "install", "-i", "/i" ;~ msgbox(0,"","toto") InstallService() Case "remove", "-u", "/u", "uninstall" RemoveService() Case Else ConsoleWrite(" - - - Help - - - " & @CRLF) ConsoleWrite("params : " & @CRLF) ConsoleWrite(" -i : install service" & @CRLF) ConsoleWrite(" -u : remove service" & @CRLF) ConsoleWrite(" - - - - - - - - " & @CRLF) Exit ;start service. EndSwitch Else _Service_init($sServiceName) Exit EndIf Func _main($iArg, $sArgs) ;~ Sleep(1000) ;~ $bMainStopped = False If Not _Service_ReportStatus($SERVICE_RUNNING, $NO_ERROR, 0) Then ;~ if $bAU3ServiceDebug then logprint("Erreur sending running status, exiting") _Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0) Exit EndIf $bServiceRunning = True ; REQUIRED #cs Dim $tcpon = true If $tcpon Then TCPStartup() Dim $tcpConn = TCPConnect("127.0.0.1",3585) TCPSend($tcpConn,"Hello " & @AutoItPID) EndIf #ce While $bServiceRunning ; REQUIRED ( dont change variable name ) ; there are several ways to find that service have to be stoped - $Running flag in loop is the first method #Region --> insert your running code here ;~ local $count = 0 ;~ if $count < 5 then ;~ logprint("main count" & $count & @crlf) ;~ If $tcpon Then TCPSend($tcpConn, "main count" & $count & @crlf) ;~ if $count < 5 then logprint("main count" & $count & @crlf) ;~ $count += 1 _Sleep(10000) _FileWriteLog(@ScriptDir & '\log.log', 'hello') ;~ if $count = 4 then ;~ while 1 ;~ if not $bServiceRunning then ;~ logprint("stop loop 4") ;~ ExitLoop ;~ EndIf ;~ WEnd ;~ endif #EndRegion --> insert your running code here WEnd _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 1000) ;~ logprint("seems service stopping") ;~ Sleep(2000) ;~ $bMainStopped = True ;~ If $tcpon Then TCPCloseSocket($tcpConn) ;~ If $tcpon Then TCPShutdown() DllCallbackFree($tServiceMain) DllCallbackFree($tServiceCtrl) _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0) DllClose($hAdvapi32_DLL) DllClose($hKernel32_DLL) ;~ _service_cleanup() ;~ exit ;~ return EndFunc ;==>_main ;~ If $bDebug Then logprint("script started") #cs If $cmdline[0] > 0 Then Switch $cmdline[1] Case "install", "-i", "/i" ;~ msgbox(0,"","toto") InstallService() Case "remove", "-u", "/u", "uninstall" RemoveService() Case Else ConsoleWrite(" - - - Help - - - " & @CRLF) ConsoleWrite("params : " & @CRLF) ConsoleWrite(" -i : install service" & @CRLF) ConsoleWrite(" -u : remove service" & @CRLF) ConsoleWrite(" - - - - - - - - " & @CRLF) Exit ;start service. EndSwitch Else _Service_init($sServiceName) Exit EndIf #ce Func _Sleep($delay) ;~ logprint("Pause " & $delay / 1000 & " seconds...") ;~ Local $dll = DllOpen("kernel32.dll") Local $result = DllCall($hKernel32_DLL, "none", "Sleep", "dword", $delay) ;~ DllClose($dll) EndFunc ;==>_Sleep ; some loging func ;~ Func logprint($text, $nolog = 0) ;~ If $nolog Then ;~ MsgBox(0, "MyService", $text, 1) ;~ Else ;~ If Not FileExists($MainLog) Then FileWriteLine($MainLog, "Log created: " & @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC) ;~ FileWriteLine($MainLog, @YEAR & @MON & @MDAY & " " & @HOUR & @MIN & @SEC & " [" & @AutoItPID & "] >> " & $text) ;~ EndIf ;~ Return 0 ;~ ConsoleWrite($text & @CRLF) ;~ EndFunc ;==>logprint Func InstallService() _Service_Create($sServiceName, $sServiceName, $SERVICE_WIN32_OWN_PROCESS, $SERVICE_AUTO_START, $SERVICE_ERROR_NORMAL, '"' & @ScriptFullPath & '"') If @error Then ConsoleWrite('Problem installing service, Error number is ' & @error & @CRLF & ' message : ' & _WinAPI_GetLastErrorMessage()) Else RunWait(@ComSpec & ' /c ' & 'sc description ' & $sServiceName & ' "' & $sDescription & '"') ConsoleWrite('Installation of service successful' & @CRLF & 'Program will exit') EndIf Exit EndFunc ;==>InstallService Func RemoveService() _Service_Stop($sServiceName) _Service_Delete($sServiceName) If Not @error Then ConsoleWrite('Uninstallation of service successful' & @CRLF & 'Program will exit') EndIf Exit EndFunc ;==>RemoveService Func _exit() ;~ if $bDebug then logprint("Exiting") ; Clean opened dll ;~ DllClose($hKernel32_DLL) ;~ DllClose($hAdvapi32_DLL) _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0) ; ;~ _service_cleanup("END") ;~ _Service_Cleanup("END") EndFunc ;==>_exit #cs ...from MSDN: The ServiceMain function should perform the following tasks: Initialize all global variables. Call the RegisterServiceCtrlHandler function immediately to register a Handler function to handle control requests for the service. The return value of RegisterServiceCtrlHandler is a service status handle that will be used in calls to notify the SCM of the service status. Perform initialization. If the execution time of the initialization code is expected to be very short (less than one second), initialization can be performed directly in ServiceMain. If the initialization time is expected to be longer than one second, call the SetServiceStatus function, specifying the SERVICE_START_PENDING service state and a wait hint in the SERVICE_STATUS structure. If your service's initialization code performs tasks that are expected to take longer than the initial wait hint value, your code must call the SetServiceStatus function periodically (possibly with a revised wait hint) to indicate that progress is being made. Be sure to call SetServiceStatus only if the initialization is making progress. Otherwise, the Service Control Manager can wait for your service to enter the SERVICE_RUNNING state assuming that your service is making progress and block other services from starting. Do not call SetServiceStatus from a separate thread unless you are sure the thread performing the initialization is truly making progress. When initialization is complete, call SetServiceStatus to set the service state to SERVICE_RUNNING. Perform the service tasks, or, if there are no pending tasks, return control to the caller. Any change in the service state warrants a call to SetServiceStatus to report new status information. If an error occurs while the service is initializing or running, the service should call SetServiceStatus to set the service state to SERVICE_STOP_PENDING if cleanup will be lengthy. After cleanup is complete, call SetServiceStatus to set the service state to SERVICE_STOPPED from the last thread to terminate. Be sure to set the dwServiceSpecificExitCode and dwWin32ExitCode members of the SERVICE_STATUS structure to identify the error. #ce ; emulating your program init() function ;~ Func main_init() ;~ $hGUI = GUICreate("Timers Using CallBack Function(s)") ;~ GUISetState($hGUI,@SW_HIDE) ; unneeded - timers run exelent without guisetstate. ;~ $MainLog = @ScriptDir & "\test_service.log" ;~ $sServiceName = "Autoit_Service" ;~ $Running = 1 ;~ if $bDebug then logprint("main_init. Stop event=" & $service_stop_event) ;~ EndFunc ;==>main_init ; stop timer function. its said SCM that service is in the process of $SERVICE_STOP_PENDING ;~ Func myStopTimer($hWnd, $Msg, $iIDTimer, $dwTime) ;~ if $bDebug then logprint("timer = " & $counter) ;~ _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, $counter) ;~ $counter += -100 ;~ EndFunc ;==>myStopTimer Func StopTimer() ;~ if $bDebug then logprint("timer = " & $counter) _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, $iServiceCounter) $iServiceCounter += -100 EndFunc ;==>StopTimer ; emulate your program main function with while loop (may be gui loop & so on) Func _Stopping() _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 3000) EndFunc ;==>_Stopping and Services.au3: ;created By arcker, for autoit community #include-once ;#include "Log.au3" #include "WinAPI.au3" #include "ServicesConstants.au3" ;~ Dim $bMainStopped = False ;~ Dim $gServiceStateRunning = False Dim $bAU3ServiceDebug = false Dim $hAdvapi32_DLL = DllOpen("Advapi32.dll") Dim $hKernel32_DLL = DllOpen("kernel32.dll") ;~ Dim $gdwCheckPoint = 1 ;~ Dim $sServiceName = "Autoit_Service" Dim $bServiceRunning = False, $iServiceCounter = 1 ; const ; Globals for Au3@service routines Dim $tServiceName,$tServiceCtrl,$tServiceMain;,$service_debug_mode = False Dim $tService_Status = DllStructCreate("dword dwServiceType;" & _ "dword dwCurrentState;dword dwControlsAccepted;dword dwWin32ExitCode;" & _ "dword dwServiceSpecificExitCode;dword dwCheckPoint;dword dwWaitHint") Dim $hService_Status_handle ;~ Dim Const $NTSL_LOOP_WAIT = -1 ;~ Dim $service_type ;~ Dim $service_stop_event ;~ Dim $NTSL_ERROR_SERVICE_STATUS = 2 ;~ Dim Const $WAIT_OBJECT_0 = 0x0 ; #INDEX# ========================================================================================================================================================== ; Title .........: Services ; AutoIt Version : 3.2.10++ ; Language ......: English ; Description ...: Windows service management for AutoIt, with AutoIt-as-service functionality. ; Authors .......: Engine, Arcker ; ...............: Shminkyboy, udgeen ; ================================================================================================================================================================== ; #FUNCTION# ======================================================================================================================================================= ; Name...........: _Service_Create ; Description ...: Creates a service. ; Syntax.........: _Service_Create($sServiceName, $sDisplayName, $iServiceType, $iStartType, $iErrorControl, $sBinaryPath _ ; [, $sLoadOrderGroup, $fTagId, $vDependencies, $sServiceUser, $sPassword, $sComputerName]) ; Parameters ....: $sServiceName - Name of the service. ; $sDisplayName - The display name to be used by user interface programs to identify the service. The maximum string length is 256 characters. ; The service control manager database preserves the case of the characters, ; but service name comparisons are always case insensitive. ; Forward-slash (/) and back-slash (\) are invalid service name characters. ; $iServiceType - The type of service. Specify one of the following service types: ; $SERVICE_KERNEL_DRIVER - Driver service. ; $SERVICE_FILE_SYSTEM_DRIVER - File system driver service. ; $SERVICE_WIN32_OWN_PROCESS - Service that runs in its own process. ; $SERVICE_WIN32_SHARE_PROCESS - Service that shares a process with other services. ; If you specify either $SERVICE_WIN32_OWN_PROCESS or $SERVICE_WIN32_SHARE_PROCESS, ; and the service is running in the context of the LocalSystem account, you can also specify the following type: ; $SERVICE_INTERACTIVE_PROCESS - The service can interact with the desktop. ; $iStartType - The service start options. Specify one of the following start types: ; $SERVICE_BOOT_START - A device driver started by the system loader. This value is valid only for driver services. ; $SERVICE_SYSTEM_START - A device driver started by the IoInitSystem function. This value is valid only for driver services. ; $SERVICE_AUTO_START - A service started automatically by the service control manager during system startup. ; $SERVICE_DEMAND_START - A service started by the service control manager when a process calls the StartService function. ; $SERVICE_DISABLED - A service that cannot be started. ; $iErrorControl - The severity of the error, and action taken, if this service fails to start. Specify one of the following values: ; $SERVICE_ERROR_IGNORE - The startup program ignores the error and continues the startup operation. ; $SERVICE_ERROR_NORMAL - The startup program logs the error in the event log but continues the startup operation. ; $SERVICE_ERROR_SEVERE - The startup program logs the error in the event log. ; If the last-known-good configuration is being started, the startup operation continues. ; Otherwise, the system is restarted with the last-known-good configuration. ; $SERVICE_ERROR_CRITICAL - The startup program logs the error in the event log, if possible. ; If the last-known-good configuration is being started, the startup operation fails. ; Otherwise, the system is restarted with the last-known good configuration. ; $sBinaryPath - The fully-qualified path to the service binary file. If the path contains a space, ; it must be quoted so that it is correctly interpreted. ; For example, "d:\\my share\\myservice.exe" should be specified as "\"d:\\my share\\myservice.exe\"". ; The path can also include arguments for an auto-start service. For example, "d:\\myshare\\myservice.exe arg1 arg2". ; These arguments are passed to the service entry point (typically the main function). ; $sLoadOrderGroup - [Optional] The name of the load ordering group of which this service is a member. ; Specify "Default" or an empty string if the service does not belong to a group. ; $fTagId - [Optional] Specify "True" if you desire a tag value that is unique in the group specified in the $sLoadOrderGroup parameter. ; Specify "False" or "Default" if you do not desire a tag value. ; The tag value is stored in @extended macro. ; You can use a tag for ordering service startup within a load ordering group by specifying a tag order vector in the ; GroupOrderList value of the following registry key: ; HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control ; Tags are only evaluated for driver services that have $SERVICE_BOOT_START or $SERVICE_SYSTEM_START start types. ; $vDependencies - [Optional] An array of services or load ordering groups that the system must start before this service can be started. ; (Dependency on a group means that this service can run if at least one member of the group is running after an attempt to ; start all members of the group.) Specify "Default" or an empty string if the service has no dependencies. ; You must prefix group names with a plus sign ("+") so that they can be distinguished from a service name, ; because services and service groups share the same name space. ; $sServiceUser - [Optional] The name of the account under which the service should run. ; If the service type is $SERVICE_WIN32_OWN_PROCESS, use an account name in the form DomainName\UserName. ; The service process will be logged on as this user. If the account belongs to the built-in domain, ; you can specify .\UserName . A shared process can run as any user. ; If the service type is $SERVICE_KERNEL_DRIVER or $SERVICE_FILE_SYSTEM_DRIVER, ; the name is the driver object name that the system uses to load the device driver. ; Specify "Default" if the driver is to use a default object name created by the I/O system. ; $sPassword - [Optional] The password to the account name specified by the $sServiceUser parameter. ; Specify "Default" or an empty string if the account has no password or if the service runs in the LocalService, NetworkService, ; or LocalSystem account. Passwords are ignored for driver services. ; $sComputerName - [Optional] The name of the target computer. The local computer is default. ; Requirement(s).: Administrative rights on the target computer. ; Return values .: Success - 1 ; Failure - 0 ; Sets @error ; Author ........: engine ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; ================================================================================================================================================================== Func _Service_Create($sServiceName, _ $sDisplayName, _ $iServiceType, _ $iStartType, _ $iErrorControl, _ $sBinaryPath, _ $sLoadOrderGroup = Default, _ $fTagId = Default, _ $vDependencies = Default, _ $sServiceUser = Default, _ $sPassword = Default, _ $sComputerName = "") Local $tLoadOrderGroup, $tTagId, $tDepend, $tServiceUser, $tPassword, $hSC, $avSC, $iSC $tLoadOrderGroup = DllStructCreate("wchar[" & Number($sLoadOrderGroup <> Default) * (StringLen($sLoadOrderGroup) + 1) & "]") DllStructSetData($tLoadOrderGroup, 1, $sLoadOrderGroup) $tTagId = DllStructCreate("dword[" & Number($fTagId) & "]") If IsArray($vDependencies) Then Local $iDepend, $tagDepend $iDepend = UBound($vDependencies) - 1 For $i = 0 To $iDepend $tagDepend &= "wchar[" & StringLen($vDependencies[$i]) + 1 & "];" Next $tDepend = DllStructCreate(StringTrimRight($tagDepend, 1)) For $i = 0 To $iDepend DllStructSetData($tDepend, $i + 1, $vDependencies[$i]) Next Else $tDepend = DllStructCreate("wchar[" & Number($vDependencies <> Default) * (StringLen($vDependencies) + 1) & "]") DllStructSetData($tDepend, 1, $vDependencies) EndIf $tServiceUser = DllStructCreate("wchar[" & Number($sServiceUser <> Default) * (StringLen($sServiceUser) + 1) & "]") DllStructSetData($tServiceUser, 1, $sServiceUser) $tPassword = DllStructCreate("wchar[" & Number($sPassword <> Default) * (StringLen($sPassword) + 1) & "]") DllStructSetData($tPassword, 1, $sPassword) $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CREATE_SERVICE) $avSC = DllCall($hAdvapi32_DLL, "ptr", "CreateServiceW", _ "ptr", $hSC, _ "wstr", $sServiceName, _ "wstr", $sDisplayName, _ "dword", $SERVICE_ALL_ACCESS, _ "dword", $iServiceType, _ "dword", $iStartType, _ "dword", $iErrorControl, _ "wstr", $sBinaryPath, _ "ptr", DllStructGetPtr($tLoadOrderGroup), _ "ptr", DllStructGetPtr($tTagId), _ "ptr", DllStructGetPtr($tDepend), _ "ptr", DllStructGetPtr($tServiceUser), _ "ptr", DllStructGetPtr($tPassword)) If $avSC[0] = 0 Then $iSC = _WinAPI_GetLastError() Else CloseServiceHandle($avSC[0]) EndIf CloseServiceHandle($hSC) Return SetError($iSC, DllStructGetData($tTagId, 1), Number($avSC[0] <> 0)) EndFunc ;==>_Service_Create ; #FUNCTION# ======================================================================================================================================================= ; Name...........: _Service_Delete ; Description ...: Deletes a service. ; Syntax.........: _Service_Delete($sServiceName [, $sComputerName]) ; Parameters ....: $sServiceName - Name of the service. ; $sComputerName - [Optional] The name of the target computer. The local computer is default. ; Requirement(s).: Administrative rights on the target computer. ; Return values .: Success - 1 ; Failure - 0 ; Sets @error ; Author ........: engine ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; ================================================================================================================================================================== Func _Service_Delete($sServiceName, $sComputerName = "") Local $hSC, $hService, $avDS, $iDS $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CONNECT) $hService = OpenService($hSC, $sServiceName, $DELETE) $avDS = DllCall($hAdvapi32_DLL, "int", "DeleteService", _ "ptr", $hService) If $avDS[0] = 0 Then $iDS = _WinAPI_GetLastError() CloseServiceHandle($hService) CloseServiceHandle($hSC) Return SetError($iDS, 0, $avDS[0]) EndFunc ;==>_Service_Delete ; #FUNCTION# ======================================================================================================================================================= ; Name...........: _Service_Exists ; Description ...: Checks if a service exists. ; Syntax.........: _Service_Exists($sServiceName [, $sComputerName]) ; Parameters ....: $sServiceName - Name of the service. ; $sComputerName - [Optional] The name of the target computer. The local computer is default. ; Requirement(s).: None. ; Return values .: Success - 1 ; Failure - 0 ; Author ........: engine ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; ================================================================================================================================================================== Func _Service_Exists($sServiceName, $sComputerName = "") Local $hSC, $hService $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CONNECT) $hService = OpenService($hSC, $sServiceName, $SERVICE_INTERROGATE) CloseServiceHandle($hService) CloseServiceHandle($hSC) Return Number($hService <> 0) EndFunc ;==>_Service_Exists ; #FUNCTION# ======================================================================================================================================================= ; Name...........: _Service_QueryType ; Description ...: Retrieves a service's type. ; Syntax.........: _Service_QueryType($sServiceName [, $sComputerName]) ; Parameters ....: $sServiceName - Name of the service. ; $sComputerName - [Optional] The name of the target computer. The local computer is default. ; Requirement(s).: None. ; Return values .: Success - Returns the type of service. Can be one of the following values: ; $SERVICE_KERNEL_DRIVER - The service is a device driver. ; $SERVICE_FILE_SYSTEM_DRIVER - The service is a file system driver. ; $SERVICE_WIN32_OWN_PROCESS - The service runs in its own process. ; $SERVICE_WIN32_SHARE_PROCESS - The service shares a process with other services. ; BitOR($SERVICE_WIN32_OWN_PROCESS, $SERVICE_INTERACTIVE_PROCESS) - The service runs in its own process ; and can interact with the desktop. ; BitOR($SERVICE_WIN32_SHARE_PROCESS, $SERVICE_INTERACTIVE_PROCESS) - The service shares a process with other services ; and can interact with the desktop. ; Failure - 0 ; Sets @error ; Author ........: engine ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; ================================================================================================================================================================== Func _Service_QueryType($sServiceName, $sComputerName = "") Local $hSC, $hService, $avQA, $tQB, $avQB, $iQE, $tQC $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CONNECT) $hService = OpenService($hSC, $sServiceName, $SERVICE_QUERY_CONFIG) ; Determine needed size of the struct in bytes $avQA = QueryServiceConfig($hService, 0, 0) ; Get Service data $tQB = DllStructCreate("ubyte[" & $avQA[4] & "]") $avQB = QueryServiceConfig($hService, DllStructGetPtr($tQB), DllStructGetSize($tQB)) ; Get last error and close service handle If $avQB[0] = 0 Then $iQE = _WinAPI_GetLastError() CloseServiceHandle($hService) CloseServiceHandle($hSC) ; Decode the ubyte structure $tQC = DllStructCreate("dword[3];uint_ptr[2];dword;uint_ptr[3]", $avQB[2]) Return SetError($iQE, 0, DllStructGetData($tQC, 1, 1)) EndFunc ;==>_Service_QueryType ; #FUNCTION# ======================================================================================================================================================= ; Name...........: _Service_Start ; Description ...: Starts a service. ; Syntax.........: _Service_Start($sServiceName [, $sComputerName]) ; Parameters ....: $sServiceName - Name of the service. ; $sComputerName - [Optional] The name of the target computer. The local computer is default. ; Requirement(s).: Administrative rights on the target computer. ; Return values .: Success - 1 ; Failure - 0 ; Sets @error ; Author ........: engine ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; ================================================================================================================================================================== Func _Service_Start($sServiceName, $sComputerName = "") Local $hSC, $hService, $avSS, $iSS $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CONNECT) $hService = OpenService($hSC, $sServiceName, $SERVICE_START) $avSS = DllCall($hAdvapi32_DLL, "int", "StartServiceW", _ "ptr", $hService, _ "dword", 0, _ "ptr", 0) If $avSS[0] = 0 Then $iSS = _WinAPI_GetLastError() CloseServiceHandle($hService) CloseServiceHandle($hSC) Return SetError($iSS, 0, $avSS[0]) EndFunc ;==>_Service_Start ; #FUNCTION# ======================================================================================================================================================= ; Name...........: _Service_Stop ; Description ...: Stops a service. ; Syntax.........: _Service_Stop($sServiceName [, $sComputerName]) ; Parameters ....: $sServiceName - Name of the service. ; $sComputerName - [Optional] The name of the target computer. The local computer is default. ; Requirement(s).: Administrative rights on the target computer. ; Return values .: Success - 1 ; Failure - 0 ; Sets @error ; Author ........: engine ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; ================================================================================================================================================================== Func _Service_Stop($sServiceName, $sComputerName = "") Local $hSC, $hService, $iCSS, $iCSSE $hSC = OpenSCManager($sComputerName, $SC_MANAGER_CONNECT) $hService = OpenService($hSC, $sServiceName, $SERVICE_STOP) $iCSS = ControlService($hService, $SERVICE_CONTROL_STOP) If $iCSS = 0 Then $iCSSE = _WinAPI_GetLastError() CloseServiceHandle($hService) CloseServiceHandle($hSC) Return SetError($iCSSE, 0, $iCSS) EndFunc ;==>_Service_Stop Func CloseServiceHandle($hSCObject) Local $avCSH = DllCall($hAdvapi32_DLL, "int", "CloseServiceHandle", _ "ptr", $hSCObject) If @error Then Return SetError(@error, 0, 0) Return $avCSH[0] EndFunc ;==>CloseServiceHandle Func ControlService($hService, $iControl) Local $avCS = DllCall($hAdvapi32_DLL, "int", "ControlService", _ "ptr", $hService, _ "dword", $iControl, _ "ptr*", 0) If @error Then Return SetError(@error, 0, 0) Return $avCS[0] EndFunc ;==>ControlService Func OpenSCManager($sComputerName, $iAccess) Local $avOSCM = DllCall($hAdvapi32_DLL, "ptr", "OpenSCManagerW", _ "wstr", $sComputerName, _ "wstr", $SERVICES_ACTIVE_DATABASE, _ "dword", $iAccess) If @error Then Return SetError(@error, 0, 0) Return $avOSCM[0] EndFunc ;==>OpenSCManager Func OpenService($hSC, $sServiceName, $iAccess) Local $avOS = DllCall($hAdvapi32_DLL, "ptr", "OpenServiceW", _ "ptr", $hSC, _ "wstr", $sServiceName, _ "dword", $iAccess) If @error Then Return SetError(@error, 0, 0) Return $avOS[0] EndFunc ;==>OpenService Func QueryServiceConfig($hService, $pServiceConfig, $iBufSize) Local $avQSC = DllCall($hAdvapi32_DLL, "int", "QueryServiceConfigW", _ "ptr", $hService, _ "ptr", $pServiceConfig, _ "dword", $iBufSize, _ "dword*", 0) Return $avQSC EndFunc ;==>QueryServiceConfig ;~ Au3@Service routines by 'Arcker'. Modified by ShminkyBoy to include support for interactive services Func _Service_Init($sServiceName) ;~ If $bAU3ServiceDebug Then logprint("_Service_Init(" & $sServiceName & ")") ;~ $service_type = _Service_QueryType($sServiceName) $tServiceCtrl = DllCallbackRegister("_Service_Ctrl", "dword", "dword;dword;ptr;ptr") ; handlerex function ;~ $tServiceCtrl = DllCallbackRegister("_Service_Ctrl", "none", "dword") ; handler ( simple ) $tServiceMain = DllCallbackRegister("_Service_ServiceMain", "none", "dword;ptr") ;~ $tServiceMain = DllCallbackRegister("_Main", "none", "dword;ptr") ;~ Local $tdispatchTable = DllStructCreate("ptr[2];ptr[2]") ;~ $tServiceName = DllStructCreate("char["&StringLen($sServiceName)&"]") ;~ DllStructSetData($tServiceName, 1, $sServiceName) ;~ DllStructSetData($tdispatchTable, 1, DllStructGetPtr($tServiceName), 1) ;~ DllStructSetData($tdispatchTable, 1, DllCallbackGetPtr($tServiceMain), 2) ;v4 : Local $tagSERVICE_TABLE_ENTRY = "STRUCT;ptr lpServiceName;ptr lpServiceProc;ENDSTRUCT" ;~ logprint($tSERVICE_TABLE_ENTRY & ";" & $tSERVICE_TABLE_ENTRY) Local $tdispatchTable = DllStructCreate($tagSERVICE_TABLE_ENTRY & ";" & $tagSERVICE_TABLE_ENTRY) ;~ If @error Then ;~ logprint("erreur de structure " & @error & @crlf) ;~ Exit ;~ EndIf $tServiceName = DllStructCreate("char["&StringLen($sServiceName)&"]") ;~ DllStructSetData($tServiceName, 1, $sServiceName) DllStructSetData($tdispatchTable, 1, DllStructGetPtr($tServiceName)) DllStructSetData($tdispatchTable, 2, DllCallbackGetPtr($tServiceMain)) ;********** ;~ DllStructSetData($tdispatchTable, 2, 0, 1) ; v4 not needed since NULL ;~ DllStructSetData($tdispatchTable, 2, 0, 2) ; v4 not needed since NULL ; here when we call this, the _service_ctrl callback is reported to the SCM DllCall($hAdvapi32_DLL, "int", "StartServiceCtrlDispatcher", "ptr", DllStructGetPtr($tdispatchTable)) ;cleanup a little $tServiceName =0 $tdispatchTable = 0 ; cleanup callback resources ;~ DllCallbackFree($tServiceMain) ;~ DllCallbackFree($tServiceCtrl) EndFunc ;==>_Service_init Func _Service_ServiceMain($iArg, $pArgs) ;~ Local $ret = DllCall($hAdvapi32_DLL, "ptr", "RegisterServiceCtrlHandlerExW", "ptr", DllStructGetPtr($tServiceName), "ptr", DllCallbackGetPtr($tServiceCtrl), "ptr", 0) ;register service ;~ If @error Or ($ret[0] = 0) Then Exit ;~ $hService_Status_handle = $ret[0] ;~ If Not $hService_Status_handle Then ;~ _Service_Cleanup() ;~ Return ;~ EndIf ;~ DllStructSetData($tService_Status, "dwServiceType", $service_type) ;~ DllStructSetData($tService_Status, "dwServiceSpecificExitCode", 0) ; report the status to the service control manager. ;~ If Not (_Service_ReportStatus($SERVICE_START_PENDING, $NO_ERROR, 3000)) Then ;~ _Service_Cleanup() ;~ Return ;~ EndIf ;~ _Service_Startup($iArg, $pArgs) ;~ _Main() ;~ if $bAU3ServiceDebug then logprint("RegisterServiceCtrlHandlerEx") Local $ret = DllCall($hAdvapi32_DLL, "ptr", "RegisterServiceCtrlHandlerEx", "ptr", DllStructGetPtr($tServiceName), "ptr", DllCallbackGetPtr($tServiceCtrl),"ptr",0) ;register service ;~ Local $ret = DllCall($hAdvapi32_DLL, "handle", "RegisterServiceCtrlHandler", "ptr", DllStructGetPtr($tServiceName), "ptr", DllCallbackGetPtr($tServiceCtrl)) ;register service If $ret[0] = 0 Then ;~ if $bAU3ServiceDebug then logprint("Error in registering service" & _WinAPI_GetLastError()) _Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0) ;~ Return Exit EndIf $hService_Status_handle = $ret[0] If Not $hService_Status_handle Then _Service_Cleanup() Return EndIf ;goto cleanup; DllStructSetData($tService_Status, "dwServiceType", _Service_QueryType($sServiceName)) DllStructSetData($tService_Status, "dwServiceSpecificExitCode", 0); ; report the status to the service control manager. If Not _Service_ReportStatus($SERVICE_START_PENDING, $NO_ERROR, 0) Then ;goto cleanup; _Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0) ;~ if $bAU3ServiceDebug then logprint("***** & error reporting Service_ReportStatus *******" & @CRLF) _Service_Cleanup() Return EndIf ;~ $service_stop_event = _WinAPI_CreateEvent(0, True, False, "") <= wonder if necessary, disabled in V3 #cs If Not _Service_ReportStatus($SERVICE_RUNNING, $NO_ERROR, 0) Then if $bAU3ServiceDebug then logprint("Erreur sending running status, exiting") _Service_ReportStatus($SERVICE_STOPPED, _WinAPI_GetLastError(), 0) Return EndIf #ce $bServiceRunning = True ; REQUIRED ;~ If $bAU3ServiceDebug Then logprint("main start") _Main($iArg, $pArgs) #region -- service stopping ;~ _service_cleanup() ;~ _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 1000); ;~ If $bAU3ServiceDebug Then logprint("main stopped. Cleanup.") #endregion -- service stopping #region - STOP STOP STOP Service Stopped, don't change it or you will have stoping status ;~ _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0) ; That all! Our AutoIt Service stops just there! 0 timeout meens "Now" ;~ Exit ;Bug here. In race conditions it's not executed. ;~ ProcessClose(@AutoItPID) <= disabled in V3, seems to works well. ;~ sleep(1000) ;~ Return #endregion - Service Stopped, don't change it or you will have stoping status EndFunc ;==>_Service_ServiceMain Func _Service_Cleanup() If $hService_Status_handle Then _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0) EndFunc ;==>_Service_Cleanup ;/*------------------------------[ service_ctrl ]------------------------------ ; * Called by the SCM whenever ControlService() is called for this service ; * ; * Parameters: ; * ctrlCode - type of control requested ; * ; * Return value: ; * none ; *----------------------------------------------------------------------------*/ Func _Service_Ctrl($dwControl, $dwEventType, $lpEventData, $lpContext) ;handler ex ;~ Func _Service_Ctrl($dwControl) ;#forceref $dwEventType, $lpEventData, $lpContext ;~ Sleep(1000) ;~ Local $return = $NO_ERROR ;~ WriteLog("_Service_Ctrl entered") ;~ If $bAU3ServiceDebug Then logprint("** SCM command received => " & $dwControl) Switch $dwControl Case $SERVICE_CONTROL_STOP,$SERVICE_ACCEPT_SHUTDOWN ; new in v4, stop when system shutdown ( better mmm ? ) ;~ If $bAU3ServiceDebug Then logprint("Received stop command for service") ;stop the service. ; ;SERVICE_STOP_PENDING should be reported before ;setting the Stop Event - hServerStopEvent - in ;service_stop(). This avoids a race condition ;which may result in a 1053 - The Service did not respond... ;error. ;~ DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_STOP_PENDING) ;~ _Service_ReportStatus($SERVICE_STOP_PENDING, $NO_ERROR, 0) $bServiceRunning = False ;~ _Service_SetStopEvent() ;~ While $bMainStopped = False ;~ If $bAU3ServiceDebug Then logprint("Main is still active") ;~ Sleep(1000) ;~ WEnd ;~ If $bAU3ServiceDebug Then logprint("Main is still active") ;~ _Service_ReportStatus($SERVICE_STOPPED, $NO_ERROR, 0) ;~ Exit ;~ _Service_ReportStatus(DllStructGetData($tService_Status,"dwCurrentState"), _WinAPI_GetLastError(), 0) ;~ _Service_SetStopEvent() ; call _Service_Cleanup() from _Svc_Main() immediately before exiting Return $NO_ERROR Case $SERVICE_CONTROL_PAUSE DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_PAUSED) Case $SERVICE_CONTROL_CONTINUE DllStructSetData($tService_Status, "dwCurrentState", $SERVICE_RUNNING) Case $SERVICE_CONTROL_INTERROGATE Return $NO_ERROR ;~ _Service_ReportStatus(DllStructGetData($tService_Status, "dwCurrentState"), $NO_ERROR, 0) ; report the service status Case $SERVICE_CONTROL_SESSIONCHANGE ; Extracting SessionID & cbSize ;~ Local $WTSSESSION_NOTIFICATION = DllStructCreate("dword cbsize; dword dwSessionId", $lpEventData) ;~ Local $cbSize = DllStructGetData($WTSSESSION_NOTIFICATION, "cbSize") ;~ Local $dwSessionId = DllStructGetData($WTSSESSION_NOTIFICATION, "dwSessionId") ;~ WriteLog("cbSize = " & $cbSize & " ,dwSessionId = " & $dwSessionId) ;Trapping events ;~ Switch $dwEventType ;~ Case $WTS_CONSOLE_CONNECT ;~ WriteLog("Console session connected", 0, 2) ;~ Case $WTS_CONSOLE_DISCONNECT ;~ WriteLog("Console session disconnected", 0, 2) ;~ Case $WTS_REMOTE_CONNECT ;~ WriteLog("Remote session connected", 0, 2) ;~ Case $WTS_REMOTE_DISCONNECT ;~ WriteLog("Remote session disconnected", 0, 2) ;~ Case $WTS_SESSION_LOGON ;~ WriteLog("Session logged on", 0, 2) ;~ Case $WTS_SESSION_LOGOFF ;~ WriteLog("Session logged off", 0, 2) ;~ Case $WTS_SESSION_LOCK ;~ WriteLog("Session locked", 0, 2) ;~ Case $WTS_SESSION_UNLOCK ;~ WriteLog("Session unlocked", 0, 2) ;~ Case $WTS_SESSION_REMOTE_CONTROL ;~ WriteLog("Session remote control", 0, 2) ;~ EndSwitch Case 128 To 255 ; custom messages ; handle custom messages Case Else ; invalid or unhandled control code ;~ $return = $ERROR_CALL_NOT_IMPLEMENTED EndSwitch ;~ _Service_ReportStatus(DllStructGetData($tService_Status, "dwCurrentState"), $NO_ERROR, 0) Return $NO_ERROR EndFunc ;==>_Service_Ctrl ;/*--------------------------[ _Service_ReportStatus ]-------------------------- ; * Sets the current status and reports it to the Service Control Manager ; * ; * Parameters: ; * currentState - the state of the service ; * exitCode - error code to report ; * waitHint - worst case estimate to next checkpoint ; * ; * Return value: ; * true - success ; * false - failure ; *----------------------------------------------------------------------------*/ Func _Service_ReportStatus($currentState, $exitCode, $waitHint) Static $gdwCheckPoint = 1 ;~ If $bAU3ServiceDebug Then logprint("Report Status received with = " & $currentState ) ;~ Local $rc = True ;~ If Not $service_debug_mode Then ;when debugging we don't report to the SCM If ($currentState = $SERVICE_START_PENDING) Then DllStructSetData($tService_Status, "dwControlsAccepted", 0) Else ;~ WriteLog("_Service_ReportStatus entered") ;~ DllStructSetData($tService_Status, "dwControlsAccepted", BitOR($SERVICE_ACCEPT_STOP, $SERVICE_ACCEPT_SESSIONCHANGE)) DllStructSetData($tService_Status, "dwControlsAccepted", BitOR($SERVICE_ACCEPT_STOP, $SERVICE_ACCEPT_SHUTDOWN)) EndIf DllStructSetData($tService_Status, "dwCurrentState", $currentState) DllStructSetData($tService_Status, "dwWin32ExitCode", $exitCode) DllStructSetData($tService_Status, "dwWaitHint", $waitHint) If ($currentState = $SERVICE_RUNNING) Or ($currentState = $SERVICE_STOPPED) Then DllStructSetData($tService_Status, "dwCheckPoint", 0) Else $gdwCheckPoint += 1 ;~ If $bAU3ServiceDebug Then logprint("dwCheckPoint => " & $gdwCheckPoint & @crlf) DllStructSetData($tService_Status, "dwCheckPoint", $gdwCheckPoint) EndIf ; report the status of the service to the service control manager. ;~ $rc = ;~ EndIf Return _Service_SetServiceStatus($hService_Status_handle, DllStructGetPtr($tService_Status)) EndFunc ;==>_Service_ReportStatus Func _Service_SetServiceStatus($hServiceStatus, $lpServiceStatus) Local $ret = DllCall($hAdvapi32_DLL, "int", "SetServiceStatus", "handle", $hServiceStatus, "ptr", $lpServiceStatus) If $ret[0] = 0 Then If $bAU3ServiceDebug Then ;~ logprint("SetServiceStatus Error" & _WinAPI_GetLastError()) EndIf EndIf If @error Or Not $ret[0] Then Return 0 Return $ret[0] EndFunc ;==>_Service_SetServiceStatus ;/*------------------------------[ service_start ]------------------------------ ; * Starts and runs the service ; *----------------------------------------------------------------------------*/ Func _Service_Startup($argc, $argv) ; report the status to the service control manager. If Not _Service_ReportStatus($SERVICE_START_PENDING, $NO_ERROR, 3000) Then Return ; create the event object. The control handler function signals ; this event when it receives the "stop" control code. ;~ $gServiceStateRunning = True ;~ $service_stop_event = _WinAPI_CreateEvent(0, True, False, "") ; report the status to the service control manager. Return _Service_ReportStatus($SERVICE_RUNNING, $NO_ERROR, 0) EndFunc ;==>_Service_Startup ;/*------------------------------[ service_stop ]------------------------------ ; * Stops the service. ; * ; * NOTE: If this service will take longer than 3 seconds, ; * spawn a thread to execute the stop code and return. ; * Otherwise the SCM will think the service has stopped responding. ; *----------------------------------------------------------------------------*/ Func _Service_SetStopEvent() ;~ $gServiceStateRunning = 0 $bServiceRunning = 0 ;~ If $service_stop_event Then _WinAPI_SetEvent($service_stop_event) EndFunc ;==>_Service_SetStopEvent Thanks for your advise: Running on W11 and Windows Server 2019, same result ! C.
  6. The pattern is still not enough to match all empty rows of the array. Try this: #include <Array.au3> Local $array[7] $array[0] = " " $array[1] = "01621" $array[2] = "xyz" $array[3] = "" $array[4] = " john smith" $array[5] = " sally turner " $array[6] = "" $array = StripEmpty2($array) _ArrayDisplay($array) Func StripEmpty2(ByRef $array, $iStart = 0) Local $sArray = StringRegExpReplace(_ArrayToString($array, Default, $iStart), "\|\s*$|(?<=\|)\s*\|", "") Return StringSplit(($iStart ? _ArrayToString($array, Default, 0, $iStart - 1) & "|" : "") & $sArray, "|", $STR_NOCOUNT) EndFunc First index is not stripped. Also having two or more empty rows at the end of the array will leave an empty space: #include <Array.au3> Local $array[8] $array[0] = " " $array[1] = "01621" $array[2] = "xyz" $array[3] = "" $array[4] = " john smith" $array[5] = " sally turner " $array[6] = "" $array[7] = "" $array = StripEmpty2($array) _ArrayDisplay($array) Func StripEmpty2(ByRef $array, $iStart = 0) Local $sArray = StringRegExpReplace(_ArrayToString($array, Default, $iStart), "\|\s*$|(?<=\|)\s*\|", "") Return StringSplit(($iStart ? _ArrayToString($array, Default, 0, $iStart - 1) & "|" : "") & $sArray, "|", $STR_NOCOUNT) EndFunc
  7. 1- make sure you are on the same CPU architecture (x86 or x64) : script and teradata 2- try using #RequireAdmin 3- ensure teradata has focus 4- try with UIAutomation 5- resort to use MouseClick (no big deal if [ACTIVE])
  8. @AspirinJunkie Thanks for the evaluation. I edited the pattern of my first script above to meet all (as far of my tests went) special cases you mentioned. As for CR, if it is required, OP can just add it along with \s as alternates. In the case of pipes included in the array, OP can change the separation character to anything he wants if needs be.
  9. Do you expect something like this: https://stackoverflow.com/a/64416329/5314940 or like this: https://forum.katalon.com/t/how-to-retrieve-response-header-of-a-network-request-in-a-browser/63834/4 or like this: https://github.com/SeleniumHQ/selenium/issues/12936 ?
  10. That's right Didn't know this exists. Thank you so much!
  11. It looks like you have a null char at the end of the string. You can do something like this to delete all trailing null chars: $sTrackArtist = BinaryToString(StringRegExpReplace(StringToBinary($sTrackArtist), '(00)+$', '')) MsgBox(0, "id3", $sTrackArtist & " - " & $sTrackTitle)
  12. Thanks for the answer I need to do that from within a webdriver session because the specific login process must be done interactively with a regular browser. Only after that interactive action by the browser (controlled by webdriver), i need to retrieve some cookies entries as well as some response-headers entries to be subsequently used in winhttp calls. I was obviously already able to retrieve cookies with "_WD_Cookies()", but not the response headers Here's my code: Local $sCapabilities = "" If FileExists("geckodriver.exe") Then _WD_UpdateDriver('Firefox') $sCapabilities = Call(SetupGecko, False) ElseIf FileExists("chromedriver.exe") Then _WD_UpdateDriver('Chrome') $sCapabilities = Call(SetupChrome, False) ElseIf FileExists("msedgedriver.exe") Then _WD_UpdateDriver('MSEdge') $sCapabilities = Call(SetupEdge, False) ElseIf FileExists("operadriver.exe") Then _WD_UpdateDriver('Opera') $sCapabilities = Call(SetupOpera, False) EndIf If not StringIsSpace($sCapabilities) Then Local $iWebDriver_PID = _WD_Startup() Local $sSession = _WD_CreateSession($sCapabilities) _WD_Window($sSession, "Maximize") _WD_Navigate($sSession, "http://www.somesite.com") If MsgBox($MB_OKCANCEL + $MB_SYSTEMMODAL + $MB_TOPMOST, "Awaiting confirmation", "Please click <OK> as soon as navigation is completed") = $idOk Then ;retrieving session cookies Local $cCookiesJson = _WD_Cookies($sSession, "GETALL") ;retrieving session last response headers (currently i'm unable to do this) ????????? Endif _WD_DeleteSession($sSession) _WD_Shutdown($iWebDriver_PID) Endif Thanks again in advance to anybody
  13. Indeed. It also uses ffmpeg.exe but it's not relevant for this issue. The issue happens with basically all files from bandcamp. Thank you! The Future Sound Of London - Environment 6.5 - 01 Axis of Rotation.mp3 chaika.zip
  14. Hi, Very nice UDF. One impovement can be to add the description to the service as an option. https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc742069(v=ws.11) Thanks anyway !
  15. It is a problem with the service trying to be launched, and the current lack of error checking, for such an important part experience, I'm looking into improving this The script for the taadd API calls a function that is responsible for sending the subscribe request to the process and launching the service if not available, here https://github.com/genius257/Manga/blob/main/www/api/taadd.au3#L35 The function is called, when you navigate to the subscription request page, via the subscribe link on a manga. The subscribe function is defined here: https://github.com/genius257/Manga/blob/main/mangaSvc/api.au3#L26
  16. Hi @Gianni 🙂, AutoItObject_Internal is much slower than AutoitObject. An issue regarding speed exists on github: https://github.com/genius257/AutoItObject-Internal/issues/10
  17. It looks like replacing the costly StringStripWS() with StringIsSpace() the function performs much better: Func _strip_Andreik(ByRef $aData, $iStart = 0) If Not IsArray($aData) Then Return SetError(1, 0, False) Local $iElements = UBound($aData) If $iStart >= $iElements Then Return SetError(2, 0, False) Local $sResult For $Index = $iStart To $iElements - 1 $sResult &= (StringIsSpace($aData[$Index]) ? $aData[$Index] & '|' : '') Next Return StringSplit(StringTrimRight($sResult, 1), '|', 2) EndFunc Totally forgot about this function. Thanks @AspirinJunkie.
  18. The tests previously conducted to assess the performance of the UDFs AutoItObject.au3 and AutoItObject_Internal.au3 under various conditions have highlighted discernible differences, albeit subtle. The analysis of the collected data underscores the slight preference in terms of speed for AutoItObject.au3. While this difference may not be considerable, it remains non-negligible in certain usage contexts. It is important to note that each UDF has its own advantages and disadvantages, which can influence their selection depending on the specific project requirements. The comparative table provided by @genius257 while informative, may spark debates and additional nuances regarding the evaluation of the performance and features of each UDF. Unfortunately, I no longer have the test code available.
  19. I have added a function and packed the whole thing into a speed comparison: #include <Array.au3> Global Const $aArrayRaw = Get_Array() Global $f_DecimalPlaces = 1 Global $iT, $a_Results[0][3] Func Get_Array() Local $aArray[1e6] For $i = 0 To UBound($aArray) - 1 $aArray[$i] = Random(0,2,1) = 2 ? " " : "x" Next Return $aArray EndFunc ;==>Get_Array ; the first measurement $aArray = $aArrayRaw ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "Andreik" $iT = TimerInit() $aArray = _strip_Andreik($aArray) $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT) ; the second measurement $aArray = $aArrayRaw ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "SmOke_N" $iT = TimerInit() $aArray = _strip_SmOke_N($aArray) $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT) ; the third measurement $aArray = $aArrayRaw ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "Nine 1" $iT = TimerInit() $aArray = _stripNine1($aArray) $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT) ; the fourth measurement $aArray = $aArrayRaw ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "Nine 2" $iT = TimerInit() $aArray = _stripNine2($aArray) $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT) ; the fifth measurement $aArray = $aArrayRaw ReDim $a_Results[UBound($a_Results) + 1][3] $a_Results[UBound($a_Results) - 1][0] = "AspirinJunkie" $iT = TimerInit() _strip_AspirinJunkie($aArray) $iT = TimerDiff($iT) $a_Results[UBound($a_Results) - 1][1] = ($iT) ; calculate results and print them out _ArraySort($a_Results, 0, 0, 0, 1) For $i = 0 To UBound($a_Results) - 1 $a_Results[$i][2] = Round($a_Results[$i][1] / $a_Results[0][1], 2) $a_Results[$i][1] = Round($a_Results[$i][1], $f_DecimalPlaces) Next _ArrayDisplay($a_Results, "Measurement Results", "", 16 + 64, Default, "name|time [ms]|factor") Func _strip_Andreik(ByRef $aData, $iStart = 0) If Not IsArray($aData) Then Return SetError(1, 0, False) Local $iElements = UBound($aData) If $iStart >= $iElements Then Return SetError(2, 0, False) Local $sResult For $Index = $iStart To $iElements - 1 $sResult &= (StringStripWS($aData[$Index], 8) ? $aData[$Index] & '|' : '') Next Return StringSplit(StringTrimRight($sResult, 1), '|', 2) EndFunc Func _stripNine1(ByRef $array, $iStart = 0) Local $sArray = StringRegExpReplace(_ArrayToString($array, Default, $iStart), "\|\s*$|(?<=\|)\s*\|", "") Return StringSplit(($iStart ? _ArrayToString($array, Default, 0, $iStart - 1) & "|" : "") & $sArray, "|", $STR_NOCOUNT) EndFunc Func _stripNine2(ByRef $array, $iStart = 0) Local $aTemp = _ArrayFindAll($array, "^\s*$", $iStart, Default, 0, 3) _ArrayInsert($aTemp, 0, UBound($aTemp)) _ArrayDelete($array, $aTemp) Return $array EndFunc ; $bNoWS = White spaces only count as empty element, true by default Func _strip_SmOke_N(ByRef $aArgs, $iStart = 0, $bNoWS = True) If UBound($aArgs, 2) Then Return SetError(1, 0, 0) ; out of bounds If $iStart = Default Or $iStart == -1 Then $iStart = 0 If $bNoWS = Default Or $bNoWS == -1 Then $bNoWS = True Local $iUB = UBound($aArgs) ; catch start out of bounds If $iStart < 0 Or $iStart > $iUB - 1 Then Return SetError(2, 0, 0) Local $aRet[$iUB] Local $iEnum = 0 ; build array without concatenation For $i = $iStart To $iUB - 1 If StringLen($aArgs[$i]) == 0 Then ContinueLoop If $bNoWS Then If StringRegExp($aArgs[$i], "(?m)^\s+$") Then ContinueLoop EndIf $aRet[$iEnum] = $aArgs[$i] $iEnum += 1 Next If $iEnum = 0 Then ; nothing found, but rather than return a false ; set error and return array where user can do what they want with it Return SetError(2, 0, $aArgs) EndIf ; resize return array ReDim $aRet[$iEnum] ; return extended as the ubound of new array Return SetExtended($iEnum, $aRet) EndFunc Func _strip_AspirinJunkie(ByRef $A, $iStart = 0, $iEnd = UBound($A) - 1) Local $x = $iStart For $i = $iStart To $iEnd If StringIsSpace($A[$i]) Then ContinueLoop $A[$x] = $A[$i] $x += 1 Next Redim $A[$x] EndFunc Nine`s first function performs best, but would still have to be adapted to certain special cases for which it currently does not work, depending on the type of data: 1. if first array element is empty it`s still in the array 2. only line breaks are not recognized as empty strings (which may be correct depending on the context) and 3. if pipes ("|") occur in the strings.
  20. For comparative testing purposes I tried to translate the script created by @Numeric1 at this link which uses AutoitObject, so as to use AutoItObject_Internal.au3 by @genius257 instead. (The latter does not require additional DLLs.). Maybe it seems a little slower and slightly less responsive (?) P.S. I created a new thread just to not hijack @Numeric1's original thread. (any improvements and corrections relating to the translation of the listing are welcome) ; =============================================================================================================================== ; original script created by @Numeric1 at the link below ; https://www.autoitscript.com/forum/topic/211824-ping-pong-game-with-autoitobject/ ; =============================================================================================================================== ; Game Overview: ; - The game consists of a paddle and a ball. ; - The player controls the paddle using the left and right arrow keys. ; - The objective is to bounce the ball off the paddle and prevent it from hitting the bottom edge of the window. ; - If the ball hits the bottom edge, the game ends. ; - As the game progresses, the speed of the ball increases periodically, making it more challenging. ; Controls: ; - Left Arrow Key: Move the paddle to the left. ; - Right Arrow Key: Move the paddle to the right. ; - S Key: Pause the game. ; - When the game is paused, press Left or Right arrow key to resume. ; Enjoy playing Ping Pong! ; =============================================================================================================================== #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GDIPlus.au3> ; #include "AutoItObject.au3" #include "AutoItObject_Internal.au3" ; <-- https://www.autoitscript.com/forum/topic/185720-autoitobject-pure-autoit #include <Misc.au3> Global $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc") _GDIPlus_Startup() Const $COLOR_RED = 0xFFFF0000 Const $COLOR_GREEN = 0xFF00FF00 Func Ball($x = 0, $y = 0, $size = 5) Local $cBall = IDispatch() ; _AutoItObject_Class() With $cBall .dx = 10 .dy = -10 .size = $size .X = $x .Y = $y .__defineGetter("move", _move) EndWith Return $cBall ; .Object EndFunc ;==>Ball Func Paddle($x = 0, $size = 5) Local $cPaddle = IDispatch() ; _AutoItObject_Class() With $cPaddle .X = $x .size = $size .dx = 20 .__defineGetter("moveLeft", _moveLeft) .__defineGetter("moveRight", _moveRight) EndWith Return $cPaddle ; .Object EndFunc ;==>Paddle Func _moveLeft($this) $this.parent.X -= $this.parent.dx If $this.parent.X < 0 Then $this.parent.X = 0 EndFunc ;==>_moveLeft Func _moveRight($this) ; , $maxX) Local $maxX = $this.arguments.values[0] Local $paddleWidth = $this.parent.size If $this.parent.X + $this.parent.dx + $paddleWidth <= $maxX Then $this.parent.X += $this.parent.dx Else $this.parent.X = $maxX - $paddleWidth EndIf EndFunc ;==>_moveRight Func GamePanel() Local $hGUI = GUICreate("Ping Pong", 400, 300, -1, -1, $WS_SIZEBOX + $WS_SYSMENU) GUISetBkColor(0x000000) GUISetState() Local $aClient = WinGetClientSize($hGUI) If @error Then Return SetError(1, 0, 0) Local $iWidth = $aClient[0] Local $iHeight = $aClient[1] Local $aGDIMap[5] $aGDIMap[0] = _GDIPlus_GraphicsCreateFromHWND($hGUI) $aGDIMap[1] = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $aGDIMap[0]) $aGDIMap[2] = _GDIPlus_ImageGetGraphicsContext($aGDIMap[1]) $aGDIMap[3] = _GDIPlus_BrushCreateSolid($COLOR_RED) $aGDIMap[4] = _GDIPlus_HatchBrushCreate(4, $COLOR_GREEN) Local $Ball = Ball(40, 40) Local $paddleX = Paddle(150, 100) Local $cGamePanel = IDispatch() ; _AutoItObject_Class() With $cGamePanel .iWidth = $iWidth .iHeight = $iHeight .ball = $Ball .paddle = $paddleX .map = $aGDIMap .speedLevel = 100 .__defineGetter("move", _move) .__defineGetter("drawStage", _drawStage) .__defineGetter("cleanUpResources", _cleanUpResources) .__destructor(_cleanUpResources) .__defineGetter("runGameLoop", _runGameLoop) EndWith Return $cGamePanel ; .Object EndFunc ;==>GamePanel Func _move($this) Local $x = $this.parent.ball.X Local $y = $this.parent.ball.Y Local $dx = $this.parent.ball.dx Local $dy = $this.parent.ball.dy Local $Width = $this.parent.iWidth Local $Height = $this.parent.iHeight Local $BallSize = $this.parent.ball.size If $y + $dy >= ($Height - 40) And $x + $BallSize >= $this.parent.paddle.X And $x <= $this.parent.paddle.X + $this.parent.paddle.size Then $dy *= -1 EndIf If $y + $dy <= 0 Then $dy = Abs($dy) EndIf If $y + $dy >= $Height - $BallSize Then MsgBox(0, "Game Over", "You missed the ball! Game Over!") Exit EndIf If $x + $dx <= 0 Then $dx = Abs($dx) EndIf If $x + $dx >= $Width - $BallSize Then $dx = -Abs($dx) EndIf $x += $dx $y += $dy $this.parent.ball.dx = $dx $this.parent.ball.dy = $dy $this.parent.ball.X = $x $this.parent.ball.Y = $y $this.parent.drawStage() EndFunc ;==>_move Func _drawStage($this) Local $hGraphics = $this.parent.map[0] Local $hBitmap = $this.parent.map[1] Local $hGraphicsCtxt = $this.parent.map[2] Local $iX = $this.parent.ball.X Local $iY = $this.parent.ball.Y Local $iRadius = $this.parent.ball.size Local $padX = $this.parent.paddle.X Local $padH = $this.parent.iHeight - 40 _GDIPlus_GraphicsClear($hGraphicsCtxt, 0xFF000000) _GDIPlus_GraphicsFillEllipse($hGraphicsCtxt, $iX - $iRadius, $iY - $iRadius, $iRadius * 2, $iRadius * 2, $this.parent.map[3]) _GDIPlus_GraphicsFillRect($hGraphicsCtxt, $padX, $padH, $this.parent.paddle.size, 10, $this.parent.map[4]) _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $this.parent.iWidth, $this.parent.iHeight) EndFunc ;==>_drawStage Func _cleanUpResources($this) ConsoleWrite("clean up ressources...." & @CRLF) Local $map = $this.parent.map _GDIPlus_GraphicsDispose($map[0]) _GDIPlus_BitmapDispose($map[1]) _GDIPlus_GraphicsDispose($map[2]) _GDIPlus_BrushDispose($map[3]) $this.parent.map = 0 _GDIPlus_Shutdown() EndFunc ;==>_cleanUpResources Func _runGameLoop($this) Local $speedUpTime = 5000 Local $lastMoveTime = TimerInit() Local $maxX = $this.parent.iWidth While 1 If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop If _IsPressed(25) Then $this.parent.paddle.moveLeft() If _IsPressed(27) Then $this.parent.paddle.moveRight($maxX) If _IsPressed(53) Then While 1 If _IsPressed(25) Or _IsPressed(27) Then ExitLoop Sleep(100) WEnd EndIf If TimerDiff($lastMoveTime) >= $speedUpTime Then $this.parent.speedLevel -= 5 If $this.parent.speedLevel < 0 Then $this.parent.speedLevel = 0 $lastMoveTime = TimerInit() EndIf $this.parent.move() Sleep($this.parent.speedLevel) WEnd EndFunc ;==>_runGameLoop Func _ErrFunc($oError) ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_ErrFunc ;================================================ Global $game = GamePanel() $game.runGameLoop() ConsoleWrite("------> the end <-------" & @CRLF) ; $game = 0 ;=================================================
  21. Yesterday
  22. Yes, why not? Whatever makes the game interesting and entertaining.
  23. I have taken note of your valuable suggestion. What do you think about this idea? : instead of making poisoned food appear, I thought about making a speed reducer appear to give the player more luck. What do you think ?
  24. Redim it's quite expensive with large arrays. With few indices every version is more than enough.
  25. Those 2 seems faster : Func StripEmpty2(ByRef $array, $iStart = 0) Local $sArray = StringRegExpReplace(_ArrayToString($array, Default, $iStart), "^\s*\||(?<=\|)\s*\||\|(?=[\s\|]*$)", "") Return StringSplit(($iStart ? _ArrayToString($array, Default, 0, $iStart - 1) & "|" : "") & $sArray, "|", $STR_NOCOUNT) EndFunc Func StripEmpty3(ByRef $array, $iStart = 0) Local $aTemp = _ArrayFindAll($array, "^\s*$", $iStart, Default, 0, 3) _ArrayInsert($aTemp, 0, UBound($aTemp)) _ArrayDelete($array, $aTemp) Return $array EndFunc
  26. That's pretty interesting. The regex overhead is the only thing that I can think of for that with a single redim. If I'm being honest, I didn't even see your post before I posted. And was to tired to test yours out once I posted lol. But proofs in the pudding so to speak.
  1. Load more activity
×
×
  • Create New...