This is beyond my comfort zone of Sendinput and Sleep.
Any help as to what am doing wrong, would much appreciated.
I have found this function WatchFolder() - updated on 2021-10-14 - AutoHotkey Community and using some of the examples shared on that thread I was ables to put this together:
#Persistent
#Include, <WatchFolder>
WatchFolder("C:\Temp\", "ReportFunction", false, 1 | 2 | 4 | 8 |16 | 32 | 64 | 256)
Return
ReportFunction(Directory, Changes) {
For Each, Change In Changes {
Action := Change.Action
Name := Change.Name
If (Action = 3)
Run, Notepad
}
}
I figured out how to watch for all the other events correctly (deleted, added etc etc). I am having problems wih the file modified event. The event occurs twice.
so in the above ebove example notepad is run twice. If I set Run to open .Url it will also open twice.
I dont know why. I tried changing a bunch of things in my ReportFunction but nothing worked.
PS: Watchfolder function is saved in Documents\Autohotkey\Lib folder and I have made no changes to it, it is as I downloaded it.
As I have checked myself, it works just fine if you modify the files in the folder yourself but while using the downloads folder like your example script in the ahk forum post or using temp folder it will execute multiple times as normal. The reason is, it's keep updating and modifying the file while downloading, you can check it as well if you download a large sized file, size will change time to time. Just to try, I downloaded your example in the ahk forum and it opened 3 notepad windows while just downloading 342bytes sized file. Temp folder is just the same, files keep written and deleted there, not easy to track and execute by those folders like that. Try to set a custom folder location and check it by modifying the files by yourself. If you must use those folders maybe you can add a sleep like 5 secs after Run command but I don't know how efficient it would be.
Related
so I use geolocator to get the place location, but it gives a decimal. But my app need the location as degrees, minutes and seconds, is there another package/lib that can do it, our a way to do that with geolocator, tried formatting with sub string but to no avail (maybe I did it wrong).
I'm in a project in which I have to run an Anylogic simulator multiple times. I made an script to modify the input data, run the simulator and then store the output data just before the next simulation run.
The idea is to externally run the simulation (from a python file). The problem is that, when the simulation ends, the simulation window doesn't close automatically so the python file won't continue executing.
I´ve tried to run the simulator without showing the animation of the simulation but still opens a window so it doesn´t work for my purpose.
I don´t know if there is an option in Anylogic to export a model that automatically closes the window once the simulation is completed or if there is any way of creating a simulator that runs without opening any window.
Thank you.
Unfortunately there is no such solution. Even if you can run without UI in Linux, it will not automatically close once the run is complete. I use a workaround:
It is a Python script that scans the outputs folder every 5 seconds and if there are changes in the files, it closes the AnyLogic file. Use this as an inspiration::
from time import sleep
from utils.data.fileSystem import FileSystem
def sync_polling_folder(path, predicate, delay_sec):
print('checking under ' + path + ' folder')
beginning = FileSystem.stat(path)
old = beginning
new = beginning
def two_files_are_different():
return not predicate(str(old), str(new))
def the_process_has_not_begun():
return str(new) == str(beginning) or str(old) == str(beginning)
# if two folders are the same, quit (means no-changes = finished)
# but if they are equal because process never started, keep going
while two_files_are_different() or the_process_has_not_begun():
print('[sleeping] because files are not written yet.')
sleep(delay_sec) # main thread waiting
old = new
new = FileSystem.stat(path)
print('[anylogic] ready to be killed')
return True
i'm using this on push button click in Qt:
QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"),
QString(),
tr("(*.csv));
it take 3-4 second to open the save Form. why? how i can improve speed?
Try to connect this slot to a QPushButton:
void MainWindow::openFD(){
QTime myopentime=QTime::currentTime();
for (int i=0;i<1000000;i++) ;//comment out this line for the real test
QString fileName = QFileDialog::getSaveFileName(this,QString(),QString(myopentime.toString("m.s.zzz")+" "+QTime::currentTime().toString("m.s.zzz"))
,tr("*.csv") );
}
Then try to run it with and without the count part.
You will see, that the count part adds some ms... without it there is not even ms (mili-second) of difference in the time shown in filename place.
So, you have to search somewhere else in your code or give us a better example.
PS:
1) You will need :
#include <QTime>
2) The line that counting is there to show you that my method works (since you will see some difference when uncomment)
Result and Answer: The problem is not on QFileDialog if this test will not give you differences but somewhere else in your code or possibly in the Window manager of your OS.
For some load testing simulations, I'm looking at scripting with AHK 1.1. The issue is we have a client-server setup with multiple workstations so I'd really like to be able to trigger the same script (or even variations) to run on multiple PCs at once, to accurately simulate multiple users all hammering the system.
Even more useful would be to make sure the same test happens at exactly (within some tolerance) the same time, to check this doesn't cause problems.
What be would the best way to do this? Do it from within AHK itself, or use some separate remote-control tool to let me fire off scripts on PCs of my choosing?
With ahk you will need scripts acting as server and clients so both needs to be running no matter the method used...
As to the TCP/IP you can do this, you just need to find out if you have any usable/open posts your scripts can use...
I just helped an australian guy the other day setup a great working lot of server/client scripts
using the Socket Class by Bentschi looking something like this
Server:
;Server
#include Socket.ahk
myTcp := new SocketTCP()
myTcp.bind("addr_any", 54321)
myTcp.listen()
myTcp.onAccept := Func("OnTCPAccept")
return
OnTCPAccept(this)
{
newTcp := this.accept()
newTcp.onRecv := func("OnTCPRecv")
newTcp.sendText("Connected")
}
OnTCPRecv(this)
{
msgbox % this.recvText()
}
Client:
;Client
#include Socket.ahk
myTcp := new SocketTCP()
myTcp.connect("your servers A_IPAddress1", 54321) ; lokal
myTcp.onRecv := Func("OnTcpRecv")
return
OnTcpRecv(this)
{
ToolTip % this.RecvText()
}
But to use and or set something like this up you may need to know what ports are usable on the network or have the ability to change settings as needed.
The speed of the TCP/IP scripts are in the low milliseconds (under 20 on my network) so no real tolerance to speak of.
Hope it helps
As wrote Sidola you can check shared folder for some file or folder. You can use
IfExist command for it. Here is example:
Loop
{
IfExist, c:\a.txt
{
break
}
}
;code to execute if c:\a.txt exists comes below.
MsgBox, 1
Also you can add Sleep command to put less stress on hdd like for example in code below:
Loop
{
IfExist, c:\a.txt
{
break
}
Sleep, 1000
}
;code to execute if c:\a.txt exists comes below.
MsgBox, 1
Also, always use AutoHotkey and its documenatation from http://ahkscript.org/ (current uptodate version, new official website)! AutoHotkey and its documentation from autohotkey.com is outdated and you may have some problems using them!
I can't provide actual code, but there is a way to kind of inject a service into your LAN machines through the Admin$ share and remotely control it. This way AHK wouldn't need to run on the LAN computers all the time.
I don't know how exactly this could be done, but PsShutdown does it to hibernate LAN PCs which is normally impossible.
In case you actually manage to do it, it would be great if you could share it.
How would I validate that a jpg file is a valid image file. We are having files written to a directory using FTP, but we seem to be picking up the file before it has finished writing it, creating invalid images. I need to be able to identify when it is no longer being written to. Any ideas?
Easiest way might just be to write the file to a temporary directory and then move it to the real directory after the write is finished.
Or you could check here.
JPEG::Error
[arguments: none] If the file reference remains undefined after a call to new, the file is to be considered not parseable by this module, and one should issue some error message and go to another file. An error message explaining the reason of the failure can be retrieved with the Error method:
EDIT:
Image::TestJPG might be even better.
You're solving the wrong problem, I think.
What you should be doing is figuring out how to tell when whatever FTPd you're using is done writing the file - that way when you come to have the same problem for (say) GIFs, DOCs or MPEGs, you don't have to fix it again.
Precisely how you do that depends rather crucially on what FTPd on what OS you're running. Some do, I believe, have hooks you can set to trigger when an upload's done.
If you can run your own FTPd, Net::FTPServer or POE::Component::Server::FTP are customizable to do the right thing.
In the absence of that:
1) try tailing the logs with a Perl script that looks for 'upload complete' messages
2) use something like lsof or fuser to check whether anything is locking a file before you try and copy it.
Again looking at the FTP issue rather than the JPG issue.
I check the timestamp on the file to make sure it hasn't been modified in the last X (5) mins - that way I can be reasonably sure they've finished uploading
# time in seconds that the file was last modified
my $last_modified = (stat("$path/$file"))[9];
# get the time in secs since epoch (ie 1970)
my $epoch_time = time();
# ensure file's not been modified during the last 5 mins, ie still uploading
unless ( $last_modified >= ($epoch_time - 300)) {
# move / edit or what ever
}
I had something similar come up once, more or less what I did was:
var oldImageSize = 0;
var currentImageSize;
while((currentImageSize = checkImageSize(imageFile)) != oldImageSize){
oldImageSize = currentImageSize;
sleep 10;
}
processImage(imageFile);
Have the FTP process set the readonly flag, then only work with files that have the readonly flag set.