OhBobSaget Posted March 24, 2021 Share Posted March 24, 2021 Hi, I am trying to do a program that will be able to receive a number of filename and populate a list but i am having some issues. Here's how i need it to work : 1) Select a number of PDF files then do a right click on them 2) Select the Merge PDF Option 3) This should open the autoIT app then show the list of file to merge -> Unfortunately Windows can't send multiple filenames to an EXE file and this is by design.. Currently, windows open 10X the autoIT program with 1 file argument... The only way for this to work at the moment it to use Send To then this will work... ( but i want it the the main context menu ) From what i saw online, you need a listener that will get this list then pass it to the main program but i don't know to much where to start. Anyone here had that kind of issue ? Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 24, 2021 Moderators Share Posted March 24, 2021 Moved to the appropriate forum, as the Developer General Discussion forum very clearly states: Quote General development and scripting discussions. Do not create AutoIt-related topics here, use the AutoIt General Help and Support or AutoIt Technical Discussion forums. Moderation Team OhBobSaget 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
argumentum Posted March 25, 2021 Share Posted March 25, 2021 5 hours ago, OhBobSaget said: -> Unfortunately Windows can't send multiple filenames to an EXE file and this is by design.. hmmm, use an IPC. I put together a few. Look at my signature Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
JockoDundee Posted March 25, 2021 Share Posted March 25, 2021 5 hours ago, OhBobSaget said: From what i saw online, you need a listener that will get this list then pass it to the main program but i don't know to much where to start. Send To is ultimately the way to go, if possible. If not, then a down and dirty way of doing it would just be to have your context menu .exe create a file, based on the argument passed to it, in a temp directory with a different extension and the full path contained in the contents. The. have it call the “real” exe only if it isn’t running yet, and then exit. Then have the “real” .exe sleep a second or so when it starts to let all the temp files be created. Then have it scoop them up and process them, then delete them and exit. It’s not pretty, but I think you’ll end up doing something like this no matter what. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Nine Posted March 25, 2021 Share Posted March 25, 2021 Here my contribution to your project. I felt it could be fun to make a POC using a RDBMS. Seems it is working quite well : #include <SQLite.au3> #include <Constants.au3> #include <Misc.au3> Local Const $SQLITE_DLL = "sqlite3.dll" Local Const $SQLITE_Database_Name = "Merge.DB" If $CmdLine[0] <> 1 Then Exit MsgBox ($MB_SYSTEMMODAL, "", "You need to provide full path file") If Not FileExists($CmdLine[1]) Then Exit MsgBox ($MB_SYSTEMMODAL, "", "File does not exist") Local $hProc While True $hProc = _Singleton("MergeListener", 1) If $hProc Then ExitLoop Sleep(Random(10, 15)) WEnd _SQLite_Startup($SQLITE_DLL, False, 1) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Startup Error", "Unable to start SQLite. Check existence of DLL") Local $hDB = _SQLite_Open($SQLITE_Database_Name) If $hDB = 0 Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Open Error", "Unable to open database") Local $aRow _SQLite_QuerySingleRow (-1, "select count(*) from Merge;", $aRow) If Not $aRow[0] Then ConsoleWrite ("Start Merge Process here" & @CRLF) _SQLite_Exec(-1, "insert into merge values('" & $CmdLine[1] & "');") _SQLite_Close() _SQLite_Shutdown() You need to create a "Merge.DB" file with a single table called "Merge" with a single column called "Path" (unique not null). And you are good to go. The actual Merge script is the one you start on the fist creation of a row. The actual Merge script can peek (select) at the table until there is no more rows added. At the end of the process, it needs to delete all rows. I think you should also have a mutex on the overall Merge process, so there is no 2 processes competing. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
OhBobSaget Posted March 25, 2021 Author Share Posted March 25, 2021 11 hours ago, JockoDundee said: Send To is ultimately the way to go, if possible. If not, then a down and dirty way of doing it would just be to have your context menu .exe create a file, based on the argument passed to it, in a temp directory with a different extension and the full path contained in the contents. The. have it call the “real” exe only if it isn’t running yet, and then exit. Then have the “real” .exe sleep a second or so when it starts to let all the temp files be created. Then have it scoop them up and process them, then delete them and exit. It’s not pretty, but I think you’ll end up doing something like this no matter what. Yes, it was my first thought on how to do it, but too dirty for me I would prefer to end up with Send To than using this method hehe Thank you JockoDundee Link to comment Share on other sites More sharing options...
OhBobSaget Posted March 25, 2021 Author Share Posted March 25, 2021 17 minutes ago, Nine said: Here my contribution to your project. I felt it could be fun to make a POC using a RDBMS. Seems it is working quite well : #include <SQLite.au3> #include <Constants.au3> #include <Misc.au3> Local Const $SQLITE_DLL = "sqlite3.dll" Local Const $SQLITE_Database_Name = "Merge.DB" If $CmdLine[0] <> 1 Then Exit MsgBox ($MB_SYSTEMMODAL, "", "You need to provide full path file") If Not FileExists($CmdLine[1]) Then Exit MsgBox ($MB_SYSTEMMODAL, "", "File does not exist") Local $hProc While True $hProc = _Singleton("MergeListener", 1) If $hProc Then ExitLoop Sleep(Random(10, 15)) WEnd _SQLite_Startup($SQLITE_DLL, False, 1) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Startup Error", "Unable to start SQLite. Check existence of DLL") Local $hDB = _SQLite_Open($SQLITE_Database_Name) If $hDB = 0 Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Open Error", "Unable to open database") Local $aRow _SQLite_QuerySingleRow (-1, "select count(*) from Merge;", $aRow) If Not $aRow[0] Then ConsoleWrite ("Start Merge Process here" & @CRLF) _SQLite_Exec(-1, "insert into merge values('" & $CmdLine[1] & "');") _SQLite_Close() _SQLite_Shutdown() You need to create a "Merge.DB" file with a single table called "Merge" with a single column called "Path" (unique not null). And you are good to go. The actual Merge script is the one you start on the fist creation of a row. The actual Merge script can peek (select) at the table until there is no more rows added. At the end of the process, it needs to delete all rows. I think you should also have a mutex on the overall Merge process, so there is no 2 processes competing. So this code snippet would work if : I select 10 PDF files, and from the context menu i select the option to launch the PDF merge ? Because this action will launch 10x this code snippet in a short period of time. From my understanding, you are creating a DB that will hold all the filepaths... but how does it know that it is now time to launch the main AutoIT App that will do the PDF Merge ? Also.... will it be able to write in that DB with 10 apps are trying at the same time to interact with Merge.DB ? Thank you Nine Link to comment Share on other sites More sharing options...
Nine Posted March 25, 2021 Share Posted March 25, 2021 (edited) Yes. This is why I have use a mutex to ensure that only one process runs at a given time. Like I already said the merge process can peek at the table. Please read carefully my comments at the end of the snippet. ps. do not quote everything we tell you, it makes the thread cumbersome for nothing. Use reply box at the end of the thread instead. pps. In my test I have started 12 listeners at a time in a close loop and all the 12 paths were written correctly in th DB... Edited March 25, 2021 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
OhBobSaget Posted March 25, 2021 Author Share Posted March 25, 2021 I downloaded the SQL3Lite, managed to create the table, column etc. then use your code sample. Just one thing that i am not too sure... When does the outside APP to merge will be called? From what i can see in the code provided this is what will do it : If Not $aRow[0] Then ConsoleWrite ("Start Merge Process here" & @CRLF) I tried replacing this ConsoleWrite command by a msgbox to see the behavior and it seems that it is never called. What i would like here is that when all the files have been processed, they are added to a list in a GUI then the user can choose various options before merging them Sorry if i am unclear. Link to comment Share on other sites More sharing options...
JockoDundee Posted March 25, 2021 Share Posted March 25, 2021 @Nine, should the insert really be after the select count(*)? How does the Merge process get called if there is only one file? _SQLite_QuerySingleRow (-1, "select count(*) from Merge;", $aRow) If Not $aRow[0] Then ConsoleWrite ("Start Merge Process here" & @CRLF) _SQLite_Exec(-1, "insert into merge values('" & $CmdLine[1] & "');") Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
JockoDundee Posted March 25, 2021 Share Posted March 25, 2021 3 hours ago, OhBobSaget said: Yes, it was my first thought on how to do it, Did you have a second thought on how to do it, because I can’t really think of a way besides some variation of what I said, aside from using different IPCs? Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Nine Posted March 25, 2021 Share Posted March 25, 2021 (edited) 1 hour ago, OhBobSaget said: I tried replacing this ConsoleWrite command by a msgbox to see the behavior and it seems that it is never called. Yes there was a small bug, select count(*) is still returning a string even if the result is 0. So try this now : #include <SQLite.au3> #include <Constants.au3> #include <Misc.au3> Local Const $SQLITE_DLL = "sqlite3.dll" Local Const $SQLITE_Database_Name = "Merge.DB" While True If _Singleton("MergeListener", 1) Then ExitLoop Sleep(Random(10, 15)) WEnd If $CmdLine[0] <> 1 Then Exit MsgBox ($MB_SYSTEMMODAL, "", "You need to provide full path file") If Not FileExists($CmdLine[1]) Then Exit MsgBox ($MB_SYSTEMMODAL, "", "File does not exist") _SQLite_Startup($SQLITE_DLL, False, 1) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Startup Error", "Unable to start SQLite. Check existence of DLL") Local $hDB = _SQLite_Open($SQLITE_Database_Name) If $hDB = 0 Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Open Error", "Unable to open database") Local $aRow _SQLite_QuerySingleRow (-1, "select count(*) from Merge;", $aRow) If $aRow[0] = "0" Then MsgBox ($MB_SYSTEMMODAL, VarGetType($aRow[0]), "Start Merge Process here" & @CRLF) _SQLite_Exec(-1, "insert into merge values('" & $CmdLine[1] & "');") _SQLite_Close() _SQLite_Shutdown() ps. make sure you delete all rows from the table before starting your test again... Edited March 25, 2021 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Nine Posted March 25, 2021 Share Posted March 25, 2021 36 minutes ago, JockoDundee said: should the insert really be after the select count(*)? Not important, it has to be started sooner or later. 37 minutes ago, JockoDundee said: How does the Merge process get called if there is only one file? To be honest I don't care, it is the Merge responsibility to manage 1 or multiple files. The POC was about the listener... “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
argumentum Posted March 25, 2021 Share Posted March 25, 2021 (edited) expandcollapse popup#NoTrayIcon #include <Mailslot.au3> ; "http://www.autoitscript.com/forum/index.php?showtopic=106710" Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest" example() ; Obviously you'll have to compile the script and associate a file type to it, in order to test this example. Func example() ; "https://www.autoitscript.com/forum/index.php?showtopic=205483&view=findpost&p=1478490" Local $hTimer = TimerInit(), $hTimerTotal = $hTimer Local $hMailSlot = _MailSlotCreate($sMailSlotName) If @error Then If $CmdLine[0] Then _MailSlotWrite($sMailSlotName, $CmdLineRaw) Exit EndIf SplashTextOn(@ScriptName, "1 sec. please") Local $iWaitTime = Round(TimerDiff($hTimer)) * 10 ; more or less, think of a good delay scheme. This is what I thought of. Local $iCount = 0, $sTemp, $sFiles = "" If $CmdLine[0] Then For $n = 1 To $CmdLine[0] example_AddThisFileToTheList($hTimer, $iCount, $sFiles, $CmdLine[$n]) Next Else ;~ If FileExists(@ScriptDir & "\*.TestAFile") Then ;~ FileDelete(@ScriptDir & "\*.TestAFile") ;~ Else ;~ For $n = 1 To 100 ; create 100 sample files with ext. ".TestAFile" ;~ FileWriteLine(@ScriptDir & "\Test file number " & StringRight("000" & $n, 3) & ".TestAFile", "Test file. Do delete.") ;~ Next ;~ EndIf EndIf Do $sTemp = example_ReadMessage($hMailSlot) If @extended Then example_AddThisFileToTheList($hTimer, $iCount, $sFiles, $sTemp) Until TimerDiff($hTimer) > $iWaitTime _MailSlotClose($hMailSlot) ; ...to free the instance, if you want to do just this run on its own. SplashOff() MsgBox(0, @ScriptName, "Listing " & $iCount & " file(s) in " & Round(TimerDiff($hTimerTotal)) & " ms. :" & @CRLF & $sFiles, 120) EndFunc ;==>example Func example_AddThisFileToTheList(ByRef $hTimer, ByRef $iCount, ByRef $sFiles, $sTemp) $hTimer = TimerInit() $iCount += 1 $sFiles &= StringReplace($sTemp, '"', '') & @CRLF EndFunc ;==>example_AddThisFileToTheList Func example_ReadMessage($hHandle) Local $iSize = _MailSlotCheckForNextMessage($hHandle) If $iSize Then Return SetError(0, $iSize, _MailSlotRead($hHandle, $iSize, 1)) Return "" EndFunc ;==>example_ReadMessage Edited March 27, 2021 by argumentum nicer code Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
JockoDundee Posted March 25, 2021 Share Posted March 25, 2021 3 hours ago, Nine said: Not important, it has to be started sooner or later Yes but in the case where only one file is selected (perhaps by accident, if merging one file is like the sound of one hand clapping), merge never gets called. But the row still gets added to the DB. Next time, multiple files do get selected (seconds or days later), the single file will get merged in with the others unintentionally. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Nine Posted March 25, 2021 Share Posted March 25, 2021 I think you are misunderstanding the way the script works. Did you try it and find a bug that can be replicated or you just assume you are right based on a wrong assumption ? Because the script works all the time for 1 or 12 or xyz files selected. An easy way to prove this, use this code : #include <Constants.au3> #include <File.au3> #include <Array.au3> Local $aList = _FileListToArray(@ScriptDir, "*.au3", $FLTA_FILES, True) For $i = 1 to 1; $aList[0] Run('merge.exe "' & $aList[$i] & '"') Sleep (50) Next Compile the latest POC into merge.exe. Then run this caller. You will see it works all the time...As I already said, ensure you delete all rows before starting a new test “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
JockoDundee Posted March 26, 2021 Share Posted March 26, 2021 4 hours ago, Nine said: I think you are misunderstanding the way the script works. I am. I am sorry. Code hard, but don’t hard code... Link to comment Share on other sites More sharing options...
Nine Posted March 26, 2021 Share Posted March 26, 2021 8 hours ago, JockoDundee said: I am sorry. No offense. I have push further the POC by writing the Merge Procedure script, to make sure that all along it was working correctly. If OP or anyone else would like to use this solution, I recommend that you put your DB into WAL mode, see this document. That would make your scripts run faster. But it will work with or without... Listener : #include <SQLite.au3> #include <Constants.au3> #include <Misc.au3> Local Const $SQLITE_DLL = "sqlite3.dll" Local Const $SQLITE_Database_Name = "Merge.DB" While True If _Singleton("MergeListener", 1) Then ExitLoop Sleep(Random(10, 15)) WEnd If $CmdLine[0] <> 1 Then Exit MsgBox ($MB_SYSTEMMODAL, "", "You need to provide full path file") If Not FileExists($CmdLine[1]) Then Exit MsgBox ($MB_SYSTEMMODAL, "", "File does not exist") _SQLite_Startup($SQLITE_DLL, False, 1) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Startup Error", "Unable to start SQLite. Check existence of DLL") Local $hDB = _SQLite_Open($SQLITE_Database_Name) If $hDB = 0 Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Open Error", "Unable to open database") Local $aRow _SQLite_QuerySingleRow (-1, "select count(*) from Merge;", $aRow) If $aRow[0] = "0" Then Run("MergeProc.exe") Do Until _SQLite_Exec(-1, "insert into merge values('" & $CmdLine[1] & "');") = $SQLITE_OK _SQLite_Close() _SQLite_Shutdown() Proc : #include <SQLite.au3> #include <Constants.au3> #include <Misc.au3> Local Const $SQLITE_DLL = "sqlite3.dll" Local Const $SQLITE_Database_Name = "Merge.DB" _Singleton("MergeProc") ; make sure that only one proc is running at a time _SQLite_Startup($SQLITE_DLL, False, 1) If @error Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Startup Error (Proc)", "Unable to start SQLite. Check existence of DLL") Local $hDB = _SQLite_Open($SQLITE_Database_Name) If $hDB = 0 Then Exit MsgBox($MB_SYSTEMMODAL, "SQLite Open Error (Proc)", "Unable to open database") Local $aRow, $iPrev = "-1", $iRes While True $iRes = _SQLite_QuerySingleRow (-1, "select count(*) from Merge;", $aRow) ; peek to see if all rows have been written (change sleep time as needed) Sleep (200) If $iRes <> $SQLITE_OK Then ContinueLoop If $iPrev = $aRow[0] Then ExitLoop $iPrev = $aRow[0] WEnd Local $aResult, $iRows, $iColumns _SQLite_GetTable(-1, "select * from Merge;", $aResult, $iRows, $iColumns) _SQLite_Exec(-1, "delete from Merge;") _SQLite_Close() _SQLite_Shutdown() _ArrayDisplay($aResult) “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
argumentum Posted March 27, 2021 Share Posted March 27, 2021 On 3/24/2021 at 4:01 PM, OhBobSaget said: From what i saw online, you need a listener that will get this list then pass it to the main program So, out of the solutions you found, what did you end up doing ? Thanks Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
OhBobSaget Posted March 30, 2021 Author Share Posted March 30, 2021 @argumentum For the moment i am trying the @Nine solution. I am currently have some stability problem with this solution, because the number of file that are passed as argument are not stable... I often select like 10-12 files but only 8-9 files end up being pass to the main merging PDF program. Also i had problem with the @Nine The statement to remove the entries in the DB "delete from Merge;" I had to find another way.... so i copy a template DB every time the software is used instead of purging the DB. As for your solution, i just took a quick look at the code and i was not sure if it was something that might work, isnt that UDF for mail stuff ? Thank you both for your help ;) Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now