我在 VS2010 中创建了一个包含多个服务的 Windows 服务项目。我试图找出一种无需复杂安装程序即可安装它的方法。但是,它似乎回滚并且不起作用。
这是 Program.cs:
static class Program
{
static void Main(string[] args)
{
bool install = false, uninstall = false, console = false;
WindowsServiceInstaller inst = new WindowsServiceInstaller();
if (args.Length > 0)
{
foreach (string arg in args)
{
switch (arg)
{
case "-i":
case "-install":
install = true;
break;
case "-u":
case "-uninstall":
uninstall = true;
break;
case "-c":
case "-console":
console = true;
break;
default:
Console.Error.WriteLine("Argument not expected: " + arg);
break;
}
}
}
if (uninstall)
{
inst.InstallServices(false, args);
}
if (install)
{
inst.InstallServices(true, args);
}
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
// scans Email table for outbound email jobs; uses multiple threads to lock and work on data in Email table
new EmailLogScanner()
// generates email digest of document status on secheduled basis; single thread
, new EmailStatusDigester()
// keeps Fax table and third-party fax service accounts synchronized; uses a fixed nb of threads, one thread syncs one account at a time
, new FaxSynchronizer()
};
if (console)
{
foreach (IDebuggableService srv in ServicesToRun)
{
string[] strs = new string[] { String.Empty };
srv.DebugStart(strs);
}
Console.WriteLine("Press any key to terminate...");
Console.ReadKey();
foreach (IDebuggableService srv in ServicesToRun)
{
srv.DebugStop();
}
Console.WriteLine("Service has exited.");
}
else
{
ServiceBase.Run(ServicesToRun);
}
}
}
这是 WindowsServiceInstaller.cs:
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
public WindowsServiceInstaller()
{
ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
serviceProcessInstaller.Account = ServiceAccount.NetworkService;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;
Installers.Add(serviceProcessInstaller);
ServiceInstaller emailLogScannerInstaller = new ServiceInstaller();
emailLogScannerInstaller.DisplayName = "Email Scanner";
emailLogScannerInstaller.StartType = ServiceStartMode.Automatic;
emailLogScannerInstaller.ServiceName = "EmailLogScanner"; // must match the ServiceBase ServiceName property
emailLogScannerInstaller.Description = "Scan for and sends out pending emails in stack.";
Installers.Add(emailLogScannerInstaller);
ServiceInstaller emailStatusDigesterInstaller = new ServiceInstaller();
emailStatusDigesterInstaller.DisplayName = "Status Digester";
emailStatusDigesterInstaller.StartType = ServiceStartMode.Automatic;
emailStatusDigesterInstaller.ServiceName = "EmailDigester";
emailStatusDigesterInstaller.Description = "Prepares document status email digests.";
Installers.Add(emailStatusDigesterInstaller);
ServiceInstaller faxSynchronizerInstaller = new ServiceInstaller();
faxSynchronizerInstaller.DisplayName = "Fax Synchronizer";
faxSynchronizerInstaller.StartType = ServiceStartMode.Automatic;
faxSynchronizerInstaller.ServiceName = "FaxSynchronizer";
faxSynchronizerInstaller.Description = "Synchronizes database with external fax service(s).";
Installers.Add(faxSynchronizerInstaller);
}
public void InstallServices(bool doInstall, string[] args)
{
try
{
using (AssemblyInstaller aInstaller = new AssemblyInstaller(typeof(Program).Assembly, args))
{
IDictionary state = new Hashtable();
aInstaller.UseNewContext = true;
try
{
if (doInstall)
{
aInstaller.Install(state);
aInstaller.Commit(state);
}
else
{
aInstaller.Uninstall(state);
}
}
catch
{
try
{
aInstaller.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
}
记录的输出(当我在命令窗口中以管理员身份运行 daemon.exe -i
时)显示以下文本。此外,我还收到“无法从命令行启动服务”对话框:
Installing assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
i =
assemblypath = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe
logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog
Installing service EmailLogScanner...
Service EmailLogScanner has been successfully installed.
Creating EventLog source EmailLogScanner in log Application...
See the contents of the log file for the C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe assembly's progress.
The file is located at C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog.
Rolling back assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
logtoconsole =
i =
assemblypath = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe
logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.InstallLog
Restoring event log to previous state for source EmailLogScanner.
Service EmailLogScanner is being removed from the system...
Service EmailLogScanner was successfully removed from the system.
更新:当我注释掉“aInstaller.Install(state)”行周围的 try...catch block 时,我得到的输出略有不同:
Installing assembly 'C:\Users\xxx\Documents\~Business\Projects\Daemon\bin\Release\Daemon.exe'.
Affected parameters are:
i =
assemblypath = C:\Users\xxx\Documents\~Business\Projects\Da
emon\bin\Release\Daemon.exe
logfile = C:\Users\xxx\Documents\~Business\Projects\Daemon\
bin\Release\Daemon.InstallLog
Installing service EmailLogScanner...
Creating EventLog source EmailLogScanner in log Application...
Source EmailLogScanner already exists on the local computer.
是因为我已经设置了事件日志源吗?如果是这样,如何跳过 AssemblyInstaller 中的该步骤?如果不是,什么? :)
最佳答案
你应该放这个
if (EventLog.SourceExists("YourEventSourceName"))
EventLog.DeleteEventSource("YourEventSourceName");
服务安装开始时。
关于c# - 尝试安装 Windows 服务 - 此代码有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8073699/