Login and Password in Registry
I'm not too fond of putting my IQfeed login and password in code like appconfig nor do I want to add it to the environment. It seems easier to use what IQFeed already stores in the Registry. Also the Product ID can be stored there. The following replacement for IQFeedLauncher.cs
using System; using System.Configuration; using System.Diagnostics; using System.Threading; using IQFeed.CSharpApiClient.Extensions; using IQFeed.CSharpApiClient.Socket; using IQFeed.CSharpApiClient.Streaming.Admin; using IQFeed.CSharpApiClient.Streaming.Admin.Messages; using Microsoft.Win32;
namespace IQFeed.CSharpApiClient { // ReSharper disable once InconsistentNaming public static class IQFeedLauncher { public static void Start(string login = null, string password = null, string productId = null, string productVersion = null, int connectionTimeoutMs = 100, int retry = 50) { var appSettings = ConfigurationManager.AppSettings;
// Add <PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" /> to csproj
RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\DTN\\IQFeed\\Startup");
login = login ??
key.GetValue("LOGIN").ToString() ??
Environment.GetEnvironmentVariable("IQCONNECT_LOGIN") ??
appSettings["IQConnect:login"].NullIfEmpty() ??
throw new Exception("Unable to find IQConnect login from environment variable or app.config");
password = password ??
key.GetValue("PASSWORD").ToString() ??
Environment.GetEnvironmentVariable("IQCONNECT_PASSWORD") ??
appSettings["IQConnect:password"].NullIfEmpty() ??
throw new Exception("Unable to find IQConnect password from environment variable or app.config");
productId = productId ??
key.GetValue("PRODUCT").ToString() ??
Environment.GetEnvironmentVariable("IQCONNECT_PRODUCT_ID") ??
appSettings["IQConnect:product_id"].NullIfEmpty() ??
throw new Exception("Unable to find IQConnect product ID from environment variable or app.config");
productVersion = productVersion ??
Environment.GetEnvironmentVariable("IQCONNECT_PRODUCT_VERSION") ??
appSettings["IQConnect:product_version"].NullIfEmpty() ??
"1.0.0.0";
var iqConnectParameters = $"-product {productId} -version {productVersion} -login {login} -password {password} -autoconnect";
Process.Start("IQConnect.exe", iqConnectParameters);
WaitForAdminPortReady(connectionTimeoutMs, retry);
WaitForServerConnectedStatus(IQFeedDefault.Hostname, IQFeedDefault.AdminPort);
}
public static void Terminate()
{
foreach (var process in Process.GetProcessesByName("IQConnect"))
{
process.Kill();
}
}
private static void WaitForAdminPortReady(int connectionTimeoutMs, int retry)
{
var adminPortReady = SocketDiagnostic.IsPortOpen(IQFeedDefault.Hostname, IQFeedDefault.AdminPort, connectionTimeoutMs, retry);
if (!adminPortReady)
throw new Exception($"Can't establish TCP connection with host: {IQFeedDefault.Hostname}:{IQFeedDefault.AdminPort}");
}
private static void WaitForServerConnectedStatus(string host, int port, int timeoutMs = 10000)
{
var manualResetEvent = new ManualResetEvent(false);
var adminClient = AdminClientFactory.CreateNew(host, port);
adminClient.Stats += AdminClientOnStats;
adminClient.Connect();
var connected = manualResetEvent.WaitOne(timeoutMs);
if (!connected)
throw new Exception($"Haven't received connected status with host: {host}:{port}");
adminClient.Stats -= AdminClientOnStats;
adminClient.Disconnect();
void AdminClientOnStats(StatsMessage message)
{
if (message.Status == StatsStatusType.Connected)
manualResetEvent.Set();
}
}
}
}

but whats the problem of using env variables?
@veng1 but look, I've understood your point. Basically, if you've saved already your credentials into IQFeed, there's no reason for throwing an error when launching the IQFeedLaucher isnt it. The problem is that your code is only windows compatible...
@mathpaquette I'm not advocating one way on the other, but conditional logic around what's returned from Environment.OSVersion could skirt this concern.
@hunterfries I totally agree with you. at the end of the day, we need to start IQConnect without parameters if I understand correctly.