I have a powershell script which needs to run a number of executables.
我有一个PowerShell脚本,它需要运行一些可执行文件。
The executables have no extension, and cannot be renamed.
可执行文件没有扩展名,无法重命名。
They all have the format <something>_test
.
它们的格式都是
_test。
When I try to run them using powershell:
当我尝试使用PowerShell运行它们时:
& $test_bin | Tee-Object -FilePath $log_output_file
It fails with the error
它会失败,并显示错误
Cannot run a document in the middle of a pipeline
I tried setting PATHEXT ($env:PATHEXT="$env:PATHEXT;_test"
) but that didn't help. I'm guessing it only supports actual extensions.
我尝试设置PATHEXT($env:PATHEXT=“$env:PATHEXT;_test”),但没有帮助。我猜它只支持实际的扩展。
Is there anyway to tell windows that a specific file is an executable, or to tell powershell to execute a file even though it thinks it's a document?
有没有什么办法可以告诉Windows某个特定的文件是可执行文件,或者告诉PowerShell执行一个文件,即使它认为它是一个文档?
更多回答
What happens when you run only & $test_bin
? ... I mean without the | Tee-Object -FilePath $log_output_file
...
当你只运行& $test_bin时会发生什么?...我是说如果没有|T形对象文件路径$log_output_file.
Then it opens a dialog to select how I want to open the file.
然后它会打开一个对话框来选择我想要打开文件的方式。
Have you tried using Start-Process
? Why is renaming not an option?` On Windows systems executables usually have an extension. ¯\_(ツ)_/¯
您尝试过使用Start-Process吗?为什么重命名不是一个选项?在Windows系统上,可执行文件通常有一个扩展名。\_(ツ)_/
Yeah I think I'll have to rename in the end because for example the golang exec library requires an extension too, so there's no general solution here.
是的,我想最后我必须重命名,因为例如,Golang exec库也需要一个扩展名,所以这里没有通用的解决方案。
Hmmm ... the solution would be to follow well known system standards. ¯\_(ツ)_/¯
嗯..。解决方案将是遵循众所周知的系统标准。\_(ツ)_/
优秀答案推荐
Example:
例如:
# Define a function which executes any file
function Start-ProcessEx ($filePath)
{
$psi = [System.Diagnostics.ProcessStartInfo]::new()
$psi.FileName = $filePath
$psi.UseShellExecute = $false # This is the key to run file as executable when it has non-executable extension
return [System.Diagnostics.Process]::Start($psi)
}
Start-ProcessEx -filePath 'C:\Program Files\Speedtest\Speedtest.randomextension'
There should be more ways to execute file with non-executable extension, this is one of variants.
应该有更多的方法来执行带有不可执行扩展名的文件,这是一个变体。
I tried setting PATHEXT ($env:PATHEXT="$env:PATHEXT;_test"
) but that didn't help
You'd have to use .
to represent files without an extension
($env:PATHEXT="$env:PATHEXT;."
)
那你就得用。表示不带扩展名的文件($env:PATHEXT=“$env:PATHEXT;.”)
Additionally, you'd have to define a file type (e.g. via cmd.exe
's internal assoc
and ftype
commands) that invokes a helper application to facilitate the execution.
此外,您还必须定义一个文件类型(例如,通过cmd.exe的内部assoc和ftype命令)来调用辅助应用程序以便于执行。
- This answer shows such a definition in the context of emulating shebang-line support on Windows, but it ultimately won't help you - see next point.
However, as of PowerShell (Core) 7.3.x, even if that wouldn't enough, because PowerShell - unlike cmd.exe
- then invokes the helper application in a new window; this problematic behavior is the subject of GitHub issue #9430.
然而,从PowerShell(Core)7.3.x开始,即使这还不够,因为PowerShell--不像cmd.exe--然后在一个新窗口中调用助手应用程序;这个有问题的行为是GitHub问题#9430的主题。
Workarounds:
解决方法:
If it is sufficient to support only redirecting the executable's output to files (and capturing stdout and stderr in separate files) - you can use Start-Process
with the -NoNewWindow
switch and the -RedirectStandardOutput
and -RedirectStandardError
parameters; e.g.:
如果仅支持将可执行文件的输出重定向到文件(并在单独的文件中捕获stdout和stderr)就足够了-您可以使用带有-NoNewWindow开关和-RedirectStandardOutput和-RedirectStandardError参数的Start-Process;例如:
Start-Process -Wait -NoNewWindow $test_bin -RedirectStandardOutput $log_output_file
- Character-encoding caveat: It is the encoding stored in
[Console]::OutputEncoding
that is used for the files created by -RedirectStandardOutput
and -RedirectStandardError
, which defaults the legacy system locale's OEM code page; (temporarily) set [Console]::OutputEncoding
to the desired encoding as needed. The same applies analogously to stdout output that PowerShell directly receives from external programs (see next point).
If you want the usual PowerShell experience - synchronous execution in the same window, with the executable process' standard streams (stdin, stdout, stderr) connected to PowerShell's streams - more work is needed:
如果您想要常见的PowerShell体验--在同一窗口中同步执行,并将可执行进程的标准流(stdin、stdout、stderr)连接到PowerShell的流--则需要做更多工作:
Helper function Invoke-ExtensionLess
(source code) below is a simple proof-of-concept that uses .NET APIs (System.Diagnostics.Process
, System.Diagnostics.ProcessStartInfo
) to support directly streaming the executable's stdout output to the PowerShell pipeline, but it lacks support for streaming pipeline (stdin) input (adding such support would require quite a bit more effort).
下面的Helper函数Wicke-ExtensionLess(源代码)是一个简单的概念验证,它使用.NET API(System.Diagnostics.Process,System.Diagnostics.ProcessStartInfo)来支持将可执行文件的标准输出直接流式传输到PowerShell管道,但它缺乏对流式管道(stdin)输入的支持(添加此类支持将需要相当多的工作)。
A sample invocation would look like this:
示例调用如下所示:
Invoke-ExtensionLess $test_bin arg1 arg2 |
ForEach-Object { "[$_]" } # sample pipeline processing.
Invoke-ExtensionLess
source code:
Invoke-ExtensionLess源代码:
# Note: No support for stdin input.
function Invoke-ExtensionLess {
param($exe)
# Find the executable's full path
$exePath = if (Test-Path -LiteralPath $exe) { Convert-Path -LiteralPath $exe } else { (Get-Command -ErrorAction Stop -Type Application $exe).Path }
$process = [System.Diagnostics.Process]::Start(
[System.Diagnostics.ProcessStartInfo] @{
FileName = $exePath
Arguments = $args.ForEach({ $a = $_ -replace '(?<!\\)(\\*)"', '$1$1\"'; ($a, "`"$a`"")[$_ -match ' '] }) -join ' '
UseShellExecute = $false
RedirectStandardOutput = $true
RedirectStandardError = $false
}
)
# Relay stdout output to the pipeline line by line (while not redirecting stderr output).
while (-not $process.StandardOutput.EndOfStream) {
$process.StandardOutput.ReadLine()
}
# Wait for the process to exit...
$process.WaitForExit()
# ... and report its exit code.
$global:LASTEXITCODE = $process.ExitCode
}
更多回答
我是一名优秀的程序员,十分优秀!