Perl and Windows UAC
While doing some Registry-related things with Perl a couple of weeks ago, I ran into something that took me nearly a day to figure out: Win32::TieRegistry asks for write access to the Registry by default, and under Win7 that requires Administrator privileges. (I kid you not, it took me over a day to figure that out.)
Well, getting what turns out to be called "elevated privileges" from Perl turns out to have been pretty hard - a lot harder than it should have been, for reasons I went into in some detail in a little article about it, but, to cut straight to the chase, I came up with a way to get Perl to restart a script after invoking UAC to gain elevated privileges. It's got some weaknesses that are inherent to the way Windows manages the console, but, well, I present to you Win32::RunAsAdmin. You can use it like this:
use Win32::RunAsAdmin qw(force);
That checks to see whether you're running with elevated privileges already, and if not, it calls the shell to run the same script again with the same arguments, and exits. Obviously, the (few) components of the module are also available separately; check the POD for details. But in all it's about ten lines.
Problem solved. Hope this helps somebody.
Excellent work. I was looking for such a module.
Is it 100% safe (i.e.
check
function)?The check function actually uses Win32::TieRegistry and tries to obtain write access - if that fails, you're not running with elevated privileges.
I couldn't find any more "official" way to determine elevation state than that.
But if I understand your question correctly, then if you are running with elevated privileges, the "use" will return silently and your script will run.
The only weirdness about the whole thing is that Windows starts a new console for Perl, which will naturally disappear after your script has run. If you want to read something on the screen, the easiest way to do it is with ; as the final line of the script, which will wait for Enter and then close the console.
Anyway, give it a try and tell me if there's anything I'm not thinking of. I can't imagine what - this really is totally simple once you actually know about the mechanism involved.
Har. HTML got me in that above. The easiest way to wait for Enter is of course <STDIN>....
Shell.Application
was added for WScript and CScript scripts, so the actual functionality should be accessible directly with Win32::API. I'm not sure at the moment what it is calling under the hood.Hi! What about
Win32::IsAdminUser()
to check for elevated privileges? The docs say:Returns non zero if the account in whose security context the current process/thread is running belongs to the local group of Administrators in the built-in system domain; returns 0 if not. On Windows Vista it will only return non-zero if the process is actually running with elevated privileges. Returns undef and prints a warning if an error occurred. This function always returns 1 on Win9X.
Source: http://search.cpan.org/~jdb/Win32-0.49/Win32.pm
Hey, Alex - great find! I swear I looked for that kind of stuff for like a week and finally just gave up. I'll put this into the next version for sure.
Thanks!