开发者

ASP.NET - remote screenshot

I made a very very simple small app to take screenshot of the desktop and send to network share. About 10 PC's would have this app installed.

My idea is, that there will be one dashboard in ASP.NET, which simply shows those screenshots on the webpage. So far, easy stuff. But, because I don't want to clog the network and send the screenshot every 1 minute, I would like to launch the .exe on the remote PC's by demand of ASP.NET user.

Unfortunately I haven't found any information (and I'm a complete ASP.NET n00b), how to launch remote executable IN the context开发者_开发知识库 of the remote PC (so I won't see screenshots of ASP server :) ) If there is no such possibility, please advise about other way to solve this.


Update after clarification:

Take a look at the situation from another angle:

Why don't you run a web server on the clients that host an asp.net page that triggers the capture. Then you can, from your root server, simply sent http requests to the clients and fetch the image.

You can try http://CassiniDev.codeplex.com - it supports external IP and hostnames.

And you may also consider simply embedding the CassiniDev-lib (a very simple example is shown here - Using CassiniDev to host ASP.Net in your application, that way you can use the web server as the reciever and the forms app can do whatever it wants on the client.

I am confident in this approach as I designed cassinidev with this as one of the primary use cases.


From asp.net you cannot. It is only HTML/JavaScript once it gets to the browser.

ActiveX is a possibility but it is quite painful and dated and limited. And painful.

The new way to do something like this is to deploy a .net Forms application or WPF app via Click Once.

You can also write a WPF Browser Application but getting the kind of permissions you would need would entail setting the site as full trust.


If a web page could launch an arbitrary .exe file on your machine, that would be a security disaster.

However, since these are your PCs, you can require them to install an ActiveX control of some kind that you could then embed in your ASP.NET page.


As others have said, there is really no way for ASP.Net to call out to the apps, but reversing the control flow should work OK...

I suppose you could have the grabber application running all the time on the users desktop, but have it make a call to a web service / file served by the server that contains an instruction for that instance of the app to grab a screenshot.

Something like...

App : Do I have to do anything? (GET /workinstruction.aspx)
Server : no. (server decides whether to request work, and return the result in (workinstruction.aspx)
App : (waits 1 minute)
App : Do I have to do anything?
Server : yes.
App : (takes screenshot and submits)
App : (waits 1 minute)
App : Do I have to do anything?

etc...


Thank you all for answering, those were interesting approaches to the subject.

Yet due to many factors I ended up with following solution:

  1. Pseudo-service (Windows Forms with tray icon and hidden form) application on client PC's. It is serving as TCP server.

  2. ASP.Net web app on the server, with TCP client function.

On request of the web user, web app is sending preformatted TCP 'activation' string to the chosen PC. Tray app is making a screenshot and sending it to predefined SMB share, available for web app to display.

Thanks again!


I've done this exact thing a few times for monitoring remote display systems. What I found was that using MiniCap.exe to capture image also took video (which was required on remote display systems). I also used Cassini as described by Sky Sanders with an ASPX-page with the following code.

Then I just reference the page from an img src="http://computer/page.aspx?paramters". (Let me know if you need more info)

    <%@ Import NameSpace="System.IO" %>
    <%@ Import NameSpace="System.Drawing" %>
    <%@ Import NameSpace="System.Drawing.Imaging" %>
    <%@ Import NameSpace="System.Diagnostics" %>
    <%

    Response.Buffer = True
    Response.BufferOutput = True

    Dim CompressionLevel As Integer = 1
    Dim compress As Integer = 1
    If Not Request.Item("compress") Is Nothing Then
        If IsNumeric(Request.Item("compress")) = True Then
            CompressionLevel = CInt(Request.Item("compress"))
        End If
    End If
    compress = CompressionLevel

    ' Resize requested?
    Dim SizeX As Integer = 100
    Dim SizeY As Integer = 75
    If Not Request.Item("width") Is Nothing Then
        If IsNumeric(Request.Item("width")) = True Then
            SizeX = CInt(Request.Item("width"))
            CompressionLevel = 10
        End If
    End If
    If Not Request.Item("height") Is Nothing Then
        If IsNumeric(Request.Item("height")) = True Then
            SizeY = CInt(Request.Item("height"))
            CompressionLevel = 10
        End If
    End If

    Dim Region As String = ""
    If Not Request.Item("region") Is Nothing Then
        Region = Request.Item("region")
    End If
    Dim XS As Integer = 0
    Dim YS As Integer = 0
    Dim XE As Integer = 1023
    Dim YE As Integer = 766

    Try
        If Region.IndexOf(",") > -1 Then
            Dim Rec() As String = Region.Split(",")
            If Rec.GetUpperBound(0) >= 3 Then
                If IsNumeric(Rec(0)) Then XS = Rec(0)
                If IsNumeric(Rec(1)) Then YS = Rec(1)
                If IsNumeric(Rec(2)) Then XE = Rec(2)
                If IsNumeric(Rec(3)) Then YE = Rec(3)
            End If

        End If
    Catch : End Try



    Dim FileType As String = "jpg"
    Dim MimeType As String = "jpeg"
    If Not Request.Item("filetype") Is Nothing Then
        FileType = Request.Item("filetype")
        MimeType = FileType
    End If
    If Not Request.Item("mimetype") Is Nothing Then
        FileType = Request.Item("mimetype")
    End If



    Dim ImageFile As String = ""
    Dim ImageThumbFile As String = ""
    Dim ImageFolder As String = Server.MapPath("~/ScreenShots/")

    If IO.Directory.Exists(ImageFolder) = False Then
        IO.Directory.CreateDirectory(ImageFolder)
    End If

    ' Delete files older than 30 minutes
    For Each File As String In IO.Directory.GetFiles(ImageFolder)
        Response.Write("File: " & File & "<br>")
        If IO.File.GetCreationTimeUtc(File).AddMinutes(30) < Now.ToUniversalTime Then
            IO.File.Delete(File)
        End If
    Next

    ' Find available filename
    Dim tmpC As Integer = 0
    While tmpC < 100
        tmpC += 1

        ImageFile = "ScreenShot_" & CStr(tmpC).PadLeft(5, "0") & "." & FileType
        ImageThumbFile = "ScreenShot_" & CStr(tmpC).PadLeft(5, "0") & "_thumb." & FileType

        If IO.File.Exists(ImageFolder & "\" & ImageFile) = False Then
            ' Found our filename
            ' Reserve it
            Dim ios As IO.FileStream = IO.File.Create(ImageFolder & "\" & ImageFile)
            ios.Close()
            ios = Nothing
            Exit While
        End If
    End While

    ' Run MiniCap

    '          " -capturedesktop" & _
Dim CMD As String = """" & Server.MapPath("/MiniCap.EXE") & """" & _
      " -save """ & ImageFolder & "\" & ImageFile & """" & _
      " -captureregion " & XS & " " & YS & " " & XE & " " & YE & _
      " -exit" & _
      " -compress " & CompressionLevel

    If Not CMD Is Nothing Then

        Dim myProcess As Process = New Process
        Dim RouteFB As String
        With myProcess
            With .StartInfo
                .FileName = "cmd.exe"
                .UseShellExecute = False
                .CreateNoWindow = True
                .RedirectStandardInput = True
                .RedirectStandardOutput = True
                .RedirectStandardError = True
            End With
            .Start()
        End With

        Dim sIn As IO.StreamWriter = myProcess.StandardInput
        sIn.AutoFlush = True

        ' Create stream reader/writer references
        Dim sOut As IO.StreamReader = myProcess.StandardOutput
        Dim sErr As IO.StreamReader = myProcess.StandardError

        ' Send commands
        sIn.Write(CMD & System.Environment.NewLine)
        sIn.Write("exit" & System.Environment.NewLine)

        ' Wait one second
        'Threading.Thread.CurrentThread.Sleep(60000)

        ' Read all data
        Response.Write(sOut.ReadToEnd)

        ' Kill process if still running
        If Not myProcess.HasExited Then
            myProcess.Kill()
        End If

        sIn.Close()
        sOut.Close()
        sErr.Close()
        myProcess.Close()
    End If


    Response.Clear()
    Response.ClearContent()



    If Not Request.Item("width") Is Nothing Or Not Request.Item("length") Is Nothing Then
        ' Resize, making thumbnail in desired size
        Dim b As Bitmap = Bitmap.FromFile(ImageFolder & "\" & ImageFile)
        Dim thumb As Bitmap = b.GetThumbnailImage(SizeX, SizeY, Nothing, IntPtr.Zero)

        ' Jpeg image codec 
        Dim jpegCodec As ImageCodecInfo
        ' Get image codecs for all image formats 
        Dim codecs As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
        ' Find the correct image codec 
        For i As Integer = 0 To codecs.Length - 1
            If (codecs(i).MimeType = "image/" & MimeType) Then
                jpegCodec = codecs(i)
                Exit For
            End If
        Next i
        Dim qualityParam As New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, compress * 10)
        Dim encoderParams As New EncoderParameters(1)
        encoderParams.Param(0) = qualityParam

        thumb.Save(ImageFolder & "\" & ImageThumbFile, jpegCodec, encoderParams)
        thumb.Dispose()
        b.Dispose()
        ' Send thumb
        Response.TransmitFile(ImageFolder & "\" & ImageThumbFile)
    Else
        ' Send normal file
        Response.TransmitFile(ImageFolder & "\" & ImageFile)
    End If


    Response.End()

%>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