UserSessions.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. using System.Threading;
  3. using System.Windows.Forms;
  4. namespace SmartCoalApplication.SystemLayer
  5. {
  6. public static class UserSessions
  7. {
  8. private static OurControl messageControl;
  9. private static bool lastRemoteSessionValue;
  10. private static EventHandler sessionChanged;
  11. private static int sessionChangedCount;
  12. private static object lockObject = new object();
  13. private sealed class OurControl : Control
  14. {
  15. public event EventHandler WmWtSessionChange;
  16. private void OnWmWtSessionChange()
  17. {
  18. if (WmWtSessionChange != null)
  19. {
  20. WmWtSessionChange(this, EventArgs.Empty);
  21. }
  22. }
  23. protected override void WndProc(ref Message m)
  24. {
  25. switch (m.Msg)
  26. {
  27. case NativeConstants.WM_WTSSESSION_CHANGE:
  28. OnWmWtSessionChange();
  29. break;
  30. default:
  31. base.WndProc(ref m);
  32. break;
  33. }
  34. }
  35. }
  36. private static void OnSessionChanged()
  37. {
  38. if (sessionChanged != null)
  39. {
  40. sessionChanged(null, EventArgs.Empty);
  41. }
  42. }
  43. /// <summary>
  44. /// Occurs when the user changes between sessions. This event will only be
  45. /// raised when the value returned by IsRemote() changes.
  46. /// </summary>
  47. /// <remarks>
  48. /// For example, if the user is currently logged in at the console, and then
  49. /// switches to a remote session (they use Remote Desktop from another computer),
  50. /// then this event will be raised.
  51. /// Note to implementors: This may be implemented as a no-op.
  52. /// </remarks>
  53. public static event EventHandler SessionChanged
  54. {
  55. add
  56. {
  57. lock (lockObject)
  58. {
  59. sessionChanged += value;
  60. ++sessionChangedCount;
  61. if (sessionChangedCount == 1)
  62. {
  63. messageControl = new OurControl();
  64. messageControl.CreateControl(); // force the HWND to be created
  65. messageControl.WmWtSessionChange += new EventHandler(SessionStrobeHandler);
  66. SafeNativeMethods.WTSRegisterSessionNotification(messageControl.Handle, NativeConstants.NOTIFY_FOR_ALL_SESSIONS);
  67. lastRemoteSessionValue = IsRemote;
  68. }
  69. }
  70. }
  71. remove
  72. {
  73. lock (lockObject)
  74. {
  75. sessionChanged -= value;
  76. int decremented = Interlocked.Decrement(ref sessionChangedCount);
  77. if (decremented == 0)
  78. {
  79. try
  80. {
  81. SafeNativeMethods.WTSUnRegisterSessionNotification(messageControl.Handle);
  82. }
  83. catch (EntryPointNotFoundException)
  84. {
  85. }
  86. messageControl.Dispose();
  87. messageControl = null;
  88. }
  89. }
  90. }
  91. }
  92. /// <summary>
  93. /// Determines whether the user is running within a remoted session (Terminal Server, Remote Desktop).
  94. /// </summary>
  95. /// <returns>
  96. /// <b>true</b> if we're running in a remote session, <b>false</b> otherwise.
  97. /// </returns>
  98. /// <remarks>
  99. /// You can use this to optimize the presentation of visual elements. Remote sessions
  100. /// are often bandwidth limited and less suitable for complex drawing.
  101. /// Note to implementors: This may be implemented as a no op; in this case, always return false.
  102. /// </remarks>
  103. public static bool IsRemote
  104. {
  105. get
  106. {
  107. return 0 != SafeNativeMethods.GetSystemMetrics(NativeConstants.SM_REMOTESESSION);
  108. }
  109. }
  110. private static void SessionStrobeHandler(object sender, EventArgs e)
  111. {
  112. if (IsRemote != lastRemoteSessionValue)
  113. {
  114. lastRemoteSessionValue = IsRemote;
  115. OnSessionChanged();
  116. }
  117. }
  118. }
  119. }