open 从 Perl 中读取 Windows 程序的数据时出现无效参数错误。

huangapple go评论57阅读模式
英文:

Invalid argument error from open when reading data from a windows program in perl

问题

我是一名中级用户,被调用来处理通过获取许可管理器状态报告来监视程序使用的例行程序。

我正在使用在运行Windows Server 2019 Standard V 1809的服务器上的Perl,目前遇到一个问题。这是一个基于有效程序的新程序,在运行获取状态的行时产生了“无效参数”错误。

我遇到问题的程序行是:

# $command1 = "c:\\Cadence\\LicenseManager\\lmutil.exe lmstat -a -c `c:\\Cadence\\LicenseManager\\license.dat |";
$command1 = ''"C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil" lmstat -a -c "C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic"'';

print "Read license status - >$command1<\n\n";
open(STATUS, $command1) || die "Couldn't run $command1: $!\n";

被注释的$command1赋值的版本是前一个程序中有效的。取消注释的版本在运行获取状态的行时产生“C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil”lmstat -a -c “C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic”的命令,从命令提示符中运行时是完美的。我能看到的主要区别是我必须使用‘,以便我可以获得处理目录名中的空格所需的引号。我没有指定目录名。取消注释的版本在命令中没有管道。我想确保这不是问题的原因,但它在命令行中无法运行。

我从代码的这部分得到的输出是:

读取许可状态 - >"C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/bin/lmutil" lmstat -a -c "C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/innovmet.lic"<

无法运行"C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/bin/lmutil" lmstat -a -c "C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/innovmet.lic": 无效的参数

有人有想法为什么Perl不喜欢我要求它运行的命令行吗?

英文:

I am an intermediate user that has been pressed into service to work with routines that monitor program use by getting license manager status reports.
I am using perl on a server that is running Windows Server 2019 Standard V 1809

I am presently having a problem with a new program (based on ones that work) which produces an “Invalid argument” error when it runs the line to get the status.

The lines in the program that I am having trouble with are:

# $command1 = &quot;c:\\Cadence\\LicenseManager\\lmutil.exe lmstat -a -c `c:\\Cadence\\LicenseManager\\license.dat |&quot;;
$command1 = &#39;&quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;&#39;;

print &quot;Read license status - &gt;$command1&lt;\n\n&quot;;
open(STATUS, $command1) || die &quot;Couldn&#39;t run $command1: $!\n&quot;;

The commented version of the $command1 assignment works from a previous program.
The uncommented version produces &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot; which runs perfectly as a command from a command prompt.
The big difference that I can see is that I had to use so that I could get the quote marks needed to handle the spaces in the directory names. I did not get to specify the directory names.
The uncommented version does not have the pipe in the command. I wanted to be sure that this was not the cause of the problem and it cannot run from the command line with it.

The output that I get from this part of the code is:
> Read license status - >"C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/bin/lmutil" lmstat -a -c "C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/innovmet.lic"<
>
> Couldn't run "C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/bin/lmutil" lmstat -a -c "C:/Program Files/InnovMetric/PolyWorks MS License Server 2022/innovmet.lic": Invalid argument

Anyone have ideas why perl doesn’t like the command line I am asking it to run?

答案1

得分: 2

修改了代码以在原始问题中进行编译后,运行时出现以下结果:

&gt;perl.exe try.pl
读取许可证状态 - &gt;&quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;&lt;

无法运行 &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;: 无效的参数

这与您的情况相符。正如 @user20284150 已经提到的,如果在open中传递没有尾随|的文件名,它将尝试打开文件&quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;。该文件不存在,因此出现错误。不清楚为什么会给出无用的错误 - 本应该期望它显示找不到文件或目录

为了显示区别,这里是一个快速演示。首先执行与您相同的操作,运行open而没有尾随的|

use strict ;
use warnings;

# 命令中没有尾随的&quot;|&quot;
my $command1 = &#39;perl -v&#39;;

print &quot;读取许可证状态 - &gt;$command1&lt;\n\n&quot;;
open(STATUS, $command1) || die &quot;无法运行 &#39;$command1&#39;: $!\n&quot;;

while(<STATUS>)
{
    print &quot;GOT --  $_&quot;;
}

运行结果如下:

&gt;perl.exe try.pl
读取许可证状态 - &gt;perl -v&lt;

无法运行 &#39;perl -v&#39;: 找不到文件或目录

这提供了有用的错误信息。现在相同的代码,但包含了尾随的|

use strict ;
use warnings;

# 注意这次有尾随的&quot;|&quot;
my $command1 = &#39;perl -v |&#39;;

print &quot;读取许可证状态 - &gt;$command1&lt;\n\n&quot;;
open(STATUS, $command1) || die &quot;无法运行 &#39;$command1&#39;: $!\n&quot;;

while(<STATUS>)
{
    print &quot;GOT --  $_&quot;;
}

这给出以下输出:

&gt;perl.exe try.pl
读取许可证状态 - &gt;perl -v |&lt;

GOT --  
GOT --  This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread
GOT --  
GOT --  Copyright 1987-2021, Larry Wall
GOT --  
GOT --  Perl may be copied only under the terms of either the Artistic License or the
GOT --  GNU General Public License, which may be found in the Perl 5 source kit.
GOT --  
GOT --  Complete documentation for Perl, including FAQ lists, should be found on
GOT --  this system using &quot;man perl&quot; or &quot;perldoc perl&quot;.  If you have access to the
GOT --  Internet, point your browser at http://www.perl.org/, the Perl Home Page.
GOT --  
英文:

After fixing the code to compile in the original question, I get this when I run it

&gt;perl.exe try.pl
Read license status - &gt;&quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;&lt;

Couldn&#39;t run &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;: Invalid argument

That matches what you have. As @user20284150 already mentioned, passing open a filename without a trailing | means it will attempt to open the file &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot;. That file doesn't exist, thus the error. No idea why it gives the unhelpful error though - would have expected it to say No such file or directory.

To show the distinction, here is a quick demo. Firstly doing the equivalent of what you did and run the open without the trailing |

use strict ;
use warnings;

# Not no trailing &quot;|&quot; in the command
my $command1 = &#39;perl -v&#39;;

print &quot;Read license status - &gt;$command1&lt;\n\n&quot;;
open(STATUS, $command1) || die &quot;Couldn&#39;t run &#39;$command1&#39;: $!\n&quot;;

while(&lt;STATUS&gt;)
{
    print &quot;GOT --  $_&quot;;
}

running gives

&gt;perl.exe try.pl
Read license status - &gt;perl -v&lt;

Couldn&#39;t run &#39;perl -v&#39;: No such file or directory

That gives a useful error

Now the same code, but with the trailing | included

use strict ;
use warnings;

# note trailing &quot;|&quot; this time
my $command1 = &#39;perl -v |&#39;;

print &quot;Read license status - &gt;$command1&lt;\n\n&quot;;
open(STATUS, $command1) || die &quot;Couldn&#39;t run &#39;$command1&#39;: $!\n&quot;;

while(&lt;STATUS&gt;)
{
    print &quot;GOT --  $_&quot;;
}

that gives this output

&gt;perl.exe try.pl
Read license status - &gt;perl -v |&lt;

GOT --  
GOT --  This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread
GOT --
GOT --  Copyright 1987-2021, Larry Wall
GOT --
GOT --  Perl may be copied only under the terms of either the Artistic License or the
GOT --  GNU General Public License, which may be found in the Perl 5 source kit.
GOT --
GOT --  Complete documentation for Perl, including FAQ lists, should be found on
GOT --  this system using &quot;man perl&quot; or &quot;perldoc perl&quot;.  If you have access to the
GOT --  Internet, point your browser at http://www.perl.org/, the Perl Home Page.
GOT --

答案2

得分: 2

尝试打开名为"C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil" lmstat -a -c "C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic"的文件进行读取。没有这样的文件。这甚至不是一个合法的文件名,因此会出现“无效参数”错误消息。

正确的方法:

my $cmd = '...';

open( my $pipe, "|-", $cmd )
   or die( "无法启动cmd: $!\n" );

