簡體   English   中英

檢查從其他應用程序啟動的DLL是否已打開

[英]Check if dll launched from another application is already open

我使用我編寫的應用程序(比如應用程序A)添加修改。

應用程序A具有允許腳本調用類庫或exe文件的功能。 它的工作原理是獲取應用程序A創建的參數對象並將其傳遞給類庫(我們稱之為應用程序B)

應用程序A幾乎是一個黑盒子,我不知道代碼是什么樣的或者是什么。 我有一個腳本格式,從應用程序A獲取一個參數對象(包含有關調用程序的相關信息,例如:當前用戶,用戶語言,項目應用程序B是從等等啟動)並將其傳遞給應用程序B.此腳本功能使用屬於應用程序A的管理員面板進行設置。

啟動程序腳本必須使用form.Show()而不是form.ShowDialog()來打開應用程序B,因為用戶必須能夠在應用程序B打開時訪問應用程序A(數據檢查等等)。

現在我希望能夠阻止應用程序B多次打開,因為它已經使用form.Show()而不是form.ShowDialog()但是我似乎無法找到合適的方法來執行這個。

我首先嘗試檢查當前進程,但發現應用程序B未在此處列出,因為它是由應用程序A啟動的。

  1. M3銷售自動化是應用程序A.
  2. 新客戶是申請B.

這可以從我的任務管理器的以下屏幕截圖中看出:

任務管理器(應用程序標簽任務管理器(進程選項卡) M3 Sales Automation和New Customer都列在應用程序部分中,但過程部分中僅列出了M3 Sales Automation。

最初我嘗試訪問這些進程,但發現因為它實際上沒有列在那里我無法檢查它並且必須看得更深一些。 現在我做了一些檢查,發現當前進程的ProcessModules中列出了NewCustomer.dll。

我在啟動器腳本中使用以下代碼來獲取信息:

        public void GetProcessModules()
        {
            ProcessModuleCollection modules = Process.GetCurrentProcess().Modules;
            string modulesOutput = string.Empty;
            foreach (ProcessModule pm in processModuleCollection)
            {
                modulesOutput += pm.ModuleName + ";\r\n";
            }

            MessageBox.Show(modulesOutput, "Modules");
        }

這輸出了一個很長的dll列表,它們是應用程序A的一部分。現在我認為我可以通過perphaps來查看NewCustomer.dll是否被多次列出,如果發生這種情況,則會阻止應用程序的啟動,因為它已經打開。 但情況並非如此,並且無論打開多少次,NewCustomer.dll都只列出一次。

所以現在我的下一步想法是查看我是否可以訪問“任務管理器應用程序”選項卡中顯示的內容。 如果我的程序列在那里,那么我想阻止它再次打開。

有沒有人有任何想法如何實現這一點?

我甚至不確定我應該搜索什么,因為每當我嘗試搜索時,我都會得到答案,而不是在這里查看與過程相關的過程。

在Windows任務管理器的“應用程序”選項卡中,您可以看到系統中打開的窗口列表,但只有一個進程(1個應用程序)可以使用2個窗口。

此代碼用於搜索系統中的窗口。 也許對您有用,因為您可以通過“新客戶”標題進行搜索,或者這可能是您未來研究的良好開端。

using System.Runtime.InteropServices;
using System.Text;

public class WndSearcher
{
    public static IntPtr SearchForWindow(string wndclass, string title)
    {
        SearchData sd = new SearchData { Wndclass=wndclass, Title=title };
        EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
        return sd.hWnd;
    }

    public static bool EnumProc(IntPtr hWnd, ref SearchData data)
    {
        // Check classname and title 
        // This is different from FindWindow() in that the code below allows partial matches
        StringBuilder sb = new StringBuilder(1024);
        GetClassName(hWnd, sb, sb.Capacity);
        if (sb.ToString().StartsWith(data.Wndclass))
        {
            sb = new StringBuilder(1024);
            GetWindowText(hWnd, sb, sb.Capacity);
            if (sb.ToString().StartsWith(data.Title))
            {
                data.hWnd = hWnd;
                return false;    // Found the wnd, halt enumeration
            }
        }
        return true;
    }

    public class SearchData
    {
        // You can put any dicks or Doms in here...
        public string Wndclass;
        public string Title;
        public IntPtr hWnd;
    } 

    private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
}

然后你打電話:

// If you're viewing this page with IE, this *should* return the hwnd of the browser
IntPtr hWnd = WndSearcher.SearchForWindow("IEFrame", "pinvoke.net: EnumWindows");

來自pinvoke.net的代碼。

實際上看完上面發布的代碼jlvaquero后,我在同一個網站上發現了以下內容

EnumDesktopWindows(user32)

我在laucher腳本中添加了以下using語句:

  1. using System.Text;
  2. using System.Runtime.InteropServices;

然后我將以下類添加到我的啟動器腳本中

    /// <summary>
/// EnumDesktopWindows Demo - shows the caption of all desktop windows.
/// Authors: Svetlin Nakov, Martin Kulov 
/// Bulgarian Association of Software Developers - http://www.devbg.org/en/
/// </summary>
public class user32
{
    /// <summary>
    /// filter function
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    public delegate bool EnumDelegate(IntPtr hWnd, int lParam);

    /// <summary>
    /// check if windows visible
    /// </summary>
    /// <param name="hWnd"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool IsWindowVisible(IntPtr hWnd);

    /// <summary>
    /// return windows text
    /// </summary>
    /// <param name="hWnd"></param>
    /// <param name="lpWindowText"></param>
    /// <param name="nMaxCount"></param>
    /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "GetWindowText",
    ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);

    /// <summary>
    /// enumarator on all desktop windows
    /// </summary>
    /// <param name="hDesktop"></param>
    /// <param name="lpEnumCallbackFunction"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    [DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
    ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam);
}

