3

我正在尝试以编程方式确定 .ps1 脚本是否正在运行。如果它运行可见,它应该重新启动自己隐藏。如果它已经隐藏,请不要采取任何措施。

我遇到的问题是一个循环,由于无法确定隐藏状态,它会不断地自行重启。

我一直在查看 get-process cmdlet 和 GWMI Win32_process 并没有看到类似 .visible 属性来检查状态。

    If ($me -eq visible ???)
{
$Invisible = New-Object System.Diagnostics.ProcessStartInfo
$Invisible.FileName = "PowerShell.exe"
$Invisible.windowStyle ="Hidden"
$Invisible.arguments = "$myInvocation.MyCommand.Definition"
$Invisible.Verb = 'runas'
[System.Diagnostics.Process]::Start($Invisible)
}

知道如果-eq反对我可以做什么领域???

4

4 回答 4

3

尝试使用 user32 函数“IsWindowVisible”

If (-not ([System.Management.Automation.PSTypeName]'My_User32').Type) {
Add-Type -Language CSharp -TypeDefinition @"
    using System.Runtime.InteropServices;
    public class My_User32
    { 
        [DllImport("user32.dll")]
        public static extern bool IsWindowVisible(int hwnd);
    }
"@
}

$proc = Start-Process powershell.exe -WindowStyle Hidden -ArgumentList $myInvocation.MyCommand.Definition -Verb runas -PassThru
If ([My_User32]::IsWindowVisible($proc.MainWindowHandle)) {
    #Window is visible
}
Else {
    #Window is not visible
}

请注意,“isWindowVisible”的返回值并不是严格意义上的布尔值。它返回窗口的 WS_VISIBLE 样式位。因为 hidden 的值是零而 visible 的值是非零的,所以它将作为布尔值工作。但是如果你想安全的话,你可以重写 If 语句来检查 -ne 0 以确定是否可见。

还要注意 $proc.MainWindowHandle 的使用。您不能使用 $proc.Handle,因为它不是父窗口的句柄。

有关“IsWindowVisible”功能的更多信息,请参阅 Microsoft 文档:http:
//msdn.microsoft.com/en-us/library/windows/desktop/ms633530%28v=vs.85%29.aspx

有关窗口样式的详细信息,请参阅 Microsoft 文档:http:
//msdn.microsoft.com/en-us/library/czada357.aspx

于 2014-03-31T18:15:15.607 回答
1

在进程中,您可以通过测试确定它是否在隐藏运行:

(get-process -Id $PID).StartInfo.WindowStyle
于 2013-12-21T14:38:42.107 回答
1

您可以通过捕获新进程来获取 StartInfo 属性:

$proc = [System.Diagnostics.Process]::Start($Invisible)
$proc.StartInfo.WindowStyle

Start-Process您还可以使用cmdlet 启动进程并设置其 StartInfo

$proc = Start-Process powershell.exe -WindowStyle Hidden -ArgumentList $myInvocation.MyCommand.Definition -Verb runas -PassThru
$proc.StartInfo.WindowStyle
于 2013-12-21T12:38:09.487 回答
1

我已经创建了一个 kludge,但它远非答案。它有一些限制,如果文件或文件夹路径中包含“隐藏”,它会错误报告。它还需要从 vbs 方法调用自身,因为内部 Start-Process cmdlet 不会像 vbs.shell 那样报告正确的wmi_win32process.commandline

If ((gwmi win32_process -filter "ProcessID=$PID" | select commandline).commandline -notmatch 'Hidden')
{
$INVISIBLE = $myInvocation.MyCommand.Definition
$COMMAND = "powershell.exe -nologo -WindowStyle Hidden -command $INVISIBLE"
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic');[Microsoft.VisualBasic.Interaction]::Shell("$COMMAND",0)
exit
}

所以它在命令行中读取的是这个。在右键单击时,使用 powershell 运行(又名可见运行)它会产生一个 wmi.commandline

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-file" "B:\INVISIBLE.ps1"

但是当通过 VBS 命令重新生成时,我们可以 grep 查找“隐藏”,因为 VBS 与 WMI 配合得很好,并将整个命令发送到值中。

powershell.exe -nologo -WindowStyle Hidden -command B:\INVISIBLE.ps1

仍然对我们可以读取的 wmi 属性或可以切换的方法的答案感兴趣。

于 2013-12-22T05:26:32.257 回答