【问题标题】:Make HTML file open in default browser instead of text editor in Windows batch file在默认浏览器中打开 HTML 文件,而不是在 Windows 批处理文件中打开文本编辑器
【发布时间】:2018-12-12 01:56:16
【问题描述】:

我有一个生成一些 HTML 页面的脚本,完成后我打开生成页面的索引文件。为此,我有以下代码:

if exist "generated_pages/index.html" start "" "generated_pages/index.html"

现在页面在我的 .html 文件的默认文本编辑器中打开,我如何确保它在用户的默认浏览器中打开?我不想对特定浏览器使用命令,因为我不知道用户的默认浏览器是什么。

【问题讨论】:

  • 我认为它是在 .html 文件的默认处理程序中打开的,这恰好是您 Windows 帐户中的文本编辑器。
  • 更改.html 扩展的默认处理程序,或以.html 文件作为参数启动浏览器。如果您使用的是 Windows,则可以强制 IE 打开它,但无论如何,您都应该允许默认处理程序打开文件。
  • 显示页面的最佳方式是使用小型 HTTP 服务器——例如IIS Express,或者如果您更喜欢无需安装的东西,则使用netcat or mongoose。这将解决您的文件关联难题,但它也可能解决您尚未考虑的其他问题——例如,浏览器安全性阻止 JavaScript 在本地文件中运行。您也可以考虑使用mshta.exe "generated_pages/index.html" 来查看您的html。
  • 使用ASSOC /? 命令查看如何管理关联。您可能还对thewindowsclub.com/change-file-associations-windows 感兴趣
  • 问题是这个脚本是为不同计算机上的其他人设计的,这就是为什么我希望 .html 使用默认浏览器打开,而不是像 chrome 这样的特定浏览器。

标签: windows batch-file cmd


【解决方案1】:

很遗憾,无法使用start 命令指定您希望启动的程序类型。它将根据文件的扩展名启动默认的关联程序,并且您将受到用户对 .html 文件文件关联的可疑选择的命运的摆布。如果您想确保您的文件只能由 Web 浏览器而不是由文本编辑器打开,那么最好将 URL 传递到 start 而不是文件系统位置。使用 http 地址作为 start 的参数应该保证打开该位置的东西是网络浏览器。

无需依赖第三方二进制文件即可通过 http 提供 .html 文件。使用 .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()

【讨论】:

    【解决方案2】:

    我不知道这是否适用于其他浏览器,但对于 Chrome,这很好。您可以使用chrome.exe 打开您的html 文件,如下所示:

    if exist "generated_pages/index.html" start "" "full\path\to\chrome.exe" file:///C:/example/generated_pages/index.html
    

    另一种方法是更改​​ Windows 帐户中 html 文件的默认处理程序。 (right-click to file => Open With... => select your browseroption "Open always html files...")。

    【讨论】:

    • 问题是这个脚本是为不同计算机上的其他人设计的,这就是为什么我希望 .html 使用默认浏览器打开,而不是像 chrome 这样的特定浏览器。
    猜你喜欢
    • 2014-12-21
    • 1970-01-01
    • 2011-10-18
    • 2012-08-03
    • 2014-06-29
    • 1970-01-01
    • 2016-12-14
    • 1970-01-01
    • 2013-02-28
    相关资源
    最近更新 更多