Skip to content
⌘ NSIS Forum Archive

Questions about UAC plugin

52 posts

sledgehammer_999#

Questions about UAC plugin

I read the wiki page and the included *.nsi files but I still have questions.
First of all I am no nsis guru.

I want my installer to run some code from the user process and some other code from the admin process. However I cannot understand how I tell it to run function A as user and function B as root...

Also I cannot understand how the program flow works between the user and admin process. Can someone explain it to me? eg based on the wiki example found here: http://nsis.sourceforge.net/UAC_plug-in

Thank you.
Anders#
I'd rather people don't use the plugin and I regret creating it in the first place. If you think you need it then you might be doing something wrong.

The general program flow is that most of the installer runs elevated (possibly as another user) and you can execute one of your functions as the user that started the installer: !insertmacro UAC_AsUser_Call Function MyFunction ${UAC_SYNCREGISTERS}
sledgehammer_999#
Why do you regret it? Is there something alternative?

So the "!insertmacro UAC_RunElevated" in .onInit make the whole installer run in admin mode and I need to explicitly tell which functions to run in user mode, right?

I need this in order to make correct file associations in Windows Vista+ , my current method seems to work only on Windows XP.
Anders#
This is the wrong approach, if you are installing to $ProgramFiles then you should write to HKLM/HKCR and not HKCU because you are doing a "all users" install. If you write to HKCU then other users will not see those registry entries.

A very basic file association is just:
WriteRegStr HKCR ".myext" "" "myprogid"
WriteRegStr HKCR "myprogid\shell\open\command" "" '"$instdir\myapp.exe" "%1"'
and should work on all versions of Windows. If .myext is a common type it might already be assigned to some other application and every new version of Windows makes it harder for you to take over those associations (In Windows 8 the UserChoice value is now encrypted to prevent you from taking it over). You should therefore add yourself to HKLM\Software\RegisteredApplications so that the user can use Default Programs/Set Program Access and Computer Defaults to select your application as the default for a popular type. Finally, if you want you can add yourself to HKCR\.myext\OpenWithProgids to list yourself in the openwith menu...
sledgehammer_999#
OK. I'll take a look into your suggestions. But I have other problems unrelated to file associations.

Currently my installer requests admin privileges before startup. This means that if a user with restricted rights launches it, give UAC credentials my installer ends up using the admin's start menu instead of the user's (assume that I want to use per user installation).
Anders#
Use "SetShellVarContext all" and $smprograms will point to the shared startmenu.

If you want to do per-user installs like Chrome you need to use "RequestExecutionLevel user" and install your app under $localappdata\Programs. This of course means you cannot write to $programfiles/$windir/HKLM/HKCR...
sledgehammer_999#
I don't know if there is any MS guideline on this, but IMO "program files" is the de facto folder of installing applications. I don't like using $localappdata

So it seems to me, if I want to achieve this kind of behavior the UAC plugin is the way to go.

