Beispiel #1
0
        // 探测一个结果集在 dp2kernel 一侧是否已经存在
        bool LocationResultsetExists(string strLocation)
        {
            string strError = "";

            // 临时的SessionInfo对象
            SessionInfo session = new SessionInfo(this);

            try
            {
                this._app_down.Token.ThrowIfCancellationRequested();

                RmsChannel channel = session.Channels.GetChannel(this.WsUrl);
                if (channel == null)
                {
                    return(false);
                }

#if DETAIL_LOG
                this.WriteErrorLog("开始探测结果集 " + strLocation);
#endif
                Record[] searchresults = null;

                // 获得检索结果的浏览格式
                // 浅包装版本
                long lHitCount = channel.DoGetSearchResult(
                    "#" + strLocation,
                    0,
                    0,
                    "id",
                    "zh",
                    null,
                    out searchresults,
                    out strError);
                if (lHitCount == -1)
                {
                    if (channel.ErrorCode == ChannelErrorCode.NotFound)
                    {
                        return(false);
                    }
                    return(false);
                }

                return(true);
            }
            finally
            {
                session.CloseSession();
                session = null;
            }
        }
Beispiel #2
0
        protected void Session_End(Object sender, EventArgs e)
        {
            SessionInfo sessioninfo = (SessionInfo)Session["sessioninfo"];

            Session["sessioninfo"] = null;

            if (sessioninfo != null)
            {
                sessioninfo.CloseSession();

                // 减去计数
                // string strClientIP = HttpContext.Current.Request.UserHostAddress.ToString();
                OpacApplication app = (OpacApplication)Application["app"];
                if (app != null)
                {
                    app.IpTable.IncIpCount(sessioninfo.ClientIP, -1);
                }
            }
        }
Beispiel #3
0
    protected void Page_Load(object sender, EventArgs e)
    {
        if (WebUtil.PrepareEnvironment(this,
                                       ref app,
                                       ref sessioninfo) == false)
        {
            return;
        }

        // 是否登录?
        if (sessioninfo.UserID == "")
        {
            sessioninfo.UserID   = "public";
            sessioninfo.IsReader = false;
        }

        string strError = "";
        int    nRet     = 0;

#if NO
        SessionInfo temp_sessioninfo = new SessionInfo(app);
        temp_sessioninfo.UserID   = app.ManagerUserName;
        temp_sessioninfo.Password = app.ManagerPassword;
        temp_sessioninfo.IsReader = false;
#endif
        LibraryChannel channel = app.GetChannel();

        try
        {
            bool   bHintDisplayName = false; // []暗示为显示名
            string strDisplayName   = this.Request["displayName"];
            string strBarcode       = this.Request["barcode"];
            string strEncyptBarcode = Request.QueryString["encrypt_barcode"];

            string strText = "";

            // 如果为加密的条码形态
            if (String.IsNullOrEmpty(strEncyptBarcode) == false)
            {
                strBarcode = OpacApplication.DecryptPassword(strEncyptBarcode);
                if (strBarcode == null)
                {
                    strError = "encrypt_barcode参数值格式错误";
                    goto ERROR1;
                }
                bHintDisplayName = true;
                goto SEARCH_COMMENT;
            }

            {
                if (String.IsNullOrEmpty(strDisplayName) == false)
                {
                    if (strDisplayName.IndexOfAny(new char[] { '[', ']' }) != -1)
                    {
                        bHintDisplayName = true;
                    }
                    strDisplayName = strDisplayName.Replace("[", "").Trim();
                    strDisplayName = strDisplayName.Replace("]", "").Trim();
                }

                nRet = 0;
                string strReaderXml        = "";
                string strOutputReaderPath = "";

                if (String.IsNullOrEmpty(strDisplayName) == false)
                {
                    byte[] timestamp = null;

                    string[] results = null;
                    long     lRet    = // temp_sessioninfo.Channel.
                                       channel.GetReaderInfo(
                        null,
                        "@displayName:" + strDisplayName,
                        "xml",
                        out results,
                        out strOutputReaderPath,
                        out timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        goto ERROR1;
                    }
                    if (lRet == 0 && bHintDisplayName == true)
                    {
                        strBarcode = "";
                        goto SEARCH_COMMENT;
                    }
                    strReaderXml = results[0];

                    // CONTINUE1:
                    if (nRet == 0)
                    {
                        strBarcode = strDisplayName;
                    }
                }

                // SEARCH_BARCODE:
                if (nRet == 0 && String.IsNullOrEmpty(strBarcode) == false)
                {
                    strReaderXml = "";
                    byte[] timestamp = null;

                    string[] results = null;
                    long     lRet    = // temp_sessioninfo.Channel.
                                       channel.GetReaderInfo(
                        null,
                        strBarcode,
                        "xml",
                        out results,
                        out strOutputReaderPath,
                        out timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        goto ERROR1;
                    }
                    if (lRet == 0)
                    {
                        goto SEARCH_COMMENT;
                    }
                    strReaderXml = results[0];
                }

                if (nRet == 0)
                {
                    /*
                     * strError = "读者显示名或者证条码号 '" + strDisplayName + "' 不存在";
                     * goto ERROR1;
                     * */
                    if (String.IsNullOrEmpty(strBarcode) == true)
                    {
                        strBarcode = strDisplayName;
                    }
                    goto SEARCH_COMMENT;
                }

                XmlDocument readerdom = null;
                nRet = OpacApplication.LoadToDom(strReaderXml,
                                                 out readerdom,
                                                 out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录 '" + strOutputReaderPath + "' 进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                strDisplayName = DomUtil.GetElementText(readerdom.DocumentElement,
                                                        "displayName");

                strBarcode = DomUtil.GetElementInnerXml(readerdom.DocumentElement,
                                                        "barcode");
            }
SEARCH_COMMENT:
            strText = strDisplayName;
            if (String.IsNullOrEmpty(strText) == true)
            {
                strText = strBarcode;
            }

            this.Label_name.Text = strText;

            string strRecipient = "";

            /*
             * if (String.IsNullOrEmpty(strDisplayName) == false)
             * {
             *  if (strDisplayName.IndexOf("[") == -1)
             *      strRecipient = "[" + strDisplayName + "]";
             *  else
             *      strRecipient = strDisplayName;
             *  if (String.IsNullOrEmpty(strEncyptBarcode) == false)
             *      strRecipient += " encrypt_barcode:" + strEncyptBarcode;
             * }
             * else
             *  strRecipient = strBarcode;
             * */
            strRecipient = BoxesInfo.BuildOneAddress(strDisplayName, strBarcode);

            string strSendMessageUrl = "./message.aspx?recipient=" + HttpUtility.UrlEncode(strRecipient);
            this.Button_sendMessage.OnClientClick = "window.open('" + strSendMessageUrl + "','_blank'); return cancelClick();";

            LoginState loginstate = GlobalUtil.GetLoginState(this.Page);
            if (loginstate == LoginState.NotLogin || loginstate == LoginState.Public)
            {
                this.Button_sendMessage.Enabled = false;
            }

            this.BrowseSearchResultControl1.Title = strText + " 所发表的书评";

            if (String.IsNullOrEmpty(strEncyptBarcode) == false)
            {
                this.Image_photo.ImageUrl = "./getphoto.aspx?encrypt_barcode=" + HttpUtility.UrlEncode(strEncyptBarcode) + "&displayName=" + HttpUtility.UrlEncode(strDisplayName);
            }
            else
            {
                this.Image_photo.ImageUrl = "./getphoto.aspx?barcode=" + HttpUtility.UrlEncode(strBarcode);
            }

            this.Image_photo.Width  = 128;
            this.Image_photo.Height = 128;

            if (this.IsPostBack == false)
            {
                string strXml = "";
                if (String.IsNullOrEmpty(strDisplayName) == false &&
                    String.IsNullOrEmpty(strBarcode) == false)
                {
                    // 创建评注记录XML检索式
                    // 用作者和作者显示名共同限定检索
                    nRet = ItemSearchControl.BuildCommentQueryXml(
                        app,
                        strDisplayName,
                        strBarcode,
                        "<全部>",
                        15000,   // app.SearchMaxResultCount
                        true,
                        out strXml,
                        out strError);
                    if (nRet == -1)
                    {
                        goto ERROR1;
                    }
                }
                else if (String.IsNullOrEmpty(strBarcode) == false)
                {
                    // 创建XML检索式
                    nRet = ItemSearchControl.BuildQueryXml(
                        this.app,
                        "comment",
                        strBarcode,
                        "<全部>",
                        "作者",
                        "exact",
                        15000,   // app.SearchMaxResultCount
                        true,
                        out strXml,
                        out strError);
                    if (nRet == -1)
                    {
                        goto ERROR1;
                    }
                }
                else if (String.IsNullOrEmpty(strDisplayName) == false)
                {
                    // 创建XML检索式
                    nRet = ItemSearchControl.BuildQueryXml(
                        this.app,
                        "comment",
                        strDisplayName,
                        "<全部>",
                        "作者显示名",
                        "exact",
                        15000,   // app.SearchMaxResultCount
                        true,
                        out strXml,
                        out strError);
                    if (nRet == -1)
                    {
                        goto ERROR1;
                    }
                }
                else
                {
                    strError = "strBarcode和strDisplayName均为空,无法进行检索";
                    goto ERROR1;
                }

                string strResultSetName = "opac_userinfo";

                // sessioninfo.Channel.
                channel.Idle += new IdleEventHandler(channel_Idle);
                try
                {
                    long lRet = //sessioninfo.Channel.
                                channel.Search(
                        null,
                        strXml,
                        strResultSetName,
                        "", // strOutputStyle
                        out strError);
                    if (lRet == -1)
                    {
                        goto ERROR1;
                    }

                    // not found
                    if (lRet == 0)
                    {
                        this.BrowseSearchResultControl1.Title = strText + " 没有发表过任何书评";
                    }
                    else
                    {
                        this.BrowseSearchResultControl1.ResultSetName = strResultSetName;
                        this.BrowseSearchResultControl1.ResultCount   = (int)lRet;
                        this.BrowseSearchResultControl1.StartIndex    = 0;
                    }
                    return;
                }
                finally
                {
                    //sessioninfo.Channel.
                    channel.Idle -= new IdleEventHandler(channel_Idle);
                }
            }
            return;

ERROR1:
            Response.Write(HttpUtility.HtmlEncode(strError));
            Response.End();
        }
        finally
        {
#if NO
            temp_sessioninfo.CloseSession();
#endif
            app.ReturnChannel(channel);
        }
    }
Beispiel #4
0
        // 创建一个馆藏地的限定结果集
        void CreateOneLocationResultset(string strLocation)
        {
            string strError = "";

            // 临时的SessionInfo对象
            SessionInfo session = new SessionInfo(this);
            try
            {
                string strQueryXml = "";
                // 构造检索实体库的 XML 检索式
                // return:
                //      -1  出错
                //      0   没有发现任何实体库定义
                //      1   成功
                int nRet = this.BuildSearchItemQuery(
    "<全部>",
    strLocation + "/",
    -1,
    "馆藏地点",
    "left",
    "zh",
    "", // strSearchStyle,
                out strQueryXml,
                out strError);
                if (nRet == -1)
                    goto ERROR1;
                if (nRet == 0)
                    return;

                this._app_down.Token.ThrowIfCancellationRequested();

                RmsChannel channel = session.Channels.GetChannel(this.WsUrl);
                if (channel == null)
                {
                    strError = "get channel error";
                    goto ERROR1;
                }

#if DETAIL_LOG
                this.WriteErrorLog("开始检索");
#endif
                long lHitCount = channel.DoSearch(strQueryXml,
    "default",
    "", // strOutputStyle,
    out strError);
                if (lHitCount == -1)
                    goto ERROR1;

                if (lHitCount == 0)
                {
                    // 没有命中任何记录,也要继续后面的处理
                }

                this._app_down.Token.ThrowIfCancellationRequested();

                DpResultSet resultset = new DpResultSet(true);

                try
                {
                    if (lHitCount > 0)
                    {
                        nRet = GetResultset(channel,
                    "default",
                    resultset,
                    out strError);
                        if (nRet == -1)
                            goto ERROR1;
                    }

                    // 写入 dp2kernel 成为永久结果集
                    nRet = UploadPermanentResultset(channel,
            strLocation,
            resultset,
            out strError);
                    if (nRet == -1)
                        goto ERROR1;
                }
                finally
                {
                    resultset.Close();
                }

                return;
            }
            finally
            {
                session.CloseSession();
                session = null;
            }

        ERROR1:
            this.WriteErrorLog("馆藏地结果集创建出错: " + strError);
            return;
        }
Beispiel #5
0
        // 探测一个结果集在 dp2kernel 一侧是否已经存在
        bool LocationResultsetExists(string strLocation)
        {
            string strError = "";

            // 临时的SessionInfo对象
            SessionInfo session = new SessionInfo(this);
            try
            {
                this._app_down.Token.ThrowIfCancellationRequested();

                RmsChannel channel = session.Channels.GetChannel(this.WsUrl);
                if (channel == null)
                    return false;

#if DETAIL_LOG
                this.WriteErrorLog("开始探测结果集 " + strLocation);
#endif
                Record[] searchresults = null;

                // 获得检索结果的浏览格式
                // 浅包装版本
                long lHitCount = channel.DoGetSearchResult(
                    "#" + strLocation,
                    0,
                    0,
                    "id",
                    "zh",
                    null,
                    out searchresults,
                    out strError);
                if (lHitCount == -1)
                {
                    if (channel.ErrorCode == ChannelErrorCode.NotFound)
                        return false;
                    return false;
                }

                return true;
            }
            finally
            {
                session.CloseSession();
                session = null;
            }
        }
Beispiel #6
0
        // 获得图书摘要信息
        // 调用时不需要SessionInfo
        public int GetBiblioSummary(string strItemBarcode,
            string strConfirmItemRecPath,
            string strBiblioRecPathExclude,
            int nMaxLength,
            out string strBiblioRecPath,
            out string strSummary,
            out string strError)
        {
            strError = "";
            strSummary = "";
            strBiblioRecPath = "";

            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this);
            // 模拟一个账户
            Account account = new Account();
            account.LoginName = "内部调用";
            account.Password = "";
            account.Rights = "getbibliosummary";

            account.Type = "";
            account.Barcode = "";
            account.Name = "内部调用";
            account.UserID = "内部调用";
            account.RmsUserName = this.ManagerUserName;
            account.RmsPassword = this.ManagerPassword;

            sessioninfo.Account = account;
            try
            {
                RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl);
                if (channel == null)
                {
                    strError = "get channel error";
                    return -1;
                }

                LibraryServerResult result = this.GetBiblioSummary(
                    sessioninfo,
                    channel,
                    strItemBarcode,
                    strConfirmItemRecPath,
                    strBiblioRecPathExclude,
                    out strBiblioRecPath,
                    out strSummary);
                if (result.Value == -1)
                {
                    strError = result.ErrorInfo;
                    return -1;
                }
                else
                {
                    if (nMaxLength != -1)
                    {
                        // 截断
                        if (strSummary.Length > nMaxLength)
                            strSummary = strSummary.Substring(0, nMaxLength) + "...";
                    }
                }
            }
            finally
            {
                sessioninfo.CloseSession();
                sessioninfo = null;
            }

            return 0;
        }
