-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathProgram.cs
181 lines (167 loc) · 6.49 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace DigiRite
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
const int UpgradedVersion = 76; // increment every release
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#if DEBUG
MessageBox.Show("Debug me", "DigiRite.exe");
#endif
int settingsVersion = Properties.Settings.Default.SavedVersion;
if (settingsVersion < UpgradedVersion)
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.SavedVersion = UpgradedVersion;
}
CustomColors.CommonBackgroundColor = Properties.Settings.Default.Background;
CustomColors.TxBackgroundColor = Properties.Settings.Default.TxBackground;
if ((args.Length >= 1) && args[0].ToUpper() == "-EMBEDDING")
{
var regServices = new RegistrationServices();
int cookie = regServices.RegisterTypeForComClients(
typeof(Ft8Auto),
RegistrationClassContext.LocalServer ,
RegistrationConnectionType.SingleUse);
applicationContext = new NoShowFormAppContext();
Application.Run(applicationContext);
regServices.UnregisterTypeForComClients(cookie);
}
else
{ Application.Run(new MainForm(1)); }
}
public static NoShowFormAppContext applicationContext;
public class NoShowFormAppContext : ApplicationContext
{
// as an automation server, we must immediately
// have an HWND so the automation class can
// get methods back on the Program's STA
class NoShowControl : Control
{
public void Create()
{ CreateHandle(); }
}
private NoShowControl toDispatch = new NoShowControl();
private MainForm mainForm = null;
private bool haveShownMain = false;
public NoShowFormAppContext()
{ // arrange for dispatch in ctor
toDispatch.Visible = false;
toDispatch.Create();
}
public void CreateMainForm()
{
toDispatch.BeginInvoke(new Action(() =>
{
if (!haveShownMain)
{
haveShownMain = true;
mainForm.FormClosed += OnFormClosed;
mainForm.Show();
}
}));
}
public void CloseMainWindow()
{
if (null != mainForm)
toDispatch.BeginInvoke(new Action(() => {
mainForm.Close();
}));
}
public void AbortMessage()
{
if (null != mainForm)
toDispatch.BeginInvoke(new Action(() => {
mainForm.AbortMessage();
}));
}
private string loggerAssemblyName;
public void SetWlEntry(object wl, int instanceNumber)
{
// only do this once
if (null == mainForm)
{
toDispatch.BeginInvoke(new Action<object>((object w) =>
{
mainForm = new MainForm(instanceNumber);
if (loggerAssemblyName != null)
mainForm.LoggerAssemblyName = loggerAssemblyName;
mainForm.SetWlEntry(w);
}), wl);
}
}
public void SetLoggerAssemblyName(string s)
{
loggerAssemblyName = s;
}
public void SendRttyMessage(String toSend)
{
if (null != mainForm)
toDispatch.BeginInvoke(new Action(() => {
mainForm.SendRttyMessage(toSend);
}));
}
public string GetCurrentMode()
{
/* THREAD SAFETY AND SYNCHRONIZATION ISSUE HERE.
** A BeginInvoke followed by AsyncWaitHandle.WaitOne
** WOULD BE a way to synchronize with the main thread.
** But it deadlocks with WriteLog. How?
** Our main thread calls into WL to do something (anything)
** to the rig and WL calls back here to check whether the
** mode should be overridden.
** but WaitOne() blocks forever because the .NET
** dispatcher for thread Main doesn't dispatch
** our action cause its in an outbound COM call.
**
** .NET probably has some mechanism for this code here
** to somehow inform the STA dispatcher for the main
** thread that we really are on the same COM causality
** as the outgoing COM call. But I couldn't find any
** .NET+COM magic to do that.
*/
#if false
// Thread safe, but deadlocks
string ret = "";
if (null != mainForm)
{
var action = new Action(() =>
{
ret = mainForm.CurrentMode.ToString();
});
var result = toDispatch.BeginInvoke(action);
result.AsyncWaitHandle.WaitOne();
result.AsyncWaitHandle.Close();
}
return ret;
#else
// Beware thread safety...but doesn't deadlock
// and the enum itself can safely be accessed from outside
// its own thread.
var form = mainForm;
if (null != form)
return form.CurrentMode.ToString();
else
return "";
#endif
}
void OnFormClosed(object sender, EventArgs e)
{ // the restaurant at the end of the universe
mainForm = null;
ExitThread();
}
}
}
}