Thanks for your time explaining things here. (I'll still visit this thread if you want to add something else).
Afrow UK#
What do you need to run under the current user that cannot be ran for all users? You really should try to avoid using the UAC plug-in if you are doing an all users install.

Stu
Anders#
Originally Posted by sledgehammer_999 View Post
I don't like using $localappdata
$localappdata\Programs is the default location for FOLDERID_UserProgramFiles
sledgehammer_999#
I am going to dig up the relevant issues from bugtracker and report bug. But until then I remembered something else.

What happens with the feature "launch program after installtion is done"? I still need to launch the program with non-admin rights.
Anders#
Originally Posted by sledgehammer_999 View Post
I am going to dig up the relevant issues from bugtracker and report bug.
Report a bug about what? This is how UAC is designed, there is not much anyone can do. It is better to just play ball instead of trying to fight it.


Originally Posted by sledgehammer_999 View Post
What happens with the feature "launch program after installtion is done"? I still need to launch the program with non-admin rights.
Yes, this is the only issue where the UAC plugin is a legitimate solution but I would personally recommend that you just remove the run box from the finish page. There is also the stdutils plugin that can start any app as the same user as explorer.exe's taskbar.
sledgehammer_999#
Originally Posted by Anders View Post
Report a bug about what? This is how UAC is designed, there is not much anyone can do. It is better to just play ball instead of trying to fight it.

Sorry wrong wording. I meant MY bugtracker. Currently my script doesn't use UAC, it requests admin elevation and runs everything under that, which causes some problems in newer OS's(I designed it on my Windows XP box.). Those issues are reported by users in my bug tracker but I was too lazy to act upon them till now.
sledgehammer_999#
I am going to dig up the relevant issues from bugtracker and report bug.
Sometimes my brains wonders off. The above should read:

I am going to dig up the relevant issues from my bugtracker and report back.
Anders#
Originally Posted by sledgehammer_999 View Post
Currently my script doesn't use UAC, it requests admin elevation and runs everything under that, which causes some problems in newer OS's(I designed it on my Windows XP box.).
These issues are not really new to Vista, they apply to all versions of NT but most people fail to test as non-admin on the older versions which is why all of these bad practices are so common. (RunAs was added in Win2000 so from then on, a installer could be running as a "different user" than explorer/desktop/taskbar etc)
sledgehammer_999#
What do I make the installer run on finish the program as user?
Is this sufficient?

!define MUI_FINISHPAGE_RUN !insertmacro UAC_AsUser_Call blah blah
What should I put in the "blah blah" section? I downloaded the zip but UAC_AsUser_Call doesn't seem to be documented...
sledgehammer_999#
Correction yes it seems that it is documented in UAC.nsh, but I still can't get to grasp my head around its parameters. Possibly because I am not good with the nsis syntax/terminology.
sledgehammer_999#
Hmmm, the parameters need more documenting. This is what I got from reading it:

UAC_AsUser_Call <Function|Label> <NSISAddressName> <UAC_* flags>
1. The first parameter is a string and can be either "Function" or "Label". It is used to indicate the type of the second parameter
2. The second parameter is the ACTUAL name of the function/label in your script that you want to be called
3. The third parameter are flags. They are enumerated in the code below the code comment in UAC.nsh. They aren't explained what each does.

So I suppose I should
!define MUI_FINISHPAGE_RUN !insertmacro UAC_AsUser_Call Function MyFunction ${UAC_SYNCREGISTERS}
And inside "MyFunction" I should launch my exe.
Is that correct?
sledgehammer_999#
Originally Posted by Anders View Post
MUI_FINISHPAGE_RUN* has to be a function, see UAC_Basic.nsi
Wow. That seems simple enough.

I was confused because my script (without UAC) currently uses:
!define MUI_FINISHPAGE_RUN "$INSTDIR\myprogram.exe"
sledgehammer_999#
I think I also need to use the UAC_SYNCINSTDIR flag, judging from its name.
And probably UAC_AsUser_ExecShell is probably more suited here to launch the program.
sledgehammer_999#
Another question:

In my current .onInit I have
!insertmacro MUI_LANGDLL_DISPLAY
Where do I put
!insertmacro Init "installer"
? Before or after that?

(I am refering to the Init macro defined in UAC_Basic.nsi)
Anders#
That probably depends on if you want the language dialog before or after the UAC prompt. If the answer is before you will probably have to manually sync $language somehow. The language in the elevated part is not going to change either way...
sledgehammer_999#
The final question is really practical:
How do I use this with the 3.0 NSIS? Is there a unicode .dll of this plugin somewhere or am I stuck with the ansi version?
Anders#
It can probably be compiled as Unicode if you have the tools or you can try to find one of the Unicode versions that were uploaded at some point.
sledgehammer_999#
I have set up msvc2008 and mingw 4.9.0 on my desktop. I am not stranger on compiling things.
Are the sources included in the .zip enough? Or do I need some extra environment from the nsis sources?
Any link to docs/forum posts would be appreciated.
Anders#
No NSIS bits are required. You probably have to set some UNICODE define to create the Unicode version though...
sledgehammer_999#
Since this is C++ code shouldn't I compile with the same compiler as NSIS is compiled or am I missing something here?

I see that the .zip file doesn't have a README with basic compilation instuctions, nor a makefile (or mvc project file).

Are you the author of this plugin? If I am not asking too much can you give an outline on how to compile this? Just feed all the .cpp files into gcc(mingw) and use the correct switch to produce a shared lib(dll)?
sledgehammer_999#
Probably I am missing something here:

gcc:
g++ -c -fpic -DUNICODE RunAs.cpp uac.cpp util.cpp
Produces errors during compilation for runas.cpp and uac.cpp but I get a util.o (object file)

msvc2008:
cl.exe /D_USRDLL /D_WINDLL /DUNICODE RunAs.cpp uac.cpp util.cpp /link /DLL /OUT:uac.dll
Produces .obj files for all 3 files but it errors out during likning.

I am not 100% that I use the correct commands/switches.
If I am using the right commands, which compiler's error output should I provide here?
Anders#
Only tested with MSVC so don't use GCC. You don't need those _* defines but you need at least "/O1s /GS- /GR- /EHs-c- /Zl /LD /DUNICODE" and "/link kernel32.lib user32.lib shell32.lib advapi32.lib ole32.lib"