总结一
1、服务安装软件编写时漏了调用一个函数,UpdateListView(),导致启动服务,一直不刷新状态,调试时一直抓着sc.start()不放,一直以为是这个问题。
报错:
{System.InvalidOperationException: 无法打开计算机“.”上的 OnlineService 服务。
---> System.ComponentModel.Win32Exception: 拒绝访问。
--- 内部异常堆栈跟踪的结尾 ---
在 System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess)
在 System.ServiceProcess.ServiceController.Start(String[] args)
在 ServerManager.ServiceAPI.RunService(String NameService) 位置 g:\大通\大通服务器\ServerManager\ServiceAPI.cs:行号 88}
解决:使用管理员调试就好了。使用管理员打开VS,调试代码,运行正常。
总结二
将服务应用程序改为服务时
步骤1:新建两个组件Windows服务、安装程序类
分别命名为OnlineService和OnlineServiceInstaller.cs
引用添加System.Configuration.Install和System.ServiceProcess
OnlineService继承ServiceBase,重写OnStart( )和重写OnStop( );
protected override void OnStart(string[] args)
{
m_server = new AsyncServer();
m_logger = new FileLogger();
m_server.SetLogger(m_logger);
m_logger.InitLogAPI(GlobalData.GetAppPath(), "OnlineServer.log");
ServerConfig config = new ServerConfig();
if (!config.ReadFile(GlobalData.GetAppPath() + "\\ServerConfig.xml"))
{
m_logger.Log("无法读取配置文件!");
return;
}
if (config.DBServerInfo == null)
{
m_logger.Log("无法从配置文件中读取数据库配置!");
return;
}
if (config.TCPServerInfo == null)
{
m_logger.Log("无法从配置文件中读取服务器配置!");
return;
}
DBGlobal.SetDBServer(config.DBServerInfo.Server, config.DBServerInfo.DBName,
config.DBServerInfo.User, config.DBServerInfo.Password);
m_server.Start(config.TCPServerInfo.IP, config.TCPServerInfo.Port);
}
protected override void OnStop()
{
if (m_server.Runing)
{
m_server.Stop();
}
}
OnlineService.Designer.cs不作修改
OnlineServiceInstaller.cs组件上添加两个控件
第一个是serviceInstaller1、第二个是serviceProcessInstaller1
OnlineServiceInstaller.Designer.cs中改写
this.serviceInstaller1.Description = "MDIA Online Server";
this.serviceInstaller1.DisplayName = "OnlineService";
this.serviceInstaller1.ServiceName = "OnlineService";
OnlineServiceInstaller.cs
[RunInstaller(true)]
public partial class OnlineServiceInstaller : Installer
{
public OnlineServiceInstaller()
{
InitializeComponent();
}
}
//public不要忘了,会出现卸载不成功或者安装不成功
onlineService.Design.cs中服务名称
namespace CmmServer
{
partial class CmmService
{
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.ServiceName = "OnlineService";
}
}
}
**OnlineServiceInstaller **类要是是公共的
OnlineService类要是公共的
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
// 同一进程中可以运行多个用户服务。若要将
// 另一个服务添加到此进程中,请更改下行以
// 创建另一个服务对象。例如,
//
// ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
//
ServicesToRun = new ServiceBase[] { new OnlineService() };
ServiceBase.Run(ServicesToRun);
}
}
总结三
服务获取AppPath时的不能再使用Windows.Form.
System.Windows.Forms.Application.StartupPath
static public string GetWindowsServiceInstallPath(string ServiceName)
{
string key = @"SYSTEM\CurrentControlSet\Services\" + ServiceName;
string path = Registry.LocalMachine.OpenSubKey(key).GetValue("ImagePath").ToString();
//替换掉双引号
path = path.Replace("\"", string.Empty);
FileInfo fi = new FileInfo(path);
return fi.Directory.ToString();
}
static public string GetAppPath()
{
string strPath = GetWindowsServiceInstallPath("OnlineService");
return strPath;
}
额外补充
生成程序如果是AnyCpu的话,在32位系统上就是32位的程序,在64位上就是64位程序,如果当SQLite是32位的时候,就会出现SQLite库的相关错误。
像这样的错误:
所生成项目的处理器架构“MSIL”与引用“System.Data.SQLite, Version=1.0.62.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86”的处理器架构“x86”不匹配
总结四
Access数据库连接报错,未在本机注册Micsoft.Access 驱动
解决办法:安装一个驱动Access驱动安装包(64位的)
ODBC驱动方式:
Driver={Microsoft Access Driver (*.mdb)};Dbq=c:somepathdbname.mdb;Uid=Admin;Pwd=pass;
微软的odbc驱动存在一些不稳定的bug,有可能导致此类错误。应该将其修改为oledb的access驱动方式。微软本身已经放弃了对odbc数据源连接方式的支持,并建议用户使用oledb方式
OLEDB驱动方式:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:somepathdbname.mdb;User Id=admin;Password=pass;
32位系统
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:somepathdbname.mdb
64位系统
Access的SQL语句和SQLServer不一样
accesss要用的是"#" +time.Text+ “#”,SQL是可以直接用单引号。
Access中* 为匹配多个字符串,但是在C#编写Access的模糊查询中必须用 %才能查询匹配%,但是,在Access中的SQL查询中只能使用 *匹配查询!
Access后缀名
.mdb Access 2007以前的版本
.accdb Access 2007以后的版本
SQL Server后缀名
备份文件是 .bak
分离出来的数数据,mdf是数据库文件,ldf是日志文件。
总结五
安装服务时,在日志里面报这个错误:
System.BadImageFormatException
解决方法:
一般有两种情况:程序目标平台不一致 & 引用dll文件的系统平台不一致。
1、程序目标平台不一致:
项目>属性>生成:x86 和x64平台
注:此种问题一般是编译错误
2、引用dll文件的系统平台不一致
程序中引用外部dll文件的目标平台的版本x86和x64不一致。
注:此种问题是运行时错误
总结6 服务自启动的方法
1、开始菜单启动
先找到“开始”菜单的“启动”关联的目录;
然后创建快捷方式到这个目录;
2、将启动的项目名称、文件位置添加到启动项即可
//添加到 当前登陆用户的 注册表启动项
RegistryKey RKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
//添加到 所有用户的 注册表启动项
RegistryKey Rkey = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
RKey.SetValue("AppName",@"C:\\AppName.exe");
AppName C:\AppName.exe
or
AppName “C:\AppName.exe”
如果你的路径中,带有空格,需要使用双引号引起来,这样能保证在启动的时候不会出现问题,如下:
// @ 符号中的双引号需要用两次来转义
RKey.SetValue("AppName", @"""C:\AppName.exe""");
3、Windows计划任务方式启动
Windows 的计划任务方式添加启动也是可以实现自启动的方式,但是个人感觉这种方式有点奇葩……
注意:任务计划需要添加引用,在 Com 中搜索 TaskScheduler,添加即可,并且要在“嵌入互操作类型”设置为false,使程序编译时,能从互操作程序集中获取 COM 类型的类型信息。