File Coverage

blib/lib/Win32/RunAsAdmin.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Win32::RunAsAdmin;
2            
3 1     1   23916 use 5.006;
  1         6  
  1         48  
4 1     1   12 use strict;
  1         2  
  1         47  
5 1     1   5 use warnings FATAL => 'all';
  1         6  
  1         49  
6            
7 1     1   502 use Win32;
  0            
  0            
8             use Cwd;
9             use Win32::OLE;
10             use Devel::PL_origargv;
11            
12             =head1 NAME
13            
14             Win32::RunAsAdmin - Simple tools for handling Windows UAC
15            
16             =head1 VERSION
17            
18             Version 0.02
19            
20             =cut
21            
22             our $VERSION = '0.02';
23            
24            
25             =head1 SYNOPSIS
26            
27             Windows UAC (User Account Control) is the mechanism used by a program to request elevated privileges,
28             that is, to run as Administrator to make changes to the system. A program requests this when it is
29             executed, normally by means of a manifest embedded in the executable, which obviously doesn't work
30             for Perl.
31            
32             Win32::RunAsAdmin allows you to fake this; you can detect if your script is running with elevated
33             privileges, and if not, you can request a restart with them. You can also simply use these tools to
34             run another process with elevated privileges.
35            
36             This is still not a perfect solution, as Windows forces the new elevated process to run in a
37             separate console. But it's perfect for many purposes, would work beautifully for C-type
38             GUI programs, and still makes it easier to run I things as admin.
39            
40             If you simply want to make sure your script is running as admin, invocation truly couldn't be simpler:
41            
42             use Win32::RunAsAdmin qw(force);
43            
44             Got it? Do you want to see it again? OK.
45            
46             use Win32::RunAsAdmin qw(force);
47            
48             But maybe you'd rather do something else before requesting a restart with elevated privileges.
49            
50             use Win32::RunAsAdmin;
51            
52             if (not Win32::RunAsAdmin::check) {
53             # Do some stuff...
54             Win32::RunAsAdmin::restart;
55             }
56            
57             But be warned: be sure you use Win32::RunAsAdmin before importing anything else that might
58             affect the current working directory! Otherwise Win32::RunAsAdmin won't actually know what
59             your original working directory was. (It uses L to get the absolute
60             real command-line arguments, so that's safe.)
61            
62             If you just want to use the infrastructure to run something else with elevated privileges,
63             that's simple, too:
64            
65             use Win32::RunAsAdmin;
66            
67             Win32::RunAsAdmin::run ($executable, $arguments, $directory);
68            
69             This is also exposed as a command-line utility "elev" when you install this module.
70            
71             =cut
72            
73             our $starting_directory;
74            
75             =head1 SUBROUTINES/METHODS
76            
77             =head2 check
78            
79             Call this to check whether you're already running with elevated privileges.
80            
81             if (Win32::RunAsAdmin::check) {
82             # Do things to update Registry values
83             } else {
84             # Just read and report Registry values
85             }
86            
87             (It just uses Win32::IsAdminUser, but I find it easier to remember it like this.)
88            
89             =cut
90            
91             sub check { Win32::IsAdminUser(); }
92            
93             =head2 run ($executable, [$arguments, [$working_directory]])
94            
95             Call this to run anything with elevated privileges. C<$executable> is the full path to the
96             executable, C<$arguments> is a string containing the arguments to be passed to the executable,
97             and C<$working_directory> is the directory to run the process in (defaults to the current
98             directory, obviously).
99            
100             =cut
101            
102             sub run {
103             my $shell = Win32::OLE->new("Shell.Application");
104             $shell->ShellExecute (shift, shift, shift, 'runas');
105             }
106            
107             =head2 escape_args (...)
108            
109             This provides a quote-escaped string for the arguments you passed, e.g. if your
110             arguments are C and C<'there>, you'll get back the string C<"hi\"" "'there">.
111            
112             =cut
113            
114             sub escape_args {
115             return '' unless @_;
116             my @args = ();
117             foreach (@_) {
118             my $a = $_;
119             $a =~ s/"/\\"/g;
120             push @args, $a;
121             }
122             return '"' . join ('" "', @args) . '"';
123             }
124            
125             =head2 restart
126            
127             Call this to restart the current script with its current command line in the current directory.
128            
129             =cut
130            
131             sub restart {
132             my @actual_args = Devel::PL_origargv->get; # Thank you, Anonymous Monk!
133             run (shift(@actual_args), shift(@actual_args) . ' ' . escape_args(@actual_args));
134             exit;
135             }
136            
137             sub import {
138             $starting_directory = getcwd();
139             restart if (defined $_[1] and $_[1] eq 'force' and not check);
140             }
141            
142             =head1 AUTHOR
143            
144             Michael Roberts, C<< >>
145            
146             There is a short article going into a little more depth about different options with dealing with UAC
147             under Perl at L.
148            
149             =head1 BUGS
150            
151             Please report any bugs or feature requests to C, or through
152             the web interface at L. I will be notified, and then you'll
153             automatically be notified of progress on your bug as I make changes.
154            
155            
156            
157            
158             =head1 SUPPORT
159            
160             You can find documentation for this module with the perldoc command.
161            
162             perldoc Win32::RunAsAdmin
163            
164            
165             You can also look for information at:
166            
167             =over 4
168            
169             =item * RT: CPAN's request tracker (report bugs here)
170            
171             L
172            
173             =item * AnnoCPAN: Annotated CPAN documentation
174            
175             L
176            
177             =item * CPAN Ratings
178            
179             L
180            
181             =item * Search CPAN
182            
183             L
184            
185             =back
186            
187            
188             =head1 ACKNOWLEDGEMENTS
189            
190            
191             =head1 LICENSE AND COPYRIGHT
192            
193             Copyright 2014 Michael Roberts.
194            
195             This program is free software; you can redistribute it and/or modify it
196             under the terms of the the Artistic License (2.0). You may obtain a
197             copy of the full license at:
198            
199             L
200            
201             Any use, modification, and distribution of the Standard or Modified
202             Versions is governed by this Artistic License. By using, modifying or
203             distributing the Package, you accept this license. Do not use, modify,
204             or distribute the Package, if you do not accept this license.
205            
206             If your Modified Version has been derived from a Modified Version made
207             by someone other than you, you are nevertheless required to ensure that
208             your Modified Version complies with the requirements of this license.
209            
210             This license does not grant you the right to use any trademark, service
211             mark, tradename, or logo of the Copyright Holder.
212            
213             This license includes the non-exclusive, worldwide, free-of-charge
214             patent license to make, have made, use, offer to sell, sell, import and
215             otherwise transfer the Package with respect to any patent claims
216             licensable by the Copyright Holder that are necessarily infringed by the
217             Package. If you institute patent litigation (including a cross-claim or
218             counterclaim) against any party alleging that the Package constitutes
219             direct or contributory patent infringement, then this Artistic License
220             to you shall terminate on the date that such litigation is filed.
221            
222             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
223             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
224             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
225             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
226             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
227             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
228             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
229             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
230            
231            
232             =cut
233            
234             1; # End of Win32::RunAsAdmin