IQFeed.CSharpApiClient icon indicating copy to clipboard operation
IQFeed.CSharpApiClient copied to clipboard

Login and Password in Registry

Open veng1 opened this issue 5 years ago • 5 comments

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();
        }
    }
}

}

veng1 avatar Aug 07 '20 18:08 veng1

image

mathpaquette avatar Aug 07 '20 23:08 mathpaquette

but whats the problem of using env variables?

mathpaquette avatar Aug 07 '20 23:08 mathpaquette

@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 avatar Aug 08 '20 12:08 mathpaquette

@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 avatar Aug 08 '20 17:08 hunterfries

@hunterfries I totally agree with you. at the end of the day, we need to start IQConnect without parameters if I understand correctly.

mathpaquette avatar Aug 08 '20 17:08 mathpaquette