我使用的是一个应用程序(比如应用程序A),我写的是对。
的修改应用程序A具有允许脚本调用类库或exe文件的功能。 它的工作原理是获取应用程序A创建的参数对象并将其传递给类库(让我们称之为应用程序B)
应用程序A几乎是一个黑盒子,我不知道代码是什么样的或者是什么。 我有一个脚本格式,它接受来自应用程序A的参数对象(包含有关调用程序的相关信息,例如:当前用户,用户语言,项目应用程序B是从等等启动的)等,并将其传递给应用程序B.此脚本功能使用作为应用程序A的一部分的管理员面板进行设置。
启动程序脚本必须使用form.Show()
而不是form.ShowDialog()
来打开应用程序B,因为用户必须能够在应用程序B打开时访问应用程序A(数据检查等等)。
现在我希望能够阻止应用B尽可能多次打开,因为它已使用form.Show()
而不是form.ShowDialog()
启动但是我似乎无法找到合适的这样做的方法。
我首先尝试检查当前进程,但发现应用程序A未在此处列出,因为它是由应用程序A启动的。
这可以从我的任务管理器的以下屏幕截图中看出:
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打开多少次都只列出一次。
所以现在我的下一步想法是查看我是否可以访问“任务管理器应用程序”选项卡中显示的内容。如果我的程序列在那里,那么我想阻止它再次打开。
有没有人有任何想法如何实现这一目标?
我甚至不确定我应该搜索什么,因为每次我尝试搜索时都会得到答案,而不是在这里查看与此相关的进程。
答案 0 :(得分:1)
在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的代码。
答案 1 :(得分:1)
实际上在查看上面发布的代码jlvaquero之后,我在同一个网站上发现了以下内容
我在laucher脚本中添加了以下使用语句:
using System.Text;
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);
}
}
希望这可以帮助其他人解决同样的问题
此致
Comic Coder