Сделать HTML-файл открытым в браузере по умолчанию вместо текстового редактора в командном файле Windows - PullRequest
0 голосов
/ 07 декабря 2018

У меня есть скрипт, который генерирует некоторые HTML-страницы, когда это делается, я открываю индексный файл сгенерированных страниц.Для этого у меня есть следующий код:

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

Прямо сейчас страница открывается в моем текстовом редакторе по умолчанию для файлов .html, как я могу убедиться, что она открывается в браузере пользователя по умолчанию?Я не хочу использовать команды для определенных браузеров, поскольку я не знаю, каким будет браузер пользователя по умолчанию.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

К сожалению, с помощью команды start невозможно указать тип программы, которую вы хотите запустить.Он запустит ассоциированную программу по умолчанию, основанную на расширении файла, и вы окажетесь на злополучной милости сомнительного выбора пользователем ассоциации файлов для файлов .html.Если вы хотите, чтобы ваш файл открывался только веб-браузером, а не текстовым редактором, то было бы лучше передать URL-адрес в start, чем в файловую систему.Использование адреса http в качестве аргумента для start должно гарантировать, что объект, открывающий местоположение, будет веб-браузером.

Обслуживание вашего файла .html через http может быть выполнено без использования сторонних двоичных файлов.Нетрудно сложно использовать методы .Net для создания элементарного веб-сервера и обслуживания веб-страницы через локальный хост.Таким образом, вы можете 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()

Дополнительным преимуществом является то, что обслуживание html поверх http может помочь вам избежать срабатывания безопасности некоторых браузеров, запрещающей выполнение JavaScript отfile: /// URLs.


Если вы хотите включить другие ссылочные файлы, такие как изображения, 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()
0 голосов
/ 07 декабря 2018

Я не знаю, работает ли это с другими браузерами, но для Chrome это работает просто отлично.Вы можете открыть файл html с помощью chrome.exe, как показано ниже:

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

Другой способ - изменить обработчик по умолчанию для файлов html в вашей учетной записи Windows.(right-click to file => Open With... => select your browser и option "Open always html files...").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...