...

close( $pipe );
die( "关闭管道时出错: $!\n"                   ) if $? == -1;
die( "子进程被信号杀死 " .( $? & 0x7F )."\n" ) if $? & 0x7F;
die( "子进程以错误退出 " .( $? >> 8 )."\n"  ) if $? >> 8;

(@pmqs建议使用open( PIPE, "$cmd |" )而不是open( my $pipe, "|-", $cmd ),但是使用只有两个参数的open是陈旧的,而且使用全局变量作为文件句柄是不好的实践。)


例如,

use v5.14;
use warnings;

my $cmd = 'perl -v';

open( my $pipe, "|-", $cmd )
   or die( "无法启动cmd: $!\n" );

while ( <$pipe> ) {
   chomp;
   say "[$_]";
}

close( $pipe );
die( "关闭管道时出错: $!\n"                   ) if $? == -1;
die( "子进程被信号杀死 " .( $? & 0x7F )."\n" ) if $? & 0x7F;
die( "子进程以错误退出 " .( $? >> 8 )."\n"  ) if $? >> 8;
>75747203.pl
[]
[This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread]
[]
[Copyright 1987-2021, Larry Wall]
[]
[Perl may be copied only under the terms of either the Artistic License or the]
[GNU General Public License, which may be found in the Perl 5 source kit.]
[]
[Complete documentation for Perl, including FAQ lists, should be found on]
[this system using "man perl" or "perldoc perl".  If you have access to the]
[Internet, point your browser at http://www.perl.org/, the Perl Home Page.]
[]
英文:

You're trying to open a file named &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\bin\lmutil&quot; lmstat -a -c &quot;C:\Program Files\InnovMetric\PolyWorks MS License Server 2022\innovmet.lic&quot; for reading. There's no such file. It's not even a legal file name, thus the Invalid argument error message.

The correct approach:

my $cmd = &#39;...&#39;;

open( my $pipe, &quot;-|&quot;, $cmd )
   or die( &quot;Can&#39;t launch cmd: $!\n&quot; );

...

close( $pipe );
die( &quot;Error closing pipe: $!\n&quot;                   ) if $? == -1;
die( &quot;Child killed by signal &quot;.( $? &amp; 0x7F ).&quot;\n&quot; ) if $? &amp; 0x7F;
die( &quot;Child exited with error &quot;.( $? &gt;&gt; 8 ).&quot;\n&quot;  ) if $? &gt;&gt; 8;

(@pmqs suggests open( PIPE, &quot;$cmd |&quot; ) instead of open( my $pipe, &quot;-|&quot;, $cmd ), but using open with only two arguments is archaïc, and using a global variable for the file handle is a bad practice.)


For example,

use v5.14;
use warnings;

my $cmd = &#39;perl -v&#39;;

open( my $pipe, &quot;-|&quot;, $cmd )
   or die( &quot;Can&#39;t launch cmd: $!\n&quot; );

while ( &lt;$pipe&gt; ) {
   chomp;
   say &quot;[$_]&quot;;
}

close( $pipe );
die( &quot;Error closing pipe: $!\n&quot;                   ) if $? == -1;
die( &quot;Child killed by signal &quot;.( $? &amp; 0x7F ).&quot;\n&quot; ) if $? &amp; 0x7F;
die( &quot;Child exited with error &quot;.( $? &gt;&gt; 8 ).&quot;\n&quot;  ) if $? &gt;&gt; 8;
&gt;75747203.pl
[]
[This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x64-multi-thread]
[]
[Copyright 1987-2021, Larry Wall]
[]
[Perl may be copied only under the terms of either the Artistic License or the]
[GNU General Public License, which may be found in the Perl 5 source kit.]
[]
[Complete documentation for Perl, including FAQ lists, should be found on]
[this system using &quot;man perl&quot; or &quot;perldoc perl&quot;.  If you have access to the]
[Internet, point your browser at http://www.perl.org/, the Perl Home Page.]
[]

huangapple
  • 本文由 发表于 2023年3月15日 21:27:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75745364.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定