Archive: UAC plugin - bring installer window to foreground


UAC plugin - bring installer window to foreground
Hey,

Thanks Anders for sharing your UAC plugin!

I've got it working in our installer but there's one major problem, the installer window doesn't come to the foreground.

I'm using v0.2.2c and I know that you've said there were some ugly hacks to get this working in an earlier version. My questions:

1. Did the hacks result in any undesirable behaviour?

2. Is there anything changed in v0.2.2c which would not allow them to work?

3. Would it be easy for me to patch v0.2.2c to get this working?

Before I delve in and try playing around with allowSetForeground(), setForeground(), etc.. I thought you could give me maybe give me some advice?

Thanks again!

Steve


I don't think there was any undesirable behavior, but IIRC the hack that works is to create a window with WS_EX_TRANSPARENT|WS_EX_LAYERED|WS_EX_TOOLWINDOW ex styles, this creates a transparent window in a hacky way. I don't think WS_EX_TRANSPARENT on a top level window is really supported etc.

I never figured out the actual cause of the problem, but my guess is that the nsis verify CRC dialog is the issue, and once you lose "foreground", SetForegroundWindow stops working.

You should be able to find the hacks by looking for the UAC_HACK_* #ifdef's.

It feels like years since I last messed around with this problem so I don't remember the details or how to reproduce it, drop by IRC and maybe we can come up with some new workaround...


Hello.

I would also be interested in a fix for that issue. With v0.2.2d I encounter the problem that the UAC dialog insn't triggered automatically, but delayed until the user clicks the installer icon in the task-bar. This means that when you launch the installer nothing will happen. Well, except for a blinking icon in the task-bar. Not every user may notice. (This was the result under Windows 7).


I have come to the conclusion that elevating in .oninit is just not going to work, and .onguiinit will have to be used instead, this of course is problematic for silent installers.

I'm guessing you guys still want silent installers to prompt (while I actually just think the process should exit with the proper error code :) )

The nsis design makes this hard to implement, but I'll try to come up with some sort of hack


Originally posted by Anders
I have come to the conclusion that elevating in .oninit is just not going to work, and .onguiinit will have to be used instead, this of course is problematic for silent installers.
So do do you suggest that simply moving the UAC initialization from .onInit to .onGuiInit will do the trick or will it require modifications inside your UAC plugin itself? Anyway, I'm going to play around with it a bit now...

BTW: currently I don't care about "silent" installers. This may easily become different in a future project, of course ;)

(double post, by accident. srry)


Update:

It seems moving the UAC initialization to .onGuiInit indeed does the trick :)

However in a MUI2-based installer, I have to use something like:

!define MUI_CUSTOMFUNCTION_GUIINIT myUacInit


You think it might conflict with anything MUI2 does in its own .onGuiInit functions?

Thanks!

That just inserts Call myUacInit in .onGUIInit so it should be fine.

Stu


Originally posted by Afrow UK
That just inserts Call myUacInit in .onGUIInit so it should be fine.

Stu
Yeah, but it also executes other MUI2-specific stuff before my custom GuiInit function. We probably don't want that to happen before UAC init or at all (in the "outer" installer).

I'm going to rewrite some stuff maybe, not sure what to do yet


Now that the "bring installer window to foreground" problem is resolved by doing the UAC init in .onGuiInit, a new question arises:

Where to call the "MUI_LANGDLL_DISPLAY" macro? :confused:

Before I did this in .onInit, but *after* the UAC init. And it worked as expected.

Now after the UAC init has moved to .onGuiInit, I get the MUI_LANGDLL_DISPLAY dialog twice, which isn't surprising.

Unfortunately moving MUI_LANGDLL_DISPLAY after UAC init again (in .onGuiInit) doesn't work. The language isn't applied!

So I assume that MUI_LANGDLL_DISPLAY must be called from .onInit rather than .onGuiInit to work correctly.

My workaround for this which appears to do the trick:

Function .onInit
${If} ${UAC_IsInnerInstance}
!insertmacro MUI_LANGDLL_DISPLAY
${EndIf}
FunctionEnd


But is it considered "safe" to use ${UAC_IsInnerInstance} even before the actual UAC initialization ???

Thanks :)

Yes, it should be safe.

I am planning to actually make some changes so that calling from onguiint is less painful, I was thinking that it would be a two stage thing, using both oninit and onguiinit.

I'm not really sure how to do it in practice, getting the correct language loaded in both instances is going to be a problem...

Or maybe it would be possible to change the plugin api so that plugins can change the language after oninit.


It sounds like you guys have a better and simpler fix using onGuiInit, but I thought I'd share my patch to v0.2.2 which works for me and does the following:

1. Reintroduce Ander's hack from version 0.0.11d which creates an invisible window to retain ability to set foreground

2. Call AllowSetForeground in inner process on outer process before running an outer operation.

3. Sleep for 5 seconds before outer window is destroyed (stops focus ability getting lost before my app splash screen shows)

It's not pretty but works for my case. Here it is: (applies to v0.2.2) http://steveridout.com/sharedFiles/uac.patch

Thanks Anders for the help over IRC