windows - 在默认浏览器中打开 HTML 文件,而不是在 Windows 批处理文件中打开文本编辑器
问题描述
我有一个生成一些 HTML 页面的脚本,完成后我打开生成页面的索引文件。为此,我有以下代码:
if exist "generated_pages/index.html" start "" "generated_pages/index.html"
现在该页面在我的 .html 文件的默认文本编辑器中打开,我如何确保它在用户的默认浏览器中打开?我不想对特定浏览器使用命令,因为我不知道用户的默认浏览器是什么。
解决方案
不幸的是,无法使用start
命令指定您希望启动的程序类型。它将根据文件的扩展名启动默认的关联程序,并且您将受到用户对 .html 文件文件关联的可疑选择的命运的摆布。start
如果您想确保您的文件仅由 Web 浏览器而不是由文本编辑器打开,那么将 URL 传递到文件系统位置会更好。使用 http 地址作为参数start
应该保证打开该位置的东西是 Web 浏览器。
通过 http 提供您的 .html 文件可以在不依赖 3rd 方二进制文件的情况下完成。使用 .Net 方法创建一个基本的 Web 服务器并通过 localhost 将网页返回给我们并不是非常困难的。这样start "" "http://localhost:port/"
,如果您的用户搞砸了他们的文件关联,您将有更好的机会避免在文本编辑器中打开文件。
将以下巫术另存为 .bat 脚本,根据需要调整 html 文件名和位置,然后试一试。
<# : httptest.bat -- https://stackoverflow.com/a/53689025/1683264
@echo off & setlocal
if exist test.html call :display test.html
goto :EOF
:display <htmlfile>
setlocal
set "infile=%~f1"
powershell -noprofile "iex (${%~f0} | out-string)"
endlocal & exit /b
: end Batch / begin PowerShell polyglot code #>
$tcpClient = new-object Net.Sockets.TcpClient
while ($port = get-random -min 1024 -max 65535) {
try {$tcpClient.Connect("localhost", $port)}
catch {$tcpClient.Dispose(); break}
}
$endpoint = new-object Net.IPEndPoint([Net.IPAddress]::Any, $port)
$listener = new-object Net.Sockets.TcpListener $endpoint
$listener.start()
cmd /c start "" "http://localhost:$($port)/"
$client = $listener.AcceptTcpClient()
$stream = $client.GetStream()
if ($stream.CanRead) {
[void]$stream.read((new-object byte[] 1024), 0, 1024);
}
if ($stream.CanWrite) {
$content = "HTTP/1.1 200 OK`n`n$(gc $env:infile)"
$out = [text.encoding]::UTF8.GetBytes($content)
$stream.write($out, 0, $out.length)
}
$stream.close()
$stream.dispose()
$listener.stop()
作为附带的好处,通过 http 提供 html 可以帮助您避免触发某些浏览器的安全性,禁止 JavaScript 从 file:/// URL 执行。
如果您想包含其他引用的文件,例如图像、css 文件、源 JavaScript 文件等,那么这确实有点棘手。这是一个更全面的示例,它最多侦听初始 http 请求 60 秒,然后在浏览器请求它们时继续提供相对路径来源的文件,直到 5 秒内没有收到任何请求。它应该正确地宣布图像和其他来源文件的 mime 类型。如果您需要更长的超时时间,请更改serve-content 5
底部附近的行。
<# : httptest2.bat -- https://stackoverflow.com/a/53689025/1683264
@echo off & setlocal
if exist "%~1" (call :display "%~1") else goto usage
goto :EOF
:usage
echo Usage: %~nx0 htmlfile
exit /b
:display <htmlfile>
setlocal
set "infile=%~f1"
powershell -noprofile "iex (${%~f0} | out-string)"
endlocal & exit /b
: end Batch / begin PowerShell polyglot code #>
Add-Type -as System.Web
$rootpath = (get-item $env:infile).DirectoryName
$filename = (get-item $env:infile).Name
$webname = [Web.HttpUtility]::UrlEncode($filename)
$tcpClient = new-object Net.Sockets.TcpClient
while ($port = get-random -min 1024 -max 65535) {
try {$tcpClient.Connect("localhost", $port)}
catch {$tcpClient.Dispose(); break}
}
cmd /c start "" "http://localhost:$($port)/$webname"
function log($polarity, $txt) {
$color = (("red","darkgray"),("green","white"))[$polarity]
write-host -nonewline "[" -f $color[1]
write-host -nonewline "*" -f $color[0]
write-host "] $txt" -f $color[1]
}
function serve-content($seconds) {
$timer = (get-date).AddSeconds($seconds)
while (!$listener.Pending()) {
start-sleep -milliseconds 10
if ((get-date) -ge $timer) { return $false }
}
$client = $listener.AcceptTcpClient()
$stream = $client.GetStream()
if ($stream.CanRead) {
$request = new-object byte[] 1024
$size = $stream.read($request, 0, $request.length)
$headers = [text.encoding]::UTF8.GetString($request, 0, $size)
if ($stream.CanWrite) {
$loc = $headers.split("`r?`n")[0] -replace "^\S+\s+|\s+HTTP/\d.+$"
$loc = $loc -replace "^/", "$rootpath/" -replace "/", "\"
$loc = [Web.HttpUtility]::UrlDecode($loc)
if ($loc) {
if (!(test-path $loc -type leaf)) {
$loc = [Web.HttpUtility]::UrlDecode($loc)
}
if (test-path $loc -type leaf) {
$response = ,"HTTP/1.1 200 OK"
$mime = [Web.MimeMapping]::GetMimeMapping($loc)
$response += ,"Content-Type: $mime"
$response += ,"Content-Length: $((gi $loc).length)","",""
$out = [text.encoding]::UTF8.GetBytes(($response -join "`n"))
[byte[]]$body = gc $loc -enc byte
$out += $body
$stream.write($out, 0, $out.length)
log $true $loc
}
else {
$response = "HTTP/1.1 404 Not Found","",@"
<html lang="en">
<head>
<title>Error 404</title>
</head>
<body>
<h3>Not Found</h3>
<p>The requested resource could not be located.</p>
</body>
</html>
"@
$out = [text.encoding]::UTF8.GetBytes(($response -join "`n"))
$stream.write($out, 0, $out.length)
log $false $loc
}
}
}
}
$stream.close()
$stream.dispose()
$client.close()
return $true
}
$endpoint = new-object Net.IPEndPoint([Net.IPAddress]::Any, $port)
$listener = new-object Net.Sockets.TcpListener $endpoint
$listener.start()
[void](serve-content 60)
while ((serve-content 5)) {}
$listener.stop()
推荐阅读
- three.js - Forge 查看器:如何在材质中禁用透明度
- c# - 虚拟路径问题
- r - 按特定日期访问 data.frame 子集会生成 NA
- jupyter-notebook - 如何从 Jupyter Notebook 制作精美的 PDF?
- xamarin - NSDictionary 到 Xamarin.iOS 中的 Json
- multithreading - C# 4.0 中的异步函数调用
- ssis - 如何修复“[OData Source [56]] 错误:无法从运行时连接管理器获取托管连接。” SSIS中的错误?
- laravel - Laravel - 队列作业不被重用?
- google-app-engine - 有没有办法在 Google App Engine 中查找实例的生成时间和其他详细信息?
- containers - 无服务器容器和具有自定义运行时灵活的 App Engine 之间有什么区别?