コード例 #1
0
        private static void NotifyListeners(StatusEntry entry)
        {
            if (sm_Listeners == null)
            {
                return;
            }

            lock (sm_Listeners)
            {
                foreach (var node in sm_Listeners)
                {
                    if (entry.TypeOfEntry == StatusEntry.EntryType.Trace && node.wantsTrace == false)
                    {
                        continue;
                    }

                    var listener = node.listener;

                    switch (entry.TypeOfEntry)
                    {
                    case StatusEntry.EntryType.Error:
                        listener.ErrorMessage(entry.Summary, entry.Details);
                        break;

                    case StatusEntry.EntryType.Warning:
                        listener.WarningMessage(entry.Summary, entry.Details);
                        break;

                    default:
                        listener.StatusMessage(entry.Summary, entry.Details);
                        break;
                    }
                }
            }
        }
コード例 #2
0
        public static void LogStatus(string msg)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Status,
                Summary     = msg
            };

            NotifyListeners(entry);
        }
コード例 #3
0
        public static void Trace(string message)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Trace,
                Summary     = message
            };

            NotifyListeners(entry);
        }
コード例 #4
0
        public static void LogWarning(string warning)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Warning,
                Summary     = warning
            };

            NotifyListeners(entry);
        }
コード例 #5
0
        public static void LogError(string error)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary     = error
            };

            NotifyListeners(entry);
        }
コード例 #6
0
        public static void LogQBError(string context, string statusMessage, int statusCode)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary     = "QuickBooks Error:" + context,
                Details     = statusMessage
            };

            entry.AddLine("Status Code:" + statusCode);

            NotifyListeners(entry);
        }
コード例 #7
0
        private void HostQueryFail(string statusMsg, int statusCode)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary     = "Host Query Failed",
                Details     = statusMsg
            };

            entry.AddLine("Status Code:" + statusCode);

            StatusMgr.LogEntry(entry);
        }
コード例 #8
0
        public static void HandleException(string context, Exception ex)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary     = context
            };

            for (var currentException = ex;
                 currentException != null;
                 currentException = currentException.InnerException)
            {
                entry.AddLine(currentException.Message);
                entry.AddLine(currentException.StackTrace);
            }

            NotifyListeners(entry);
        }
コード例 #9
0
ファイル: SDKBatch.cs プロジェクト: hellfirehd/Zombie
        private void StatusMessage(int idx, string Heading, string StatusMessage, int statusCode, bool IsError)
        {
            StatusEntry.EntryType t = StatusEntry.EntryType.Status;
            if (IsError)
            {
                t = StatusEntry.EntryType.Error;
            }

            var entry = new StatusEntry()
            {
                TypeOfEntry = t,
                Summary     = Heading + "detected for index " + idx,
                Details     = StatusMessage
            };

            entry.AddLine("Status Code:" + statusCode);

            StatusMgr.LogEntry(entry);
        }
コード例 #10
0
        /// <summary>
        /// Creates and SDK connection using the specified connection configuration
        /// </summary>
        /// <param name="config">The connection configuration to use</param>
        /// <returns>a usable connection or null if an error occurred</returns>
        public static SDKConnection GetConnection(ConnectionConfig config)
        {
            if (_thisApplication == null)
            {
                throw new Exception("Application ID is not set");
            }

            try
            {
                var cn = new SDKConnection(_thisApplication, config);

                if (config.ConnectionType != FCConnectionType.Online)
                {
                    cn.QueryDesktopVersion();
                }

                lock (_connections)
                {
                    _connections.Add(cn);
                }

                return(cn);
            }
            catch (SDKException sdkex)
            {
                var entry = new StatusEntry()
                {
                    TypeOfEntry = StatusEntry.EntryType.Error,
                    Summary     = sdkex.Message,
                    Details     = sdkex.ProblemDetail
                };

                StatusMgr.LogEntry(entry);

                return(null);
            }
        }
コード例 #11
0
        /// <summary>
        /// SDK updates treat truncation as an error.  So it is important to trim
        /// values that are found to be too long
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string LimitedString(string val, int maxLength, string reference)
        {
            if (val == null)
            {
                return(string.Empty);
            }

            if (val.Length > maxLength)
            {
                var entry = new StatusEntry()
                {
                    TypeOfEntry = StatusEntry.EntryType.Warning,
                    Summary     = "Data truncated",
                    Details     = reference + " exceeds maximum length(" + maxLength
                                  + "), value will be truncated"
                };

                StatusMgr.LogEntry(entry);

                return(val.Substring(0, maxLength));
            }

            return(val);
        }
コード例 #12
0
ファイル: SDKBatch.cs プロジェクト: cubski/Zombie
        private bool RunOneBatch(out IteratorCall _iterCall)
        {
            const string ERROR_CONTEXT = "QuickBooks query follow-up";

            _iterCall = null;

            var resp = _mgr.DoRequests(_msg);

            if (resp == null || resp.ResponseList == null)
            {
                throw new Exception("null response returned from batch");
            }

            if (resp.ResponseList.Count == 0)
            {
                throw new Exception("no response items returned from batch");
            }

            bool errors = false;

            var lstResponse = resp.ResponseList;

            for (int idx = 0; idx < lstResponse.Count; idx++)
            {
                var itm = lstResponse.GetAt(idx);

                if (itm == null)
                {
                    var entry = new StatusEntry()
                    {
                        TypeOfEntry = StatusEntry.EntryType.Error,
                        Summary = "null reponse item encountered",
                        Details = resp.ToXMLString()
                    };

                    StatusMgr.LogEntry(entry);

                    return false;
                }

                ClosureSpec cls = null;
                int rqID = int.Parse(itm.RequestID);

                if (_clousures.ContainsKey(rqID))
                {
                    cls = _clousures[rqID];
                }

                if (itm.StatusCode == 0)
                {
                    if (cls != null)
                    {
                        try
                        {
                            cls.success(itm.Detail);
                        }
                        catch (Exception ex)
                        {
                            StatusMgr.HandleException(ERROR_CONTEXT, ex);
                            return false;
                        }
                    }

                    if (_iterator != null)
                    {

                        int iteratorRemaining = 0;

                        try
                        {
                            //iterator remaining count can be toxic, it
                            //iterator is not set up correctly
                            iteratorRemaining = itm.iteratorRemainingCount;
                        }
                        catch (System.Runtime.InteropServices.COMException)
                        {
                            StatusMgr.LogError("Iterator not properly initialized");
                        }

                        if (iteratorRemaining > 0)
                        {
                            _iterCall = new IteratorCall()
                            {
                                iterator = _iterator,
                                iteratorId = itm.iteratorID,
                                remaining = iteratorRemaining
                            };
                        }
                    }
                }
                else if (cls != null && cls.allowEmptyReturn
                            && (itm.StatusCode == 1 || itm.StatusCode == 500))
                {
                    //process empty result
                    try
                    {
                        cls.success(null);
                    }
                    catch (Exception ex)
                    {
                        StatusMgr.HandleException(ERROR_CONTEXT, ex);
                        return false;
                    }
                }
                else
                {
                    switch (itm.StatusSeverity.ToLower())
                    {
                        case "info":
                            StatusMgr.Trace(itm.StatusMessage);
                            if (cls != null)
                            {
                                try
                                {
                                    cls.success(itm.Detail);
                                }
                                catch (Exception ex)
                                {
                                    StatusMgr.HandleException(ERROR_CONTEXT, ex);
                                    return false;
                                }
                            }
                            break;

                        case "warning":
                        case "warn":
                            StatusMessage(idx, "Warning", itm.StatusMessage, itm.StatusCode, false);
                            if (cls != null)
                            {
                                try
                                {
                                    cls.success(itm.Detail);
                                }
                                catch (Exception ex)
                                {
                                    StatusMgr.HandleException(ERROR_CONTEXT, ex);
                                    return false;
                                }
                            }
                            break;

                        case "error":
                        default:
                            if (cls != null && cls.failure != null)
                            {
                                try
                                {
                                    cls.failure(itm.StatusMessage, itm.StatusCode);
                                }
                                catch (Exception ex)
                                {
                                    StatusMgr.HandleException(ERROR_CONTEXT, ex);
                                    return false;
                                }
                            }
                            else
                            {
                                StatusMessage(idx, "Error", itm.StatusMessage, itm.StatusCode, true);
                            }
                            errors = true;
                            break;
                    }
                }
                //end of response loop
            }
            return errors == false;
        }
コード例 #13
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        public static void HandleException(string context, Exception ex)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary = context
            };

            for (var currentException = ex;
                    currentException != null;
                    currentException = currentException.InnerException)
            {
                entry.AddLine(currentException.Message);
                entry.AddLine(currentException.StackTrace);
            }

            NotifyListeners(entry);
        }
コード例 #14
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        public static void LogStatus(string msg)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Status,
                Summary = msg
            };

            NotifyListeners(entry);
        }
コード例 #15
0
ファイル: SDKBatch.cs プロジェクト: hellfirehd/Zombie
        public bool Run()
        {
            switch (_msg.RequestList.Count)
            {
            case 0:
                StatusMgr.LogError("No items in batch to process");
                return(false);

            case 1:
                break;

            default:
                if (_iterator != null)
                {
                    StatusMgr.LogError("Iterators are only allowed in single request batches");
                    return(false);
                }
                _msg.Attributes.OnError = SDK.ENRqOnError.roeContinue;
                break;
            }

            try
            {
                bool retVal = false;

                IteratorCall iterCall = null;

                do
                {
                    retVal = RunOneBatch(out iterCall);

                    if (iterCall != null)
                    {
                        if (!iterCall.iterator(iterCall.iteratorId, iterCall.remaining))
                        {
                            return(false); //user cancelled
                        }
                    }
                }while (retVal == true && iterCall != null);

                return(retVal);
            }
            catch (System.Runtime.InteropServices.COMException cex)
            {
                var entry = new StatusEntry()
                {
                    Summary     = "Request Error",
                    TypeOfEntry = StatusEntry.EntryType.Error
                };
                entry.AddLine(cex.Message);

                try
                {
                    //This may not be the source of the error
                    //entry.AddLine(_msg.ToXMLString());

                    //this causes further COM errors
                    //entry.AddLine(_msg.Attributes.ResponseData.ToString());
                    entry.AddLine("Enable SDK logging for further diagnostics");
                }
                catch (Exception)
                {
                }

                StatusMgr.LogEntry(entry);

                return(false);
            }
        }
コード例 #16
0
ファイル: SDKConnection.cs プロジェクト: pkpjpm/Zombie
        private void HostQueryFail(string statusMsg, int statusCode)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary = "Host Query Failed",
                Details = statusMsg
            };

            entry.AddLine("Status Code:" + statusCode);

            StatusMgr.LogEntry(entry);
        }
コード例 #17
0
 public static void LogEntry(StatusEntry entry)
 {
     NotifyListeners(entry);
 }
コード例 #18
0
ファイル: ConnectionMgr.cs プロジェクト: pkpjpm/Zombie
        /// <summary>
        /// Creates and SDK connection using the specified connection configuration
        /// </summary>
        /// <param name="config">The connection configuration to use</param>
        /// <returns>a usable connection or null if an error occurred</returns>
        public static SDKConnection GetConnection(ConnectionConfig config)
        {
            if (_thisApplication == null)
            {
                throw new Exception("Application ID is not set");
            }

            try
            {
                var cn = new SDKConnection(_thisApplication, config);

                if (config.ConnectionType != FCConnectionType.Online)
                {
                    cn.QueryDesktopVersion();
                }

                lock (_connections)
                {
                    _connections.Add(cn);
                }

                return cn;
            }
            catch (SDKException sdkex)
            {
                var entry = new StatusEntry()
                {
                    TypeOfEntry = StatusEntry.EntryType.Error,
                    Summary = sdkex.Message,
                    Details = sdkex.ProblemDetail
                };

                StatusMgr.LogEntry(entry);

                return null;
            }
        }
コード例 #19
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        private static void NotifyListeners(StatusEntry entry)
        {
            if (sm_Listeners == null) return;

            lock (sm_Listeners)
            {
                foreach (var node in sm_Listeners)
                {
                    if (entry.TypeOfEntry == StatusEntry.EntryType.Trace && node.wantsTrace == false)
                    {
                        continue;
                    }

                    var listener = node.listener;

                    switch (entry.TypeOfEntry)
                    {
                        case StatusEntry.EntryType.Error:
                            listener.ErrorMessage(entry.Summary, entry.Details);
                            break;

                        case StatusEntry.EntryType.Warning:
                            listener.WarningMessage(entry.Summary, entry.Details);
                            break;

                        default:
                            listener.StatusMessage(entry.Summary, entry.Details);
                            break;
                    }
                }
            }
        }
