public static int RunNamedPipeHandler(int parentWindowHandle, String commandPipeName)
        {
            int result = -1;
            int pipe_connect_timeout = 10000; // Millisecond timeout

            try
            {
                _logger.LogMsg(Level.Debug, "Entering RunNamedPipeHandler().");

                // Get the (short) pipe name and host name from the full path.
                // The .NET functions do not want the full path, only the name. Path format: "\\hostname\pipe\mypipename.pip"
                String host_name = null;
                String pipe_name = null;
                if (!ParsePipePath(commandPipeName, out host_name, out pipe_name))
                {
                    _logger.LogMsg(Level.Fatal, String.Format("Invalid command pipe path {0}. Connector cannot continue.", commandPipeName));
                    return result;
                }

                // Create the .NET pipe wrapper object.
                NamedPipeClientStream pipeClientStream = CreatePipeStream(pipe_name, host_name, pipe_connect_timeout);

                // Read from pipe
                _logger.LogMsg(Level.Debug, String.Format("Opening .NET StreamReader."));

                Boolean keep_on_processing = true;
                String msg = null;

                while (keep_on_processing)
                {
                    // Qlikview seems to need some time to respond so we always sleep a few seconds.
                    if (_messageWaitMilliseconds > 0)
                    {
                        //_logger.LogMsg(Level.Debug, String.Format("Sleeping in message handler loop for {0} milliseconds.", _messageWaitMilliseconds.ToString()));
                        Thread.Sleep(_messageWaitMilliseconds);
                    }

                    // *** Get the next full XML message from the QlikView command pipe.
                    msg = ReadNextCommandMessage(pipeClientStream);

                    if (String.IsNullOrEmpty(msg))
                    {
                        _logger.LogMsg(Level.Info, "No message received on command pipe.");
                        keep_on_processing = false;
                        //no_response++;
                        //if (no_response > 10)
                        //{
                        //    keep_on_processing = false;
                        //}
                    }
                    else
                    {
                        _logger.LogMsg(Level.Debug, String.Format("Command message received (length {0}). XML follows: \r\n{1}", msg.Length.ToString(), msg));

                        // *** Handle command message
                        QlikViewMessage command_msg = new QlikViewMessage();
                        if (command_msg.Load(msg))
                        {

                            switch (command_msg.MessageType)
                            {
                                case QlikViewCommandTypes.Connect:
                                    // Get connection string, send "OK" response.
                                    _connectionString = command_msg.GetConnectionString();
                                    _logger.LogMsg(Level.Info, String.Format("Handling QVX_CONNECT. Connection String: {0}", _connectionString));

                                    // TO DO: Test the connection with the Java proxy ? This would be a round trip to
                                    // the remote server so it could be a performance issue.
                                    String connect_error_msg;
                                    String connect_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                    if (!Properties.Settings.Default.SimulateConnection)
                                    {
                                        Boolean success = TestConnection(_driverName, _connectionString, _userName, _password, out connect_error_msg);
                                        if (!success)
                                        {
                                            connect_response_xml = QlikViewMessage.MakeGenericReplyMessage(false, null, connect_error_msg);
                                        }

                                    }
                                    SendCommandMessage(pipeClientStream, connect_response_xml);

                                    keep_on_processing = true;
                                    break;

                                case QlikViewCommandTypes.Execute:
                                    // Get the SQL and data pipe name from the QVX_EXECUTE message.
                                    command_msg.GetSQLStatementAndDataPipeName(out _sql, out _dataPipePath);
                                    _logger.LogMsg(Level.Debug, String.Format( "Handling QVX_EXECUTE. Data pipe path: [{0}], SQL: [{1}].", _dataPipePath, _sql ));

                                    // Send QVX_OK before writing to data pipe.
                                    String execute_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                    SendCommandMessage(pipeClientStream, execute_response_xml);

                                    // TO DO: need to get driver, connectionstring, username, password
                                    //String drivername = Properties.Settings.Default.dr

                                    // Write data to the data pipe.
                                    if (!String.IsNullOrEmpty(_sql) && !String.IsNullOrEmpty(_dataPipePath))
                                    {
                                        RunBigDataQueryJava(_dataPipePath, _connectionString, _sql);
                                    }
                                    // Keep on procressing - there mat be multiple QVX_EXECUTE - one for each SQL statement in the script.
                                    keep_on_processing = true;

                                    break;

                                case QlikViewCommandTypes.GenericCommand:
                                    String generic_val;
                                    String generic_response_xml;
                                    command_msg.ParseGenericCommand(out generic_val);
                                    _logger.LogMsg(Level.Debug, String.Format("Handling QVX_GENERIC_COMMAND: {0}", generic_val));
                                    switch( generic_val ) {

                                        case QlikViewGenericCommandValues.GetCustomCaption:
                                            // Send the caption?
                                            if (!Properties.Settings.Default.DisableCustomSQLButton)
                                            {
                                                // This causes QlikView to display the custom SQL button.
                                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { _customButtonCaption });
                                            }
                                            else
                                            {
                                                // This reply prevents QlikView from displaying the custom SQL button.
                                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                            }
                                            SendCommandMessage(pipeClientStream, generic_response_xml);
                                            keep_on_processing = true;
                                            break;

                                        case QlikViewGenericCommandValues.DisableQlikViewSelectButton:
                                            // NOTE: we disable the "Select" button by default since it appears to an ODBC-only thing.
                                            if (Properties.Settings.Default.DisableQlikViewSelectButton)
                                            {
                                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { "true" });
                                            }
                                            else
                                            {
                                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                            }
                                            SendCommandMessage(pipeClientStream, generic_response_xml);
                                            keep_on_processing = true;
                                            break;

                                        case QlikViewGenericCommandValues.HaveStarField:
                                            generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { "true" });
                                            SendCommandMessage(pipeClientStream, generic_response_xml);
                                            keep_on_processing = true;
                                            break;

                                        case QlikViewGenericCommandValues.IsConnected:
                                            generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { "true" });
                                            SendCommandMessage(pipeClientStream, generic_response_xml);
                                            keep_on_processing = true;
                                            break;

                                        default:
                                            _logger.LogMsg(Level.Warn, String.Format("Unknown QVX_GENERIC_COMMAND type received: [{0}].", generic_val));

                                            // TO DO: Stop listening because we don't know what to do ? Or just ignore and keep going?
                                            keep_on_processing = false;
                                            break;
                                    }
                                    break;

                                case QlikViewCommandTypes.EditConnect:
                                    _logger.LogMsg(Level.Debug, String.Format("Handling QVX_EDIT_CONNECT."));
                                    // TO DO / PROBLEM: the connection string parameter in the message is ALWAYS BLANK. There does not appear
                                    // to be any way to get the connection string that is currently in the QlikView script. This means we cannot
                                    // parse it to get the individual pieces before displaying the dialog.
                                    String new_connection_string = command_msg.GetConnectionString();

                                    // Call the dialog and return the modified connection string if OK (skip if Cancel).

                                    ShowCustomConnectDialog(ref new_connection_string);
                                    if (!String.IsNullOrEmpty(new_connection_string))
                                    {
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { new_connection_string });
                                    }
                                    else
                                    {
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                    }
                                    SendCommandMessage(pipeClientStream, generic_response_xml);

                                    // Continue listening on the command pipe.
                                    keep_on_processing = true;

                                    break;

                                case QlikViewCommandTypes.EditSelect:
                                    _logger.LogMsg(Level.Debug, String.Format("Handling QVX_EDIT_SELECT."));
                                    // Call the dialog and return the modified SQL string.
                                    String new_sql = null;
                                    ShowCustomSQLDialog(ref new_sql);
                                    if( !String.IsNullOrEmpty(new_sql ) )
                                    {
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { new_sql });
                                    }
                                    else
                                    {
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                    }
                                    SendCommandMessage(pipeClientStream, generic_response_xml);

                                    // Continue listening on the command pipe.
                                    keep_on_processing = true;

                                    break;

                                case QlikViewCommandTypes.Disconnect:
                                    _logger.LogMsg(Level.Debug, String.Format("Handling QVX_DISCONNECT."));
                                    // There is nothing to parse out since this has no defined parameters

                                    // TO DO: Actually do something to disconnect from the data source ?
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                    SendCommandMessage(pipeClientStream, generic_response_xml);

                                    //
                                    keep_on_processing = true;

                                    break;

                                case QlikViewCommandTypes.Terminate:
                                    _logger.LogMsg(Level.Debug, String.Format("Handling QVX_TERMINATE."));
                                    // There is nothing to parse out since this has no defined parameters

                                    // TO DO: Actually do something to shut down the Java query if running (async - not yet implemented).
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                    SendCommandMessage(pipeClientStream, generic_response_xml);

                                    // Exit becaue we are shutting down.
                                    keep_on_processing = false;

                                    break;

                                default:
                                    _logger.LogMsg(Level.Warn, String.Format("Connector does not yet support this command message type: {0}.", command_msg.MessageType));
                                    // If we don't know the message type, just exit.
                                    // TO DO: Handle all the other QlikView message types.
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(QlikViewResponseTypes.QvxUnknownCommand);
                                    SendCommandMessage(pipeClientStream, generic_response_xml);
                                    keep_on_processing = true;
                                    break;
                            }
                        }
                        else
                        {
                            _logger.LogMsg(Level.Error, "Invalid command message format.");
                            keep_on_processing = false;
                        }

                        if (!keep_on_processing)
                        {
                            _logger.LogMsg(Level.Debug, "Exiting message handler loop. Connector program terminating. ");
                        }
                    }

                } // end while (keep_on_processing)

                result = 0;
            }
            catch (Exception ex)
            {
                _logger.LogMsg(Level.Fatal, "Unexpected error in RunNamedPipeHandler(): " + ex.Message);
            }

            return result;
        }
