-
Notifications
You must be signed in to change notification settings - Fork 2
Description
目的
在ZCMS中专题可视化制作,原来的截图用的是html2canvas,其原理是解析html和css,在Canvas上绘制截图,相当于实现了浏览器的css解析部分的功能,不但无法正确还实际的界面效果,绘制的的速度还很慢,甚至会因为脚本错误导致无法返回截图。
现在的思路是用C#在本地跑一个http服务器,并响应js请求对网页截屏,然后上传图像到远程服务器。
实现过程
-
在baidu 里搜索“C#截图”找到一些文章
如 https://blog.csdn.net/weixin_36381867/article/details/79434143 -
为了写C#,找一下相关的文档
https://www.asp.net/get-started -
查 .netcore的api手册,没有找到与http通讯有关的内容,在microsofe全站搜索“CopyFromScreen”找到了 https://docs.microsoft.com/zh-cn/dotnet/api/system.drawing.graphics.copyfromscreen?view=netframework-4.7.2#System_Drawing_Graphics_CopyFromScreen_System_Int32_System_Int32_System_Int32_System_Int32_System_Drawing_Size_
看来 .net core里没有CopyFromScreen,.net framework里有 CopyFromScreen。
怎么办?
先尝试一下在.net core里用.net framework里的功能
在google里搜索“.net core Bitmap”
找到这个页面
https://stackoverflow.com/questions/40892189/net-core-and-system-drawing
大意是,.net core的TargetFramework 为 netcoreapp 它是跨平台的,没有包含操作系统的api如目录操作等。
.NET Framework 的 TargetFramework 为net46
它们是不能混用的。
所以我们要开始一个新的项目,基于.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/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