File Coverage

blib/lib/Win32/VBScript.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package Win32::VBScript;
2             $Win32::VBScript::VERSION = '0.05';
3 1     1   774 use strict;
  1         1  
  1         25  
4 1     1   5 use warnings;
  1         2  
  1         30  
5              
6 1     1   12 use Carp;
  1         2  
  1         63  
7 1     1   855 use Digest::SHA qw(sha1_hex);
  1         3784  
  1         83  
8 1     1   864 use File::Slurp;
  1         13292  
  1         77  
9 1     1   431 use Win32::OLE;
  0            
  0            
10              
11             require Exporter;
12             our @ISA = qw(Exporter);
13             our %EXPORT_TAGS = ('ini' => [qw(
14             compile_prog_vbs compile_prog_js
15             compile_func_vbs compile_func_js
16             )]);
17             our @EXPORT = qw();
18             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'ini'} } );
19              
20             my $VBRepo = $ENV{'TEMP'}.'\\Repo01';
21              
22             my $proxy_invoke = compile_func_vbs([ <<'EOP' ])->func('IProg');
23             Function IProg(ByVal MT, ByVal MNum, ByVal MBool)
24             MBool = UCase(Mid(MBool, 1, 1))
25             Dim ZNum : If MNum = "1" Then ZNum = 1 Else ZNum = 0
26             Dim ZBool : If MBool = "T" Then ZBool = True Else ZBool = False
27              
28             Dim OS : Set OS = CreateObject("WScript.Shell")
29             IProg = OS.Run(MT, ZNum, ZBool)
30             End Function
31             EOP
32              
33             sub new {
34             my $pkg = shift;
35              
36             my ($type, $lang, $code) = @_;
37              
38             unless ($type eq 'prog' or $type eq 'func') {
39             croak "E010: Invalid type ('$type'), expected ('prog' or 'func')";
40             }
41              
42             unless (-d $VBRepo) {
43             mkdir $VBRepo or croak "E020: Can't mkdir '$VBRepo' because $!";
44             }
45              
46             my $dat_engine;
47             my $dat_comment;
48              
49             if ($lang eq 'vbs') {
50             $dat_engine = 'VBScript';
51             $dat_comment = q{'};
52             }
53             elsif ($lang eq 'js') {
54             $dat_engine = 'JScript';
55             $dat_comment = q{//};
56             }
57             else {
58             croak "E030: Invalid language ('$lang'), expected ('vbs' or 'js')";
59             }
60              
61             my $dat_text = ''; for (@$code) { $dat_text .= $_."\n"; }
62             my $dat_sha1 = sha1_hex($dat_text);
63             my $dat_class = "InlineWin32COM.WSC\\_$dat_sha1.wsc";
64              
65             my %dat_func;
66              
67             for (split m{\n}xms, $dat_text) {
68             if (m{\A \s* (?: function | sub) \s+ (\w+) (?: \z | \W)}xmsi) {
69             $dat_func{$1} = undef;
70             }
71             }
72              
73             my $file_content;
74              
75             if ($type eq 'prog') {
76             $file_content = $dat_comment.' -- '.$dat_engine.qq{\n\n}.$dat_text;
77             }
78             elsif ($type eq 'func') {
79             $file_content =
80             qq{\n}.
81             qq{\n}.
82             qq{
83             qq{description="Inline::WSC Class" }.
84             qq{progid="$dat_class" }.
85             qq{version="1.0">\n}.
86             qq{ \n}.
87             qq{ \n}.
88             join('', map { qq{ \n} } sort { lc($a) cmp lc($b) } keys %dat_func).
89             qq{ \n}.
90             qq{ \n}.
91             qq{ \n}.
94             qq{\n};
95             }
96             else {
97             croak "E040: Panic -- Invalid type ('$type'), expected ('prog' or 'func')";
98             }
99              
100             my $file_name = 'T_'.$dat_sha1.'.txt';
101             my $file_full = $VBRepo.'\\'.$file_name;
102              
103             write_file($file_full, $file_content);
104              
105             if ($type eq 'func') {
106             my $obj = Win32::OLE->GetObject('script:'.$file_full);
107              
108             unless ($obj) {
109             #~ my $file_text = eval{ scalar(read_file($file_full)) } || '???';
110             croak "E050: ",
111             "Couldn't Win32::OLE->GetObject('script:$file_full')",
112             " -> ".Win32::GetLastError().
113             " -> ".Win32::FormatMessage(Win32::GetLastError());
114             }
115              
116             for my $method (keys %dat_func) {
117             $dat_func{$method} = sub { $obj->$method(@_); };
118             }
119             }
120              
121             bless {
122             'name' => $file_name,
123             'type' => $type,
124             'lang' => $lang,
125             'func' => \%dat_func,
126             }, $pkg;
127             }
128              
129             sub compile_prog_vbs {
130             my ($code) = @_;
131             Win32::VBScript->new('prog', 'vbs', $code);
132             }
133              
134             sub compile_prog_js {
135             my ($code) = @_;
136             Win32::VBScript->new('prog', 'js', $code);
137             }
138              
139             sub compile_func_vbs {
140             my ($code) = @_;
141             Win32::VBScript->new('func', 'vbs', $code);
142             }
143              
144             sub compile_func_js {
145             my ($code) = @_;
146             Win32::VBScript->new('func', 'js', $code);
147             }
148              
149             sub _run {
150             my $self = shift;
151             my ($scr, $mode, $level) = @_;
152              
153             unless ($scr eq 'cscript' or $scr eq 'wscript') {
154             croak "E060: Invalid script ('$scr'), expected ('cscript' or 'wscript')";
155             }
156              
157             unless ($mode eq 'a' or $mode eq 's') {
158             croak "E061: Invalid mode ('$mode'), expected ('a' or 's')";
159             }
160              
161             unless ($level eq 'pl' or $level eq 'ms') {
162             croak "E062: Invalid level ('$level'), expected ('pl' or 'ms')";
163             }
164              
165             my $name = $self->{'name'};
166             my $lang = $self->{'lang'};
167             my $type = $self->{'type'};
168              
169             unless ($type eq 'prog') {
170             croak "E065: Invalid type ('$type'), expected ('prog')";
171             }
172              
173             my $full = $VBRepo.'\\'.$name;
174              
175             unless (-f $full) {
176             croak "E070: Panic -- can't find executable '$full'";
177             }
178              
179             my $engine =
180             $lang eq 'vbs' ? 'VBScript' :
181             $lang eq 'js' ? 'JScript' :
182             croak "E080: Panic -- invalid language ('$lang'), expected ('vbs' or 'js')";
183              
184             my @param = ($scr, '//Nologo', '//E:'.$engine, $full);
185              
186             if ($level eq 'pl') {
187             if ($mode eq 'a') {
188             system 1, @param; # asynchronous
189             }
190             elsif ($mode eq 's') {
191             system @param; # sequentially
192             }
193             else {
194             croak "E082: Panic -- invalid mode ('$mode'), expected ('a' or 's')";
195             }
196             }
197             elsif ($level eq 'ms') {
198             my $PCmd = join(' ', map { qq{"$_"} } @param);
199             my $PNum = $scr eq 'cscript' ? '1' : '0';
200             my $PBool = $mode eq 's' ? 'True' : 'False';
201              
202             # RC = CreateObject("WScript.Shell").Run($PCmd 0, False)
203             # ==> 0 = CMD Prompt will not be shown,
204             # ==> 1 = CMD Prompt will be shown,
205             # ==> False = Do not wait for program to finish
206             # ==> True = Wait for program to finish
207              
208             $proxy_invoke->($PCmd, $PNum, $PBool);
209             }
210             else {
211             croak "E084: Panic -- invalid level ('$level'), expected ('pl' or 'ms')";
212             }
213             }
214              
215             sub pl_cscript {
216             my $self = shift;
217             $self->_run('cscript', 's', 'pl'); # s = sequentially
218             }
219              
220             sub pl_wscript {
221             my $self = shift;
222             $self->_run('wscript', 's', 'pl'); # s = sequentially
223             }
224              
225             sub pl_async {
226             my $self = shift;
227             $self->_run('wscript', 'a', 'pl'); # a = asynchronous
228             }
229              
230             sub ms_cscript {
231             my $self = shift;
232             $self->_run('cscript', 's', 'ms'); # s = sequentially
233             }
234              
235             sub ms_wscript {
236             my $self = shift;
237             $self->_run('wscript', 's', 'ms'); # s = sequentially
238             }
239              
240             sub ms_async {
241             my $self = shift;
242             $self->_run('wscript', 'a', 'ms'); # a = asynchronous
243             }
244              
245             sub func {
246             my $self = shift;
247             my $mname = shift;
248              
249             $self->{'func'}{$mname};
250             }
251              
252             sub flist {
253             my $self = shift;
254             my $sf = $self->{'func'};
255              
256             sort grep { $sf->{$_} } keys %$sf;
257             }
258              
259             1;
260              
261             __END__