Skip to content

用c#实现http服务器接受ajax请求,c#实现网页截图并上传文件到远程服务器 #36

@abeet

Description

@abeet

目的

在ZCMS中专题可视化制作,原来的截图用的是html2canvas,其原理是解析html和css,在Canvas上绘制截图,相当于实现了浏览器的css解析部分的功能,不但无法正确还实际的界面效果,绘制的的速度还很慢,甚至会因为脚本错误导致无法返回截图。
现在的思路是用C#在本地跑一个http服务器,并响应js请求对网页截屏,然后上传图像到远程服务器。

实现过程

所以我们要开始一个新的项目,基于.NET Framework的实现

先看文档
https://docs.microsoft.com/zh-cn/dotnet/framework/index
记下可能要参考的文档
https://docs.microsoft.com/zh-cn/dotnet/framework/network-programming/network-programming-samples
《网络编程示例》
https://docs.microsoft.com/en-us/dotnet/api/system.net.httplistener?redirectedfrom=MSDN&view=netframework-4.7.2
没想到.NET Framework开启一个http访问也挺简单的。。。

遇到“c# 未能找到类型或命名空间”的解决
找到右侧的“解决方案“1个项目””下的子目录“引用”,右键点击,“添加引用”,选择“.net”,活动鼠标,找到“System.Drawing”,选中它,点击确定。就OK了!

在git上搜索
“Graphics.FromImage BackgroundImage WindowState ShowInTaskbar FormBorderStyle”
找到截图功能参考代码
https://github.com/Horiatu/PrintScreen/blob/master/PrintScreen/CaptureForm.cs
支持按下alt键

https://github.com/sysr-q/xcap/blob/master/src/Snap.cs
有图片上传示例

https://github.com/fish-li/ClownFish.Tucao/blob/master/src/client/ClownFish.Tucao.WinClient/CaptureForm.cs

https://github.com/Dinokaiz2/AUTONOTE/blob/master/AUTONOTE/SnipForm.cs
中文注释

https://github.com/adzm/BusinessCats/blob/master/SnippingCat.cs

https://github.com/rayel/SinaWeiboClient/blob/master/WeiboClient/Forms/ScreenShot.cs

在github上搜索”new HttpListener HttpListenerContext HttpListenerRequest 200 route“

”new HttpListener HttpListenerContext HttpListenerRequest 200 routes“
”new HttpListener HttpListenerContext HttpListenerRequest 200 router“
找了一些实现HTTPServer的代码,选择最简短的几个类

https://github.com/MemoryPenguin/CodeSync2/blob/master/CodeSync2-Server/Network/HttpServer.cs
https://github.com/klasbj/fsxrelay/blob/master/fsx_relay_console/HttpServer.cs
https://github.com/ktos/BasicRestServer/blob/master/BasicRestServer.Netmf/BasicRestServer.cs

结合
https://github.com/Dinokaiz2/AUTONOTE/blob/93e60d91b9/AUTONOTE/SnipForm.cs

https://github.com/ktos/BasicRestServer/blob/master/BasicRestServer.Netmf/BasicRestServer.cs
实现了,访问
http://localhost:8080/capture?x=11&y=22&w=444&h=333
将主屏幕的特定位置载图的效果。

现在要定位浏览器所在的窗口进行截图,我设想浏览器所在窗口即鼠标所在窗口,
于是在github上搜索
”AllScreens CopyFromScreen Cursor.Position“
找到如下代码,来获取当前鼠标所在屏幕的办法
https://github.com/pj-martins/ScreenCapture/blob/master/CaptureHelper.cs

将之前实现的word中图片上传到服务器的部分逻辑移到这个c#程序里

js交互部分比较简单,就不写了。

c#实现网页截图就这么完成了,代码量还挺少,发布后不到20k,耶。

还可以改进的地方,滚动窗口截长图——现在zcms里专题的编辑区是限定在一个iframe里的,要找到这个iframe并滚动它可能有点麻烦,容后再实现。

打包成服务后出现了一个大问题

总是截图失败,取到的鼠标位置总是0,0,取到的屏幕宽总是为1024*768,
在google上搜索“c# service Screen”
找到文章
https://stackoverflow.com/questions/4712532/why-does-print-screen-in-a-windows-service-return-a-black-image
原来出于安全考虑后台服务不允许读取屏幕。
只能把截屏程序另外写一个了。

查资料解决以下问题

  • C#怎么调用其他exe并传参
  • C#怎么设置windows程序不显示任务栏图标
  • C#被调用的程序怎么返回值或者怎么判断图片已写入
  • C# 强制退出程序的强健写法

所有问题解决后,仍然有问题还是获取不到真实屏幕,看来是另外一个问题了
搜索”服务 新进程 运行 Windows 7“——这个搜索词是在多次尝试后才得到的
发现文章
http://www.cnblogs.com/gnielee/archive/2010/04/08/session0-isolation-part2.html
再在github上搜索”CreateProcessAsUser“
找到项目
https://github.com/murrayju/CreateProcessAsUser
把代码搬过来,又有几个问题

  • 调试时执行 StartProcessAsCurrentUser 总是出错,
    查资料,并测试,后来发现,在以服务模式运行才能正常执行这个方法
  • StartProcessAsCurrentUser 传参数时,没有把第一个参数传过去,刚好我原来代码的第一个参数是图片保存路径,这导致了图片总是找不到,
    反复测试,用Logger输出参数,才发现参数少了一个,于是多加一个参数,终于跑通了

注意一下后台服务的 ApplicationData 目录在 C:\Users\abeet\AppData\Roaming\zving.com
而前台应用的 ApplicationData 目录在 C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions