Use PowerShell commands in WinCC OA to create screenshots with child panels

I am sure there are lots of great things to achieve with Windows PowerShell in WinCC OA. I have decided to show you how to circumvent a restriction in WinCC OA some of you might know when printing panels:
Starting with Windows 8 and above child panels cannot be printed due to technical restrictions of the operating systems.
In the past I created an example which used some external programs (like "boxcutter") to create screenshots including child panels. But often third party programs are not very welcome.

I did some initial tests with Windows PowerShell and found it to be working great (tested in Windows 7 and Windows 10).
A test directly from the command line

The goal from above test was to directly execute the command instead of having to write a temporary script file.

Running this successfully I was able to encapsulate this into a small function within WinCC OA:
int PSscreenShot(int x1, int y1, int x2, int y2, const string &fpath)
{
  string prog = "powershell -command \"& "
                "{[Reflection.Assembly]::LoadWithPartialName(\\\"System.Drawing\\\"); "
                "$bounds = [Drawing.Rectangle]::FromLTRB(" +
                      x1 + ", " + y1 + ", " + x2 + ", " + y2 + "); "
                "$bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height; "
                "$graphics = [Drawing.Graphics]::FromImage($bmp); "
                "$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, "
                                         "$bounds.size); "
                "$bmp.Save(\\\"" + fpath + "\\\"); "
                "$graphics.Dispose(); "
                "$bmp.Dispose()}\"";
  
  string sout = "";
  int ret = 0;
  
  if (prog != "")
  {
    ret = system(prog, sout);
    //DebugTN(ret, sout);
    return ret;
  }

  return -1;  
}

Using the function is straight forward, just give the right arguments to create screenshots from whatever you like, also from something else than WinCC OA. In the following example I will create a screenshot of my current panel, including child panels, if there are some displayed on top of the current panel.
  // save in pictures folder of the project
  string fpath=getPath(PICTURES_REL_PATH) + "screenshot_" +
               formatTime("%Y%m%d_%H%M%S", getCurrentTime()) + ".png";
  strreplace(fpath, "/", "\\");

  // get the position and size
  int x, y, w, h; 
  panelPosition(myModuleName(), "", x, y);
  panelSize("", w, h);

  // set the coordinates for the screenshot
  int x1 = x;
  int x2 = x1 + w;
  int y1 = y;
  int y2 = y1 + h;
  
  // call the screenshot function
  if (PSscreenShot(x1, y1, x2, y2, fpath) == 0)
  {
    // DebugTN("success");
  }

The following screenshot shows a panel with an embedded module and an open child panel. The screenshot was created with the script from above by the button on the bottom of the screenshot.

If you want to open the created png file with the Windows Photo Viewer (maybe for printing?), replace the "Success"-DebugTN command with the following:
    // open Windows Photo Viewer 
    system("%SystemRoot%\\System32\\rundll32.exe "
           "\"%ProgramFiles%\\Windows Photo Viewer\\PhotoViewer.dll\", "
           "ImageView_Fullscreen " + fpath);

Thanks to Mr. Daxer from Insoft for the idea to use Windows PowerShell instead of boxcutter.

Best regards,
Andreas

4 comments:

  1. Replies
    1. This particular example will not work in Linux because of the missing PowerShell. In Linux you can still use the WinCC OA function printPanel to also capture child-panels.

      Delete
  2. Funktioniert sehr gut!
    Zusatztip! Wenn man den Screenshot als Hintergrundbild in ein Panel lädt, dann kann man die WinCC OA Druckfunktionen wie bekannt weiter verwenden.

    ReplyDelete
  3. Very nice article, I enjoyed reading your post, very nice share, I want to twit this to my followers. Thanks!. Zonnepanelen installateur

    ReplyDelete