Beispiel #7
0
        void submit_button_Click(object sender, EventArgs e)
        {
            string strError = "";

            OpacApplication app         = (OpacApplication)this.Page.Application["app"];
            SessionInfo     sessioninfo = (SessionInfo)this.Page.Session["sessioninfo"];

            string strCreator = sessioninfo.UserID;

            // 先创建一条书目记录
            TextBox biblio_title     = (TextBox)this.FindControl("edit_biblio_title");
            TextBox biblio_author    = (TextBox)this.FindControl("edit_biblio_author");
            TextBox biblio_publisher = (TextBox)this.FindControl("edit_biblio_publisher");
            TextBox biblio_isbn      = (TextBox)this.FindControl("edit_biblio_isbn");
            TextBox biblio_price     = (TextBox)this.FindControl("edit_biblio_price");
            TextBox biblio_summary   = (TextBox)this.FindControl("edit_biblio_summary");

            // 检查必备字段
            if (String.IsNullOrEmpty(biblio_title.Text) == true)
            {
                strError = "尚未输入书名/刊名";
                goto ERROR1;
            }

            DropDownList store_dbname = (DropDownList)this.FindControl("store_dbname");

            string strBiblioDbName = store_dbname.SelectedValue;

            if (String.IsNullOrEmpty(strBiblioDbName) == true)
            {
                strError = "尚未选定目标库";
                goto ERROR1;
            }

            string strBiblioRecPath = "";
            string strMarcSyntax    = "";
            string strMARC          = "";

            // 得到目标书目库的MARC格式
            ItemDbCfg cfg = app.GetBiblioDbCfg(strBiblioDbName);

            if (cfg == null)
            {
                strError = "目标库 '" + strBiblioDbName + "' 不是系统定义的的书目库";
                goto ERROR1;
            }

            strMarcSyntax = cfg.BiblioDbSyntax;

            int nRet = BuildBiblioRecord(
                strMarcSyntax,
                biblio_title.Text,
                biblio_author.Text,
                biblio_publisher.Text,
                biblio_isbn.Text,
                biblio_price.Text,
                biblio_summary.Text,
                strCreator,
                out strMARC,
                out strError);

            if (nRet == -1)
            {
                goto ERROR1;
            }

            // 保存
            // 将MARC格式转换为XML格式
            nRet = MarcUtil.Marc2Xml(
                strMARC,
                strMarcSyntax,
                out string strXml,
                out strError);
            if (nRet == -1)
            {
                goto ERROR1;
            }

#if NO
            SessionInfo temp_sessioninfo = new SessionInfo(app);
            temp_sessioninfo.UserID   = app.ManagerUserName;
            temp_sessioninfo.Password = app.ManagerPassword;
            temp_sessioninfo.IsReader = false;
#endif

            string strOutputBiblioRecPath = "";

            LibraryChannel channel = sessioninfo.GetChannel(true);
            try
            {
                strBiblioRecPath = strBiblioDbName + "/?";


                long lRet = // temp_sessioninfo.Channel.
                            channel.SetBiblioInfo(
                    null,
                    "new",
                    strBiblioRecPath,
                    "xml",
                    strXml,
                    null,
                    "",
                    out strOutputBiblioRecPath,
                    out byte[] baOutputTimestamp,
                    out strError);
                if (lRet == -1)
                {
                    strError = "创建书目记录发生错误: " + strError;
                    goto ERROR1;
                }
            }
            finally
            {
#if NO
                temp_sessioninfo.CloseSession();
                temp_sessioninfo = null;
#endif
                sessioninfo.ReturnChannel(channel);
            }

            // 清除每个输入域的内容
            biblio_title.Text     = "";
            biblio_author.Text    = "";
            biblio_publisher.Text = "";
            biblio_isbn.Text      = "";
            biblio_summary.Text   = "";
            biblio_price.Text     = "";

            strBiblioRecPath = strOutputBiblioRecPath;

            CommentControl commentcontrol = (CommentControl)this.FindControl("commentcontrol");
            // 创建评注记录
            if (String.IsNullOrEmpty(commentcontrol.EditTitle) == false ||
                String.IsNullOrEmpty(commentcontrol.EditContent) == false)
            {
                string strWarning = "";
                commentcontrol.BiblioRecPath = strBiblioRecPath;

                nRet = commentcontrol.DoSubmit(
                    out strWarning,
                    out strError);
                if (nRet == -1)
                {
                    goto ERROR1;
                }
                if (String.IsNullOrEmpty(strWarning) == false)
                {
                    this.SetDebugInfo("warninginfo", strWarning);
                }
            }

            string strUrl = "./book.aspx?bibliorecpath="
                            + HttpUtility.UrlEncode(strBiblioRecPath);
            string strText = "新的荐购书目记录创建成功。点击此处可查看:<a href='"
                             + strUrl
                             + "' target='_blank'>"
                             + strUrl
                             + "</a>";
            SetInfo(strText);
            this.SetDebugInfo("succeedinfo", strText);
            return;

ERROR1:
            SetDebugInfo("errorinfo", strError);
        }
Beispiel #8
0
        // 创建书目过滤结果集
        // 书目过滤结果集的特点是,直接针对书目库进行检索,在 dp2kernel 一端就成为永久结果集
        void CreateBiblioFilterResultset(string strQueryXml,
                                         string strResultsetName)
        {
            string strError = "";

            // TODO: 要设法把临时的 Session 对象管理起来。在 Application down 的时候,主动对这些 session 的 Channels 执行 stop
            // 临时的 SessionInfo 对象
            SessionInfo session = new SessionInfo(this);

            try
            {
                this._app_down.Token.ThrowIfCancellationRequested();

                // RmsChannel channel = session.Channels.GetChannel(this.WsUrl);
                RmsChannel channel = _slowChannelList.GetChannel(session.Channels, this.WsUrl);
                if (channel == null)
                {
                    strError = "get channel null error";
                    goto ERROR1;
                }

                try
                {
#if DETAIL_LOG
                    this.WriteErrorLog("开始检索");
#endif
                    long lHitCount = channel.DoSearch(strQueryXml,
                                                      "#~" + strResultsetName,
                                                      "", // strOutputStyle,
                                                      out strError);
                    if (lHitCount == -1)
                    {
                        goto ERROR1;
                    }

                    if (lHitCount == 0)
                    {
                        // 没有命中任何记录,也要继续后面的处理

                        // 结果集为空,也要在 dp2kernel 端创建一个结果集对象
                        long lRet = channel.DoWriteRecords(null,
                                                           new RecordBody[0],
                                                           "createResultset,name:#" + strResultsetName + ",clear,permanent",
                                                           out RecordBody[] results,
                                                           out strError);
                        if (lRet == -1)
                        {
                            goto ERROR1;
                        }
                        return;
                    }

                    this._app_down.Token.ThrowIfCancellationRequested();

                    // 最后一次执行改名、排序
                    {
                        long lRet = channel.DoWriteRecords(null,
                                                           null,
                                                           "renameResultset,oldname:#~" + strResultsetName + ",newname:#" + strResultsetName + ",permanent,sort",
                                                           out RecordBody[] results,
                                                           out strError);
                        if (lRet == -1)
                        {
                            goto ERROR1;
                        }
                    }

                    return;
                }
                finally
                {
                    _slowChannelList.ReturnChannel(session.Channels, channel);
                }
            }
            finally
            {
                session.CloseSession();
                session = null;
            }

ERROR1:
            this.WriteErrorLog("书目 '" + strResultsetName + "' 结果集创建出错: " + strError);
        }
Beispiel #9
0
        // 创建一个馆藏地的限定结果集
        void CreateOneLocationResultset(string strLocation)
        {
            string strError = "";

            // TODO: 要设法把临时的 Session 对象管理起来。在 Application down 的时候,主动对这些 session 的 Channels 执行 stop
            // 临时的 SessionInfo 对象
            SessionInfo session = new SessionInfo(this);

            try
            {
                // 构造检索实体库的 XML 检索式
                // return:
                //      -1  出错
                //      0   没有发现任何实体库定义
                //      1   成功
                int nRet = this.BuildSearchItemQuery(
                    "<全部>",
                    strLocation + "/",
                    -1,
                    "馆藏地点",
                    "left",
                    "zh",
                    "", // strSearchStyle,
                    out string strQueryXml,
                    out strError);
                if (nRet == -1)
                {
                    goto ERROR1;
                }
                if (nRet == 0)
                {
                    return;
                }

                this._app_down.Token.ThrowIfCancellationRequested();

                // RmsChannel channel = session.Channels.GetChannel(this.WsUrl);
                RmsChannel channel = _slowChannelList.GetChannel(session.Channels, this.WsUrl);
                if (channel == null)
                {
                    strError = "get channel null error";
                    goto ERROR1;
                }

                try
                {
#if DETAIL_LOG
                    this.WriteErrorLog("开始检索");
#endif
                    long lHitCount = channel.DoSearch(strQueryXml,
                                                      "default",
                                                      "", // strOutputStyle,
                                                      out strError);
                    if (lHitCount == -1)
                    {
                        goto ERROR1;
                    }

                    if (lHitCount == 0)
                    {
                        // 没有命中任何记录,也要继续后面的处理
                    }

                    this._app_down.Token.ThrowIfCancellationRequested();

                    DpResultSet resultset = new DpResultSet(true);

                    try
                    {
                        if (lHitCount > 0)
                        {
                            nRet = GetResultset(channel,
                                                "default",
                                                resultset,
                                                out strError);
                            if (nRet == -1)
                            {
                                goto ERROR1;
                            }
                        }

                        // 写入 dp2kernel 成为永久结果集
                        nRet = UploadPermanentResultset(channel,
                                                        strLocation,
                                                        resultset,
                                                        out strError);
                        if (nRet == -1)
                        {
                            goto ERROR1;
                        }
                    }
                    finally
                    {
                        resultset.Close();
                    }
                }
                finally
                {
                    _slowChannelList.ReturnChannel(session.Channels, channel);
                }

                return;
            }
            finally
            {
                session.CloseSession();
                session = null;
            }

ERROR1:
            this.WriteErrorLog("馆藏地 '" + strLocation + "' 结果集创建出错: " + strError);
            return;
        }
Beispiel #10
0
        // 重设密码
        // parameters:
        //      strParameters   参数字符串。如果 queryword 使用 NB: 形态,注意要这样使用 NB:姓名|,因为这是采用前方一致检索的,如果没有竖线部分,可能会匹配上不该命中的较长的名字
        //      strMessageTempate   消息文字模板。其中可以使用 %name% %barcode% %temppassword% %expiretime% %period% 等宏
        //      strMessage  返回拟发送给读者的消息文字
        // return:
        //      -2  读者的图书馆账户尚未注册手机号
        //      -1  出错
        //      0   因为条件不具备功能没有成功执行
        //      1   功能成功执行
        public int ResetPassword(
            // string strLibraryCodeList,
            string strParameters,
            string strMessageTemplate,
            out string strMessage,
            out string strError)
        {
            strError = "";
            strMessage = "";

            MessageInterface external_interface = this.GetMessageInterface("sms");

            Hashtable parameters = StringUtil.ParseParameters(strParameters, ',', '=');
            string strQueryWord = (string)parameters["queryword"];
            string strPatronBarcodeParam = (string)parameters["barcode"];
            string strNameParam = (string)parameters["name"];
            string strTelParam = (string)parameters["tel"];
            string strLibraryCodeList = (string)parameters["librarycode"];  // 控制检索读者记录的范围

            int nMaxHitCount = 10;

            bool bReturnMessage = false;
            string strStyle = (string)parameters["style"];
            if (StringUtil.IsInList("returnMessage", strStyle) == true)
            {
                // 直接给调用者返回拟发送到手机短信的内容。要求调用者具有特殊权限才行,要求在调用本函数前判断好。
                bReturnMessage = true;
            }
            else
            {
                if (external_interface == null)
                {
                    strError = "当前系统尚未配置短消息 (sms) 接口,无法进行重设密码的操作";
                    return -1;
                }
            }

            if (string.IsNullOrEmpty(strQueryWord) == true)
            {
                strError = "缺乏 queryword 参数";
                return -1;
            }
            if (bReturnMessage == false && string.IsNullOrEmpty(strNameParam) == true)
            {
                strError = "缺乏 name 参数";
                return -1;
            }
            if (string.IsNullOrEmpty(strTelParam) == true)
            {
                strError = "缺乏 tel 参数";
                return -1;
            }

            // 判断电话号码是否为手机号码
            if (strTelParam.Length != 11)
            {
                strError = "所提供的电话号码应该是 11 位的手机号码";
                return 0;
            }

            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this);
            try
            {
                RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl);
                if (channel == null)
                {
                    strError = "get channel error";
                    return -1;
                }

                List<KernelRecord> records = null;

                // 获得读者记录
                // return:
                //      -2  当前没有配置任何读者库,或者可以操作的读者库
                //      -1  error
                //      0   not found
                //      1   命中1条
                //      >1  命中多于1条
                int nRet = this.GetReaderRecXmlForLogin(
                    channel,
                    strLibraryCodeList,
                    strQueryWord,
                    nMaxHitCount,
                    "id,xml,timestamp",
                    out records,
                    out strError);
                if (nRet == -1 || nRet == -2)
                {
                    strError = "以登录名 '" + strQueryWord + "' 检索读者记录出错: " + strError;
                    return -1;
                }
                if (nRet == 0)
                {
                    strError = "读者帐户 '" + strQueryWord + "' 不存在";
                    return 0;
                }
#if NO
                if (nRet > 1)
                {
                    strError = "登录名 '" + strLoginName + "' 所匹配的帐户多于一个";
                    return 0;
                }
#endif
                List<KernelRecord> results = null;

                // 筛选读者记录
                // return:
                //      -2  尚未注册手机号
                //      -1  出错
                //      0   完成筛选
                nRet = FilterPatron(records,
            strNameParam,
            strPatronBarcodeParam,
            strTelParam,
            out results,
            out strError);
                if (nRet == -1)
                    return -1;

                if (results.Count == 0)
                {
                    if (nRet == -2)
                    {
                        strError = "读者帐户 '" + strQueryWord + "' " + strError;
                        return -2;
                    }

                    strError = "符合条件的读者帐户 '" + strQueryWord + "' 不存在";
                    return 0;
                }

                XmlDocument output_dom = new XmlDocument();
                output_dom.LoadXml("<root />");

                foreach (KernelRecord record in results)
                {
                    string strLibraryCode = "";
                    // 获得读者库的馆代码
                    // return:
                    //      -1  出错
                    //      0   成功
                    nRet = GetLibraryCode(
                        record.RecPath,
                        out strLibraryCode,
                        out strError);
                    if (nRet == -1)
                        return -1;

                    XmlDocument readerdom = null;
                    nRet = LibraryApplication.LoadToDom(record.Xml,
                        out readerdom,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                        return -1;
                    }

                    // 观察 password 元素的 lastResetTime 属性,需在规定的时间长度以外才能再次进行重设
                    DateTime end;
                    // 观察在 password 元素 tempPasswordExpire 属性中残留的失效期,必须在这个时间以后才能进行本次操作
                    // parameters:
                    //      now 当前时间。本地时间
                    // return:
                    //      -1  出错
                    //      0   已经过了失效期
                    //      1   还在失效期以内
                    nRet = CheckOldExpireTime(readerdom,
                        this.Clock.Now,
                        out end,
                        out strError);
                    if (nRet == -1)
                        return -1;
                    if (nRet == 1)
                    {
                        strError = "本次重设密码的操作距离上次操作间隔不足一小时,操作被拒绝。请在 " + end.ToShortTimeString() + " 以后再进行操作";
                        return 0;
                    }

                    string strBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode");
                    string strRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID");
                    string strName = DomUtil.GetElementText(readerdom.DocumentElement, "name");

                    // 重新设定一个密码
                    Random rnd = new Random();
                    string strReaderTempPassword = rnd.Next(1, 999999).ToString();

                    DateTime expire = this.Clock.Now + new TimeSpan(1, 0, 0);   // 本地时间
                    string strExpireTime = DateTimeUtil.Rfc1123DateTimeStringEx(expire);

                    if (bReturnMessage == true)
                    {
                        XmlElement node = output_dom.CreateElement("patron");
                        output_dom.DocumentElement.AppendChild(node);

                        // 直接给调用者返回消息内容。消息内容中有临时密码,属于敏感信息,要求调用者具有特殊权限才行。

                        DomUtil.SetElementText(node, "tel", strTelParam);
                        DomUtil.SetElementText(node, "barcode", strBarcode);
                        DomUtil.SetElementText(node, "name", strName);
                        DomUtil.SetElementText(node, "tempPassword", strReaderTempPassword);
                        DomUtil.SetElementText(node, "expireTime", expire.ToLongTimeString());
                        DomUtil.SetElementText(node, "period", "一小时");
                        DomUtil.SetElementText(node, "refID", strRefID);    // 在所提供的姓名或者电话号码命中不止一条读者记录的情形,调用者后面使用读者记录的 refID 来绑定特别重要。
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(strMessageTemplate) == true)
                            strMessageTemplate = "%name% 您好!\n您的读者帐户(证条码号为 %barcode%)已设临时密码 %temppassword%,在 %period% 内登录会成为正式密码";

                        string strBody = strMessageTemplate.Replace("%barcode%", strBarcode)
                            .Replace("%name%", strName)
                            .Replace("%temppassword%", strReaderTempPassword)
                            .Replace("%expiretime%", expire.ToLongTimeString())
                            .Replace("%period%", "一小时");
                        // string strBody = "读者(证条码号) " + strBarcode + " 的帐户密码已经被重设为 " + strReaderNewPassword + "";

                        // 向手机号码发送短信
                        {
                            // 发送消息
                            try
                            {
                                // 发送一条消息
                                // parameters:
                                //      strPatronBarcode    读者证条码号
                                //      strPatronXml    读者记录XML字符串。如果需要除证条码号以外的某些字段来确定消息发送地址,可以从XML记录中取
                                //      strMessageText  消息文字
                                //      strError    [out]返回错误字符串
                                // return:
                                //      -1  发送失败
                                //      0   没有必要发送
                                //      >=1   发送成功,返回实际发送的消息条数
                                nRet = external_interface.HostObj.SendMessage(
                                    strBarcode,
                                    readerdom.DocumentElement.OuterXml,
                                    strBody,
                                    strLibraryCode,
                                    out strError);
                            }
                            catch (Exception ex)
                            {
                                strError = external_interface.Type + " 类型的外部消息接口Assembly中SendMessage()函数抛出异常: " + ex.Message;
                                nRet = -1;
                            }
                            if (nRet == -1)
                            {
                                strError = "向读者 '" + strBarcode + "' 发送" + external_interface.Type + " message时出错: " + strError;
                                if (this.Statis != null)
                                    this.Statis.IncreaseEntryValue(
                                    strLibraryCode,
                                    "重设密码通知",
                                    external_interface.Type + " message 重设密码通知消息发送错误数",
                                    1);
                                this.WriteErrorLog(strError);
                                return -1;
                            }
                            else
                            {
                                if (this.Statis != null)
                                    this.Statis.IncreaseEntryValue(
                strLibraryCode,
                "重设密码通知",
                external_interface.Type + " message 重设密码通知消息发送数",
                nRet);  // 短信条数可能多于次数
                                if (this.Statis != null)
                                    this.Statis.IncreaseEntryValue(strLibraryCode,
                                    "重设密码通知",
                                    external_interface.Type + " message 重设密码通知人数",
                                    1);
                            }
                        }
                    }

                    byte[] output_timestamp = null;
                    nRet = ChangeReaderTempPassword(
            sessioninfo,
            record.RecPath,
            readerdom,
            strReaderTempPassword,
            strExpireTime,
            record.Timestamp,
            out output_timestamp,
            out strError);
                    if (nRet == -1)
                        return -1;  // 此时短信已经发出,但临时密码并未修改成功
                }

                if (StringUtil.IsInList("returnMessage", strStyle) == true)
                    strMessage = output_dom.DocumentElement.OuterXml;
            }
            finally
            {
                sessioninfo.CloseSession();
                sessioninfo = null;
            }

            if (bReturnMessage == false)
                strError = "临时密码已通过短信方式发送到手机 " + strTelParam + "。请按照手机短信提示进行操作";
            return 1;
        }
Beispiel #11
0
        public int LoadCfg(
            bool bReload,
            string strDataDir,
            string strHostDir,  // 为了脚本编译时候获得dll目录
            out string strError)
        {
            strError = "";
            int nRet = 0;
            LibraryApplication app = this;  // new CirculationApplication();

            // this.m_lock.AcquireWriterLock(m_nLockTimeout);
            this.LockForWrite();    // 2016/10/16
            try
            {

                // 装载配置文件的过程,只能消除以前的 StartError 挂起状态,其他状态是无法消除的
                // 本函数过程也约定好,只进行 StartError 挂起,不做其他挂起
#if NO
            if (app.HangupReason == LibraryServer.HangupReason.StartingError)
                app.HangupReason = LibraryServer.HangupReason.None;
#endif
                if (app.HangupList.Count > 0)
                {
                    ClearHangup("StartingError");
                }
                try
                {
                    DateTime start = DateTime.Now;

                    this.DataDir = strDataDir;
                    this.HostDir = strHostDir;

                    string strFileName = PathUtil.MergePath(strDataDir, "library.xml");
                    string strBinDir = strHostDir;  //  PathUtil.MergePath(strHostDir, "bin");
                    string strCfgDir = PathUtil.MergePath(strDataDir, "cfgs");
                    string strCfgMapDir = PathUtil.MergePath(strDataDir, "cfgsmap");
                    string strLogDir = PathUtil.MergePath(strDataDir, "log");
                    string strOperLogDir = PathUtil.MergePath(strDataDir, "operlog");
                    string strZhengyuanDir = PathUtil.MergePath(strDataDir, "zhengyuan");
                    string strDkywDir = PathUtil.MergePath(strDataDir, "dkyw");
                    string strPatronReplicationDir = PathUtil.MergePath(strDataDir, "patronreplication");
                    string strStatisDir = PathUtil.MergePath(strDataDir, "statis");
                    string strSessionDir = PathUtil.MergePath(strDataDir, "session");
                    string strColumnDir = PathUtil.MergePath(strDataDir, "column");
                    string strTempDir = PathUtil.MergePath(strDataDir, "temp");

                    app.m_strFileName = strFileName;

                    app.CfgDir = strCfgDir;

                    app.CfgMapDir = strCfgMapDir;
                    PathUtil.CreateDirIfNeed(app.CfgMapDir);	// 确保目录创建


                    // log
                    app.LogDir = strLogDir;	// 日志存储目录
                    PathUtil.CreateDirIfNeed(app.LogDir);	// 确保目录创建

                    // zhengyuan 一卡通
                    app.ZhengyuanDir = strZhengyuanDir;
                    PathUtil.CreateDirIfNeed(app.ZhengyuanDir);	// 确保目录创建

                    // dkyw 一卡通
                    app.DkywDir = strDkywDir;
                    PathUtil.CreateDirIfNeed(app.DkywDir);	// 确保目录创建

                    // patron replication
                    app.PatronReplicationDir = strPatronReplicationDir;
                    PathUtil.CreateDirIfNeed(app.PatronReplicationDir);	// 确保目录创建


                    // statis 统计文件
                    app.StatisDir = strStatisDir;
                    PathUtil.CreateDirIfNeed(app.StatisDir);	// 确保目录创建

                    // session临时文件
                    app.SessionDir = strSessionDir;
                    PathUtil.CreateDirIfNeed(app.SessionDir);	// 确保目录创建

                    if (bReload == false)
                        CleanSessionDir(this.SessionDir);

                    // 各种临时文件
                    app.TempDir = strTempDir;
                    PathUtil.CreateDirIfNeed(app.TempDir);	// 确保目录创建

                    if (bReload == false)
                    {
#if NO
                    try
                    {
                        string strTempFileName = Path.GetTempFileName();
                        File.Delete(strTempFileName);
                        string strTempDir1 = Path.GetDirectoryName(strTempFileName);
                        long count = 0;
                        long size = PathUtil.GetAllFileSize(strTempDir1, ref count);
                        app.WriteErrorLog("系统临时文件目录 " + Path.GetTempPath() + " 内的全部临时文件尺寸为 " + size.ToString() + ", 文件个数为 " + count.ToString());
                    }
                    catch
                    {
                    }
#endif

#if NO
                    if (PathUtil.TryClearDir(app.TempDir) == false)
                        app.WriteErrorLog("清除临时文件目录 " + app.TempDir + " 时出错");
#endif
                        try
                        {
                            PathUtil.ClearDir(app.TempDir);
                        }
                        catch (Exception ex)
                        {
                            app.WriteErrorLog("清除临时文件目录 " + app.TempDir + " 时出现异常: " + ExceptionUtil.GetDebugText(ex));
                        }
                    }

                    this.InitialLoginCache();
                    this.InitialBiblioSummaryCache();

                    if (bReload == false)
                    {
                        if (app.HasAppBeenKilled() == true)
                        {
                            app.WriteErrorLog("*** 发现library application先前曾被意外终止 ***");
                        }
                    }

                    this.WriteErrorLog("*********");

                    if (bReload == true)
                        app.WriteErrorLog("library (" + Version + ") application 开始重新装载 " + this.m_strFileName);
                    else
                        app.WriteErrorLog("library (" + Version + ") application 开始初始化。");

                    //
#if NO
            if (bReload == false)
            {
                app.m_strWebuiFileName = PathUtil.MergePath(strDataDir, "webui.xml");
                // string strWebUiFileName = PathUtil.MergePath(strDataDir, "webui.xml");
                nRet = LoadWebuiCfgDom(out strError);
                if (nRet == -1)
                {
                    // strError = "装载配置文件-- '" + strWebUiFileName + "'时发生错误,原因:" + ex.Message;
                    app.WriteErrorLog(strError);
                    goto ERROR1;
                }
            }
#endif

#if LOG_INFO
                    app.WriteErrorLog("INFO: 开始装载 " + strFileName + " 到 XMLDOM");
#endif

                    //

                    XmlDocument dom = new XmlDocument();
                    try
                    {
                        dom.Load(strFileName);
                    }
                    catch (FileNotFoundException)
                    {
                        strError = "file '" + strFileName + "' not found ...";
                        goto ERROR1;
                    }
                    catch (Exception ex)
                    {
                        strError = "装载配置文件-- '" + strFileName + "' 时发生错误,错误类型:" + ex.GetType().ToString() + ",原因:" + ex.Message;
                        app.WriteErrorLog(strError);
                        // throw ex;
                        goto ERROR1;
                    }

                    app.LibraryCfgDom = dom;

#if LOG_INFO
                    app.WriteErrorLog("INFO: 初始化内存参数");
#endif

                    // *** 进入内存的参数开始
                    // 注意修改了这些参数的结构后,必须相应修改Save()函数的相关片断

                    // 2011/1/7
                    bool bValue = false;
                    DomUtil.GetBooleanParam(app.LibraryCfgDom.DocumentElement,
                        "debugMode",
                        false,
                        out bValue,
                        out strError);
                    this.DebugMode = bValue;
                    WriteErrorLog("是否为调试态: " + this.DebugMode);

                    // 2013/4/10 
                    // uid
                    this.UID = app.LibraryCfgDom.DocumentElement.GetAttribute("uid");
                    if (string.IsNullOrEmpty(this.UID) == true)
                    {
                        this.UID = Guid.NewGuid().ToString();
                        this.Changed = true;
                        WriteErrorLog("自动为 library.xml 添加 uid '" + this.UID + "'");
                    }

                    // 内核参数
                    // 元素<rmsserver>
                    // 属性url/username/password
                    XmlElement node = dom.DocumentElement.SelectSingleNode("rmsserver") as XmlElement;
                    if (node != null)
                    {
                        app.WsUrl = DomUtil.GetAttr(node, "url");

                        if (app.WsUrl.IndexOf(".asmx") != -1)
                        {
                            strError = "装载配置文件 '" + strFileName + "' 过程中发生错误: <rmsserver>元素url属性中的 dp2内核 服务器URL '" + app.WsUrl + "' 不正确,应当为非.asmx形态的地址...";
                            app.WriteErrorLog(strError);
                            goto ERROR1;
                        }

                        app.ManagerUserName = DomUtil.GetAttr(node,
                            "username");

                        try
                        {
                            app.ManagerPassword = Cryptography.Decrypt(
                                DomUtil.GetAttr(node, "password"),
                                EncryptKey);
                        }
                        catch
                        {
                            strError = "<rmsserver>元素password属性中的密码设置不正确";
                            // throw new Exception();
                            goto ERROR1;
                        }

                        CfgsMap = new CfgsMap(this.CfgMapDir/*,
                        this.WsUrl*/);
                        CfgsMap.Clear();
                    }
                    else
                    {
                        app.WsUrl = "";
                        app.ManagerUserName = "";
                        app.ManagerPassword = "";
                    }

                    // 元素 <mongoDB>
                    // 属性 connectionString / instancePrefix
                    node = dom.DocumentElement.SelectSingleNode("mongoDB") as XmlElement;
                    if (node != null)
                    {
                        this.MongoDbConnStr = DomUtil.GetAttr(node, "connectionString");
                        this.MongoDbInstancePrefix = node.GetAttribute("instancePrefix");
                    }
                    else
                    {
                        this.MongoDbConnStr = "";
                        this.MongoDbInstancePrefix = "";
                        this.AccessLogDatabase = new AccessLogDatabase();
                        this.HitCountDatabase = new HitCountDatabase();
                        this.ChargingOperDatabase = new ChargingOperDatabase();
                    }

                    // 预约到书
                    // 元素<arrived>
                    // 属性dbname/reserveTimeSpan/outofReservationThreshold/canReserveOnshelf/notifyTypes
                    node = dom.DocumentElement.SelectSingleNode("arrived") as XmlElement;
                    if (node != null)
                    {
                        app.ArrivedDbName = DomUtil.GetAttr(node, "dbname");
                        app.ArrivedReserveTimeSpan = DomUtil.GetAttr(node, "reserveTimeSpan");

                        int nValue = 0;
                        nRet = DomUtil.GetIntegerParam(node,
                            "outofReservationThreshold",
                            10,
                            out nValue,
                            out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog("元素<arrived>属性outofReservationThreshold读入时发生错误: " + strError);
                            goto ERROR1;
                        }

                        app.OutofReservationThreshold = nValue;

                        bValue = false;
                        nRet = DomUtil.GetBooleanParam(node,
                            "canReserveOnshelf",
                            true,
                            out bValue,
                            out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog("元素<arrived>属性canReserveOnshelf读入时发生错误: " + strError);
                            goto ERROR1;
                        }

                        app.CanReserveOnshelf = bValue;

                        // 没有这个属性的时候,默认 "dpmail,email",否则依其值,哪怕为 ""
                        if (node.GetAttributeNode("notifyTypes") == null)
                            app.ArrivedNotifyTypes = "dpmail,email";
                        else
                            app.ArrivedNotifyTypes = node.GetAttribute("notifyTypes");

                    }
                    else
                    {
                        app.ArrivedDbName = "";
                        app.ArrivedReserveTimeSpan = "";
                        app.OutofReservationThreshold = 10;
                        app.CanReserveOnshelf = true;
                        app.ArrivedNotifyTypes = "dpmail,email";
                    }

                    // 2013/9/24
                    // 借期提醒通知定义
                    // 元素 <monitors/readersMonitor>
                    // 属性 notifyDef
                    node = dom.DocumentElement.SelectSingleNode("monitors/readersMonitor") as XmlElement;
                    if (node != null)
                    {
                        // 提醒通知的定义
                        app.NotifyDef = DomUtil.GetAttr(node, "notifyDef");
                    }
                    else
                    {
                        app.NotifyDef = "";
                    }

                    // <login>
                    node = dom.DocumentElement.SelectSingleNode("login") as XmlElement;
                    if (node != null)
                    {
                        this.CheckClientVersion = DomUtil.GetBooleanParam(node,
                            "checkClientVersion",
                            false);
                    }
                    else
                    {
                        this.CheckClientVersion = false;
                    }

                    // <circulation>
                    node = dom.DocumentElement.SelectSingleNode("circulation") as XmlElement;
                    if (node != null)
                    {
                        {
                            string strList = DomUtil.GetAttr(node, "patronAdditionalFroms");
                            if (string.IsNullOrEmpty(strList) == false)
                                this.PatronAdditionalFroms = StringUtil.SplitList(strList);
                            else
                                this.PatronAdditionalFroms = new List<string>();
                        }

                        {
                            string strList = DomUtil.GetAttr(node, "patronAdditionalFields");
                            if (string.IsNullOrEmpty(strList) == false)
                                this.PatronAdditionalFields = StringUtil.SplitList(strList);
                            else
                                this.PatronAdditionalFields = new List<string>();
                        }

                        {
                            string strList = DomUtil.GetAttr(node, "patronReplicationFields");
                            if (string.IsNullOrEmpty(strList) == false)
                                this.PatronReplicationFields = StringUtil.SplitList(strList);
                            else
                                this.PatronReplicationFields = StringUtil.SplitList(strList);
                        }

                        int v = 0;
                        nRet = DomUtil.GetIntegerParam(node,
                            "maxPatronHistoryItems",
                            10, // 100,
                            out v,
                            out strError);
                        if (nRet == -1)
                            app.WriteErrorLog(strError);
                        this.MaxPatronHistoryItems = v;

                        nRet = DomUtil.GetIntegerParam(node,
        "maxItemHistoryItems",
        10, // 100,
        out v,
        out strError);
                        if (nRet == -1)
                            app.WriteErrorLog(strError);
                        this.MaxItemHistoryItems = v;

                        this.VerifyBarcode = DomUtil.GetBooleanParam(node, "verifyBarcode", false);

                        this.AcceptBlankItemBarcode = DomUtil.GetBooleanParam(node, "acceptBlankItemBarcode", true);

                        this.AcceptBlankReaderBarcode = DomUtil.GetBooleanParam(node, "acceptBlankReaderBarcode", true);

                        this.VerifyBookType = DomUtil.GetBooleanParam(node, "verifyBookType", false);
                        this.VerifyReaderType = DomUtil.GetBooleanParam(node, "verifyReaderType", false);
                        this.BorrowCheckOverdue = DomUtil.GetBooleanParam(node, "borrowCheckOverdue", true);

                        this.CirculationNotifyTypes = node.GetAttribute("notifyTypes");
                    }
                    else
                    {
                        this.PatronAdditionalFroms = new List<string>();
                        this.PatronAdditionalFields = new List<string>();
                        this.MaxPatronHistoryItems = DEFAULT_MAXPATRONHITSTORYITEMS;
                        this.MaxItemHistoryItems = DEFAULT_MAXITEMHISTORYITEMS;
                        this.VerifyBarcode = false;
                        this.AcceptBlankItemBarcode = true;
                        this.AcceptBlankReaderBarcode = true;
                        this.VerifyBookType = false;
                        this.VerifyReaderType = false;
                        this.BorrowCheckOverdue = true;
                        this.CirculationNotifyTypes = "";
                    }

                    // <channel>
                    node = dom.DocumentElement.SelectSingleNode("channel") as XmlElement;
                    if (node != null)
                    {
                        int v = 0;
                        nRet = DomUtil.GetIntegerParam(node,
                            "maxChannelsPerIP",
                            50,
                            out v,
                            out strError);
                        if (nRet == -1)
                            app.WriteErrorLog(strError);
                        if (this.SessionTable != null)
                            this.SessionTable.MaxSessionsPerIp = v;

                        nRet = DomUtil.GetIntegerParam(node,
        "maxChannelsLocalhost",
        150,
        out v,
        out strError);
                        if (nRet == -1)
                            app.WriteErrorLog(strError);
                        if (this.SessionTable != null)
                            this.SessionTable.MaxSessionsLocalHost = v;
                    }
                    else
                    {
                        if (this.SessionTable != null)
                        {
                            this.SessionTable.MaxSessionsPerIp = 50;
                            this.SessionTable.MaxSessionsLocalHost = 150;
                        }
                    }

                    // <cataloging>
                    node = dom.DocumentElement.SelectSingleNode("cataloging") as XmlElement;
                    if (node != null)
                    {
                        // 是否允许删除带有下级记录的书目记录
                        bValue = true;
                        nRet = DomUtil.GetBooleanParam(node,
                            "deleteBiblioSubRecords",
                            true,
                            out bValue,
                            out strError);
                        if (nRet == -1)
                            app.WriteErrorLog(strError);
                        this.DeleteBiblioSubRecords = bValue;
                    }
                    else
                    {
                        this.DeleteBiblioSubRecords = true;
                    }

                    // 入馆登记
                    // 元素<passgate>
                    // 属性writeOperLog
                    node = dom.DocumentElement.SelectSingleNode("passgate") as XmlElement;
                    if (node != null)
                    {
                        string strWriteOperLog = DomUtil.GetAttr(node, "writeOperLog");

                        this.PassgateWriteToOperLog = ToBoolean(strWriteOperLog,
                            true);
                    }
                    else
                    {
                        this.PassgateWriteToOperLog = true;
                    }

                    // 对象管理
                    // 元素<object>
                    // 属性 writeOperLog
                    node = dom.DocumentElement.SelectSingleNode("object") as XmlElement;
                    if (node != null)
                    {
                        string strWriteOperLog = DomUtil.GetAttr(node, "writeGetResOperLog");

                        this.GetObjectWriteToOperLog = ToBoolean(strWriteOperLog,
                            false);
                    }
                    else
                    {
                        this.GetObjectWriteToOperLog = false;
                    }

                    // 2015/11/26
                    // 日志特性
                    // 元素<log>
                    node = dom.DocumentElement.SelectSingleNode("log") as XmlElement;
                    if (node != null)
                    {
                        int nValue = 0;
                        DomUtil.GetIntegerParam(node,
                            "accessLogMaxCountPerDay",
                            10000,
                            out nValue,
                            out strError);
                        this.AccessLogMaxCountPerDay = nValue;
                    }
                    else
                    {
                        this.AccessLogMaxCountPerDay = 10000;
                    }

                    // 消息
                    // 元素<message>
                    // 属性dbname/reserveTimeSpan/defaultQueue
                    node = dom.DocumentElement.SelectSingleNode("message") as XmlElement;
                    if (node != null)
                    {
                        this.MessageDbName = DomUtil.GetAttr(node, "dbname");
                        this.MessageReserveTimeSpan = DomUtil.GetAttr(node, "reserveTimeSpan");
                        // 2016/4/10
                        this.OutgoingQueue = DomUtil.GetAttr(node, "defaultQueue");

                        // 2010/12/31 add
                        if (String.IsNullOrEmpty(this.MessageReserveTimeSpan) == true)
                            this.MessageReserveTimeSpan = "365day";
                    }
                    else
                    {
                        this.MessageDbName = "";
                        this.MessageReserveTimeSpan = "365day";
                        this.OutgoingQueue = "";
                    }

                    // OPAC服务器
                    // 元素<opacServer>
                    // 属性url
                    node = dom.DocumentElement.SelectSingleNode("opacServer") as XmlElement;
                    if (node != null)
                    {
                        app.OpacServerUrl = DomUtil.GetAttr(node, "url");
                    }
                    else
                    {
                        app.OpacServerUrl = "";
                    }

                    // 违约金
                    // 元素<amerce>
                    // 属性dbname/overdueStyle
                    node = dom.DocumentElement.SelectSingleNode("amerce") as XmlElement;
                    if (node != null)
                    {
                        app.AmerceDbName = DomUtil.GetAttr(node, "dbname");
                        app.OverdueStyle = DomUtil.GetAttr(node, "overdueStyle");
                    }
                    else
                    {
                        app.AmerceDbName = "";
                        app.OverdueStyle = "";
                    }

                    // 发票
                    // 元素<invoice>
                    // 属性dbname
                    node = dom.DocumentElement.SelectSingleNode("invoice") as XmlElement;
                    if (node != null)
                    {
                        app.InvoiceDbName = DomUtil.GetAttr(node, "dbname");
                    }
                    else
                    {
                        app.InvoiceDbName = "";
                    }

                    // *** 进入内存的参数结束

                    // bin dir
                    app.BinDir = strBinDir;

                    nRet = 0;

                    {
#if LOG_INFO
                        app.WriteErrorLog("INFO: LoadReaderDbGroupParam");
#endif
                        // <readerdbgroup>
                        app.LoadReaderDbGroupParam(dom);

#if LOG_INFO
                        app.WriteErrorLog("INFO: LoadItemDbGroupParam");
#endif

                        // <itemdbgroup> 
                        nRet = app.LoadItemDbGroupParam(dom,
                            out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog(strError);
                            goto ERROR1;
                        }

                        // 临时的SessionInfo对象
                        SessionInfo session = new SessionInfo(this);
                        try
                        {
#if LOG_INFO
                            app.WriteErrorLog("INFO: InitialKdbs");
#endif

                            // 初始化kdbs
                            nRet = InitialKdbs(session.Channels,
                                out strError);
                            if (nRet == -1)
                            {
                                app.WriteErrorLog("ERR001 首次初始化kdbs失败: " + strError);
                                // DefaultThread可以重试初始化

                                // session.Close();
                                // goto ERROR1;
                            }
                            else
                            {
#if LOG_INFO
                                app.WriteErrorLog("INFO: CheckKernelVersion");
#endif

                                // 检查 dpKernel 版本号
                                nRet = CheckKernelVersion(session.Channels,
                                    out strError);
                                if (nRet == -1)
                                    goto ERROR1;
                            }

#if LOG_INFO
                            app.WriteErrorLog("INFO: InitialVdbs");
#endif

                            // 2008/6/6  重新初始化虚拟库定义
                            // 这样,其他地方调用的InitialVdbs()就可以去除了
                            // TODO: 为了提高运行速度,可以优化为,只有当<virtualDatabases>元素下的内容有改变时,才重新进行这个初始化
                            this.vdbs = null;
                            nRet = app.InitialVdbs(session.Channels,
                                out strError);
                            if (nRet == -1)
                            {
                                app.WriteErrorLog("ERR002 首次初始化vdbs失败: " + strError);
                            }

                        }
                        finally
                        {
                            session.CloseSession();
                            session = null;

#if LOG_INFO
                            app.WriteErrorLog("INFO: 临时 session 使用完毕");
#endif
                        }

                    }

                    // 时钟
                    string strClock = DomUtil.GetElementText(dom.DocumentElement, "clock");
                    try
                    {
                        this.Clock.Delta = Convert.ToInt64(strClock);
                    }
                    catch
                    {
                        // TODO: 写入错误日志
                    }

                    // *** 初始化操作日志环境
                    if (bReload == false)   // 2014/4/2
                    {
                        // this.OperLogDir = strOperLogDir;    // 2006/12/7 
#if LOG_INFO
                        app.WriteErrorLog("INFO: OperLog.Initial");
#endif

                        // oper log
                        nRet = this.OperLog.Initial(this,
                            strOperLogDir,
                            out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog(strError);
                            goto ERROR1;
                        }
                    }

                    // *** 初始化统计对象
                    // if (bReload == false)   // 2014/4/2
                    {
#if LOG_INFO
                        app.WriteErrorLog("INFO: Statis.Initial");
#endif

                        this.Statis = new Statis();
                        nRet = this.Statis.Initial(this, out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog(strError);
                            goto ERROR1;
                        }
                    }

#if LOG_INFO
                    app.WriteErrorLog("INFO: InitialLibraryHostAssembly");
#endif
                    // 初始化LibraryHostAssembly对象
                    // 必须在ReadersMonitor以前启动。否则其中用到脚本代码时会出错。2007/10/10 changed
                    // return:
                    //		-1	出错
                    //		0	成功
                    nRet = this.InitialLibraryHostAssembly(out strError);
                    if (nRet == -1)
                    {
                        app.WriteErrorLog(strError);
                        goto ERROR1;
                    }

#if LOG_INFO
                    app.WriteErrorLog("INFO: InitialExternalMessageInterfaces");
#endif

                    // 初始化扩展消息接口
                    nRet = app.InitialExternalMessageInterfaces(
                    out strError);
                    if (nRet == -1)
                    {
                        strError = "初始化扩展的消息接口时出错: " + strError;
                        app.WriteErrorLog(strError);
                        // goto ERROR1;
                    }

                    // 创建 MSMQ 消息队列
#if LOG_INFO
                    app.WriteErrorLog("INFO: Message Queue");
#endif

                    ///
                    app.InitialMsmq();

                    // 初始化 mongodb 相关对象
                    nRet = InitialMongoDatabases(out strError);
                    if (nRet == -1)
                    {
                        // app.HangupReason = LibraryServer.HangupReason.StartingError;
                        app.AddHangup("ERR002");
                        app.WriteErrorLog("ERR002 首次初始化 mongodb database 失败: " + strError);
                    }

#if LOG_INFO
                    app.WriteErrorLog("INFO: 准备下属数据库对象");
#endif
                    //
                    this.IssueItemDatabase = new IssueItemDatabase(this);
                    this.OrderItemDatabase = new OrderItemDatabase(this);
                    this.CommentItemDatabase = new CommentItemDatabase(this);

#if LOG_INFO
                    app.WriteErrorLog("INFO: MessageCenter");
#endif
                    // 
                    this.MessageCenter = new MessageCenter();
                    this.MessageCenter.ServerUrl = this.WsUrl;
                    this.MessageCenter.MessageDbName = this.MessageDbName;

                    this.MessageCenter.VerifyAccount -= new VerifyAccountEventHandler(MessageCenter_VerifyAccount); // 2008/6/6 
                    this.MessageCenter.VerifyAccount += new VerifyAccountEventHandler(MessageCenter_VerifyAccount);

                    if (this.BatchTasks == null)
                        this.BatchTasks = new BatchTaskCollection();    // Close() 的时候会设置为 null。因此这里要准备重新 new

                    // 启动批处理任务
                    // TODO: 这一段考虑分离到一个函数中
                    if (bReload == false)
                    {
                        string strBreakPoint = "";

#if LOG_INFO
                        app.WriteErrorLog("INFO: DefaultThread");
#endif
                        // 启动DefaultThread
                        try
                        {
                            DefaultThread defaultThread = new DefaultThread(this, null);
                            this.BatchTasks.Add(defaultThread);

                            defaultThread.StartWorkerThread();

                            this.defaultManagerThread = defaultThread;
                        }
                        catch (Exception ex)
                        {
                            app.WriteErrorLog("启动后台任务 DefaultThread 时出错:" + ex.Message);
                            goto ERROR1;
                        }

#if LOG_INFO
                        app.WriteErrorLog("INFO: OperLogThread");
#endif
                        // 启动 OperLogThread
                        try
                        {
                            OperLogThread thread = new OperLogThread(this, null);
                            this.BatchTasks.Add(thread);

                            thread.StartWorkerThread();

                            this.operLogThread = thread;
                        }
                        catch (Exception ex)
                        {
                            app.WriteErrorLog("启动后台任务 OperLogThread 时出错:" + ex.Message);
                            goto ERROR1;
                        }

#if LOG_INFO
                        app.WriteErrorLog("INFO: ArriveMonitor");
#endif
                        // 启动ArriveMonitor
                        try
                        {
                            ArriveMonitor arriveMonitor = new ArriveMonitor(this, null);
                            this.BatchTasks.Add(arriveMonitor);

                            arriveMonitor.StartWorkerThread();
                        }
                        catch (Exception ex)
                        {
                            app.WriteErrorLog("启动批处理任务ArriveMonitor时出错:" + ex.Message);
                            goto ERROR1;
                        }

#if LOG_INFO
                        app.WriteErrorLog("INFO: ReadersMonitor");
#endif
                        // 启动ReadersMonitor
                        try
                        {
                            ReadersMonitor readersMonitor = new ReadersMonitor(this, null);
                            this.BatchTasks.Add(readersMonitor);

                            readersMonitor.StartWorkerThread();
                        }
                        catch (Exception ex)
                        {
                            app.WriteErrorLog("启动批处理任务ReadersMonitor时出错:" + ex.Message);
                            goto ERROR1;
                        }

#if LOG_INFO
                        app.WriteErrorLog("INFO: MessageMonitor");
#endif
                        // 启动MessageMonitor
                        try
                        {
                            MessageMonitor messageMonitor = new MessageMonitor(this, null);
                            this.BatchTasks.Add(messageMonitor);

                            // 从断点记忆文件中读出信息
                            // return:
                            //      -1  error
                            //      0   file not found
                            //      1   found
                            nRet = ReadBatchTaskBreakPointFile(messageMonitor.DefaultName,
                                out strBreakPoint,
                                out strError);
                            if (nRet == -1)
                            {
                                app.WriteErrorLog("ReadBatchTaskBreakPointFile时出错:" + strError);
                            }

                            if (messageMonitor.StartInfo == null)
                                messageMonitor.StartInfo = new BatchTaskStartInfo();   // 按照缺省值来

                            // 如果需要从断点启动
                            if (nRet == 1)
                                messageMonitor.StartInfo.Start = "!breakpoint";  //strBreakPoint;

                            messageMonitor.ClearProgressFile();   // 清除进度文件内容
                            messageMonitor.StartWorkerThread();
                        }
                        catch (Exception ex)
                        {
                            app.WriteErrorLog("启动批处理任务MessageMonitor时出错:" + ex.Message);
                            goto ERROR1;
                        }

                        // 启动DkywReplication
                        // <dkyw>
                        node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("dkyw") as XmlElement;
                        if (node != null)
                        {
#if LOG_INFO
                            app.WriteErrorLog("INFO: DkywReplication");
#endif
                            try
                            {
                                DkywReplication dkyw = new DkywReplication(this, null);
                                this.BatchTasks.Add(dkyw);

                                /*
                                // 从断点记忆文件中读出信息
                                // return:
                                //      -1  error
                                //      0   file not found
                                //      1   found
                                nRet = ReadBatchTaskBreakPointFile(dkyw.DefaultName,
                                    out strBreakPoint,
                                    out strError);
                                if (nRet == -1)
                                {
                                    app.WriteErrorLog("ReadBatchTaskBreakPointFile时出错:" + strError);
                                }
                                 * */
                                bool bLoop = false;
                                string strLastNumber = "";

                                // return:
                                //      -1  出错
                                //      0   没有找到断点信息
                                //      1   找到了断点信息
                                nRet = dkyw.ReadLastNumber(
                                    out bLoop,
                                    out strLastNumber,
                                    out strError);
                                if (nRet == -1)
                                {
                                    app.WriteErrorLog("ReadLastNumber时出错:" + strError);
                                }

                                if (dkyw.StartInfo == null)
                                    dkyw.StartInfo = new BatchTaskStartInfo();   // 按照缺省值来

                                if (bLoop == true)
                                {
                                    // 需要从断点启动
                                    if (nRet == 1)
                                        dkyw.StartInfo.Start = "!breakpoint";  //strBreakPoint;

                                    dkyw.ClearProgressFile();   // 清除进度文件内容
                                    dkyw.StartWorkerThread();
                                }
                            }
                            catch (Exception ex)
                            {
                                app.WriteErrorLog("启动批处理任务DkywReplication时出错:" + ex.Message);
                                goto ERROR1;
                            }
                        }

                        // 启动PatronReplication
                        // <patronReplication>
                        // 读者库数据同步 批处理任务
                        // 从卡中心同步读者数据
                        node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("patronReplication") as XmlElement;
                        if (node != null)
                        {
#if LOG_INFO
                            app.WriteErrorLog("INFO: PatronReplication");
#endif
                            try
                            {
                                PatronReplication patron_rep = new PatronReplication(this, null);
                                this.BatchTasks.Add(patron_rep);

                                patron_rep.StartWorkerThread();
                            }
                            catch (Exception ex)
                            {
                                app.WriteErrorLog("启动批处理任务PatronReplication时出错:" + ex.Message);
                                goto ERROR1;
                            }
                        }

                        // 启动 LibraryReplication

#if LOG_INFO
                        app.WriteErrorLog("INFO: LibraryReplication ReadBatchTaskBreakPointFile");
#endif
                        // 从断点记忆文件中读出信息
                        // return:
                        //      -1  error
                        //      0   file not found
                        //      1   found
                        nRet = ReadBatchTaskBreakPointFile("dp2Library 同步",
                            out strBreakPoint,
                            out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog("ReadBatchTaskBreakPointFile() 时出错:" + strError);
                        }
                        // 如果nRet == 0,表示没有断点文件存在,也就不必自动启动这个任务

                        // strBreakPoint 并未被使用。而是断点文件是否存在,这一信息有价值。

                        if (nRet == 1)
                        {
#if LOG_INFO
                            app.WriteErrorLog("INFO: LibraryReplication");
#endif
                            try
                            {

                                // 从断点文件中取出断点字符串
                                // 断点字符串格式:序号.偏移量@日志文件名
                                //  或者:序号@日志文件名
                                // 获得断点信息的整个过程的代码,是否适宜归入TraceDTLP类?
                                // 如果成熟,可以归纳作为BatchTask基类的一个特性。

                                LibraryReplication replication = new LibraryReplication(this, null);
                                this.BatchTasks.Add(replication);

                                if (replication.StartInfo == null)
                                    replication.StartInfo = new BatchTaskStartInfo();   // 按照缺省值来
                                replication.StartInfo.Start = "date=continue";  // 从断点开始做
                                replication.ClearProgressFile();   // 清除进度文件内容
                                replication.StartWorkerThread();
                            }
                            catch (Exception ex)
                            {
                                app.WriteErrorLog("启动批处理任务时出错:" + ex.Message);
                                goto ERROR1;
                            }
                        }

                        // 启动 RebuildKeys

#if LOG_INFO
                        app.WriteErrorLog("INFO: RebuildKeys ReadBatchTaskBreakPointFile");
#endif
                        // 从断点记忆文件中读出信息
                        // return:
                        //      -1  error
                        //      0   file not found
                        //      1   found
                        nRet = ReadBatchTaskBreakPointFile("重建检索点",
                            out strBreakPoint,
                            out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog("ReadBatchTaskBreakPointFile() 时出错:" + strError);
                        }
                        // 如果nRet == 0,表示没有断点文件存在,也就不必自动启动这个任务

                        // strBreakPoint 并未被使用。而是断点文件是否存在,这一信息有价值。

                        if (nRet == 1)
                        {
#if LOG_INFO
                            app.WriteErrorLog("INFO: RebuildKeys");
#endif
                            try
                            {

                                // 从断点文件中取出断点字符串
                                RebuildKeys replication = new RebuildKeys(this, null);
                                this.BatchTasks.Add(replication);

                                if (replication.StartInfo == null)
                                    replication.StartInfo = new BatchTaskStartInfo();   // 按照缺省值来
                                replication.StartInfo.Start = "dbnamelist=continue";  // 从断点开始做
                                replication.ClearProgressFile();   // 清除进度文件内容
                                replication.StartWorkerThread();
                            }
                            catch (Exception ex)
                            {
                                app.WriteErrorLog("启动批处理任务时出错:" + ex.Message);
                                goto ERROR1;
                            }
                        }
                    }

                    // 公共查询最大命中数
                    {
                        XmlNode nodeTemp = this.LibraryCfgDom.DocumentElement.SelectSingleNode("//virtualDatabases");
                        if (nodeTemp != null)
                        {
                            try
                            {
                                string strMaxCount = DomUtil.GetAttr(nodeTemp, "searchMaxResultCount");
                                if (String.IsNullOrEmpty(strMaxCount) == false)
                                    this.SearchMaxResultCount = Convert.ToInt32(strMaxCount);
                            }
                            catch
                            {
                            }
                        }
                    }


#if NO
            if (bReload == false)
            {
                PathUtil.CreateDirIfNeed(strColumnDir);	// 确保目录创建
                nRet = LoadCommentColumn(
                    PathUtil.MergePath(strColumnDir, "comment"),
                    out strError);
                if (nRet == -1)
                {
                    app.WriteErrorLog("装载栏目存储时出错: " + strError);
                }
            }
#endif

                    // 升级library.xml文件版本
                    if (bReload == false)
                    {
#if LOG_INFO
                        app.WriteErrorLog("INFO: UpgradeLibraryXml");
#endif
                        nRet = this.UpgradeLibraryXml(out strError);
                        if (nRet == -1)
                        {
                            app.WriteErrorLog("升级library.xml时出错:" + strError);
                        }
                    }

                    if (bReload == true)
                        app.WriteErrorLog("library application结束重新装载 " + this.m_strFileName);
                    else
                    {
                        TimeSpan delta = DateTime.Now - start;
                        app.WriteErrorLog("library application成功初始化。初始化操作耗费时间 " + delta.TotalSeconds.ToString() + " 秒");

                        // 写入down机检测文件
                        app.WriteAppDownDetectFile("library application成功初始化。");

                        if (this.watcher == null)
                        {
#if LOG_INFO
                            app.WriteErrorLog("INFO: BeginWatcher");
#endif

                            BeginWatcher();
#if LOG_INFO
                            app.WriteErrorLog("INFO: End BeginWatcher");
#endif
                        }

#if NO
                if (this.virtual_watcher == null)
                    BeginVirtualDirWatcher();
#endif
                    }

                    if (this.MaxClients != 255) // 255 通道情况下不再检查版本失效日期 2016/11/3
                    {
                        DateTime expire = new DateTime(2017, 3, 1); // 上一个版本是 2016/11/1
                        if (DateTime.Now > expire)
                        {
                            if (this.MaxClients == 255)
                            {
                                this.WriteErrorLog("*** 当前 dp2library 版本已于 " + expire.ToLongDateString() + " 失效。请系统管理员注意主动升级 dp2library");
                            }
                            else
                            {
                                // 通知系统挂起
                                // this.HangupReason = HangupReason.Expire;
                                app.AddHangup("Expire");
                                this.WriteErrorLog("*** 当前 dp2library 版本因为长期没有升级,已经失效。系统被挂起。请立即升级 dp2library 到最新版本");
                            }
                        }
                    }
                    else
                        this.WriteErrorLog("*** 特殊版本不检查失效日期。请系统管理员注意每隔半年主动升级一次 dp2library");

                    // 2013/4/10
                    if (this.Changed == true)
                        this.ActivateManagerThread();
                }
                catch (Exception ex)
                {
                    strError = "LoadCfg() 抛出异常: " + ExceptionUtil.GetDebugText(ex);
                    goto ERROR1;
                }

                return 0;
            }
            finally
            {
                // this.m_lock.ReleaseWriterLock();
                this.UnlockForWrite();
            }
        // 2008/10/13 
        ERROR1:
            if (bReload == false)
            {
                if (this.watcher == null)
                {
#if LOG_INFO
                    app.WriteErrorLog("INFO: BeginWatcher");
#endif

                    BeginWatcher();
#if LOG_INFO
                    app.WriteErrorLog("INFO: End BeginWatcher");
#endif
                }
#if NO
                if (this.virtual_watcher == null)
                    BeginVirtualDirWatcher();
#endif

            }

            if (bReload == true)
                app.WriteErrorLog("library application重新装载 " + this.m_strFileName + " 的过程发生严重错误 [" + strError + "],服务处于残缺状态,请及时排除故障后重新启动");
            else
            {
                // app.HangupReason = LibraryServer.HangupReason.StartingError;
                app.AddHangup("StartingError");
                app.WriteErrorLog("library application初始化过程发生严重错误 [" + strError + "],当前此服务处于残缺状态,请及时排除故障后重新启动");
            }
            return -1;
        }