首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Powershell -如果没有Excel进程,就添加捕获。

Powershell -如果没有Excel进程,就添加捕获。
EN

Stack Overflow用户
提问于 2013-10-27 10:18:13
回答 3查看 2.5K关注 0票数 3

是否有方法将if/else捕捉添加到仅

代码语言:javascript
复制
$excelId = get-process excel | %{$_.Id} | ?{$before -notcontains $_}

如果没有excel进程运行?例如,如果Excel正在运行,那么get-process id,如果没有,则忽略它。

获取-进程:找不到一个名为"excel“的进程。验证进程名并再次调用cmdlet。At run.ps1:3 char:24 + $before = @(get-process <<<< excel %{$_.Id} )+ CategoryInfo : ObjectNotFound:(excel:String) Get-Process,ProcessCommandException + FullyQualifiedErrorId : NoProcessFoundForGivenName,CategoryInfo

我的代码第3-5行如下:

代码语言:javascript
复制
$before = @(get-process excel | %{$_.Id} ) 
$excel=new-object -com excel.application
$excelId = get-process excel | %{$_.Id} | ?{$before -notcontains $_}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-27 10:36:57

我会这样做:

代码语言:javascript
复制
$before = Get-Process | % { $_.Id }
$excel=new-object -com excel.application
$excelId = Get-Process excel | % { $_.Id } | ? { $before -notcontains $_ }

这通过预先收集所有进程的ID来避免这个问题。这样,无论是否存在现有Excel进程,我们都遵循相同的步骤。如果没有,则筛选器? { $before -notcontains $_ }将不匹配和排除任何进程,我们将只获得新进程的PID。

但是,我不反对Efran Cobisi's answer:这是处理这个特定场景的另一种有效方法。

票数 2
EN

Stack Overflow用户

发布于 2013-10-27 10:25:37

您可以使用-ErrorAction参数,告诉PowerShell,无论Get-Process的结果是什么,都要告诉SilentlyContinue脚本;在此之后,将根据错误的最终存在情况来设置$? (因此,您所寻找的进程的缺失也是如此):

代码语言:javascript
复制
$excel = Get-Process excel -ErrorAction SilentlyContinue
if (-not $?) { 'Excel is not running.' }
票数 6
EN

Stack Overflow用户

发布于 2015-09-09 09:27:55

对于这个问题,已经有了很好的答案,但我有另一种基于Get进程(和其他几个cmdlet)怪癖的方法:

代码语言:javascript
复制
Get-Process 'exce[l]'

会照你说的做。

The Quirk解释了

Get-Process cmdlet和许多其他cmdlet以不同的方式处理通配符的名称。同时:

代码语言:javascript
复制
Get-Process 'NonExistentProc'

将生成错误,使用:

代码语言:javascript
复制
Get-Process 'NonExistentProc*'

如果将通配符“*”添加到末尾,则不会生成错误。在本例中,您可能会猜测返回一个空数组。这对我来说是最有意义的,但是当没有找到匹配时,就会返回$null。

对于您的情况,如果您使用:

代码语言:javascript
复制
get-process 'excel*'

如果excel没有运行,您将不会收到错误,但是您将匹配“excelHelper”和以“excel”开头的任何进程名,这可能是一个问题。您可以通过使用非常窄的通配符模式来解决这个问题:

代码语言:javascript
复制
get-process 'exce[l]'

括号通配符将匹配括号中的任何一个字符。通常一个集合或范围是给定的,但是这里我们使用了单个字符的简并情况。只有“excel”才会匹配,但是由于使用通配符,不查找匹配将不会生成错误。

如果要将其概括为处理任何给定的进程名,则可以计算模式:

代码语言:javascript
复制
$procName = 'excel'
Get-Process "$($procName.Substring(0, $procName.length-1))[$($procName[-1])]"

(好吧,这很难看,但它有效,如果你愿意的话,你可以把它分开。)

一些替代方案.

@Efran:

代码语言:javascript
复制
$excel = Get-Process excel -ErrorAction SilentlyContinue

很好(我投了赞成票),但是错误被添加到$error中。在一些较大的系统中,我看到了稍后检查或处理$error的脚本,所以我通常更喜欢使用-ErrorAction Ignore

代码语言:javascript
复制
$excel = Get-Process excel -ErrorAction Ignore

文件上说:

与SilentlyContinue不同,忽略不会将错误消息添加到$Error自动变量中。

但也要记住:

忽略值是在WindowsWindows3.0中引入的。

但这正变得越来越不成问题。

@Peter的答案简单且逻辑正确(忽略可能的竞赛条件,见下文)。我投了赞成票。虽然在这个例子中没有真正的性能问题(我刚刚测试过,在我的机器上运行了200个进程,他的代码仍然立即运行),但我感到很困扰的是,我正在创建199个不需要的流程对象。

真正的潜在问题是使用更大的PID集(我可以看到的所有进程的PID)--冲突的可能性更大,其中一个捕获的PID用于终止的进程,而PID在目标进程启动时被重用。在这个不太可能的情况下(因为时间窗口太小)但是可能发生的事件,目标进程将从考虑中被删除(因为它的PID将在$before列表中),并且看起来没有启动任何进程。

这是一个非常小的窗口,而且可能不需要担心,但是您可以跟踪process StartTime属性和ID,从而使碰撞的可能性变得非常小。您可以消除使用[System.Diagnostics.Process]::GetProcessById打开进程的PID重用的可能性(返回包含系统句柄的流程对象),但这可能不值得(但如果您这样做了,请确保通过调用process对象的close方法来关闭句柄)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19616946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档