Is it possible to run a child process as a parent process?
My directory structure looks like this:
app/program.exe
app/bin/internal.exe
app/bin/something.dll
The program.exe just executes the internal.exe with some arguments.
#include <stdio.h>
#include <process.h>
int main(void) {
_execl(".\\bin\\internal.exe",
"internal.exe", "some args", NULL);
return 0;
}
The arguments are important; without them internal.exe won't do anything.
This mostly works alright, but doesn't integrate well with the taskbar. The program shows up in the taskbar as internal.exe, and pinning it to the taskbar isn't useful, because clicking on the pinned shortcut will execute internal.exe without the arguments, and it will close immediately.
I'd like it to show up as program.exe on the taskbar, so that pinning it to the taskbar pins the working "launcher" instead of the internal part.
Is this possible?
You can't change the child to become the parent in terms of actual processes. The taskbar works at a higher level and gives you more control.
MSDN says:
The following items describe common scenarios that require an explicit AppUserModelID. They also point out cases where multiple explicit AppUserModelIDs should be used.
...
Cooperative or chained processes that to the user are part of the same application should have the same AppUserModelID applied to each process. Examples include games with a launcher process (chained) and Microsoft Windows Media Player, which has a first-run/setup experience running in one process and the main application running in another process (cooperative).
If you are not the author of the child application things become complicated.
If it is Java or some other type of framework it should have the IsHostApp value set. If not, you can try playing with UseExecutableForTaskbarGroupIcon and TaskbarGroupIcon but these will not change the AppUserModelID. Setting NoStartPage will prevent the user from pinning the child application.
If you know how to find the window of the child application you can call SHGetPropertyStoreForWindow in the parent and set the id to the same id as your parent process and/or set the System.AppUserModel.Relaunch* properties.
Related
I have an unrepeatable bug of unknown origin in my single threaded window manager that occurs fairly infrequently (once every 2-3 weeks). Something happens that causes me to lose keyboard input. Mouse events are still handled properly so I know the event loop is still running, but the key press event is no longer triggered. Actually, the key is no longer grabbed. When I press XCB_MOD_MASK_4+2 to switch to desktop 2, the 2 will show up in the text editor or terminal that currently has the input focus, instead of being grabbed by the window manager. I thought maybe it was related to xcb_allow_events, so via IPC I can execute these three tests (from within the window manager, cmd is received from an external process):
if (strcmp(cmd,"test0")==0)
xcb_allow_events(wm.conn, XCB_ALLOW_ASYNC_KEYBOARD, XCB_CURRENT_TIME);
else if (strcmp(cmd,"test1")==0)
xcb_allow_events(wm.conn, XCB_ALLOW_SYNC_KEYBOARD, XCB_CURRENT_TIME);
else if (strcmp(cmd,"test2")==0)
keyboard();
void keyboard()
{
int i,m,k;
xcb_void_cookie_t cookie;
spawn("/usr/bin/xmodmap -e 'keycode 108 = Super_L'");
spawn("/usr/bin/xmodmap -e 'remove mod1 = Super_L'");
for (i=0; i<LENGTH(key_bindings); i++)
{
m = key_bindings[i].mod;
k = keysc(key_bindings[i].keysym);
info("grabbing key: %s (%d), mod: %d",key_bindings[i].keysym,k,m);
cookie = xcb_grab_key_checked(wm.conn, 0, wm.root, m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
if (xcb_request_check (wm.conn, cookie))
error("can't grab key");
}
}
None of these tests help. I know the keyboard function works properly because it works on window manager startup. Also I can see in the log file that the key grabs in the keyboard function are actually being executed (without error) when prompted via IPC. The current workaround is to send sigterm to the window manager process, and then restart the wm. At that point everything works fine again.
I'm looking for techniques that might be helpful in tracking down the source of this problem, or in correcting the problem once it occurs (another test). Unfortunately, since I have no clue of the source of this problem, or what triggers it, I cannot make a simple test case to demonstrate. BTW I check the log files when this happens, and I don't see any pattern leading up to the problem. Each function logs an entry on entrance and exit.
Update 2021-02-12: I thought a restart would be a good workaround until I found the root cause of this problem. My restart function contains only one line:
execvp(lwm_argv[0], lwm_argv);
where lwm_argv is the argv provided as an argument to main.
I was very surprised to see that this did not alleviate the problem. I have to completely kill the old process then launch an new one to alleviate the problem. So this problem is PID dependant??? Further, I'm fairly convinced that this problem is somehow related to the stdout/stderr output of other applications launched from within the window manager using execvp. I've stopped launching applications from within the window manager and the problem went away. Any ideas of how launching other applications (and their output) could be affecting the keygrabs within the window manager would be appreciated.
You could try using strace or perf trace on the X server to see what it is doing with the key events. It ought to read them from somewhere in /dev/input and send them as events to connected clients.
If it isn't sending you events, then you might need to dig into its internal state, perhaps by building a debug server and connecting to it with GDB, to see why it isn't sending those events.
But if it is sending events to your WM then they're getting lost somewhere in the library stack.
I have two different background thread who does similar thing but at different time in my WPF application. both are right now independent background worker.
1) first thread runs when you launch application, it downloads all images from connected printer to PC location.
2) second thread does the same thing when use click on some link in my application.
As both worker are independent, even though first thread's downloading process are still running, if user click on link the second thread start their work too
What I would like to do is, when user click on 2nd thread, is there any way I will know about status of first thread ? I mean if i know that first thread is doing it's work then I don't want to even start second thread. I need only second thread when first one got cancelled by some other reason.
I heard about Mutex but I dont know how it works. Pls share ur idea and some example if you know how to handle this.
Thanks
Dee
I would recommend that you make a manager to handle the background threads. Maybe something like this:
interface IDownloadManager
{
bool IsRunning {get; }
void Start();
void Stop();
event Action DownloadStarted;
event Action DownloadCompleted;
event Action<Image> ImageDownloaded;
}
This manager should handle the starting/stopping and monitoring of the backgroundworkers. That way, you won't start more than one download process.
I'm developing a simple win32 application with two processes sharing memory through a file mapping. At a certain point in the second process, I want to check if the other process has already closed the handle associated to the file mapping.
Is there a Windows function to retrieve the number of handles associated to my shared memory???
Thanks in advance for any help...
There's nothing in the API to do that. If you want to know when the other process has finished its work, create a manual reset event with CreateEventEx, and have the other process set the event when its work is done. The first process can use one of the wait functions to query the status of the event.
I am replacing many batch files, that do almost the exact same thing, with one WPF executable. I have the program written, but I am having troubles with my "console" like display.
Within the program I call an executable to perform a task. This executable sends it's output messages to the console. I am able to redirect those to my "console" like display with the following.
Process p = new Process();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = MyExecutable;
p.StartInfo.Arguments = MyArguments;
p.Start();
while (!p.StandardOutput.EndOfStream)
{
string _output = p.StandardOutput.ReadLine();
// This is my display string ObservableCollection
_displayString.Add(new DisplayData { _string = _output, _color = System.Windows.Media.Brushes.Black, _fontSize = 12 });
// This is to redirect to a Console & what I want to get rid of
Console.WriteLine(_output);
}
p.WaitForExit();
When the executable is done running I use a MessageBox to ask the user if they want to run the executable again. The problem is that when the MessageBox is up the user is unable to scroll on my "console" like window to make an informative decision. To temporarily work around this I launch a console at start up, see this, and write the output stream from the process running the executable to the console so the user can scroll through the information and make a decision.
I am using a listbox to display a collection of textblocks, see this. I am not attached to anything for making the display, or MessageBox'es.
How can I make a "console" like display that will take a user input (MessageBox, direct input, etc...), but also allow them to scroll through the data before they make their decision?
EDIT:
As to the comments I have been receiving I am not clear on what I am trying to accomplish. I have a batch file that runs a executable multiple times with different arguments per run. There is a lot of setup before and between the executable calls. I have created an executable to replace many flavors of a similar batch file with drop down menus for the user to change settings at run time. When the user likes their settings they click a "Start" button, and away it goes doing setups and prompting questions as it goes and then finally runs executable for the first time.
My issue is when the called executable, inside mine, is done running the user needs to decide if they want to run it again for different reasons. I need to prompt the user "Run again - 'Yes' or 'No'?", and that is where I am running into problems. A MessageBox doesn't allow me to scroll on my Progress Window. I have tried a Modeless dialog box, but with Show() the program continues on, and ShowDialog() is the same issue as the MessageBox.
Any suggestions on how to do this would be appreciated.
You are in Windows, but trying to use DOS paradigm. Windows is event-based system! You need to write "event handlers" but not put all your code in one function.
However, there is a trick, which allows to show Modal (read "blocking your code") dialog in Modeless (read "not blocking your window"). Not sure how to implement this in WPF, but idea is to re-enable your window (which acts as parent for your dialog). You need to do this in your dialog event handler (WM_INITDIALOG equivalent?).
Also (in WinAPI) you may run dialog with NULL as parent window.
I'm using CreateProcess() with startup flags set to STARTF_USESHOWWINDOW and SW_HIDE to start an application in the background with its window hidden.
I'm doing this to run a scheduled maintenance tasks and i don't want to be bothered with windows.
In most cases the windows are hidden but there are cases where the program's window pops right out in front of you (for example Google's Chrome - i started testing with different apps to see whether this was a once time problem but nope...).
This happens less in Windows XP, but it happens a lot on Vista.
Is there a flag that I am missing? Is there any other way to create a process with its window hidden?
Thanks!
my sample code is:
char *ProgramName
STARTUPINFO StartupInfoF;
PROCESS_INFORMATION ProcessInfoF;
memset(&StartupInfoF, 0, sizeof(StartupInfoF));
memset(&ProcessInfoF, 0, sizeof(ProcessInfoF));
StartupInfoF.cb = sizeof(StartupInfoF);
StartupInfoF.wShowWindow = SW_HIDE;
StartupInfoF.dwFlags = STARTF_USESHOWWINDOW;
if (CreateProcess(ProgramName,
"",
0,
0,
FALSE,
DETACHED_PROCESS,
0,
0,
&StartupInfoF,
&ProcessInfoF) == FALSE)
{
// error
}
else
{
// OK
}
You can start the process on another desktop, using the lpDesktop member of the STARTUPINFO structure passed to CreateProcess. This way the process will have all its windows shown, but on another desktop, so you (or your users) won't be bothered with it.
I've never worked with multiple desktops so I can't say what would be the side effects, but I think it's doable. Start by looking into CreateDesktop and move onward.
I don't remember the answer to your question, but I'd like to suggest that maybe you shouldn't keep the window totally hidden? If you want the window out of the way, minimizing it will suffice; hiding it completely only removes the ability to check on your scheduled maintenance tasks.
Some programs could ignore/override SW_HIDE flag. You could try to hide window after child process started.
Another option is to try to use CreateProcessAsUser to run processes in Session 0 which has isolated desktop (starting from Vista version).
I'd suggest making it a service. For one thing, that will allow it to run your scheduled maintanence even when nobody is logged in. For another, it is fairly easy to set services up so that they don't have access to the desktop.