通过Xlib截屏
一,测试环境
硬件:VirtualBox 7.0
操作系统:UbuntuKylin 20.04.3 LTS
二,测试
参考:https://github.com/SollyBunny/screenshot
下载screenshot-main.zip,直接make报错,需要修改。
修改如下,去掉我暂时不关注的逻辑:
// filename: main.c #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> #include <X11/cursorfont.h> #include <png.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <dirent.h> /* LSBFirst: BGRA -> RGBA */ static void convertrow_lsb(unsigned char *drow, unsigned char *srow, XImage *img) { int sx, dx; for(sx = 0, dx = 0; dx < img->bytes_per_line; sx += 4) { drow[dx++] = srow[sx + 2]; /* B -> R */ drow[dx++] = srow[sx + 1]; /* G -> G */ drow[dx++] = srow[sx]; /* R -> B */ if (img->depth == 32) drow[dx++] = srow[sx + 3]; /* A -> A */ else drow[dx++] = 255; } } /* MSBFirst: ARGB -> RGBA */ static void convertrow_msb(unsigned char *drow, unsigned char *srow, XImage *img) { int sx, dx; for(sx = 0, dx = 0; dx < img->bytes_per_line; sx += 4) { drow[dx++] = srow[sx + 1]; /* G -> R */ drow[dx++] = srow[sx + 2]; /* B -> G */ drow[dx++] = srow[sx + 3]; /* A -> B */ if (img->depth == 32) drow[dx++] = srow[sx]; /* R -> A */ else drow[dx++] = 255; } } static void writeaspng(XImage *img, FILE *fp) { png_structp png_struct_p; png_infop png_info_p; void (*convert)(unsigned char *, unsigned char *, XImage *); unsigned char *drow = NULL, *srow; int h; png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_info_p = png_create_info_struct(png_struct_p); png_init_io(png_struct_p, fp); png_set_IHDR( png_struct_p, png_info_p, img->width, img->height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); png_write_info(png_struct_p, png_info_p); srow = (unsigned char *)img->data; drow = calloc(1, img->width * 4); if(img->byte_order == LSBFirst) convert = convertrow_lsb; else convert = convertrow_msb; for(h = 0; h < img->height; ++h) { convert(drow, srow, img); srow += img->bytes_per_line; png_write_row(png_struct_p, drow); } png_write_end(png_struct_p, NULL); free(drow); png_free_data(png_struct_p, png_info_p, PNG_FREE_ALL, -1); png_destroy_write_struct(&png_struct_p, NULL); } int main(int argc, char* argv[]) { Display *display = XOpenDisplay(":0"); int screen = XDefaultScreen(display); Window root = RootWindow(display, screen); XImage *image = XGetImage( display, root, 0, 0, DisplayWidth(display, screen), DisplayHeight(display, screen), AllPlanes, ZPixmap ); char filename[64]; sprintf(filename, "%ld.png", time(NULL)); printf("Info: filename is %s\n", filename); FILE *fp; fp = fopen(filename, "wb"); writeaspng(image, fp); fclose(fp); XCloseDisplay(display); return 0; }
编译:
$ gcc main.c -o screenshot -lX11 -lpng -O0 -g
运行:
$ ./screenshot
Invalid MIT-MAGIC-COOKIE-1 key段错误 (核心已转储)
因为是通过ssh远程到VirtualBox,找不到桌面?
直接登录桌面本地,在桌面里启用终端,再执行./screenshot,生成的图片是ok的,完美的截取了桌面屏幕。
再在ssh终端执行也正常了。
再试试注销掉本地桌面,退出到登录界面,此时在ssh终端执行仍然报段错误。
所以这个程序需要有用户登录桌面后才能正常执行?
通过gdb调试,挂在XDefaultScreen()函数里,看来如果未登录的话,这个函数无法执行?
错误相关帖子:
https://unix.stackexchange.com/questions/199891/invalid-mit-magic-cookie-1-key-when-trying-to-run-program-remotely
https://askubuntu.com/questions/1238389/invalid-mit-magic-cookie-1-key-message-while-running-a-program-with-the-termin
https://unix.stackexchange.com/questions/649651/invalid-mit-magic-cookie-1-keyxhost-unable-to-open-display-0
https://serverfault.com/questions/51005/how-to-use-xauth-to-run-graphical-application-via-other-user-on-linux
https://blog.csdn.net/Anne332/article/details/118903921
https://www.jb51.cc/linux/696301.html
看来,只能参考x11vnc的代码了
待续~
——–
更新:
通过参考x11vnc的代码运行,导出一个环境变量就可以了:
$ export XAUTHORITY=/var/run/lightdm/root/:0
$ sudo ./screenshot
Info: filename is 1667785594.png
参考:
快速了解X:https://tldp.org/HOWTO/Remote-X-Apps.html
https://tldp.org/HOWTO/Remote-X-Apps-6.html
转载请保留地址:http://www.lenky.info/archives/2022/11/3221 或 http://lenky.info/?p=3221
备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来信讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。
法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。