0

Application A (for example: AutoCAD, Word,...) when runs, it'll call a DLL X at runtime to perform tasks → open form Login

Application B (for example: Photoshop, Excel...) when runs, it'll call a DLL Y at runtime to perform tasks → I would like to close the above login form can do this?

Is that possible?

Image description

Oosutsuke
  • 79
  • 3
  • 12

3 Answers3

0

well if its just about closing the running proccess the easiest way would probably be like something like

using System.Diagnostics;
var autocad = Process.GetProcesses().FirstOrDefault(w=>w.ProcessName == "AutoCAD");
autocad.Close();

for opening you could probably cycle the proccesses for the needed names. its not very efficent tough but it would get the job done if its just opening and closing you´re after

subkonstrukt
  • 446
  • 2
  • 15
  • I want to close the form being opened in AutoCAD, but AutoCAD does not close(not quit) – Oosutsuke Apr 19 '17 at 08:17
  • so you´re trying to close a form that gets opened by autocad but only the dialog not the entire autocad proccess? – subkonstrukt Apr 19 '17 at 08:19
  • Yes, it's true. – Oosutsuke Apr 19 '17 at 08:30
  • well you could try to use the win api if the windows is recognized correctly like [DllImport("user32.dll")] public static extern int FindWindow(string lpClassName,string lpWindowName); and then send the close message (F060 I think) - but thats not guranteed to be successfull this hugely depends on the application you want to modify, overall its a not that trivial task – subkonstrukt Apr 19 '17 at 09:44
  • Thank you. I was able to do it based on bN_'s answer. – Oosutsuke Apr 20 '17 at 00:44
0

You could keep checking for new processes with a (just an example) windowless console application. I have an example:

  1. Make a new project with a console application and the login form

  2. Make the Console application a windows application like this:

enter image description here
Press properties enter image description here Select Windows application

Make a timer in the console application that checks for processes:

public static bool IsOpen = false;

static void Main(string[] args)
{
    Timer t = new Timer(TimerCallback, null, 0, 1200);
    while ( true )
    {
        //keep it running
    }
}

private static void TimerCallback(Object o)
{
    if ( !IsOpen && Process.GetProcesses().Select( r => r.ProcessName ).Contains( "EXCEL" ) )
    {
        //Excel is running, show the form
        Form1 loginForm = new Form1();
        loginForm.ShowDialog();
        //Stop it from spawning a million forms by setting bool
        IsOpen = true;
    }
}

The logic for closing a Form when an application closes can be put inside this timer too, use it the same way.

To open a form from a console window however you need to add references to the console application:

enter image description here

If you want process names:
Just use a form and add this:

foreach ( var proc in Process.GetProcesses() )
{
    MessageBox.Show( proc.ProcessName );
}

This will show you the names of all processes currently running.

EpicKip
  • 4,015
  • 1
  • 20
  • 37
  • so the login form is in a separate process? – Lei Yang Apr 19 '17 at 08:30
  • @LeiYang Its not from excel itself so yes. – EpicKip Apr 19 '17 at 08:31
  • @LeiYang Not sure why you would want to do this but... like this you can – EpicKip Apr 19 '17 at 08:32
  • i'm not the OP. – Lei Yang Apr 19 '17 at 08:37
  • @LeiYang I know I'm speaking in a general sense as why someone would want to spawn login forms when other applications open – EpicKip Apr 19 '17 at 08:38
  • i think it's like applocker, most android systems has that feature. – Lei Yang Apr 19 '17 at 08:42
  • @LeiYang I know those but I'm not sure if a novice in c# can make that for windows – EpicKip Apr 19 '17 at 08:43
  • @EpicKip: Thank you very much for your effort! I read your answer, but it seems does not look like that I want. I have attached an image in the question, Please check whether it can be done !? – Oosutsuke Apr 19 '17 at 09:00
  • @Oosutsuke I don't understand from the picture. Do you open the login form? – EpicKip Apr 19 '17 at 09:02
  • @EpicKip: The login form is any form that is already open in Application A before executing the action in Application B. Moreover, I searched Google ROT without results. What is ROT stands for? Abbreviations of letters? – Oosutsuke Apr 19 '17 at 09:07
  • @Oosutsuke So application A is not yours and neither is the login form? Because that will be hard. ROT stands for Running Objects Table, if you're going to manipulate forms from another application this might be needed – EpicKip Apr 19 '17 at 09:14
0

Here is a little sample that shows how to close a Window in another process. Create a new Windows Forms project, Add two Forms in it and add two buttons on the first one and put that code in Form1 :

public partial class Form1 : Form
{
    delegate bool EnumWindowsProc(IntPtr Hwnd, IntPtr lParam);

    [DllImport("user32", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private extern static bool EnumThreadWindows(int threadId, EnumWindowsProc callback, IntPtr lParam);

    [DllImport("user32", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);

    [DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
    private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    private const int WM_CLOSE = 0x10;

    public Form1()
    {
        InitializeComponent();
        button1.Click += button1_Click;
        button2.Click += button2_Click;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var frm = new Form2();
        frm.Show(this);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Process[] processes = Process.GetProcessesByName("FindWindowSample");

        foreach (Process p in processes)
        {
            var handle = FindWindowInProcess(p, x => x == "Form2");

            if (handle != IntPtr.Zero)
            {
                SendMessage(handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
            }
        }
    }

    public static IntPtr FindWindowInProcess(Process process, Func<string, bool> compareTitle)
    {
        IntPtr windowHandle = IntPtr.Zero;

        foreach (ProcessThread t in process.Threads)
        {
            windowHandle = FindWindowInThread(t.Id, compareTitle);
            if (windowHandle != IntPtr.Zero)
            {
                break;
            }
        }

        return windowHandle;
    }

    private static IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle)
    {
        IntPtr windowHandle = IntPtr.Zero;
        EnumThreadWindows(threadId, (hWnd, lParam) =>
        {
            StringBuilder text = new StringBuilder(200);
            GetWindowText(hWnd, text, 200);
            if (compareTitle(text.ToString()))
            {
                windowHandle = hWnd;
                return false;
            }
            return true;
        }, IntPtr.Zero);

        return windowHandle;
    }
}

Compile and then run two instances of the application. On the first one click on Button1 to show Form2. On the second instance click on Button2 to close Form2 from the first instance.

bN_
  • 772
  • 14
  • 20