DeviceLostException during CTRL ALT DEL in Direct3D using C# - c#

I am using the Microsoft.DirectX and Microsoft.DirectX.Direct3D references to do some drawing on my form. While I am running the program and the user presses CTRL ALT DEL in Windows XP and brings up the "Windows Security" form, when returning back to the Form, a DeviceLostException is thrown and when trying to handle this exception there seems to be no way to get it back.
I have done a little research into the matter and have tried several coding solutions.
try
{
_d3ddevice.Present();
}
catch
{
DeviceLost = true;
}
if (DeviceLost)
{
AttemptRecovery();
}
this.Invalidate();
ReadKeyboard();
base.OnPaint(e);
}
private void AttemptRecovery()
{
try
{
_d3ddevice.TestCooperativeLevel();
}
catch (DeviceLostException)
{
Application.Exit();
}
catch (DeviceNotResetException)
{
try
{
_d3ddevice.Reset(_params);
DeviceLost = false;
InitGraphics();
CameraPositioning();
VertexDeclaration();
IndicesDeclaration();
}
catch (DeviceLostException)
{
}
}
}
When the program calls TestCooperativeLevel(), it said online if it catches the DeviceLostException again that there is no point in trying to reset the device.
What can I do to reset the device and continue drawing in my form?

2 things in 4 points :
You shouldn't use Microsoft.DirectX, it's deprecated since a long, long time. Check out SlimDX or SharpDX instead.
In order to re-create your device, you first have to wait until the device can be restored
When the device can be restored, you have to free all video-memory objects, and recreate them.
You call the Reset method.

Related

Microsoft Edge Process ID changes, how to change/keep track of it?

I have a WPF app that will be acting like a desktop, with certain apps available, such as Microsoft Edge browser. I am able to open multiple windows of it, add a button to a custom taskbar, but the problem is, you could find the process by name, but then the buttons/program doesnt know which correct window to open. And if I search by ID, VS gives me:
System.ArgumentException:'Process with an Id of #### is not running'
Since Microsoft it self, changes the ID of the initial ID that it starts with.
So the methods right now im using for trying to get the right window is:
public void NewTabClick(object sender, RoutedEventArgs e)
{
//NewTabClick is a click event that gets created with every new button
MessageBox.Show("NewTabClicked");
ShowWindow(GetWindowHandle(), 3);
}
private IntPtr GetWindowHandle()
{
try
{
//Here is where i get the exception error
return Process.GetProcessById(ProcessId).MainWindowHandle;
}
catch (NullReferenceException)
{
return IntPtr.Zero;
}
}
ProcessId is set when we start the app itself in another method like this
private void StartApp()
{
var process = Process.Start(ProgramPath);
SetProcessId(process);
}
private void SetProcessId(Process process)
{
ProcessId = process.Id;
}
Is there a way to keep track/change/update which ID it should look for, or another way to keep track of these windows/browsers?
Thanks in advance!

How can you prevent multiple instances of RDP from opening using Process.Start?

I am simply trying to open the Windows RDP application through a button click event in my C# application, but what I get is 4 or 5 instances of RDP on a single click. I was wondering if this is a result of having the code in a button click event. I've researched Mutex, but it doesn't seem to be what I'm looking for in this particular case. Any ideas?
private void btnRemote_Click(object sender, EventArgs e)
{
string rdcSupport = "C:\\Windows\\System32\\mstsc.exe";
try
{
procRDC.StartInfo.FileName = rdcSupport;
procRDC.Start();
procRDC.WaitForInputIdle();
SendKeys.Send("support_server1");
SendKeys.Send("{ENTER}");
}
catch
{
Console.WriteLine("Failed to open...");
}
}
May be SendKeys doing some mess. I would recomend using MSTSC parameters:
try
{
Process procRDC = Process.Start(rdcSupport, "/v:support_server1");
}
catch
{
Console.WriteLine("Failed to open...");
}
You don't show how you create/initialize procRDP.
See MSTSC help: https://technet.microsoft.com/en-us/library/cc753907(v=ws.11).aspx

How can I completely stop all Kinect streams and functions on window close?

