Hello,
I created a docker for X7 with two buttons.
It works fine. (Thanks to bonus630. Great project).
Please could you explain or point me to other previous topic about :
1. How to check from other application if the docker is installed?
2. How to start or close the docker from other application?
3. How to press one of the buttons from other application?
Thank you in advance
Thank you, FaneDuru for going deep into my problem and I apologize for my English. 1. When I close Corel it saves configuration with loaded client docker and unloaded server docker. On the next starts of Corel instances Process class uses this configuration and loads all configurations as clients. After that I open CorelDraw.Application COM object and for me it is chosen randomly. In COM object I can close client and start server docker. When they are started control is mine :-). and "scenario works well ". 2. The suggestion to use QueryQuit event is excellent , I thing, I will use it. In addition I will clear an external flag (file or registry) and on the first instance of QueryQuit event the program will set it. All the rest will be clients. So thanks once again for the idea. 3. External helper is only for preparing the network configuration of clients and server .
Glad to see you figuring up 'scenario;..
if 'ServerFlagFileName' keeps only a flag I think is easier to use registry. The VBA for using it is simple:
MyFlag = GetSetting("MyMacroName", "Settings", "Flag", "Something to be returned when the registry key was not created, yet")
The flag is loaded: SaveSetting "MyMacroName", "Settings", "Flag", "1" or "0"
And you can use it from the helper application, too...
Yes I am interested in seeing your helper X# code. Any code is interesting at least for the sake of learning...
I am keeping the file as flag because it can be set from other machine easy.
The helper can be started from other machine too.
The main part of the helper code is:
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.IO;
using System.Diagnostics;
using System.Management;
using Microsoft.Win32;
using Corel.Interop.VGCore;
using System.Runtime.InteropServices.ComTypes;
namespace StartCorelWorker
{
partial class Program
//===========================================================================================================
static Boolean SetDefaultClientConfiguration()
CorelDRAW.Application app = new CorelDRAW.Application();
app.Visible = true;
String serverGUID = "533768c9-af16-4144-ba3e-520abed3fa47";
String clientGUID = "a2b2f5fc-defb-4371-88ab-7ce0ed8cb054";
app.FrameWork.HideDocker(serverGUID);
app.FrameWork.ShowDocker(clientGUID);
Boolean rt = app.FrameWork.IsDockerVisible(clientGUID);
app.Quit();
app = null;
GC.Collect();
GC.WaitForPendingFinalizers();
System.Windows.Forms.Application.DoEvents();
return rt;
}
//------------------------------------------------------------------------------------
static int KillAllCorelrProcess()
Process currentProcess = Process.GetCurrentProcess();
String oname = GetProcessOwner(currentProcess.Id);
try
for (int ntries = 0; ntries < 10; ntries++)
int sumproc = 0;
Process[] localByName = Process.GetProcessesByName("CorelDRW");
for (int i = 0; i < localByName.GetLength(0); i++)
String oname1 = GetProcessOwner(localByName[i].Id);
if (oname == oname1)
sumproc++;
localByName[i].Kill();
System.Threading.Thread.Sleep(100);
if (sumproc == 0)
AppendToLog("All proceses are killed");
return 0;
AppendToLog("Error in proceses killing");
catch (Win32Exception w)
AppendToLog(w.ToString());
return -1;
//===================== MAIN =============================================================
static void Main(string[] args)
KillAllCorelrProcess();
SetDefaultClientConfiguration();
Int32 numberworkers = Convert.ToInt32(args[0]);
Process curproc = Process.GetCurrentProcess();
Int32 ncorels = 0;
foreach (Process pr in localByName)
if (GetProcessOwner(curproc.Id) == GetProcessOwner(pr.Id))
ncorels++;
for (Int32 nc = ncorels; nc < numberworkers; nc++)
Process cpr = StartNewCorelWorker();
// Check for file existance flag to start server docker
String exitfile = "RunAsServer.txt";
if (File.Exists(exitfile))
SetDistributor();
//------------------------------------------------ SUBS ------------------------------------------------------------------------
static String GetProcessOwner(int processId)
String query = "Select * From Win32_Process Where ProcessID = " + processId;
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
String[] argList = new String[] { "", "" };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
// return DOMAIN\user
return argList[1] + "\\" + argList[0];
catch (Exception e)
return "NO OWNER";
static Process StartNewCorelWorker()
IntPtr hwnd;
Process threads = new Process();
threads.StartInfo.FileName = "C:\\Program Files\\Corel\\CorelDRAW Graphics Suite X7\\Programs64\\Coreldrw.exe";
threads.StartInfo.Arguments = "";
// if (!System.IO.File.Exists(threads.StartInfo.Arguments))
// return null;
threads.StartInfo.UseShellExecute = false;
threads.StartInfo.RedirectStandardOutput = true;
threads.Start();
// wait for Corel to start different windows
int i;
for (i = 0; i < 2000; i++)
System.Threading.Thread.Sleep(10);
hwnd = FinddWindowByProcess("CorelDRAW17", threads.Id);
if (hwnd != IntPtr.Zero)
goto started;
threads.Kill();
// AppendToLog("error - could not start for 20 secs. Kill it.");
return null;
started:
//Guid("bde248ef-64f4-409d-a7c8-7157afa4eb7e")
//Menubar-f3016f3c-2847-4557-b61a-a2d05319cf18
IntPtr Menubar;
Menubar = FindChildWindow(hwnd, "Menubar-f3016f3c-2847-4557-b61a-a2d05319cf18");
if (Menubar != IntPtr.Zero)
goto started2;
started2:
IntPtr menuitem = FindChildWindow(hwnd, "3eaa9bbe-28fd-4672-9128-02974ee96332");
IntPtr Toolbar;
Toolbar = FindChildWindow(hwnd, "Toolbar-7c905e2a-cb64-4ba1-aff0-c306f392680c");
if (Toolbar != IntPtr.Zero)
goto started3;
started3:
//view+docker-a2b2f5fc-defb-4371-88ab-7ce0ed8cb054
//HwndWrapper[DefaultDomain;;cb384a41-6164-42cb-af02-31b6ffd8f2bf]
IntPtr workerwnd;
workerwnd = FindChildWindow(hwnd, "a2b2f5fc-defb-4371-88ab-7ce0ed8cb054");
if (workerwnd != IntPtr.Zero)
goto started4;
started4:
return threads;
There are not updated code parts but the idea can be understood. The code with common calls to WIN32 API is skipped too.
Thanks for share it!
But I must confess I do not understand too much...
I can not see the communication (client - server) part and I just try to suppose what it really does. When you name client (or server) docker should I understand that at a specific time the client docker and server docker will be connected? And they will send and receive packets for and from each other? Or you use only the helper application like communication interface?
I also did not understand too much about the real need/scope of this project... From what I (think I) understood, I would structure this project in the next way:
1. The helper should listen on a specific port and after connection it will only start corel application. At request it will check if corel application process is running and if not it will be started again... Besides that it will be able to show a specific docker of the running corell application, in case of all of them are hidden.
2. The client (server) docker will be a real client (server) able to make connections clients - server. The sequence of which docker will be firstly opened or closed will be handled inside corel by the docker itself helped only by corel built events. I mean if the docker needed to be secondly shown is by mistake made visible, it will commit suicide and a specific corel event will open (it, them) again in the right sequence. They will directly communicate changing packets between each other. In this way clicking the buttons you put in discussion in your initial post is easy and all the necessary information to be changed will be done without help of anything else. The docker status (hide, visible) is directly transmitted and directly controlled from one docker to the other (placed on different computers). The single need for helper is in the moment when any (client, server) docker is hidden and necessary to be shown. The docker must also be able to show one or both of them in the necessary sequence at the server request. The server already informed by the docker that it became hidden... If the helper is installed only on computers having client docker even simpler...
Am I missing something?
Corel is able to work with two parallel sessions or more (if computer has enough resources). Do you intend to use this corel facility? I mean I try to understand the ' static int KillAllCorelrProcess()' method... Killing corel process instead of quitting from inside corel is not good enough, I think. I just suppose that on computer with the client docker is there somebody working... Is all process automated and no need of computer operator? Otherwise all the changes in documents or VBA (if any) will be lost.
Without seeing the whole project it is difficult to understand and help more...
I wish you happy holidays!