Example #2
0
        public static int RunNamedPipeHandler(int parentWindowHandle, String commandPipeName)
        {
            int result = -1;
            int pipe_connect_timeout = 10000; // Millisecond timeout

            try
            {
                _logger.LogMsg(Level.Debug, "Entering RunNamedPipeHandler().");

                // Get the (short) pipe name and host name from the full path.
                // The .NET functions do not want the full path, only the name. Path format: "\\hostname\pipe\mypipename.pip"
                String host_name = null;
                String pipe_name = null;
                if (!ParsePipePath(commandPipeName, out host_name, out pipe_name))
                {
                    _logger.LogMsg(Level.Fatal, String.Format("Invalid command pipe path {0}. Connector cannot continue.", commandPipeName));
                    return(result);
                }

                // Create the .NET pipe wrapper object.
                NamedPipeClientStream pipeClientStream = CreatePipeStream(pipe_name, host_name, pipe_connect_timeout);


                // Read from pipe
                _logger.LogMsg(Level.Debug, String.Format("Opening .NET StreamReader."));

                Boolean keep_on_processing = true;
                String  msg = null;

                while (keep_on_processing)
                {
                    // Qlikview seems to need some time to respond so we always sleep a few seconds.
                    if (_messageWaitMilliseconds > 0)
                    {
                        //_logger.LogMsg(Level.Debug, String.Format("Sleeping in message handler loop for {0} milliseconds.", _messageWaitMilliseconds.ToString()));
                        Thread.Sleep(_messageWaitMilliseconds);
                    }

                    // *** Get the next full XML message from the QlikView command pipe.
                    msg = ReadNextCommandMessage(pipeClientStream);

                    if (String.IsNullOrEmpty(msg))
                    {
                        _logger.LogMsg(Level.Info, "No message received on command pipe.");
                        keep_on_processing = false;
                        //no_response++;
                        //if (no_response > 10)
                        //{
                        //    keep_on_processing = false;
                        //}
                    }
                    else
                    {
                        _logger.LogMsg(Level.Debug, String.Format("Command message received (length {0}). XML follows: \r\n{1}", msg.Length.ToString(), msg));

                        // *** Handle command message
                        QlikViewMessage command_msg = new QlikViewMessage();
                        if (command_msg.Load(msg))
                        {
                            switch (command_msg.MessageType)
                            {
                            case QlikViewCommandTypes.Connect:
                                // Get connection string, send "OK" response.
                                _connectionString = command_msg.GetConnectionString();
                                _logger.LogMsg(Level.Info, String.Format("Handling QVX_CONNECT. Connection String: {0}", _connectionString));

                                // TO DO: Test the connection with the Java proxy ? This would be a round trip to
                                // the remote server so it could be a performance issue.
                                String connect_error_msg;
                                String connect_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                if (!Properties.Settings.Default.SimulateConnection)
                                {
                                    Boolean success = TestConnection(_driverName, _connectionString, _userName, _password, out connect_error_msg);
                                    if (!success)
                                    {
                                        connect_response_xml = QlikViewMessage.MakeGenericReplyMessage(false, null, connect_error_msg);
                                    }
                                }
                                SendCommandMessage(pipeClientStream, connect_response_xml);

                                keep_on_processing = true;
                                break;

                            case QlikViewCommandTypes.Execute:
                                // Get the SQL and data pipe name from the QVX_EXECUTE message.
                                command_msg.GetSQLStatementAndDataPipeName(out _sql, out _dataPipePath);
                                _logger.LogMsg(Level.Debug, String.Format("Handling QVX_EXECUTE. Data pipe path: [{0}], SQL: [{1}].", _dataPipePath, _sql));

                                // Send QVX_OK before writing to data pipe.
                                String execute_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                SendCommandMessage(pipeClientStream, execute_response_xml);

                                // TO DO: need to get driver, connectionstring, username, password
                                //String drivername = Properties.Settings.Default.dr

                                // Write data to the data pipe.
                                if (!String.IsNullOrEmpty(_sql) && !String.IsNullOrEmpty(_dataPipePath))
                                {
                                    RunBigDataQueryJava(_dataPipePath, _connectionString, _sql);
                                }
                                // Keep on procressing - there mat be multiple QVX_EXECUTE - one for each SQL statement in the script.
                                keep_on_processing = true;


                                break;

                            case QlikViewCommandTypes.GenericCommand:
                                String generic_val;
                                String generic_response_xml;
                                command_msg.ParseGenericCommand(out generic_val);
                                _logger.LogMsg(Level.Debug, String.Format("Handling QVX_GENERIC_COMMAND: {0}", generic_val));
                                switch (generic_val)
                                {
                                case QlikViewGenericCommandValues.GetCustomCaption:
                                    // Send the caption?
                                    if (!Properties.Settings.Default.DisableCustomSQLButton)
                                    {
                                        // This causes QlikView to display the custom SQL button.
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { _customButtonCaption });
                                    }
                                    else
                                    {
                                        // This reply prevents QlikView from displaying the custom SQL button.
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                    }
                                    SendCommandMessage(pipeClientStream, generic_response_xml);
                                    keep_on_processing = true;
                                    break;

                                case QlikViewGenericCommandValues.DisableQlikViewSelectButton:
                                    // NOTE: we disable the "Select" button by default since it appears to an ODBC-only thing.
                                    if (Properties.Settings.Default.DisableQlikViewSelectButton)
                                    {
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { "true" });
                                    }
                                    else
                                    {
                                        generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                    }
                                    SendCommandMessage(pipeClientStream, generic_response_xml);
                                    keep_on_processing = true;
                                    break;

                                case QlikViewGenericCommandValues.HaveStarField:
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { "true" });
                                    SendCommandMessage(pipeClientStream, generic_response_xml);
                                    keep_on_processing = true;
                                    break;

                                case QlikViewGenericCommandValues.IsConnected:
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { "true" });
                                    SendCommandMessage(pipeClientStream, generic_response_xml);
                                    keep_on_processing = true;
                                    break;

                                default:
                                    _logger.LogMsg(Level.Warn, String.Format("Unknown QVX_GENERIC_COMMAND type received: [{0}].", generic_val));

                                    // TO DO: Stop listening because we don't know what to do ? Or just ignore and keep going?
                                    keep_on_processing = false;
                                    break;
                                }
                                break;


                            case QlikViewCommandTypes.EditConnect:
                                _logger.LogMsg(Level.Debug, String.Format("Handling QVX_EDIT_CONNECT."));
                                // TO DO / PROBLEM: the connection string parameter in the message is ALWAYS BLANK. There does not appear
                                // to be any way to get the connection string that is currently in the QlikView script. This means we cannot
                                // parse it to get the individual pieces before displaying the dialog.
                                String new_connection_string = command_msg.GetConnectionString();

                                // Call the dialog and return the modified connection string if OK (skip if Cancel).

                                ShowCustomConnectDialog(ref new_connection_string);
                                if (!String.IsNullOrEmpty(new_connection_string))
                                {
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { new_connection_string });
                                }
                                else
                                {
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                }
                                SendCommandMessage(pipeClientStream, generic_response_xml);

                                // Continue listening on the command pipe.
                                keep_on_processing = true;

                                break;

                            case QlikViewCommandTypes.EditSelect:
                                _logger.LogMsg(Level.Debug, String.Format("Handling QVX_EDIT_SELECT."));
                                // Call the dialog and return the modified SQL string.
                                String new_sql = null;
                                ShowCustomSQLDialog(ref new_sql);
                                if (!String.IsNullOrEmpty(new_sql))
                                {
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true, new String[] { new_sql });
                                }
                                else
                                {
                                    generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(false);
                                }
                                SendCommandMessage(pipeClientStream, generic_response_xml);

                                // Continue listening on the command pipe.
                                keep_on_processing = true;

                                break;


                            case QlikViewCommandTypes.Disconnect:
                                _logger.LogMsg(Level.Debug, String.Format("Handling QVX_DISCONNECT."));
                                // There is nothing to parse out since this has no defined parameters

                                // TO DO: Actually do something to disconnect from the data source ?
                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                SendCommandMessage(pipeClientStream, generic_response_xml);

                                //
                                keep_on_processing = true;

                                break;

                            case QlikViewCommandTypes.Terminate:
                                _logger.LogMsg(Level.Debug, String.Format("Handling QVX_TERMINATE."));
                                // There is nothing to parse out since this has no defined parameters

                                // TO DO: Actually do something to shut down the Java query if running (async - not yet implemented).
                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(true);
                                SendCommandMessage(pipeClientStream, generic_response_xml);

                                // Exit becaue we are shutting down.
                                keep_on_processing = false;

                                break;

                            default:
                                _logger.LogMsg(Level.Warn, String.Format("Connector does not yet support this command message type: {0}.", command_msg.MessageType));
                                // If we don't know the message type, just exit.
                                // TO DO: Handle all the other QlikView message types.
                                generic_response_xml = QlikViewMessage.MakeGenericReplyMessage(QlikViewResponseTypes.QvxUnknownCommand);
                                SendCommandMessage(pipeClientStream, generic_response_xml);
                                keep_on_processing = true;
                                break;
                            }
                        }
                        else
                        {
                            _logger.LogMsg(Level.Error, "Invalid command message format.");
                            keep_on_processing = false;
                        }

                        if (!keep_on_processing)
                        {
                            _logger.LogMsg(Level.Debug, "Exiting message handler loop. Connector program terminating. ");
                        }
                    }
                } // end while (keep_on_processing)

                result = 0;
            }
            catch (Exception ex)
            {
                _logger.LogMsg(Level.Fatal, "Unexpected error in RunNamedPipeHandler(): " + ex.Message);
            }


            return(result);
        }