2019年08月03日

PCのスクショをとって、http サーバで提供する

監視カメラサーバをPCで動かしているんだが、別のところでも同じ画面が見たい
ただ複数のクライアントを動かすとサーバの負荷があがるので、台数が増やせない

というニッチな要望に対応したバッチファイル その2

今度は、http サーバとして動作します
悪用されると困るので、localhost のみ対応

参考にしたのは、

使用例:
httpserve.bat を実行するとポート 8080 で待ち受ける

とすると、スクリーンショットが現れる

httpserve.bat

@echo off
cd /d %~dp0

:最小化状態で実行する
if not "%X_MIMIMIZED%"=="1" (
    set X_MIMIMIZED=1
    start /min cmd /c,"%~0" %*
    exit
)

:これ以下に必要な処理を書く
echo "最小化!"
:loop
powershell.exe -NoProfile -ExecutionPolicy Unrestricted  .\httpserver.ps1
timeout /t 10
goto loop


 httpserver.ps1

# simple http server written in powershell
#
$port = 8080
$root = "d:\htm"


[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $strm) {
$bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
$graphics = [Drawing.Graphics]::FromImage($bmp)

$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)

$bmp.Save($strm, [System.Drawing.Imaging.ImageFormat]::Jpeg)

$graphics.Dispose()
$bmp.Dispose()
}

function Get-PrimaryScreenshot($mstream) {            
[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")            
[void] [Reflection.Assembly]::LoadWithPartialName("System.Drawing")            
$Screens = [system.windows.forms.screen]::AllScreens            

foreach ($Screen in $Screens) {            
$DeviceName = $Screen.DeviceName            
$Width  = $Screen.Bounds.Width            
$Height  = $Screen.Bounds.Height            
$IsPrimary = $Screen.Primary            

if( $IsPrimary )
{
$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, $Width, $Height)
screenshot $bounds $mstream
}

}         

}


$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 2560, 1080)
$mstream = New-Object System.IO.MemoryStream

[console]::TreatControlCAsInput = $true
Write-Host "Simple Http Server start."


$listener = New-Object system.net.HttpListener
$listener.Prefixes.Add('http://127.0.0.1:'+$port+'/')
$listener.Start()
while($true) {

if ([console]::KeyAvailable) {
$key = [system.console]::readkey($true)
if (($key.modifiers -band [consolemodifiers]"control") -and($key.key -eq "C")) {
"Terminating..."
break
}
}

$context = $listener.GetContext() # block

$request = $context.Request

$request.RawUrl
if( $request.RawUrl -eq "/" )
{
$path = $root + "\index.html"
}
else
{
$path = $root + $request.RawUrl.Replace("/", "\");
}

$path

 $response = $context.Response
 if( $path.EndsWith("\screen.jpg" ) )
 {
Get-PrimaryScreenshot $mstream

$response.ContentType = "image/jpeg"
$buffer = [System.Byte[]]::CreateInstance([System.Byte],$mstream.length)
$mstream.seek(0,0)
$mstream.read($buffer, 0, $buffer.length)
$mstream.seek(0,0)
 }
 else
 {
if( Test-Path $path ) {
# 要求されたURLに対応するコンテンツを返す。
$page = Get-Content -Path $path -Encoding Byte

if( $path.EndsWith(".png"))
{
$response.ContentType = "image/png"
$buffer = Get-Content -Path $path -Encoding Byte
}
elseif( $path.EndsWith(".jpg"))
{
$response.ContentType = "image/jpeg"
$buffer = Get-Content -Path $path -Encoding Byte
}
else
{
$page = Get-Content -Path $path
$buffer = [System.Text.Encoding]::UTF8.GetBytes($page)
}
} else {
# 404
"404"
$errfile = $root + "\404.html"
$page = Get-Content -Path $errfile
$buffer = [System.Text.Encoding]::UTF8.GetBytes($page)
}
}
$response.ContentLength64 = $buffer.Length
$output = $response.OutputStream
$output.Write($buffer,0,$buffer.Length)

$output.Close()
}

$listener.Stop()





index.html

<head>
<meta http-equiv="refresh" content="10" />
</head>

<img src=screen.jpg>




posted by とーふ at 15:38| Comment(0) | PCソフト
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: