1.问题描述

JJY主服务器采用Windows服务方式运行时,在读tb_0031消息对应的外部文件时失败.而在控制台方式下正常。
读文件失败的结果是单据没有发送,且错误类型是文件路径不存在(ERROR_PATH_NOT_FOUND).在程序采用忽略该消息记录并删除的逻辑控制下,系统表现出DRP系统的数据已抽取(tb_)但没有发送出去,并且在tb_0031没有痕迹。

这些文件是由DD抽取服务器生成,由主服务器发送给平台,再由平台送抵目标机构.
文件存放主目录是2个服务器共享的.实际环境是在主服务器上的一个共享目录,映射为Y盘.DD抽取服务器的bbox.conf指向该映射盘.
例如,

    <!--抽取文件输出目录--><export_path>Y:\data\retail\autosend</export_path> 

DD抽取服务器在抽取数据生成消息包,保存到tb_0031时,对于超过32k字节大小(可配置)的消息采用外部文件的方式,f007b_0031中保存带路径的文件名。
主服务器SEMQ在发送记录的消息时,直接打开其中内容指向的文件.

dd.conf有以下关于最小外部文件大小的配置:

    <!--最小外部文件字节数,默认:8k--><ext_file_min_size>10240</ext_file_min_size>

主服务器采用Windows服务方式的原因是,以控制台方式运行,在需要重新启动进程时,直接关闭进程而不是优雅地停止,服务器没有提醒并等待客户端用户保存工作的机会.
基于hotfox的本地服务器在控制台方式下有2种优雅结束的方式:
.Ctrl-C:但为了避免远程控制时操作人员习惯用Ctrl-C复制文本而导致进程意外终止
.ServerManager控制:通过与服务器通信由协议调用IManager接口实现.(目前的实现是直接操纵服务还是通过与服务器通信?)

在JJY的分离部署,主服务器必须采用服务方式的环境需求下,问题归结为:Windows服务方式下如何访问映射盘.

此问题在我的工作机器上可以验证重现。

以下的测试和验证活动都是在我的工作机器上进行的,系统为:Windows Professional XP 2002 SP3.

2.寻求解决之道

根据网上搜索到的资料中,验证以下方法不可行:
(1)linkd/subst/net use
(2)以Administrator启动服务
(3)把NT AUTHORITY\NETWORK SERVICE加入到Administrator组
(4)用srvany,以Administrator启动

instsrv srvany C:\Windows\System32\srvany.exe

用svrany启动服务,注册文件如下:

Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\instsrv\Parameters]
"AppParameters"="-d"
"Application"="D:\\das\\Retail Server\\hotfoxd.exe"
"AppDirectory"="D:\\das\\Retail Server"

下面2个经过测试看似可行的方法:
1.使用WNetAddConnection2
在插件的Activate方法中利用WNetAddConnection2建立映射盘,在后台线程中可以访问.

    NETRESOURCE nr;DWORD res;TCHAR szUserName[32] = "administrator",szPassword[32] = "xxxxx",szLocalName[32] = "x:",szRemoteName[MAX_PATH] = "\\\\127.0.0.1\\t";nr.dwType = RESOURCETYPE_ANY;nr.lpLocalName = szLocalName;nr.lpRemoteName = szRemoteName;nr.lpProvider = NULL;res = WNetAddConnection2(&nr, szPassword, szUserName, FALSE);

2.使用ImpersonateLoggedOnUser

#include "Tlhelp32.h."
BOOL GetTokenByName(HANDLE &hToken,LPSTR lpName)
{     if(!lpName)     {     return FALSE;     }     HANDLE        hProcessSnap = NULL;     BOOL          bRet      = FALSE;     PROCESSENTRY32 pe32      = {0};     hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);     if (hProcessSnap == INVALID_HANDLE_VALUE)     return (FALSE);     pe32.dwSize = sizeof(PROCESSENTRY32);     if (Process32First(hProcessSnap, &pe32))     {      do     {     if(!lstrcmpi(pe32.szExeFile,lpName))     {     HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,     FALSE,pe32.th32ProcessID);     bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken);     CloseHandle (hProcessSnap);     return (bRet);     }     }     while (Process32Next(hProcessSnap, &pe32));     bRet = TRUE;     }     else     bRet = FALSE;     CloseHandle (hProcessSnap);     return (bRet);
}   #include <Winnetwk.h>
#pragma comment(lib,"Mpr.lib");
ACE_THR_FUNC_RETURN test_proc(void*) {do {GetTokenByName(hToken,"EXPLORER.EXE");bool br = ImpersonateLoggedOnUser (hToken);string fn = "X:\\a.txt";HANDLE handle = CreateFile(fn.c_str(),GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);err = GetLastError();if (handle!=INVALID_HANDLE_VALUE) {CloseHandle(handle);}RevertToSelf ();Sleep(3000);} while(1);
};    

方法(1)需要针对服务方式运行增加映射盘配置.

方法(2)ImpersonateLoggedOnUser要在访问映射盘的线程中调用,限制了使用.

这2种方法都不适用.以何种方式运行对程序应该是透明的.或者是外部逻辑.这个问题的产生应属于误用.

以下是2则相关的官方说明:
http://support.microsoft.com/default.aspx?scid=kb;en-us;827421#appliesto
A service that runs under a LocalSystem account or under a local user account can only access mapped drives that the service creates. Mapped drives are stored for each logon session. If a service runs under a LocalSystem account or under a local user account that does not create certain mapped drives, the service cannot access these mapped drives. Additionally, a service that runs under a local user account that creates certain mapped drives also receives a new set of mapped drives if you log off and then you log on again as the same local user.
服务只能访问服务自己创建的映射盘.

http://support.microsoft.com/kb/180362/en-us
A service should not directly access local or network resources through mapped drive letters. Additionally, a service should not use the WNetXXXXXXX APIs to add, remove, or query any mapped drive letters. Although the WNetXXXXXXX APIs may return successfully, the results will be incorrect. A service (or any process that is running in a different security context) that must access a remote resource should use the Universal Naming Convention (UNC) name to access the resource. UNC names do not suffer from the limitations described in this article.

不应该使用WNetXXXXXXX API.应该使用UNC.

备忘资料:
How to map a network drive to be used by a service

3.处理对策

鉴于上述的测试结果和官方说明,结合实际情况提出以下处理方案:
(1)以console方式运行:
hotfox增加<enable_control_c>配置,控制是否允许Ctrl-C终止进程,仅对console有效.

<!--是否允许Ctrl-C终止进程,默认:true -->
<enable_contol_c>false</enable_control_c> 

(2)完善ServerManager支持远程控制hotfox停止

通过170-Request请求停止服务器.

这需要检查程序后确定或者修改以支持

(3)路径配置采用UNC
以后此类分离部署需要共享的目录采用UNC方式.
如:

    <!--抽取文件输出目录--><export_path>\\127.0.0.1\share\data\retail\autosend</export_path> 

对于目前正在运行的系统,由于有历史记录需要处理,不能采用此方式.
所以,如果保持采用服务方式,并且考虑历史数据处理,采用以下临时方法过渡.

(4)临时方法:服务运行时创建映射盘
。更新bbox.dll.
。修改bbox.conf配置,增加以下内容:

<map_drive>
<log_user>administrator</log_user> <!-- 登录帐号 -->
<pswd>test123</pswd> <!-- 帐号密码 -->
<drive>X:</drive> <!--驱动器盘符 -->
<remote>\\127.0.0.1\t</remote> <!--共享目录 -->
</map_drive>

。修改服务登录身份,以登录帐号用户运行,默认是本地系统帐户(LocalSystem)

JJY本地服务器以服务方式运行不能读取消息文件相关推荐

  1. 以Windows服务方式运行.NET Core程序

    原文:以Windows服务方式运行.NET Core程序 在之前一篇博客<以Windows服务方式运行ASP.NET Core程序>中我讲述了如何把ASP.NET Core程序作为Wind ...

  2. linux redhat 下让redis以服务方式运行

    1.从官网 下载 redis-2.8.9.tar.gz之后,将redis解压在/usr/local下,目录是redis-2.8.9,然后按照官网给出的办法安装redis即可. 2.安装完在redis- ...

  3. Windows以服务方式运行Java程序

    Windows以服务方式运行Java程序 Windows以服务方式运行Java程序 方式1:通过windows的startup自启动实现 方式2:通过winsw实现windows的服务注册与启动 Wi ...

  4. 运行时读取PAK文件

    运行时读取PAK文件 https://zhuanlan.zhihu.com/p/79209172 运行时读取PAK文件 安宁 游戏/仿真开发,UE4用户 运行时加载资产的问题 Unreal运行时加载资 ...

  5. netcore一键部署到linux服务器以服务方式后台运行

    AntDeploy 是我开发一款开源一键发布插件 将本地vs中的代码,一键打包,部署到任意的远程服务器 部署方式支持 windows服务,linux服务,docker容器,iis 支持增量发布(只更新 ...

  6. 在Ubuntu上以服务方式运行Java程序

    女主宣言 最近小编在项目中遇到了一个问题,打包的jar文件需要作为服务来使用,但是如何才能保证让jar文件开机自启动呢.小编使用的是Ubuntu的系统,所以查阅了相关资料之后,整理了此篇文章,供大家参 ...

  7. 在Windows上以服务方式运行 MSOPenTech/Redis

    ServiceStack.Redis 使用教程里提到Redis最好还是部署到Linux下去,Windows只是用来做开发环境,现在这个命题发生改变了,在Windows上也可以部署生产环境的Redis, ...

  8. 文件夹恢复后java运行慢,eclipse中每次重新启动服务,运行环境下的文件夹或者文件被还原...

    手动在tomcat运行环境修改了文件,但是每次在eclipse中重启tomcat的时候,总是会把eclipse中的文件更新到tomcat,类似还原,包括上传文件到服务器运行目录,重启的时候,会把上传的 ...

  9. python 英文字符频率统计 采用降序方式输出_Python读取英文文件并记录每个单词出现次数后降序输出示例...

    本文实例讲述了Python读取英文文件并记录每个单词出现次数后降序输出.分享给大家供大家参考,具体如下: 对文中出现的句号,逗号和感叹号做了相应的处理 sorted排序函数用法: 按照value值降序 ...

最新文章

  1. Java中String 和StringBuffer的区别
  2. HTML5能为我们带来什么?(一)
  3. 关于python_关于 Python
  4. display:inline-block之用法
  5. 求一个向量变换为另一个向量的矩阵_OpenGL里旋转等变换矩阵为什么是4x4的矩阵...
  6. 大数据隐私保护技术之脱敏技术
  7. 13届蓝桥杯c++组日常练习问题记录
  8. 【Windows】安装win10虚拟机
  9. AI自动写报告,原来如此简单
  10. Java层Binder框架通信原理(转自Cloud Chou's Tech Blog)
  11. 针对谷氨酰胺运输体的小分子抑制剂
  12. c语言中以w方式进行文件操作时,文件操作
  13. 【异构图神经网络】HGraph || 附:AI研究生时间规划 建议(研一、研二、研三)
  14. 网站关键词html代码,html网站代码+网站关键词如何优化呢
  15. 抖音只能上下滑动吗_仿抖音上下滑动播放视频
  16. 从零开始学版图(一)——反相器版图
  17. modbus串口连接java程序报错总结
  18. C#控制CAD打印图片
  19. Python在GF(2⁸)有限域上求解多项式的乘法逆元——基于扩展欧几里得算法
  20. Curl 命令和用法

热门文章

  1. 四年级计算机考试反思,考试反思四年级作文
  2. 加强立法规制个人信息滥用
  3. 关于“其他容量”的清理方法
  4. 近视?老花眼?恢复视力,就用这一招!
  5. php中fwrite函数的用法,PHP函数fwrite的用法
  6. 查找badiexit
  7. ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ...
  8. 董源烟岚重溪图——澄心堂纸本考证
  9. 为什么王者荣耀总是服务器中断,王者荣耀服务器正在维护中怎么回事 7月4日王者荣耀进不去怎么办...
  10. 微软提供的android模拟器