IDNT / vncsnapshot

VNC Snapshot is a command line utility for VNC (Virtual Network Computing) available from RealVNC, among others. The utility allows one to take a snapshot from a VNC server and save it as a JPEG file. Unix, Linux and Windows platforms are supported. The original source is located at https://sourceforge.net/projects/vncsnapshot/
GNU General Public License v2.0
15 stars 5 forks source link

Avoid Windows pointer circle/waiting icon during snapshots #2

Closed wassilis83 closed 3 weeks ago

wassilis83 commented 10 months ago

I have another annoying issue that I really cannot solve by myself.. each time I run vncsnapshot, I Will have for a second the pointer on the remote server in a loading/circle status. If I run vncsnapshot with count parameters, the pointer Will change Just on First screenshot and all the others Will be ok, so this could be a solution but since I'm using vncsnapshot as part of a big bash script that Will check,organize and put the snapshot in a dedicated folder structure for massive remote servers control, I have to run vncsnapshot as oneshot script without count parameters. Probably the loading icon triggers each time There Is an inizialization of the connection and this Is why the issue Is not present with count parameter. I was thinking to recompile the code with something like a keep Alive connection, but cannot found a way to do this. Any suggestions?

mazocode commented 10 months ago

I'm not sure if I understood this correctly, but when using count, the client simply sleeps until the next frame before saving a new screenshot (https://github.com/IDNT/vncsnapshot/blob/53ecbdf36b0058e68bfa9af46461c50e798d328f/vncsnapshot.c#L245).

To create a delay, you could use the same logic before the first screenshot is saved (for example by introducing a new argument like "skip-frames"). The logic should go somewhere around here: https://github.com/IDNT/vncsnapshot/blob/53ecbdf36b0058e68bfa9af46461c50e798d328f/vncsnapshot.c#L162

wassilis83 commented 10 months ago

I'm not sure if I understood this correctly, but when using count, the client simply sleeps until the next frame before saving a new screenshot (

https://github.com/IDNT/vncsnapshot/blob/53ecbdf36b0058e68bfa9af46461c50e798d328f/vncsnapshot.c#L245

). To create a delay, you could use the same logic before the first screenshot is saved (for example by introducing a new argument like "skip-frames"). The logic should go somewhere around here:

https://github.com/IDNT/vncsnapshot/blob/53ecbdf36b0058e68bfa9af46461c50e798d328f/vncsnapshot.c#L162

Dear, thank you for your response. The issue arises from the fact that I would like to monitor remote stations using your very useful application. However, as I explained earlier, I need to manipulate the position of the screenshots in real-time because we are dealing with massive monitoring of multiple workstations for days/h24. Consequently, I cannot put everything in the same folder, or I would end up with millions of files in that folder. To achieve this result, I have to create an infinite loop around vncsnapshot without the count parameter for several reasons:

  1. I have to specify a fixed number of repetitions but I want infinite snapshots.
  2. Using count, vncsnapshot forces the use of a name that is a sequential numerical type, and instead, I want a timestamp.
  3. Since there are many screenshots, I cannot think of rearranging them massively with a second script set in cron, so the filtering operation must be performed before the screenshot is taken.

I could certainly recompile your program from sources to suit my needs, but there was too much work to do, so I preferred to create a bash script that precisely creates an infinite loop around vncsnapshot without count and organize the file structure in the best way possible. Now the problem with this approach is that I would like to remain completely anonymous towards various VNC servers. Unfortunately, it seems that every time a VNC connection is established, the Windows pointer remains in a loading phase for a second. Since my idea is to take screenshots every 10 seconds, the operator in front of the computer sees this anomalous behavior, which I would like to avoid.

This problem does not occur using count because, as mentioned, the connection remains active, but I can no longer manipulate the behavior of the screenshots. To solve the problem, I essentially recompiled another version of vncsnapshot.c from sources that I named vnckeepalive, completely cleaning up the code and leaving only the connection implementation so that once launched, a fake connection remains active as a keepalive. With this active connection, each subsequent snapshot executed without count will not generate the problem with the mouse pointer. Of course, I had to work a bit on the script to ensure that the loop is executed only if the keepalive connection has been established. I don't think it's the most elegant way, but it works.

I don't know if you have any other ideas regarding this. In any case, I am reporting here how I recompiled the code for the vncsnapshot_keepalive version.

/*
* OPEN SOCKET FOR VNCSNAPSHOT TO AVOID MOUSE LOADING CURSOR ON SERVER SIDE
 */
static const char *ID = "$Id: vncsnapshot.c,v 1.7 2004/09/09 00:22:33 grmcdorman Exp $";

#include <time.h>
#include <ctype.h>

