0

私は、アドオンの変更を記述したアプリケーション(たとえばアプリケーションA)を操作します。

アプリケーションAには、スクリプトがクラスライブラリまたはexeファイルを呼び出せるようにする機能があります。これは、アプリケーションAによって作成されたパラメーターオブジェクトを取得し、それをクラスライブラリに渡すことによって機能します(アプリケーションBと呼びます)。

アプリケーションAはほとんどブラックボックスであり、コードがどのように見えるか、または何をするのかわかりません。アプリケーションAからパラメーターオブジェクト(呼び出し側プログラムに関する関連情報を含む、たとえば、現在のユーザー、ユーザー言語、アプリケーションBが起動されたアイテムなど)をアプリケーションBに渡すスクリプト形式があります。このスクリプト機能アプリケーションAの一部である管理者パネルを使用して設定されます。

ランチャースクリプトは、アプリケーションBが開いている間(データチェックなど)にユーザーがアプリケーションAにアクセスできる必要があるため、アプリケーションBを開かform.Show()ないように使用する必要があります。form.ShowDialog()

form.Show()アプリケーションBはを使用して起動されたため、現在可能な限り複数回開かないようにしたいと思いますが、form.ShowDialog()これを行うための適切な方法が見つからないようです。

最初に現在のプロセスを確認しようとしましたが、アプリケーションAによって起動されるため、アプリケーションBがここにリストされていないことがわかりました。

  1. M3セールスオートメーションはアプリケーションAです
  2. 新規顧客はアプリケーションBです

これは、私のタスクマネージャーからの次のスクリーンショットから見ることができます。

タスクマネージャー([アプリケーション]タブ) タスクマネージャー([プロセス]タブ) M3 SalesAutomationとNewCustomerの両方がアプリケーションセクションにリストされていますが、M3SalesAutomationのみがプロセスセクションにリストされています。

最初にプロセスにアクセスしようとしましたが、実際にはそこにリストされていないため、それを確認できず、もう少し深く調べる必要があることがわかりました。ここでさらにチェックを行ったところ、NewCustomer.dllが現在のプロセスのProcessModulesにリストされていることがわかりました。

ランチャースクリプトで次のコードを使用して情報を取得しました。

        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");
        }

これにより、アプリケーションAの一部であるdllの長いリストが出力されました。これで、NewCustomer.dllが複数回リストされているかどうかを確認し、これが発生した場合は、アプリケーションが既に開いているため、アプリケーションの起動を防ぐことができると思いました。 。ただし、これは当てはまらず、NewCustomer.dllは、開いている回数に関係なく1回だけリストされます。

そこで、次の考えは、[タスクマネージャーのアプリケーション]タブに表示されているものにアクセスできるかどうかを確認することです。私のプログラムがそこにリストされている場合、それが再び開かないようにしたいです。

誰かがこれを達成する方法について何かアイデアがありますか?

何を検索すればよいのかさえわかりません。検索しようとするたびに、ここでは関係のないプロセスを調べることについて話している回答が得られます。

4

2 に答える 2

1

Windows タスク マネージャーの [アプリケーション] タブには、システムで開かれているウィンドウのリストが表示されますが、2 つのウィンドウを表示するプロセスは 1 つ (1 つのアプリケーション) しかありません。

このコードは、システム内のウィンドウを検索するためのものです。「新規顧客」のタイトルで検索できるので便利かもしれませんし、将来の調査の良い出発点かもしれません。

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からのコード。

于 2012-11-15T12:31:34.617 に答える
1

実際に、上記の 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);
        }
    }

これが同じ問題を抱えている他の人に役立つことを願っています

よろしく、

コミックコーダー

于 2012-11-15T16:09:00.040 に答える