簡體   English   中英

使HTML文件在默認瀏覽器中打開,而不是在Windows批處理文件中打開文本編輯器

[英]Make HTML file open in default browser instead of text editor in Windows batch file

我有一個生成一些HTML頁面的腳本,完成后,我打開生成的頁面的索引文件。 為此,我有以下代碼:

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

現在,該頁面在.html文件的默認文本編輯器中打開,如何確保它在用戶的默認瀏覽器中打開? 我不想為特定的瀏覽器使用命令,因為我不知道用戶的默認瀏覽器將是什么。

不幸的是,無法使用start命令指定要start的程序類型。 它將基於文件的擴展名啟動默認的關聯程序,而您對於用戶對.html文件的文件關聯的可疑選擇感到不滿。 如果要確保僅通過Web瀏覽器而不是通過文本編輯器打開文件,則最好將URL傳遞給start不是文件系統位置。 使用http地址作為start參數應確保打開位置的設備將是Web瀏覽器。

無需依賴第三方二進制文件即可通過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()

我不知道這是否適用於其他瀏覽器,但是對於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 browser然后option "Open always html files..." )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM