WindowFunc header file. Window (not MS Windows) related functions.
${WinWait}
Waits for a window to exist by title or PID (title optional, partial title accepted; PID required) and optional class (full classname required if used). Can specify a timeout value. Returns -1 if timed out, or the window handle if successful.
${WinWaitVisible}
Waits for a window to exist and be visible by title or PID (title optional, partial title accepted; PID required) and optional class (full classname required if used). Can specify a timeout value. Returns -1 if timed out, or the window handle if successful.
${EnumWindows}
Enumerates all windows or visible windows only, and passes the window's handle, title, class, and visibility to a user defined function.
NOTES:
It is always best to specify both a title and class. Some apps have multiple windows with the same title and different class, or different titles but the same class.
A child window will return as visible only if all of its parent or parent's parent (etc.) windows are visible.
Not all apps use the standard windows titlebar, some use a custom titlebar. In this case the window title cannot be read and this function will likely fail (timeout or get stuck in a loop). Be wary of this situation and use the window classname where appropriate.
Here's a POC for some of the missing parts of what we were talking about. Notice the absence of EnumWindows...wish I'd have known I could do it that way before, much faster.
I have an idea: Along with the splash, we can call system dlls to change the window title to (AppName)Portable. Too bad I have no idea how... I know you use user32.dll...
I'll go check out MSDN.
Insert original signature here with Greasemonkey Script.
Ok, let's give this a try.
@haustin
I tried to exclude WordFunc/WordFind when not needed, like we did with ProcFunc. However in this library it is not known whether it is needed until the function is called from within the Section (mode specified as title). At this point it is too late to insert WordFunc/WordFind (must be done outside of the section). Can you think of a solution?
@digit
Why would you want to change an app's window title? I mean it could be done, but for what purpose? Also, not all apps use a "standard" windows title bar, and therefore the title cannot be changed (or even read in some cases).
John wants the portable apps to be distinctive, if you were to change the title from 'OpenOffice.org Impress' to 'OpenOffice.org Impress Portable Provided by PortableApps.com' or something.
Better than the splash, less intrusive and longer lasting.
Somebody know how to work MSDN?
Insert original signature here with Greasemonkey Script.
EDIT - n/m, that's probably the dumbest thing I've ever said.
EDIT2 - here
Added ${EnumWindows}
And the "Very Clever Use of FindWindow" Award goes to... wraithdu!
I originally thought of copying your ProcessClose (a la EnumWindows()) and then discovered that's exactly how AutoHotKey does it. I never even noticed that FindWindow lent itself to looping with the childafter argument. Duh!
And of course it should be faster... it's built-in!
I tried to exclude WordFunc/WordFind when not needed, like we did with ProcFunc.
The only way I can think of is to create separate macros for WinWaitTitle and WinWaitPID. An additional benefit would be that it would reduce the number of user-visible arguments and remove the visible overloading of the title-or-pid argument.
Finally (and one reason I originally thought of it being in ProcFunc), WinWaitPID really should check to see if the target process still exists and return 0 if not (instead of continuing to wait for it to present a window).
Amazing stuff, yet again. -hea
P.S. You just want two NSIS Wiki pages, don't you.
<EDIT>
A child window will return as visible if any one of its parent or parent's parent (etc.) is visible.
Actually, MSDN says it will return as visible only if the window and all of its ancestors are visible. But it shouldn't matter in this context because the only ancestor of a child of the desktop is the always-visible desktop.
</EDIT>
Ahh, guess I read MSDN wrong...it's a little unclear actually.
I'll add the check for PID existence to the function here, no need to call the whole thing from ProcFunc.
I thought about 4 separate macros also, but thought it was a little cumbersome, assuming you wanted to keep the "Visible" macro separate as well. I just couldn't think of a way to distinguish between a windows title and PID otherwise (title could be just numbers).
Re: ProcFunc - I know we did a crap load of work tweaking the inclusion of WordFind...so do you think I should ditch "SearchProcessPaths" anyway to simplify the library? It's the same reasoning why I didn't include any kind of search in this library for EnumWindows.
Actually, come to think of it, a user might want to restrict matches by PID and title. So it should probably be something like:
Your call on whether to include ${WinWaitVisible} and ${WinWaitTitleVisible} macros.
Re: ProcFunc...so do you think I should ditch "SearchProcessPaths" anyway to simplify the library?
Well... I'd probably lean that direction. But it would be nice to include a user_func example using WordFind so users won't have to figure it out.
Lest you think the exercise was pointless ;-), I have hacked your ProcessExists code to allow returning multiple PIDs (in a space-separated list) and to allow an exclusion list of PIDs (also space-separated) that won't get matched. The exclude functionality was also added to ProcessWait. You guessed it, ${ProcessExistsExclude} and ${ProcessWaitExclude} require WordFind! And as it's still in the "hacked" state, it doesn't yet account for users who don't need WordFunc.
If you're wondering about ProcFunc's mode numering, I renumbered it to 0=Exists, 1=GetPath, 2=GetName; +4 to match by PID; +8 to return multiple PIDs; +16 to use PID exclude list. Obviously, not all combinations make sense, so only these are implemented: 0, 1, 4, 5, 6, 8, 16, 24.
Also, I changed the process name-or-PID test to:
...so that it works for any 3-letter extensions (including EXE and BIN).
Using all of the aforementioned, I have successfully gotten OpenOfficePortable to display the splash until right before OOo's own splash shows up, by changing the splash timeout to 999999 and modifying the last part of OpenOfficePortable.nsi to look like this:
-hea
I think I'm going to get rid of SearchProcessPaths (but I'm keeping a copy!!).
I'm still pondering the WinWait funcs.
I think your Multi and Exclude ideas are interesting. But for your example, you could use the ${Execute} macro to return the exact PID you're concerned with, allowing you to skip the ProcessWaitExclude.
Either way, when you get those functions hammered out, you should publish them. You'd probably get more of a response from the NSIS forum as far as usage goes. Could lead to a wiki of your own
I think I'm going to get rid of SearchProcessPaths (but I'm keeping a copy!!).
Yeah, it would probably be the handiest example implementation of a user_func -- that's why I suggested including it as an example. The other two (if you wanted to include that many) could be:
And, yes, I actually tested this one. Note how Test2 lends itself readily to an eject script...
I think your Multi and Exclude ideas are interesting. But for your example, you could use the ${Execute} macro to return the exact PID you're concerned with, allowing you to skip the ProcessWaitExclude.
Actually, ${Execute} execs soffice.EXE which in turn loads soffice.BIN. The EXE doesn't create any windows, only the BIN does. I would imagine that other programs spawn multiple processes when launched as well. That's why my test code (OOo) first looks for running processes that match the target, then launches the parent process that spawns the target, then looks for a matching target that wasn't there in the first place. At that point, we have a useful PID (even if
AllowMultipleInstances=true
). For the majority of programs, the ${Execute} macro I requested would work beautifully.Could lead to a wiki of your own
I was kinda hoping you'd consider merging them with your ProcFunc.nsh and correcting any stupid coding errors (remember, I fired my code reviewer :P). I don't mind "{based on|influenced by} {idea|code|crap} contributed by [Real Name]" or similar, but otherwise, I prefer to influence the world behind the scenes. :cool:
-hea
P.S. My POS XPSP2 machine BSOD'd when I was mostly done with this post. Grrr.
Fortunately I was using Firefox with
browser.sessionstore.enabled=true
(which by default writes to disk only every 10 sec, not every page load). Unfortunately, since posting requires logging in, Session Restore didn't bring back my unfinished post. So, I had to manually edit my sessionstore.bak to retrieve the contents of my unposted comments and unencode all of the %nn nonsense. Minor pain, but thank god I was using Firefox!