#include "vncsnapshot.h"

char *programName;

int main(int argc, char **argv)
{

  programName = argv[0];

  if (!InitializeSockets()) {
      return 1;
  }

  /* Interpret resource specs and process any remaining command-line arguments
     (i.e. the VNC server name).  If the server name isn't specified on the
     command line, getArgsAndResources() will complain and exit. */

  GetArgsAndResources(argc, argv);

  /* Unless we accepted an incoming connection, make a TCP connection to the
     given VNC server */

  if (!listenSpecified) {
    if (!ConnectToRFBServer(vncServerHost, vncServerPort)) exit(1);
  }

  /* Initialise the VNC connection, including reading the password */

  if (!InitialiseRFBConnection()) exit(1);

  if (!AllocateBuffer()) exit(1);

  /* Tell the VNC server which pixel format and encodings we want to use */

  SendSetPixelFormat();
  SendSetEncodings();

  /* Stay in execution undefinetly */
  while (SendIncrementalFramebufferUpdateRequest()) {
      sleep(5);
  }

  return 0;

}

and this is the bash part


#!/bin/bash
# This software takes snapshots using vnc protocol
# on remote workstations and organize them in a daily folder's structure.
# Tested with tyghtVnc server 2.8.81
# RELIES ON VNCSNAPSHOT PROJECT https://github.com/IDNT/vncsnapshot

# Define list of remote VNC servers(IP or NETBIOS) and related snapshot folder's name as an associative array
# To use NETBIOS names install winbind, libnss-winbind and edit in /etc/nsswitch.conf hosts line with  files dns wins
declare -A servers=(
    ["CLAUDIA-PC"]="Claudia"
    ["DANIELE-PC"]="Daniele"
    ["TANIA-PC"]="Tania"
    #["IT-DEPARTMENT-P"]="IT-Department"
)

# Define vncsnapshot paramenters
path="/mnt/shared_data/utenti/ilaria/osserva/"
passwd="/mnt/shared_data/utenti/ilaria/osserva/src/osserva_passwd"
# VNC stream quality is from 0 to 9
vncQuality="3"
# Jpg quality is from 0 to 100

# Jpg quality is from 0 to 100
jpgQuality="10"
# Frame rate
frameRate="10"
# Folders retain
keep="7"

# Function to perform the task
run_instance() {

    while true; do

            local server="$1"
            local today=$(date +'%Y-%m-%d')
            local folder="${servers[$server]}"
            local folder_path="${path}${folder}/${today}"
            local process_name="vnckeepalive/${folder}"

            if ! pgrep -f "${process_name}" > /dev/null; then

                # A fake vncsnapshot process made just for keep alive the connection so will be no glitch in windows cursor on connection
                exec -a "${process_name}" "${path}"src/vnckeepalive -passwd "$passwd" -quiet "${server}:0" fake.jpg & #>/dev/null 2>&1

            else

                # Check if the folder exists, if not, create it
                if [ ! -d "$folder_path" ]; then
                    mkdir -p "$folder_path"
                    # Set specific user and group for the folder
                    chown -R admin:admin "${path}${folder}"
                    #echo "Created folder: $folder_path"
                fi

                    # Delete folders older than a specific limit (e.g., 7 days) with error suprression
                    find "${path}${folder}" -mindepth 1 -maxdepth 1 -type d -mtime +"$keep" -exec rm -r {} \;

                    # Get the current date and time in the desired format
                    local timestamp=$(date +'%Y%m%d_%H%M%S')

                    # The real vncsnapshot process
                    "${path}"src/vncsnapshot -passwd "$passwd" -quiet -quality "$jpgQuality" -vncQuality "$vncQuality" "${server}:0" "${folder_path}/${folder}_${timestamp}.jpg" #>/dev/null 2>&1

            fi

    sleep "$frameRate"; done

}

# Loop through each server in the associative array and run the function with a delay between instances
for server in "${!servers[@]}"; do
    run_instance "$server" &
    sleep 1  # Add a delay of 1 second between starting each instance
done

# Wait for all background processes to finish (optional)
wait
mazocode commented 10 months ago

Thank you for sharing your idea to work around this issue.

Personally, I firmly believe that users should always be aware that their actions are being monitored. In most jurisdictions, this type of surveillance will probably only be legal in exceptional and justified cases and within strict limits. But I'm just going to assume that you already made sure that this type of surveillance is legal for your purpose.

In my opinion, the tool is not suitable for this use case. The main reason for this is the memory, bandwidth and other resource requirements, as a full screen must be transmitted and saved every 10 seconds. A permanent recording of the session as a video stream with a low frame rate would probably make more sense here and I guess that there are already ready-made solutions available for this purpose.