然后,我在啟動腳本中添加了以下函數來調用新類並執行處理以發現活動窗口

/// <summary>
    /// Checks if application window open.
    /// </summary>
    /// <returns></returns>
    private static bool IfApplicationWindowOpen(string windowName)
    {
        List<string> collection = new List<string>();
        user32.EnumDelegate filter = delegate(IntPtr hWnd, int lParam)
        {
            StringBuilder strbTitle = new StringBuilder(255);
            int nLength = user32.GetWindowText(hWnd, strbTitle, strbTitle.Capacity + 1);
            string strTitle = strbTitle.ToString();

            if (user32.IsWindowVisible(hWnd) && string.IsNullOrEmpty(strTitle) == false)
            {
                collection.Add(strTitle);
            }
            return true;
        };

        if (user32.EnumDesktopWindows(IntPtr.Zero, filter, IntPtr.Zero))
        {
            foreach (string item in collection)
            {
                if (item.ToString().Equals(windowName))
                {
                    return true;
                    break;
                }
            }
        }
        return false;
    }

最后我修改了我的啟動功能,以包括對活動窗口的檢查

/// <summary>
    /// Starts the new customer.
    /// </summary>
    /// <param name="param">The param.</param>
    public static void StartNewCustomer(Parameter param)
    {
        string windowName = "New Customer";
        if (!IfApplicationWindowOpen(windowName))
        {

            GlobalFactory globalfactory = param.GlobalFactory;

            try
            {
                Generic objNewCustomer = new Generic();
                objNewCustomer.StartNewCustomerFromCustomer(param);
            }
            catch (TypeInitializationException tx)
            {
                globalfactory.ErrorHandler.Log(tx, (int)msmsError.ErrorSeverity.Major | (int)msmsError.ErrorSeverity.User);
            }
            catch (Exception ex)
            {
                globalfactory.ErrorHandler.Log(ex, (int)msmsError.ErrorSeverity.Major | (int)msmsError.ErrorSeverity.User);
            }
        }
        else
        {
            MessageBox.Show("The application " + windowName + " is already open", windowName + ": Launch Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

希望這可以幫助其他人解決同樣的問題

問候,

漫畫編碼器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM