Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello all, I want to pass command line arguments in already running mfc dialog based application without creating new instance of the application. please guide me on this.

What I have tried:

searching on the internet about this problem, have not find any solution yet.
Posted
Updated 7-Jun-16 4:29am

Quote:
Hello all, I want to pass command line arguments in already running mfc dialog based application without creating new instance of the application. please guide me on this.
Short answer: It is impossible.
By OS design, it is impossible to change commandline parameters after instance launch.
Either you launch a new instance everytime, or you do interprocess communications.
 
Share this answer
 
To pass command line arguments you have to start another instance. But this instance can check if another one is already running, pass the arguments and terminate.

This requires three steps:

  • Detect running instances
  • Passing arguments
  • Handling passed arguments

Detect running instances


A common method to do this is using global mutexes. See CreateMutex function (Windows)[^] and Avoiding Multiple Application Instances[^].

Passing arguments


As already mentioned this requires some kind of IPC (Inter Process Communication). One solution is broadcasting a registered message. See RegisterWindowMessage function (Windows)[^] and BroadcastSystemMessage function (Windows)[^].

Handling passed arguments


This depends on your application and must be implemented by you.

Here an untested example (portions has been copied from existing code):
BOOL CMyApp::InitInstance()
{
    // ...
    
    // Register a private global message.
    // This message is used to pass command line arguments 
    //  to another running instance of this application.
    // Must be member of this class (public or CMainFrame must be friend).
    m_nPrivateMessage = 
        ::RegisterWindowMessage(_T("my_unique_application_identifier"));
    
    // Create a global mutex.
    HANDLE hMutexAppRunning = ::CreateMutex(NULL, FALSE, 
        _T("Global\\my_unique_application_identifier"));
    DWORD dwErr = ::GetLastError();
    // Mutex exists already (handle returned) or 
    //  access to existing mutex denied (handle is NULL).
    if (dwErr == ERROR_ALREADY_EXISTS || dwErr == ERROR_ACCESS_DENIED)				
    {
        // Copy arguments to a memory object which must be freed by the receiving application.
        // Using global memory here with a double null terminated list of strings.
        int cmdSize = 1;
        for (int i = 0; i < __argc; i++)
            cmdSize += 1 + _tcslen(__argv[i]);
        HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, cmdSize * sizeof(TCHAR));
        LPTSTR lpBuf = ::GlobalLock(hGlobal);
        for (int i = 0; i < __argc; i++)
        {
            size_t len = 1 + _tcslen(__argv[i]);
            memcpy(lpBuf, __argv[i], len);
            lpBuf += len;
        }
        *lpBuf = _T('\0');
        ::GlobalUnlock(hGlobal);
        DWORD dwRecipients = BSM_APPLICATIONS;	// broadcast to applications only
        ::BroadcastSystemMessage( 
        	BSF_IGNORECURRENTTASK | BSF_ALLOWSFW,	// do not send to ourself
        	&dwRecipients,		// broadcast to applications only
        	m_nPrivateMessage,		// message registered above
        	(WPARAM)hGlobal,		// message-specific: data
        	(LPARAM)::GetDesktopWindow());	// message-specific: Desktop window handle
        return FALSE;
    }
    // A new mutex has been created and this is the only instance.
    // The mutex handle is automatically closed when the application terminates.
    
    // ...
    return TRUE;
}


// Message map entry. Requires access to the m_nPrivateMessage member of the application class.
ON_REGISTERED_MESSAGE(App()->m_nPrivateMessage, OnPrivateBroadcast)

// Message send by another instance when it detects an already running instance.
// wParam: Global memory block with double null terminated string list of arguments
// lParam: Desktop window handle of the other instance.
LRESULT CMainFrame::OnPrivateBroadcast(WPARAM wParam, LPARAM lParam)
{
    int argc = 0;
    LPTSTR args = ::GlobalLock((HGLOBAL)wParam);
    while (*args)
    {
        // args points to each argument here (first is application path)
        // Process it here

        // To begin of next argument (second null char at end of list)
        args += 1 + _tcslen(args);
        ++argc;
    }
    // Unlock and free the memory.
    ::GlobalUnlock((HGLOBAL)wParam);
    ::GlobalFree((HGLOBAL)wParam);

    // Restore size and bring on top if on same desktop
    if (NULL == lParam || ::GetDesktopWindow() == reinterpret_cast<HWND>(lParam))
    {
        if (IsIconic())
            ShowWindow(SW_RESTORE);
        CWnd *pWndChild = GetLastActivePopup();
        if (pWndChild)
            pWndChild->SetForegroundWindow();
    }
    return TRUE;
}
 
Share this answer
 
You cannot. It the application is already running, it already got all the information from the command line. Forget it.

However, you need to use a lot more complicated approach. The idea is: you should pass command line from another instance of the same application, another process. Obviously, it should use some IPC mechanism. The first process should use IPC to receive command line data and handle it; it has nothing to do with its real command line, which is already used. The second process should try to detect first instance and, if it presents, use IPC to pass data and then terminate immediately.

Actually, this behavior is one of the aspects of the single-instance application development. I did not implement this mechanism in C++, but you can read my articles and past answers related to different technologies, just to read the detailed description of the idea:
Custom Windows right-click command launching multiple instances,
Enter multiple commands to only one process instance.
All Three Features of Single-Instance Applications at One Shot, .NET,
Single-Instance Applications Behavior, now for Free Pascal.

Implementation of the same mechanism in C++ will be a bit more complex, but Windows API (if you use MFC, this is just Windows) has everything to implement it.

—SA
 
Share this answer
 
Comments
CPallini 7-Jun-16 4:57am    
5.
Sergey Alexandrovich Kryukov 7-Jun-16 9:45am    
Thank you, Carlo.
—SA
George Jonsson 7-Jun-16 7:53am    
5:ed
Good articles.
Sergey Alexandrovich Kryukov 7-Jun-16 9:44am    
Thank you, George.
—SA
The general solution you should likely Google for is 'IPC' ie Inter-Process Communication

There are lots of options, but without more details from you on what you're doing, it would be hard to suggest a specific technique

You could look at named pipes, shared memory to name but two
 
Share this answer
 
Comments
CPallini 7-Jun-16 4:57am    
5.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900