I've been playing around with Kinect for Windows SDK 1.8 for a bit, just re-familiarizing myself with it after some time away. I have a basic application running that uses the color and skeleton streams to overlay a skeleton on a video feed of the user, while also displaying their torso's X, Y, and Z coordinates in realtime. All of this works perfectly, but I've run into an issue with shutting the application down. A first, my Window_Close event looked like this:
private void Window_Closed(object sender, EventArgs e)
{
// Turn off timers.
RefreshTimer.IsEnabled = false;
RefreshTimer.Stop();
UpdateTimer.IsEnabled = false;
UpdateTimer.Stop();
// Turn off Kinect
if (this.mainKinect != null)
{
try
{
this.mainKinect.Stop();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
this.TxtBx_KinectStatus.Text += "\n[" + DateTime.Now.TimeOfDay.ToString() + "] " + this.mainKinect.UniqueKinectId.ToString() + " has been turned off.";
}
// Shut down application
Application.Current.Shutdown();
}
I added the 'Application.Current.Shutdown()' only because my program would hang and never actually close when I closed the window. I stepped through the function to find that it hangs on this.mainKinect.Stop(), where mainKinect is the Kinect object referring to the physical Kinect. I thought that maybe it couldn't shut down both streams properly, so I added
this.mainKinect.ColorStream.Disable();
this.mainKinect.SkeletonStream.Disable();
just before the Stop(). I found out that it actually hangs on the SkeletonStream.Disable(), and I don't know why. Most of the rest of my code is straight from their examples, so I don't know why this doesn't work. If you have any ideas, or would like me to post more of my code, please don't hesitate.
I always check all streams, if they are enabled. Any enabled stream I disable, the next step to detach all previously attached eventhandlers, at the end I call the Stop() in a try-catch block and logs the Exception Message to get a hint in the case of any problem.
public void StopKinect()
{
if (this.sensor == null)
{
return;
}
if (this.sensor.SkeletonStream.IsEnabled)
{
this.sensor.SkeletonStream.Disable();
}
if (this.sensor.ColorStream.IsEnabled)
{
this.sensor.ColorStream.Disable();
}
if (this.sensor.DepthStream.IsEnabled)
{
this.sensor.DepthStream.Disable();
}
// detach event handlers
this.sensor.SkeletonFrameReady -= this.SensorSkeletonFrameReady;
try
{
this.sensor.Stop()
}
catch (Exception e)
{
Debug.WriteLine("unknown Exception {0}", e.Message)
}
}
hope this helps.

Upgraded winforms app now getting NullReferenceException calling menuitems PerformClick method, any ideas?

Background:
A WinForms app, originally written in .NET 1.1 migrated via Visual
Studio to .NET 4.0. Typical menu bar at the top of main app form (NB:
not migrated to ToolStripMenuItem), as you might expect there is a
File menuitem that contains an Exit menu item.
I have implemented Ctrl-L shortcut which will bring up a modal lock
form. I also have a timer component on the main form which will
automatically bring up the lock form if there's no activity for
configurable amount of time.
When the lock form is shown you can either unlock (requiring user to
login again) or quit. If you choose to quit then my code does a
fileExitMenuItem.PerformClick() call.
Problem:
For some strange reason after the migration if I quit from the lock
form which was displayed either automatically or due to Ctrl-L
shortcut then I get a NullReferenceException thrown on the
fileExitMenuItem.PerformClick() line of code.
fileExitMenuItem is not null; with break-when-exception-thrown
switched on I can browse all of fileExitMenuItems properties.
I can break in the designer code of the form and watch the click event
handler being attached. If I use the File >> Exit menu item directly I
can break on the code in the event handler.
So this is a total WTF moment. Any suggestions on what to look at will be greatly appreciated
[UPDATE 1] As requested here is some code - this method is called whenever the user presses Ctrl-L or the lock timer elapses:
private void LockApplication()
{
try
{
// Stop the timer so we don't get any more elapsed events whilst we are waiting
// for a user to respond to the lockdown dialog. In addition stop the callout reminder
// time as once we have locked we don't want that doing it's thing.
lockdownTimer.Stop();
calloutsReminderTimer.Stop();
// Clone the current identity so we can check it later.
var previousIdentity = (CudosIdentity)BOUtilities.CurrentIdentity.Clone();
// Show lockdown form.
System.Windows.Forms.DialogResult result;
using (var lockForm = new Forms.applicationLockedForm())
result = lockForm.ShowDialog(this);
if (result == DialogResult.OK)
{
// Did we unlock with a different login?
if (!previousIdentity.Equals(BOUtilities.CurrentIdentity))
{
// Yes, so lose all changes.
CloseOpenForms();
if (_currentLoadSpec != null)
_currentLoadSpec.CancelContent();
}
RefreshLockTimerSetting(null);
}
else
fileExitMenuItem.PerformClick();
}
catch (Exception ex)
{
Helper.LogError(ex);
}
finally
{
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
}
This is the code for the exit menu item:
private void fileExitMenuItem_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
When the following line in LockApplication method from above is called I get the NullReferenceException:
fileExitMenuItem.PerformClick();
[UPDATE 2] Call stack info when the above line is executed:
[External Code]
Cudos.exe!Cudos.mainForm.LockApplication() Line 1132 + 0x10 bytes C#
Cudos.exe!Cudos.mainForm.fileLockCudosMenuItem_Click(object sender, System.EventArgs e) Line 1594 + 0x8 bytes C#
[External Code]
Cudos.exe!Cudos.mainForm.Main() Line 1880 + 0x1d bytes C#
[External Code]
I am not sure, but I will try to remove the restart of the timers if you call the Perform_Click.
The Tick event could be called when there is no more the application because you call Application.Exit().
private void LockApplication()
{
try
{
lockdownTimer.Stop();
calloutsReminderTimer.Stop();
.....
if (result == DialogResult.OK)
{
......
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
else
fileExitMenuItem.PerformClick();
}
catch (Exception ex)
{
Helper.LogError(ex);
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
// remove the finally clause
}
In the end I gave up and just hacked it by changing the fileExitMenuItem.PerformClick() to Application.Exit(). So I still don't have any idea why it was throwing the exception but it at least now works. I guess if I put more logic into the fileExitMenuItem click handler I will just have to remember to extract it into a method and update this hack to call that method to.

Ignoring queued mouse events

I have an application written in C# targeting .NET Compact Framework 3.5, running on Windows CE. From time to time, operations lasting for a second or so are being performed on the UI thread. I currently set the Cursor.Current property to indicate that the application is busy, but this does not prevent mouse events from eager users to queue up. This sometimes leads to unintended clicks.
What is the best way to ignore queued mouse messages on the .NET Compact Framework platform? Sadly, the code has to run on the UI thread.
Disabling the controls won't help you, as I've found from my POS application that the users can sneak in another click in about 50ms, especially when using a touch screen that is not calibrated.
One of the problems this creates is when producing an invoice, you can't have a duplicate click produce another invoice, just because there's a 50ms delay before clearing the current invoice.
In cases like this, I use a pattern similar to this:
public static void ClearMouseClickQueue()
{
Message message;
while (PeekMessage(out message,IntPtr.Zero, (uint) MessageCodes.WM_MOUSEFIRST,(uint) MessageCodes.WM_MOUSELAST,1) != 0)
{
}
}
private object approvalLockObject = new object();
private void btnApproveTransaction_Click(object sender, EventArgs e)
{
ApproveTransactionAndLockForm();
}
private void ApproveTransactionAndLockForm()
{
lock (approvalLockObject)
{
if (ApprovalLockCount == 0)
{
ApprovalLockCount++;
ApproveTransaction();
}
else
{
CloseAndRetry();
}
}
}
private void ApproveTransaction()
{
ClearMouseClickQueue();
this.Enabled = false;
Logger.LogInfo("Before approve transaction");
MouseHelper.SetCursorToWaitCursor();
... validate invoice and print
}
In case you need to reenable the screen, do this:
this.Enabled = true;
ApprovalLockCount = 0;
DialogResult = DialogResult.None;
I believe that the best solution is to prevent the events from happening. You can do that by disabling all the controls and re-enabling them, when the lengthy operation finishes.

Categories