P/调用第三方弹出窗口
P/Invoke to third party popup window
当前情况:
在我当前的项目中,我必须在C#Winforms应用程序中使用旧的C DLL来在Hardlock Licensing Dongle上写入。
我的应用程序是一个简单的接口,允许用户向加密狗写许可证信息。如果加密狗已经包含数据,则C DLL向用户显示了对话框。如果信息已成功写入加密狗,则C DLL显示一个确认对话框。
当我们的物流部门使用此工具时,他们将写很多加密狗(一天200至800)。因此他们不想确认消息框。
在搜索解决方案以关闭第三方库的弹出窗口/消息框时,我发现了一些使用Platform Invoke的示例。在本文中使用解决方案未能成功地播放后如何抑制我无法更改的代码显示的对话框?我尝试了以下方法:
我每500毫秒我检查是否显示了弹出窗口,并使用Enter确认。
private void initButton_Click(object sender, EventArgs e)
{
messageBoxCloseTimer.Interval = 500;
messageBoxCloseTimer.Start();
WriteDongle();
}
private void WriteDongle()
{
// This code shows a message box
}
private void MessageBoxCloseTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
BeginInvoke(new MethodInvoker(delegate
{
var hwnd = FindWindow("#32770", "Information");
if (hwnd.ToInt32() < 1) // Window not found
return;
SendKeys.Send("{ENTER}");
messageBoxCloseTimer.Stop();
}));
}
[DllImport("user32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
// C++ dll which is used to write the dongle
[DllImport("License.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern Int16 peak_BurnDongle(
Int16 iType,
[MarshalAs(UnmanagedType.LPStr)] ref string pszSysID,
int iProgPort,
Int16 iSigPort);
问题:
有时我会得到AccessViolationException。不幸的是,此错误不是确定性的。经过一些加密狗写后,它是否会发生。引起此错误的最佳机会是,如果我快速单击按钮(执行上面的代码),例如每2秒钟一次。
doese有人看到一个明显的错误吗?谢谢!
Windows EventLog:
Anwendung: VizLicInitializer.exe
Frameworkversion: v4.0.30319
Beschreibung: Der Prozess wurde aufgrund eines Ausnahmefehlers beendet.
Ausnahmeinformationen: System.AccessViolationException
Stapel:
bei System.Drawing.SafeNativeMethods+Gdip.GdipCreateBitmapFromStream(IStream, IntPtr ByRef)
bei System.Drawing.Bitmap..ctor(System.Type, System.String)
bei System.Windows.Forms.ThreadExceptionDialog..ctor(System.Exception)
bei System.Windows.Forms.Application+ThreadContext.OnThreadException(System.Exception)
bei System.Windows.Forms.Application+ThreadContext.PreTranslateMessage(MSG ByRef)
bei System.Windows.Forms.Application+ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FPreTranslateMessage(MSG ByRef)
bei System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32)
bei System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
bei System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
bei System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
bei VizLicInitializer.Program.Main()
编辑:
感谢Luc向我发送了以下解决方案(仍然没有解决我的问题,但仍然比我的解决方案更好):
internal static void RegisterWindowCreatedEvent()
{
var hHook = SetWindowsHookEx(HookType.WH_SHELL, winDelegate, IntPtr.Zero, AppDomain.GetCurrentThreadId());
}
private static int ShellHookProcDelegate(int code, IntPtr wParam, IntPtr lParam)
{
if (code != HSHELL_WINDOWCREATED)
{
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
StringBuilder wCaption = new StringBuilder();
GetWindowCaption(wParam, wCaption, wCaption.Capacity);
if (wCaption.ToString() == "Information")
{
SendMessage(wParam, 0x0010, IntPtr.Zero, IntPtr.Zero);
}
return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
}
private delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);
private static readonly HookProc winDelegate = ShellHookProcDelegate;
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll")]
private static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
const int HSHELL_WINDOWCREATED = 1;
[DllImport("user32.dll", EntryPoint = "GetWindowText",CharSet = CharSet.Auto)]
static extern IntPtr GetWindowCaption(IntPtr hwnd,StringBuilder lpString, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam);
遵循Hans Passant的方法,我使用应用程序验证符获取以下错误详细信息。
在堆栈跟踪的开头,我看到了一些" user32"answers" sendmessage"行。我使用sendmessage将关闭消息发送到MessageBox窗口。但是为什么会发生?我必须说我不知道其余的堆栈跟踪意味着什么。
<avrf:logfile xmlns:avrf="Application Verifier">
<avrf:logSession Version="2" PID="4024" TimeStarted="2016-06-22 : 15:38:26">
<avrf:logEntry Severity="Error" StopCode="0x13" LayerName="Heaps" Time="2016-06-22 : 15:38:54">
<avrf:message>First chance access violation for current stack trace.</avrf:message>
<avrf:parameter1>0 - Invalid address causing the exception.</avrf:parameter1>
<avrf:parameter2>94e5d8f - Code address executing the invalid access.</avrf:parameter2>
<avrf:parameter3>2ad984 - Exception record.</avrf:parameter3>
<avrf:parameter4>2ad9a0 - Context record.</avrf:parameter4>
<avrf:stackTrace>
<avrf:trace>vrfcore!VerifierDisableVerifier+73c ( @ 0)</avrf:trace>
<avrf:trace>vfbasics!+6c7462f0 ( @ 0)</avrf:trace>
<avrf:trace>vfbasics!+6c747982 ( @ 0)</avrf:trace>
<avrf:trace>vfbasics!+6c74728a ( @ 0)</avrf:trace>
<avrf:trace>ntdll!RtlReleasePrivilege+114 ( @ 0)</avrf:trace>
<avrf:trace>ntdll!RtlGetGroupSecurityDescriptor+30c ( @ 0)</avrf:trace>
<avrf:trace>ntdll!RtlGetGroupSecurityDescriptor+211 ( @ 0)</avrf:trace>
<avrf:trace>ntdll!KiUserExceptionDispatcher+f ( @ 0)</avrf:trace>
<avrf:trace>HLPROG!GetListOfParPorts+f86a ( @ 0)</avrf:trace>
<avrf:trace>verifier!VerifierGetProviderHelper+ce0d ( @ 0)</avrf:trace>
<avrf:trace>vrfcore!VerifierTlsSetValue+431 ( @ 0)</avrf:trace>
<avrf:trace>vfbasics!+6c746ba5 ( @ 0)</avrf:trace>
<avrf:trace>ntdll!wcsncmp+58 ( @ 0)</avrf:trace>
<avrf:trace>ntdll!EtwEventRegister+135 ( @ 0)</avrf:trace>
<avrf:trace>ntdll!RtlImageNtHeader+2b1 ( @ 0)</avrf:trace>
<avrf:trace>ntdll!LdrLoadDll+66 ( @ 0)</avrf:trace>
<avrf:trace>vfbasics!+6c746fd7 ( @ 0)</avrf:trace>
<avrf:trace>KERNELBASE!GetDiskFreeSpaceExA+2bd0 ( @ 0)</avrf:trace>
<avrf:trace>clr!StrongNameFreeBuffer+201d1 ( @ 0)</avrf:trace>
<avrf:trace>clr!StrongNameFreeBuffer+20234 ( @ 0)</avrf:trace>
<avrf:trace>clr!PreBindAssemblyEx+1747a ( @ 0)</avrf:trace>
<avrf:trace>clr!PreBindAssemblyEx+17edb ( @ 0)</avrf:trace>
<avrf:trace>clr!CreateAssemblyNameObject+2f57 ( @ 0)</avrf:trace>
<avrf:trace>clr!CreateAssemblyNameObject+2ec2 ( @ 0)</avrf:trace>
<avrf:trace>clr!CreateAssemblyNameObject+2dcb ( @ 0)</avrf:trace>
<avrf:trace>clr!CreateAssemblyNameObject+2d64 ( @ 0)</avrf:trace>
<avrf:trace>clr!DllCanUnloadNowInternal+173 ( @ 0)</avrf:trace>
<avrf:trace>clr!+5ba12a0c ( @ 0)</avrf:trace>
<avrf:trace>????????+07F73967</avrf:trace>
<avrf:trace>????????+07F73645</avrf:trace>
<avrf:trace>????????+07F73579</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cb918a ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cbb71c ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+5827c720 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+582590cc ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+585b8aae ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+585b7841 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cc1d00 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cc6bb1 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cc6b99 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cc6ae0 ( @ 0)</avrf:trace>
<avrf:trace>????????+0035A093</avrf:trace>
<avrf:trace>USER32!gapfnScSendMessage+1cf ( @ 0)</avrf:trace>
<avrf:trace>USER32!gapfnScSendMessage+2cf ( @ 0)</avrf:trace>
<avrf:trace>USER32!gapfnScSendMessage+908 ( @ 0)</avrf:trace>
<avrf:trace>USER32!DispatchMessageW+f ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57d1b6bc ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cd5701 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cd5389 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cd5202 ( @ 0)</avrf:trace>
<avrf:trace>System.Windows.Forms.ni!+57cb15e1 ( @ 0)</avrf:trace>
</avrf:stackTrace>
</avrf:logEntry>
</avrf:logSession>
</avrf:logfile>
我认为您的代码在关闭弹出窗口之前试图写信给加密狗。
考虑一下:1.您启动计时器并写信给加密狗。2.计时器发射,但弹出窗口还没有,所以什么也没有发生。3.弹出窗口再次单击按钮时显示。4.在计时器再次发射之前(关闭弹出窗口),您可以致电WritedOngle。
在启动计时器之前,请尝试禁用按钮并在关闭弹出时启用它。
另外,您可以尝试将某些窗口创建事件连接起来,过滤您所需的窗口,然后在那里调用您的关闭弹出代码(从来没有自己做,所以这只是脑震荡)。在显示弹出窗口时,您仍然需要提防将其写入加密狗。在Win32上创建新窗口时,如何通知我?
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 如何在Qt窗口小部件中使用QStringView(或QStringRef)
- 问:如何使用C++中的按钮从窗口打开窗口
- SDL 窗口不会弹出
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- 如何在cpp文件之间切换窗口?在Qt中
- QuadTree只在窗口的右上角绘制
- VS Code "command":"make"与终端窗口中的命令行"make"不同
- 如何在C++中找到active directory中禁用和锁定的窗口帐户
- 如何包装第三方DLL在R中使用
- 处理闪烁窗口事件
- 如何通过按下第三个窗口中的按钮,将QString从一个窗口获取到另一个窗口
- C++win32 API创建多个类似视口的窗口
- SFML RenderWindow打开窗口需要很长时间
- 如何将不同的可执行文件合并到一个窗口框架中进行编码?像浏览器一样
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- QOpenGLWidget:检索第三方库的窗口句柄
- P/调用第三方弹出窗口
- 在第三方应用程序的窗口顶部绘制
- 在第三方窗口上显示QT小部件(在Windows中)