コード例 #20
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        public static void Trace(string message)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Trace,
                Summary = message
            };

            NotifyListeners(entry);
        }
コード例 #21
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        public static void LogWarning(string warning)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Warning,
                Summary = warning
            };

            NotifyListeners(entry);
        }
コード例 #22
0
ファイル: SDKBatch.cs プロジェクト: cubski/Zombie
        private void StatusMessage(int idx, string Heading, string StatusMessage, int statusCode, bool IsError)
        {
            StatusEntry.EntryType t = StatusEntry.EntryType.Status;
            if(IsError) t = StatusEntry.EntryType.Error;

            var entry = new StatusEntry()
            {
                TypeOfEntry = t,
                Summary = Heading + "detected for index " + idx,
                Details = StatusMessage
            };

            entry.AddLine("Status Code:" + statusCode);

            StatusMgr.LogEntry(entry);
        }
コード例 #23
0
ファイル: SDKBatch.cs プロジェクト: cubski/Zombie
        public bool Run()
        {
            switch(_msg.RequestList.Count)
            {
                case 0:
                StatusMgr.LogError("No items in batch to process");
                return false;

                case 1:
                break;

                default:
                if (_iterator != null)
                {
                    StatusMgr.LogError("Iterators are only allowed in single request batches");
                    return false;
                }
                _msg.Attributes.OnError = SDK.ENRqOnError.roeContinue;
                break;
            }

            try
            {
                bool retVal = false;

                IteratorCall iterCall = null;

                do
                {
                    retVal = RunOneBatch(out iterCall);

                    if (iterCall != null)
                    {
                        if (!iterCall.iterator(iterCall.iteratorId, iterCall.remaining))
                        {
                            return false; //user cancelled
                        }
                    }
                }
                while (retVal == true && iterCall != null);

                return retVal;
            }
            catch (System.Runtime.InteropServices.COMException cex)
            {
                var entry = new StatusEntry()
                {
                    Summary = "Request Error",
                    TypeOfEntry = StatusEntry.EntryType.Error
                };
                entry.AddLine(cex.Message);

                try
                {
                    //This may not be the source of the error
                    //entry.AddLine(_msg.ToXMLString());

                    //this causes further COM errors
                    //entry.AddLine(_msg.Attributes.ResponseData.ToString());
                    entry.AddLine("Enable SDK logging for further diagnostics");
                }
                catch (Exception)
                {
                }

                StatusMgr.LogEntry(entry);

                return false;
            }
        }
コード例 #24
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        public static void LogError(string error)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary = error
            };

            NotifyListeners(entry);
        }
