Thanks, I will have a look. Another user is reporting another issue as well (possibly just the Unicode build though).
Stu
LockedList plug-in
320 posts
Seems OK here. What operating system?
Stu
Stu
OK found it. Added to changelog for next build:
StuFixed ZeroMemory call:
ZeroMemory(File.ProcessCaption, sizeof(File.ProcessFullPath)); -> ZeroMemory(File.ProcessFullPath, sizeof(File.ProcessFullPath));
XP SP2 32-bit, for the record, but you're way ahead of me 🙂
RC4 uploaded. Hopefully both issues sorted.
Stu
Stu
non-unicode again; no such luck here.. although on the first two runs I got this instead:
on a different note; from..
..there was a request to add an option to only show the dialog if there were locked files found. Any thoughts on this?
I don't have a need for it myself as I'm performing a few other tests anyway (check if the target file exists, check if the file I want to install is newer, check if the file can be opened for write mode*) and abort the page display if the file being in a locked state isn't an issue.
* I read the thread with the caveat about 'shared write', but apparently some 'locked' files can happily be renamed just as well. Shared write is highly unlikely for the files I'm dealing with (DLLs), so that's okay.
Are you a developer who uses NSIS to distribute your application? Are you a Winamp plug-in developer who wants to use NSIS to distribute your plug-in? Have suggestions for other people like you? This is the place.
..there was a request to add an option to only show the dialog if there were locked files found. Any thoughts on this?
I don't have a need for it myself as I'm performing a few other tests anyway (check if the target file exists, check if the file I want to install is newer, check if the file can be opened for write mode*) and abort the page display if the file being in a locked state isn't an issue.
* I read the thread with the caveat about 'shared write', but apparently some 'locked' files can happily be renamed just as well. Shared write is highly unlikely for the files I'm dealing with (DLLs), so that's okay.
Yes, showing the daialog only if files are locked is a good suggestion. We don't want this dialog to interfere unless it is necessary. BTW, also possibly giving the search path is also a good option . This will avoid by listing all files individually.
Can anyone also tell me if this plugin has any compatibility problem with UMUI, since I'm not able to show the dialog in the same. It just skips to the next dialog in the list , instead of showing the locked files.
Can anyone also tell me if this plugin has any compatibility problem with UMUI, since I'm not able to show the dialog in the same. It just skips to the next dialog in the list , instead of showing the locked files.
Moreover, this plugin is depended upon Microsoft.VC90.CRT runtime . This causes crash of the dialog , since on new machines this does not exist. Any solution ?
I'm a little busy with University at the moment and there are still some issues with LockedList to be sorted. I'll then see if I can sort the CRT dependency.
Edit: And not showing the dialog is not really an option as obviously the scan takes place while the dialog is visible!!
Stu
Edit: And not showing the dialog is not really an option as obviously the scan takes place while the dialog is visible!!
Stu
Uploaded v1.0:
v1.0 - 29th March 2010
* Fixed CRT dependency.
* Improved percent complete calculations.
* Now pushes /next to stack in between stack items.
* Fixed memory leak in AddItem().
* Fixed crashes caused by using AddFile plug-in function.
* General code cleanup.
I had reports of duplicated Window captions and this may be fixed too.
Stu
v1.0 - 29th March 2010
* Fixed CRT dependency.
* Improved percent complete calculations.
* Now pushes /next to stack in between stack items.
* Fixed memory leak in AddItem().
* Fixed crashes caused by using AddFile plug-in function.
* General code cleanup.
I had reports of duplicated Window captions and this may be fixed too.
Stu
Sweet - thanks for the update!
Out of curiosity.. what happens with AddModule when supplying 64bit DLLs?
Or, in the case of AddFile, what happens with regard to the filesystem redirection on $SYSDIR / the use of SysNative?
I've adjusted my installers to use $WINDIR\SysNative if ${AtLeastWinVista} and disable/revert FS redirection on XP64 (can't rely on the hotfix/existence of the folder), but it dawned upon me that I haven't the foggiest how LockedList responds to these things 🙂
I'll try a few tests myself later - just musing in here.
Out of curiosity.. what happens with AddModule when supplying 64bit DLLs?
Or, in the case of AddFile, what happens with regard to the filesystem redirection on $SYSDIR / the use of SysNative?
I've adjusted my installers to use $WINDIR\SysNative if ${AtLeastWinVista} and disable/revert FS redirection on XP64 (can't rely on the hotfix/existence of the folder), but it dawned upon me that I haven't the foggiest how LockedList responds to these things 🙂
I'll try a few tests myself later - just musing in here.
As NSIS is 32-bit, the plug-in cannot enumerate modules of 64-bit processes (the AddModule plug-in function). This can only be fixed if a 64-bit version of NSIS is developed.Disabling redirection will have no effect. It is doing string comparisons only so whatever path you give it is what it will match on. To avoid this issue, you can simply use \subpath\modulename.dll instead of a full path.
Stu
gah - totally missed that rather prominently displayed bit in the readme. Any work-around ideas? I can still detect that I can't open it for writing / can't overwrite it, so i can still detect that -something- has it locked.*
Not using the full path should probably work in this instance, even though it reduces it to just the filename. I suppose that might give issues if, say, one wants to check what application is locking "c:\somedir\somefile.ext" by using "somefile.ext" and another application has "c:\anotherdir\somefile.ext" open.
Edit: Not that there's any point in doing this in my case - given that they're 64bit DLLs.
* Edit: I suppose I could use LockedList's stack output function for the 32bit parts, my own functions (that don't identify the locking process, of course) for the 64bit parts and populate some manner of list display myself - possibly using an NSDialogs timer to refresh the list periodically (not spotting a hook into the automatic update part of the LockedList dialog - and I'd need the timer for my own function anyway). Hmmm.
Not using the full path should probably work in this instance, even though it reduces it to just the filename. I suppose that might give issues if, say, one wants to check what application is locking "c:\somedir\somefile.ext" by using "somefile.ext" and another application has "c:\anotherdir\somefile.ext" open.
Edit: Not that there's any point in doing this in my case - given that they're 64bit DLLs.
* Edit: I suppose I could use LockedList's stack output function for the 32bit parts, my own functions (that don't identify the locking process, of course) for the 64bit parts and populate some manner of list display myself - possibly using an NSDialogs timer to refresh the list periodically (not spotting a hook into the automatic update part of the LockedList dialog - and I'd need the timer for my own function anyway). Hmmm.
Unfortunately there isn't a way around this (at least not using EnumProcessModules/EnumProcessModulesEx). I guess one option is to use the AddApplication plug-in function on top of a manual lock check.
Stu
Stu
AddApplication? I saw the AddApplications method (not documented, but in the examples), but figured that was a bit heavy-handed; other (InstallShield, I think) installers claiming every single application must be closed (usually for no good reason) often just tend to annoy me 🙂
Short of creating a completely custom page - is there any way to add to the LockedList list manually? I suppose through poking at SysListView32 directly, if nothing else. Might be cleaner to add a method to add custom data, but I'm not sure how that would interfere with things like the context menu, automatic clearing of items, etc.
Short of creating a completely custom page - is there any way to add to the LockedList list manually? I suppose through poking at SysListView32 directly, if nothing else. Might be cleaner to add a method to add custom data, but I'm not sure how that would interfere with things like the context menu, automatic clearing of items, etc.
oh, on a rather unrelated note, I'm still getting the odd bits in the top of the list - but the new version at least seems to spit out some useful information; it reports the process ID as 4 (which, according to taskman, is the System process).
This is from the supplied module/notepad example:
I have no idea why it's listing that - notepad certainly isn't running (if it is, it adds a 2nd line listing notepad itself). Windows XP, 32bit, SP2 and any other information you'd need, just say the word 🙂
This is from the supplied module/notepad example:
I have no idea why it's listing that - notepad certainly isn't running (if it is, it adds a 2nd line listing notepad itself). Windows XP, 32bit, SP2 and any other information you'd need, just say the word 🙂
Sorry should have mentioned that was fixed a few mins after I uploaded. Yeh not sure why I added AddApplications - someone must have asked for it. Probably useful if you are going to be rebooting the system after installation and you don't want people to lose their work. How about AddClass or AddCaption? How would adding custom data work?
If your application is 64-bit, did you try adding the actual executable using AddModule? That should work.
Stu
If your application is 64-bit, did you try adding the actual executable using AddModule? That should work.
Stu
Ah, I'll have to re-test.
=====
Unfortunately, AddClass, AddCaption, looping over processes etc. wouldn't do much good as I don't have the particulars of the application(s) that might use these libraries. They're basically DLLs that other developers can, and are likely to, make use of.. but I don't think we can dictate "Thou Shalt Useth This Class" 🙂
Adding (err.. and removing, I suppose) custom data basically just to populate the list and have LockedList realize whether the list is empty or not.
E.g. Let's say I run my own function to at least check if -something- is locking a 64bit file.. I can't tell what is locking it, but at least I can tell the user that something is. Quite possibly, they'll know what's locking it and can then close it.
So having identified that a particular file is locked, say I call:
LockedList::AddCustomItem "path\filename" ["unknown process"]
That adds the custom item to the locked list internal list and display list. The display list so that, obviously, it is displayed..and the internal list so that if the other locks that LockedList handled itself are closed, it doesn't immediately report that there's nothing left to close.
This would require a companion function a la...
LockedList::RemoveCustomItem "path\filename" that would remove the matching item. I'm *presuming* that it wouldn't require some manner of unique ID to be returned from AddCustomItem that would then get fed to RemoveCustomItem, instead just string matching.. but whatever is easier/better/etc.
This function would get called if my own function determines that said lock is, in fact, gone.
Unfortunately this probably means quite a few other changes - can't just add an nsDialogs timer to your dialog to periodically call my function / add a button to manually refresh / etc. so the plugin would have to call it and so forth and so on.
Hence why I was already thinking that -maybe- it's better I create my own custom page with a list (probably through EmbeddedList), and populate that out of the LockedList stack methods. I'd lose the automatic checking - instead having to re-requery LockedList.. or.. actually I guess I can just check if the process that LockedList reported is still present when I do my refresh.. that should have the same effect?
I'd better check that System process bit first 🙂
=====
Unfortunately, AddClass, AddCaption, looping over processes etc. wouldn't do much good as I don't have the particulars of the application(s) that might use these libraries. They're basically DLLs that other developers can, and are likely to, make use of.. but I don't think we can dictate "Thou Shalt Useth This Class" 🙂
Adding (err.. and removing, I suppose) custom data basically just to populate the list and have LockedList realize whether the list is empty or not.
E.g. Let's say I run my own function to at least check if -something- is locking a 64bit file.. I can't tell what is locking it, but at least I can tell the user that something is. Quite possibly, they'll know what's locking it and can then close it.
So having identified that a particular file is locked, say I call:
LockedList::AddCustomItem "path\filename" ["unknown process"]
That adds the custom item to the locked list internal list and display list. The display list so that, obviously, it is displayed..and the internal list so that if the other locks that LockedList handled itself are closed, it doesn't immediately report that there's nothing left to close.
This would require a companion function a la...
LockedList::RemoveCustomItem "path\filename" that would remove the matching item. I'm *presuming* that it wouldn't require some manner of unique ID to be returned from AddCustomItem that would then get fed to RemoveCustomItem, instead just string matching.. but whatever is easier/better/etc.
This function would get called if my own function determines that said lock is, in fact, gone.
Unfortunately this probably means quite a few other changes - can't just add an nsDialogs timer to your dialog to periodically call my function / add a button to manually refresh / etc. so the plugin would have to call it and so forth and so on.
Hence why I was already thinking that -maybe- it's better I create my own custom page with a list (probably through EmbeddedList), and populate that out of the LockedList stack methods. I'd lose the automatic checking - instead having to re-requery LockedList.. or.. actually I guess I can just check if the process that LockedList reported is still present when I do my refresh.. that should have the same effect?
I'd better check that System process bit first 🙂
System process being reported has indeed been fixed - thanks! 😁
How about this:
Usage:AddCustom [/icon path] application process callback
GetFunctionAddress $R0 IsMyAppRunning
LockedList::AddCustom /icon $PLUGINSDIR\icon.ico "My App" "myapp.exe" $R0
StuFunction IsMyAppRunning
Pop $R0 ; $R0 = myapp.exe in case you want to know
${If} [myapp is locking files]
Push true
${Else}
Push false
${EndIf}
FunctionEnd
Yeah, seems like that would work (and be more flexible for general use). How often would the callback be called? Unless it blocks the thread, etc.
Uploaded v1.1. The callback is called initially before adding the custom item and then again every second after searching has completed.
Edit: And FYI Why do win32 calls GetModuleFileNameEx, EnumProcessModules, EnumProcessModulesEx fail in Wow64?
Edit 2: LockedList uses GetProcessImageFileName if it exists so LockedList will work for all executables (32-bit or 64-bit) but cannot work for 64-bit modules. One idea (which Process Explorer uses) is to run a secondary 64-bit process which relays information back to the 32-bit process (in this case, the plug-in) but this would be a lot of work.
Stu
Edit: And FYI Why do win32 calls GetModuleFileNameEx, EnumProcessModules, EnumProcessModulesEx fail in Wow64?
Edit 2: LockedList uses GetProcessImageFileName if it exists so LockedList will work for all executables (32-bit or 64-bit) but cannot work for 64-bit modules. One idea (which Process Explorer uses) is to run a secondary 64-bit process which relays information back to the 32-bit process (in this case, the plug-in) but this would be a lot of work.
Stu
Just tried, but the "LockedListCustom.nsi" example goes straight through without invoking the callback function, it seems. I'm using the regular DLL, MD5: 0dd1e0aee3b2aba0483c5d50c4656ba6
Re Edit: yeah, I found similar information a bit after I asked the initial question.. almost makes sense if not for it being something MSFT -could- have addressed if they really wanted to; alas 🙂
Re Edit 2: Right - I wouldn't delve into that right away 🙂
Re Edit: yeah, I found similar information a bit after I asked the initial question.. almost makes sense if not for it being something MSFT -could- have addressed if they really wanted to; alas 🙂
Re Edit 2: Right - I wouldn't delve into that right away 🙂
Thanks, fixed. Reminder for future I must always test release DLL's as well as debug DLL's 🙂
Stu
Stu
Excellent - That is actually a pretty elegant solution to an entirely non-elegant problem.. makes LockedList extremely flexible as a sweet side-effect 🙂
One question if I may; the Custom example (which is still titled 'Using AddModule and notepad.exe' - btw) seems to use $R0 - the callback function address - 3 times. The docs only specify it once. I commented out the 2nd and 3rd and the example still runs so I suppose they're at least not required - but now I'm curious as to why they're there 😁
*goes to hit the actual installer code to try and hook his simplified locked file check into this*
One question if I may; the Custom example (which is still titled 'Using AddModule and notepad.exe' - btw) seems to use $R0 - the callback function address - 3 times. The docs only specify it once. I commented out the 2nd and 3rd and the example still runs so I suppose they're at least not required - but now I'm curious as to why they're there 😁
*goes to hit the actual installer code to try and hook his simplified locked file check into this*
Sweet - as far as I can tell, this will work beautifully.. still have to test it in the wild, but several quick simple tests haven't revealed any particular problems.
So now I have...
${LockCheck} : a simple locked files checker macro bit that only reports -if- a file is locked (if it exists, and if we care (version number check)), not -what- is locking it..
1. that I feed target/source files into with a single line call for each module
2. if it is determined none of the files are locked (based on the output of the macro), skip the LockedList dialog, otherwise...
3. initialize the LockedList dialog with those Module (32bit) or Custom (64bit) items that were determined to be locked, which will report the locking applications (32bit) and my Custom items (64bit)
4. which will automagically check everything except for the Custom items for which it calls...
5. a callback which invokes the simple locked files checking macro ${LockCheck} and...
6. tells lockedlist whether or not the file is unlocked based on its output again.
It's not perfect, but it's much better than going *BOINK* at a user mid-file installation with a can't-overwrite-this-file dialog 🙂
So now I have...
${LockCheck} : a simple locked files checker macro bit that only reports -if- a file is locked (if it exists, and if we care (version number check)), not -what- is locking it..
1. that I feed target/source files into with a single line call for each module
2. if it is determined none of the files are locked (based on the output of the macro), skip the LockedList dialog, otherwise...
3. initialize the LockedList dialog with those Module (32bit) or Custom (64bit) items that were determined to be locked, which will report the locking applications (32bit) and my Custom items (64bit)
4. which will automagically check everything except for the Custom items for which it calls...
5. a callback which invokes the simple locked files checking macro ${LockCheck} and...
6. tells lockedlist whether or not the file is unlocked based on its output again.
It's not perfect, but it's much better than going *BOINK* at a user mid-file installation with a can't-overwrite-this-file dialog 🙂
I just realized that when the dialog closes, the stack value for the next button is always "next" - which means you can't discern from it whether the user clicked the next (all apps were closed / there was nothing to close to begin with) or the 'ignore' button.
These are one and the same button just with custom captions on them, of course - which also leads to the work-around: grab the text off of the button and compare it to the '/ignore text' flag value you defined. Just thought it might be good if the plugin handled this in the value it pushes to the stack 🙂
These are one and the same button just with custom captions on them, of course - which also leads to the work-around: grab the text off of the button and compare it to the '/ignore text' flag value you defined. Just thought it might be good if the plugin handled this in the value it pushes to the stack 🙂
Done. Also added an IsFileLocked utility function. See the changelog for full details.
Stu
Stu
Sweet - seems you're on a roll 😳
If IsFileLocked works well, I can replace the internal (FileOpen "path" "a") test.
At the moment, though, the Pop'ed value seems to be the passed "path" parameter?
( I popped a few more time to different vars, they all seem to be null )
If IsFileLocked works well, I can replace the internal (FileOpen "path" "a") test.
At the moment, though, the Pop'ed value seems to be the passed "path" parameter?
( I popped a few more time to different vars, they all seem to be null )