コード例 #25
0
ファイル: SDKBatch.cs プロジェクト: hellfirehd/Zombie
        private bool RunOneBatch(out IteratorCall _iterCall)
        {
            const string ERROR_CONTEXT = "QuickBooks query follow-up";

            _iterCall = null;

            var resp = _mgr.DoRequests(_msg);

            if (resp == null || resp.ResponseList == null)
            {
                throw new Exception("null response returned from batch");
            }

            if (resp.ResponseList.Count == 0)
            {
                throw new Exception("no response items returned from batch");
            }

            bool errors = false;

            var lstResponse = resp.ResponseList;

            for (int idx = 0; idx < lstResponse.Count; idx++)
            {
                var itm = lstResponse.GetAt(idx);

                if (itm == null)
                {
                    var entry = new StatusEntry()
                    {
                        TypeOfEntry = StatusEntry.EntryType.Error,
                        Summary     = "null reponse item encountered",
                        Details     = resp.ToXMLString()
                    };

                    StatusMgr.LogEntry(entry);

                    return(false);
                }

                ClosureSpec cls  = null;
                int         rqID = int.Parse(itm.RequestID);

                if (_clousures.ContainsKey(rqID))
                {
                    cls = _clousures[rqID];
                }

                if (itm.StatusCode == 0 || itm.StatusCode == 500)
                {
                    if (cls != null)
                    {
                        try
                        {
                            cls.success(itm.Detail);
                        }
                        catch (Exception ex)
                        {
                            StatusMgr.HandleException(ERROR_CONTEXT, ex);
                            return(false);
                        }
                    }

                    if (_iterator != null)
                    {
                        int iteratorRemaining = 0;

                        try
                        {
                            //iterator remaining count can be toxic, it
                            //iterator is not set up correctly
                            iteratorRemaining = itm.iteratorRemainingCount;
                        }
                        catch (System.Runtime.InteropServices.COMException)
                        {
                            StatusMgr.LogError("Iterator not properly initialized");
                        }

                        if (iteratorRemaining > 0)
                        {
                            _iterCall = new IteratorCall()
                            {
                                iterator   = _iterator,
                                iteratorId = itm.iteratorID,
                                remaining  = iteratorRemaining
                            };
                        }
                    }
                }
                else if (cls != null && cls.allowEmptyReturn &&
                         itm.StatusCode == 1)
                {
                    //process empty result
                    try
                    {
                        cls.success(null);
                    }
                    catch (Exception ex)
                    {
                        StatusMgr.HandleException(ERROR_CONTEXT, ex);
                        return(false);
                    }
                }
                else
                {
                    switch (itm.StatusSeverity.ToLower())
                    {
                    case "info":
                        StatusMgr.Trace(itm.StatusMessage);
                        if (cls != null)
                        {
                            try
                            {
                                cls.success(itm.Detail);
                            }
                            catch (Exception ex)
                            {
                                StatusMgr.HandleException(ERROR_CONTEXT, ex);
                                return(false);
                            }
                        }
                        break;

                    case "warning":
                    case "warn":
                        StatusMessage(idx, "Warning", itm.StatusMessage, itm.StatusCode, false);
                        if (cls != null)
                        {
                            try
                            {
                                cls.success(itm.Detail);
                            }
                            catch (Exception ex)
                            {
                                StatusMgr.HandleException(ERROR_CONTEXT, ex);
                                return(false);
                            }
                        }
                        break;

                    case "error":
                    default:
                        if (cls != null && cls.failure != null)
                        {
                            try
                            {
                                cls.failure(itm.StatusMessage, itm.StatusCode);
                            }
                            catch (Exception ex)
                            {
                                StatusMgr.HandleException(ERROR_CONTEXT, ex);
                                return(false);
                            }
                        }
                        else
                        {
                            StatusMessage(idx, "Error", itm.StatusMessage, itm.StatusCode, true);
                        }
                        errors = true;
                        break;
                    }
                }
                //end of response loop
            }
            return(errors == false);
        }
コード例 #26
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
 public static void LogEntry(StatusEntry entry)
 {
     NotifyListeners(entry);
 }
コード例 #27
0
ファイル: Safe.cs プロジェクト: cubski/Zombie
        /// <summary>
        /// SDK updates treat truncation as an error.  So it is important to trim
        /// values that are found to be too long
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static string LimitedString(string val, int maxLength, string reference)
        {
            if (val == null) return string.Empty;

            if (val.Length > maxLength)
            {
                var entry = new StatusEntry()
                {
                    TypeOfEntry = StatusEntry.EntryType.Warning,
                    Summary = "Data truncated",
                    Details = reference + " exceeds maximum length(" + maxLength
                        + "), value will be truncated"
                };

                StatusMgr.LogEntry(entry);

                return val.Substring(0, maxLength);
            }

            return val;
        }
コード例 #28
0
ファイル: StatusMgr.cs プロジェクト: cubski/Zombie
        public static void LogQBError(string context, string statusMessage, int statusCode)
        {
            var entry = new StatusEntry()
            {
                TypeOfEntry = StatusEntry.EntryType.Error,
                Summary = "QuickBooks Error:" + context,
                Details = statusMessage
            };

            entry.AddLine("Status Code:" + statusCode);

            NotifyListeners(entry);
        }
コード例 #29
0
ファイル: SDKConnection.cs プロジェクト: pkpjpm/Zombie
        private void HostQuerySuccess(SDK.IQBBase baseObj)
        {
            var respHost = baseObj as SDK.IHostRet;

            if (respHost == null)
            {
                string typeName = "null type";

                if (baseObj != null)
                {
                    typeName = baseObj.Type.GetAsString();
                }
                throw new Exception("1.0 host query failure: unexpected detail type:" + typeName);
            }

            var lstVersion = respHost.SupportedQBXMLVersionList;
            double candidateVersion = 0.0;
            string versionList = string.Empty;

            for (int idx = 0; idx < lstVersion.Count; idx++)
            {
                string svers = lstVersion.GetAt(idx);

                if (versionList != string.Empty)
                {
                    versionList += ", ";
                }

                versionList += svers;

                double dver = 0.0;

                if (!double.TryParse(svers, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out dver))
                {
                    StatusMgr.LogStatus("Unexpected SDK version:" + svers);

                    continue;
                }

                if (dver > candidateVersion && dver <= MAX_DESKTOP_QBXML_VERSION)
                {
                    candidateVersion = dver;
                }
            }

            if (candidateVersion == 0.0)
            {
                StatusMgr.FormatError("No compatible SDK version found, using {0}", MAX_DESKTOP_QBXML_VERSION);
                candidateVersion = MAX_DESKTOP_QBXML_VERSION;
            }

            _SDKMajorVersion = (short)candidateVersion;

            string minor = (candidateVersion - _SDKMajorVersion).ToString();

            if (minor.Length > 1)
            {
                minor = minor.Substring(2, minor.Length - 1);
                _SDKMinorVersion = short.Parse(minor);
            }
            else
            {
                _SDKMinorVersion = 0;
            }

            var successEntry = new StatusEntry()
            {
                Summary = "QuickBooks Connection Established",
                TypeOfEntry = StatusEntry.EntryType.Status
            };

            successEntry.AddLine(string.Format("{0} version {1}.{2}", Safe.Value(respHost.ProductName),
                    Safe.Value(respHost.MajorVersion), Safe.Value(respHost.MinorVersion)));

            successEntry.AddLine(string.Format("Supported qbXML versions:{0}", versionList));
            successEntry.AddLine(string.Format("Using version {0}.{1}", _SDKMajorVersion, _SDKMinorVersion));

            StatusMgr.LogEntry(successEntry);
        }
コード例 #30
0
        private void HostQuerySuccess(SDK.IQBBase baseObj)
        {
            var respHost = baseObj as SDK.IHostRet;

            if (respHost == null)
            {
                string typeName = "null type";

                if (baseObj != null)
                {
                    typeName = baseObj.Type.GetAsString();
                }
                throw new Exception("1.0 host query failure: unexpected detail type:" + typeName);
            }

            var    lstVersion       = respHost.SupportedQBXMLVersionList;
            double candidateVersion = 0.0;
            string versionList      = string.Empty;

            for (int idx = 0; idx < lstVersion.Count; idx++)
            {
                string svers = lstVersion.GetAt(idx);

                if (versionList != string.Empty)
                {
                    versionList += ", ";
                }

                versionList += svers;

                double dver = 0.0;

                if (!double.TryParse(svers, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out dver))
                {
                    StatusMgr.LogStatus("Unexpected SDK version:" + svers);

                    continue;
                }

                if (dver > candidateVersion && dver <= MAX_DESKTOP_QBXML_VERSION)
                {
                    candidateVersion = dver;
                }
            }

            if (candidateVersion == 0.0)
            {
                StatusMgr.FormatError("No compatible SDK version found, using {0}", MAX_DESKTOP_QBXML_VERSION);
                candidateVersion = MAX_DESKTOP_QBXML_VERSION;
            }

            _SDKMajorVersion = (short)candidateVersion;

            string minor = (candidateVersion - _SDKMajorVersion).ToString();

            if (minor.Length > 1)
            {
                minor            = minor.Substring(2, minor.Length - 1);
                _SDKMinorVersion = short.Parse(minor);
            }
            else
            {
                _SDKMinorVersion = 0;
            }

            var successEntry = new StatusEntry()
            {
                Summary     = "QuickBooks Connection Established",
                TypeOfEntry = StatusEntry.EntryType.Status
            };

            successEntry.AddLine(string.Format("{0} version {1}.{2}", Safe.Value(respHost.ProductName),
                                               Safe.Value(respHost.MajorVersion), Safe.Value(respHost.MinorVersion)));

            successEntry.AddLine(string.Format("Supported qbXML versions:{0}", versionList));
            successEntry.AddLine(string.Format("Using version {0}.{1}", _SDKMajorVersion, _SDKMinorVersion));

            StatusMgr.LogEntry(successEntry);
        }