WCF项目的架构设计
本文将介绍以WCF开发项目为主的架构设计,主要从类库的分类和代码的结构。
下面将以一个WCF实例做具体的介绍。此项目底层是一个Windows Service,WCF服务Hosted在此Windows Service上,WCF向外暴露REST接口供第三方调用,仅为单向通讯。
项目的目录结构如下图:
项目介绍:
***CentralService:
Windows service 项目,它是一个windows service的壳,同时定义关于此服务的权限、介绍、名称等内容,里面会调用OnStart和OnStop事件,分别关联Windows服务的启动和停止事件。具体的工作在下面的***StartEngine项目中,之所以分离开有以下两方面原因:
1.为方便调试,除在Windows服务中可以启动整个程序,一般会新建一个Console程序启动整个程序以便调试,所以启动程序最好是一个操作单元(unit,即***StartEngine项目)
2.OnStart和OnStop默认有一个超时时间(timeout),所以在启动服务时为了避免不超时一般采用另起一个新线程启动整个程序,单独做一个操作单元会很方便新线程调用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using ***.***.Remote;
using log4net; namespace ***CentralService
{
public partial class ***CentralService : ServiceBase
{
public ***CentralService()
{
InitializeComponent();
if(!System.Diagnostics.EventLog.SourceExists("***CentralServiceSource"))
{
System.Diagnostics.EventLog.CreateEventSource("***CentralServiceSource", "***CentralServiceLog");
}
eventLog1.Source = "***CentralServiceSource";
eventLog1.Log = "***CentralServiceLog";
} private ILog _log = LogManager.GetLogger(typeof (***CentralService));
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart ***CentralService.");
_log.Info("In OnStart ***CentralService.");
Thread thread = new Thread(delegate() { CentralServiceEngine.StartService(); });
thread.Start();
} protected override void OnStop()
{
eventLog1.WriteEntry("In onStop ***CentralService.");
_log.Info("In onStop ***CentralService.");
Thread thread = new Thread(delegate() { CentralServiceEngine.StopService(); });
thread.Start();
}
}
}
***StartEngine:
整个项目的启动单元
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using System.Text;
using log4net; namespace ***。***.Remote
{
public static class CentralServiceEngine
{
private static WebServiceHost host_ParameterValidateService;
private static WebServiceHost host_DomainOperateService;
private static WebServiceHost host_RemoteInstallService;
//private static Logger _logger = LogManager.CreateLogger();
private static ILog _log = LogManager.GetLogger(typeof (CentralServiceEngine)); public static void StartService()
{
_log.Info("In OnStart ***CentralService.");
try
{
int port = ;
if (!int.TryParse(CommonStaticValues.RestServicePort, out port))
{
throw new Exception(
"The configured RestServicePort value must be int type, please try http://localhost:8889 to check if the service started.");
}
string restServiceURL = "http://localhost:" + port; host_ParameterValidateService = new WebServiceHost(typeof (ParameterValidateService),
new Uri(restServiceURL + "/validate"));
ServiceEndpoint ep = host_ParameterValidateService.AddServiceEndpoint(
typeof (IParameterValidateService), new WebHttpBinding(), ""); host_DomainOperateService = new WebServiceHost(typeof (DomainOperateService),
new Uri(restServiceURL + "/domain"));
ServiceEndpoint ep1 = host_DomainOperateService.AddServiceEndpoint(typeof (IDomainOperateService),
new WebHttpBinding(), ""); host_RemoteInstallService = new WebServiceHost(typeof (RemoteInstallService),
new Uri(restServiceURL + "/remoteinstall"));
ServiceEndpoint ep2 = host_RemoteInstallService.AddServiceEndpoint(typeof (IRemoteInstallService),
new WebHttpBinding(), ""); ServiceDebugBehavior stp =
host_ParameterValidateService.Description.Behaviors.Find<ServiceDebugBehavior>();
stp.HttpHelpPageEnabled = false; ServiceDebugBehavior stp1 = host_DomainOperateService.Description.Behaviors.Find<ServiceDebugBehavior>();
stp1.HttpHelpPageEnabled = false; ServiceDebugBehavior stp2 = host_RemoteInstallService.Description.Behaviors.Find<ServiceDebugBehavior>();
stp2.HttpHelpPageEnabled = false; host_ParameterValidateService.Open();
host_DomainOperateService.Open();
host_RemoteInstallService.Open(); _log.Info("WCF Rest Service is up and running"); }
catch (Exception ex)
{
_log.Error("***CentralService occur exception.", ex);
}
Console.Read();
} public static void StopService()
{
if (host_ParameterValidateService != null)
{
host_ParameterValidateService.Close();
host_DomainOperateService.Close();
host_RemoteInstallService.Close();
//_logger.Log("Validate Service is down and closed");
_log.Info("All Services is down and closed");
for (int i = ; i < CommonStaticValues.All***BackgroundThreads.Length; i++)
{ var th = CommonStaticValues.All***BackgroundThreads[i];
if (th != null)
{
th.Abort();
th = null;
} }
}
//_logger.Log("In onStop ***CentralService.");
_log.Info("In onStop ***CentralService.");
} }
}
***WCFRestContract:
WCF服务的接口项目,包含如下内容以方便其他项目调用本项目的主要功能是:
1.定义WCF服务的接口
2.整个程序中用到的公共实体(Entity)
3.整个程序中用到的公共方法
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ***.***.Remote; namespace ***.***.Remote
{
[DataContractFormat]
[ServiceContract]
public interface IRemoteInstallService
{
//this is an example: http://localhost:8899/remoteinstall/task/6e4e5792-f654-4b0d-a97a-c84cb0d04e3b
[WebGet(UriTemplate = "Task/{id}", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string GetInstallationState(string id); //this is a test url
[WebGet(UriTemplate = "Task/Test", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string TestRemoteInstallationService(); //this is an example: http://localhost:8899/remoteinstall/Invoke?targetmachine=10.175.28.126&installerlocation="C:\Work\***exes\TroubleShooting\MA-QC48471\Clients\MachineAccountingSetup.exe"&command="C:\Work\IPSexes\TroubleShooting\MA-QC48471\Clients\MachineAccountingSetup.exe" /s /instance=-1 /v" /qn " /v"/L*v \"c:\IPS_RD\MA-Client-Installer-9b66ba27-bcb5-4909-aca8-2925a5b10e94.log\""&installertype=0
//the url must be url encode, so the true url is http://localhost:8899/remoteinstall/Invoke?targetmachine=10.175.28.126&installerlocation=%22C%3A%5CWork%5CIPSexes%5CTroubleShooting%5CMA-QC48471%5CClients%5CMachineAccountingSetup.exe%22&command=%22C%3A%5CWork%5CIPSexes%5CTroubleShooting%5CMA-QC48471%5CClients%5CMachineAccountingSetup.exe%22++%2Fs+%2Finstance%3D-1+%2Fv%5C%22+%2Fqn+%22+%2Fv%22%2FL*v+%22c%3A%5C***_RD%5CMA-Client-Installer-9b66ba27-bcb5-4909-aca8-2925a5b10e94.log%22%0D%0A&installertype=0
[WebGet(UriTemplate =
"Invoke?targetmachine={targetIPorMachineName}&installerlocation={installerLocation}&command={commandLine}&installertype={installerType}"
,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string ExecuteInstallationForTestOnHttpGetMethod(string targetIPorMachineName, string installerLocation, string commandLine,
InstallerTypeEnum installerType); //below is an example for Json data
//{
// "targetmachine": "10.175.28.126",
// "installerlocation": "\"C:\\Work\\IPSexes\\TroubleShooting\\MA-QC48471\\Clients\\MachineAccountingSetup.exe\"",
// "command": "\"C:\\Work\\IPSexes\\TroubleShooting\\MA-QC48471\\Clients\\MachineAccountingSetup.exe\" \/s \/instance=-1 \/v\" \/qn \" \/v\"\/L*v \\\"c:\\IPS_RD\\MA-Client-Installer-9b66ba27-bcb5-4909-aca8-2925a5b10e94.log\\\"\"",
// "installertype": 0
//}
[WebInvoke(Method = "POST",
UriTemplate = "ExecuteInstallation",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string ExecuteInstallation(Stream stream); [WebGet(UriTemplate = "Task/ALL", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string GetAllTask(); [WebGet(UriTemplate = "Task/Running", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string GetAllRunningTask(); [WebGet(UriTemplate = "Task/Successed", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string GetAllSuccessedTask(); [WebGet(UriTemplate = "Task/Failed", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
string GetAllFailedTask(); }
}
***WcfRestService:
WCF服务的具体实现,真正服务的实现和处理都在这个项目中。
本项目的所有方法一般只是个壳,具体的业务实现需调用***CentralServiceCore,目的是保证整个项目的稳定。
为了项目的稳定(windows service或client程序),在这里的每个方法都要做try catch,捕获所有从底层服务或本方法抛出的异常。
一般底层服务不再需要try catch异常,因为会一直抛到最上层被这个项目给抓住,多线程调用的底层方法需自己捕获并处理异常。
主要功能如下:
1.catch住整个程序的所有异常
2.记录异常等日志信息
3.记录方法调用日志信息
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using Newtonsoft.Json;
using log4net; namespace ***.***.Remote
{
public class RemoteInstallService : IRemoteInstallService
{
private ILog _log = LogManager.GetLogger(typeof (RemoteInstallService)); public string GetInstallationState(string id)
{
_log.Info(string.Format("Entry Method GetInstallationState({0})",id));
ExecuteResult executeResult = new ExecuteResult();
try
{
executeResult = new RemoteInstall().GetInstallationState(id);
}
catch (Exception exception)
{
_log.Error(exception);
executeResult.ExecuteTaskId = id;
executeResult.State = ExecuteStatusEnum.Unknow;
executeResult.Message = exception.Message;
}
string result = JsonConvert.SerializeObject(executeResult);
_log.Info(string.Format("Entry then Out Method GetInstallationState({0}), Result:{1}", id,result));
return result;
} public string ExecuteInstallationForTestOnHttpGetMethod(string targetIPorMachineName,
string installerLocation,
string commandLine,
InstallerTypeEnum installerType)
{
_log.Info(string.Format("Entry Method ExecuteInstallationForTestOnHttpGetMethod({0},{1},{2},{3})", targetIPorMachineName, installerLocation, commandLine, installerType));
ExecuteResult executeResult = new ExecuteResult();
executeResult.ExecuteTaskId = Guid.NewGuid().ToString();
try
{
executeResult = new RemoteInstall().ExecuteInstallationSync(targetIPorMachineName, installerLocation,
commandLine, executeResult.ExecuteTaskId,
installerType);
}
catch (Exception exception)
{
_log.Error(exception);
executeResult.State = ExecuteStatusEnum.Unknow;
executeResult.Message = exception.Message;
}
string result = JsonConvert.SerializeObject(executeResult);
_log.Info(string.Format("Entry then Out Method ExecuteInstallationForTestOnHttpGetMethod({0},{1},{2},{3}), Result:{4}", targetIPorMachineName, installerLocation, commandLine, installerType, result));
return result;
} public string ExecuteInstallation(System.IO.Stream stream)
{
_log.Info(string.Format("Entry Method ExecuteInstallation(),{0}", "stream type, see follow data"));
ExecuteResult executeResult = new ExecuteResult();
executeResult.ExecuteTaskId = Guid.NewGuid().ToString();
try
{
StreamReader reader = new StreamReader(stream);
string data = reader.ReadToEnd();
_log.Info(string.Format("Entry Method ExecuteInstallation({0})", data));
RemoteInstallationEntity remoteInstallationEntity;
try
{
remoteInstallationEntity =
JsonConvert.DeserializeObject<RemoteInstallationEntity>(data);
}
catch (Exception ex)
{
_log.Error(ex);
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message = string.Format("The Post data -{0}- is not valide. ERROR: {1}", data, ex);
return JsonConvert.SerializeObject(executeResult);
}
executeResult = new RemoteInstall().ExecuteInstallationASync(remoteInstallationEntity.TargetMachine,
remoteInstallationEntity.InstallerLocation,
remoteInstallationEntity.Command,
executeResult.ExecuteTaskId,
(InstallerTypeEnum)
remoteInstallationEntity.InstallerType);
}
catch (Exception exception)
{
_log.Error(exception);
executeResult.State = ExecuteStatusEnum.Unknow;
executeResult.Message = exception.Message;
}
string result = JsonConvert.SerializeObject(executeResult);
_log.Info(string.Format("Entry then Out Method ExecuteInstallation(), Result:{0}", result)); return result;
} public string GetAllTask()
{
List<ExecuteResult> list=new List<ExecuteResult>();
try
{
list = CommonStaticValues.AllTaskResultList;
}
catch (Exception ex)
{
_log.Error(ex);
}
return JsonConvert.SerializeObject(list);
} public string GetAllRunningTask()
{
List<ExecuteResult> list = new List<ExecuteResult>();
try
{
list = CommonStaticValues.AllTaskResultList.FindAll(x=>x.State==ExecuteStatusEnum.Running);
}
catch (Exception ex)
{
_log.Error(ex);
}
return JsonConvert.SerializeObject(list);
} public string GetAllSuccessedTask()
{
List<ExecuteResult> list = new List<ExecuteResult>();
try
{
list = CommonStaticValues.AllTaskResultList.FindAll(x => x.State == ExecuteStatusEnum.Successed);
}
catch (Exception ex)
{
_log.Error(ex);
}
return JsonConvert.SerializeObject(list);
} public string GetAllFailedTask()
{
List<ExecuteResult> list = new List<ExecuteResult>();
try
{
list = CommonStaticValues.AllTaskResultList.FindAll(x => x.State == ExecuteStatusEnum.Failed);
}
catch (Exception ex)
{
_log.Error(ex);
}
return JsonConvert.SerializeObject(list);
} public string TestRemoteInstallationService()
{
_log.Info(string.Format("Entry Method TestRemoteInstallationService()"));
return "Test Successed!";
}
}
}
***CentralServiceCore:
这个项目是具体的业务实现,***WcfRestService中的服务一般调用***CentralServiceCore里的方法,以方便处理异常。本项目的内容一般不需捕获异常,出了问题直接抛给了***WcfRestService,复杂的逻辑一般在这里处理。多线程的调用需要在这里做异常处理。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Castor.UniversalInstaller;
using System.Net;
using Castor.UniversalInstaller.Util;
using tinyClient;
using log4net;
using System.Threading; namespace ***.***.Remote
{
public class RemoteInstall
{
private ILog _log = LogManager.GetLogger(typeof (RemoteInstall)); public ExecuteResult GetInstallationState(string taskid)
{
ExecuteResult executeResult= CommonStaticValues.AllTaskResultList.Find(x => x.ExecuteTaskId == taskid);
if(executeResult==null)
{
executeResult=new ExecuteResult();
executeResult.ExecuteTaskId = taskid;
executeResult.State=ExecuteStatusEnum.NotFound;
executeResult.Message = string.Format("Not Found this Taskid:{0} in *** Service", taskid);
}
return executeResult;
} public ExecuteResult ExecuteInstallationSync(string targetIPorMachineName, string installerLocation, string commandLine, string taskId, InstallerTypeEnum installerType)
{
ExecuteResult executeResult = new ExecuteResult();
executeResult.ExecuteTaskId = taskId;
executeResult.State=ExecuteStatusEnum.Running;
executeResult.BeginTime = DateTime.Now;
CommonStaticValues.AllTaskResultList.Add(executeResult);
//Step 1 TODO: Run pre or post script string machineName, ip, errMessage;
Helper.TryParseComputerNameIP(targetIPorMachineName, out machineName, out ip, out errMessage);
int exitCode = ; if (machineName.ToLower().Trim() == GetCurrentMachineName().ToLower().Trim())//Local Installation
{
//executeResult = InstalledToLocalMachine(targetIPorMachineName, installerLocation, commandLine, taskId, executeResult, machineName);
ProcessStartInfo processStartInfo = new ProcessStartInfo();
if (commandLine.StartsWith("msiexec.exe", StringComparison.CurrentCultureIgnoreCase))
{
processStartInfo.FileName = "msiexec.exe";
processStartInfo.Arguments = commandLine.Substring(processStartInfo.FileName.Length + );
}
else // fix local install error
{
processStartInfo.FileName = installerLocation;
processStartInfo.Arguments = Regex.Replace(commandLine,
string.Format("[\\\"]?{0}[ \\\"]?",
installerLocation.Trim().Replace("\\", "\\\\")), "",
RegexOptions.IgnoreCase);
}
processStartInfo.UseShellExecute = false;
processStartInfo.CreateNoWindow = true; var process = Process.Start(processStartInfo);
process.WaitForExit(CommonStaticValues.InstallationTimeOutMinute);
exitCode = process.ExitCode; }
else//Remote Installation. Tiny command please refer to "psexec", please search "psexec" via google for more help.
{
string remoteLocationToDelete=string.Empty;
string command_c = string.Empty;//-c: Copy the specified program to the remote system for execution. If you omit this option the application must be in the system path on the remote system.
if (!commandLine.StartsWith("msiexec.exe", StringComparison.CurrentCultureIgnoreCase))
{
command_c = " -c";
}
else if (!installerLocation.ToLower().Contains("sbx") || installerType != InstallerTypeEnum.DatabaseInstall)
// for sbX DB products, it contains other service installers, not copy to remote machines
{
remoteLocationToDelete = Helper.CopyFileToComputer(installerLocation, targetIPorMachineName);
if (!string.IsNullOrEmpty(remoteLocationToDelete))
{
commandLine = commandLine.Replace(installerLocation, remoteLocationToDelete);
}
}
string remoteCommandLine=string.Empty;
remoteCommandLine += command_c;
remoteCommandLine += string.IsNullOrEmpty(CommonStaticValues.DomainAdmin) ?
"" :
string.Format(" -u {0} -p {1}", CommonStaticValues.DomainAdmin, CommonStaticValues.DomainPassword); remoteCommandLine = string.Format(@"\\{0} execute {1} {2}", targetIPorMachineName, remoteCommandLine, commandLine); var tinyHelper = new TinyHelper();
var args = tinyHelper.SplitCommandLineArgument(remoteCommandLine);
TinyParameter tp = tinyHelper.CommandLineParser(args);
TinyResponse rsp = new TinyResponse();
try
{
tinyHelper.StartRemoteService(tp);
rsp = tinyHelper.ExecuteCommand(tp);
}
finally
{
try
{
// Ignore error in stopping service error:
tinyHelper.StopService(tp);
}
catch (Exception ex)
{
_log.Error(string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, ErrorMessage: {4}",
targetIPorMachineName, installerLocation, commandLine, taskId,
ex.Message));
}
}
exitCode = rsp.CmdRetCode == ? rsp.TinyRetCode : rsp.CmdRetCode; // delete the temperary installer if it exists
try
{
if (File.Exists(remoteLocationToDelete))
File.Delete(remoteLocationToDelete);
}
catch { }
} if (ExitCodeHelper.IsSucess(exitCode))
{
executeResult.State = ExecuteStatusEnum.Successed;
}
else
{
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message =
string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, Exit code: {4}",
targetIPorMachineName, installerLocation, commandLine, taskId,
ExitCodeHelper.GetExitCodeFormatedMessage(exitCode));
_log.Error(executeResult.Message);
} return executeResult;
} public ExecuteResult ExecuteInstallationASync(string targetIPorMachineName, string installerLocation, string commandLine, string taskId, InstallerTypeEnum installerType)
{
ExecuteResult executeResult = new ExecuteResult(); int currentAvaliableThreadIndex = CommonStaticValues.GetAvaliableThreadIndex();
if (currentAvaliableThreadIndex == int.MaxValue)
{
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message =
string.Format(
"There are more than {0} tasks being work now, please wait 10 minutes to retry your task, or change the MaxInvokeInstallationThreadCount in config file, or contact the administrator for help.",
CommonStaticValues.AllIPSBackgroundThreads.Length);
return executeResult;
}
executeResult.ExcuteThreadIndex = currentAvaliableThreadIndex;
executeResult.ExecuteTaskId = taskId;
executeResult.State = ExecuteStatusEnum.Running;
executeResult.BeginTime = DateTime.Now;
CommonStaticValues.AllTaskResultList.Add(executeResult);
//Step 1 TODO: Run pre or post script string machineName, ip, errMessage;
Helper.TryParseComputerNameIP(targetIPorMachineName, out machineName, out ip, out errMessage); if (machineName.ToLower().Trim() == GetCurrentMachineName().ToLower().Trim()) //Local Installation
{
CommonStaticValues.AllIPSBackgroundThreads[currentAvaliableThreadIndex] =
new Thread(delegate()
{
try
{
ExecuteInstallationOnLocalMachine(executeResult, machineName,
targetIPorMachineName, installerLocation,
commandLine);
}
catch (Exception exception)
{
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message =
string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, ERROR MESSAGE: {4}",
targetIPorMachineName, installerLocation, commandLine,
executeResult.ExecuteTaskId,
exception.Message); _log.Error(
"ExecuteInstallationASync-ExecuteInstallationOnLocalMachine ERROR:",
exception);
}
executeResult.EndTime = DateTime.Now;
});
CommonStaticValues.AllIPSBackgroundThreads[currentAvaliableThreadIndex].Start(); }
else
//Remote Installation. Tiny command please refer to "psexec", please search "psexec" via google for more help.
{
CommonStaticValues.AllIPSBackgroundThreads[currentAvaliableThreadIndex] =
new Thread(delegate()
{
try
{
ExecuteInstallationOnRemoteMachine(executeResult, machineName,
targetIPorMachineName, installerLocation,
commandLine, installerType); }
catch (Exception exception)
{
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message =
string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, ERROR MESSAGE: {4}",
targetIPorMachineName, installerLocation, commandLine,
executeResult.ExecuteTaskId,
exception.Message); _log.Error("ExecuteInstallationASync-ExecuteInstallationOnRemoteMachine ERROR:", exception);
}
executeResult.EndTime = DateTime.Now;
});
CommonStaticValues.AllIPSBackgroundThreads[currentAvaliableThreadIndex].Start();
} return executeResult;
} private void ExecuteInstallationOnLocalMachine(ExecuteResult executeResult, string machineName, string deliveredIPorMachineName, string installerLocation, string commandLine)
{
ProcessStartInfo processStartInfo = new ProcessStartInfo();
if (commandLine.StartsWith("msiexec.exe", StringComparison.CurrentCultureIgnoreCase))
{
processStartInfo.FileName = "msiexec.exe";
processStartInfo.Arguments = commandLine.Substring(processStartInfo.FileName.Length + );
}
else // fix local install error
{
processStartInfo.FileName = installerLocation;
processStartInfo.Arguments = Regex.Replace(commandLine,
string.Format("[\\\"]?{0}[ \\\"]?",
installerLocation.Trim().Replace("\\", "\\\\")), "",
RegexOptions.IgnoreCase);
}
processStartInfo.UseShellExecute = false;
processStartInfo.CreateNoWindow = true; _log.Debug(string.Format("Run Method ExecuteInstallationOnLocalMachine, processStartInfo.FileName:{0}, processStartInfo.Arguments:{1}", processStartInfo.FileName, processStartInfo.Arguments));
var process = Process.Start(processStartInfo);
process.WaitForExit(CommonStaticValues.InstallationTimeOutMinute);
int exitCode = process.ExitCode;
if (ExitCodeHelper.IsSucess(exitCode))
{
executeResult.State = ExecuteStatusEnum.Successed;
}
else
{
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message =
string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, Exit code: {4}",
deliveredIPorMachineName, installerLocation, commandLine, executeResult.ExecuteTaskId,
ExitCodeHelper.GetExitCodeFormatedMessage(exitCode));
_log.Error(executeResult.Message);
}
} private void ExecuteInstallationOnRemoteMachine(ExecuteResult executeResult, string machineName, string deliveredIPorMachineName, string installerLocation, string commandLine, InstallerTypeEnum installerType)
{
string remoteLocationToDelete = string.Empty;
string command_c = string.Empty;//-c: Copy the specified program to the remote system for execution. If you omit this option the application must be in the system path on the remote system.
if (!commandLine.StartsWith("msiexec.exe", StringComparison.CurrentCultureIgnoreCase))
{
command_c = " -c";
}
else if (!installerLocation.ToLower().Contains("sbx") || installerType != InstallerTypeEnum.DatabaseInstall)
// for sbX DB products, it contains other service installers, not copy to remote machines
{
remoteLocationToDelete = Helper.CopyFileToComputer(installerLocation, machineName);
if (!string.IsNullOrEmpty(remoteLocationToDelete))
{
commandLine = commandLine.Replace(installerLocation, remoteLocationToDelete);
}
}
string remoteCommandLine = string.Empty;
remoteCommandLine += command_c;
remoteCommandLine += string.IsNullOrEmpty(CommonStaticValues.DomainAdmin) ?
"" :
string.Format(" -u {0} -p {1}", CommonStaticValues.DomainAdmin, CommonStaticValues.DomainPassword); remoteCommandLine = string.Format(@"\\{0} execute {1} {2}", machineName, remoteCommandLine, commandLine); var tinyHelper = new TinyHelper();
var args = tinyHelper.SplitCommandLineArgument(remoteCommandLine);
TinyParameter tp = tinyHelper.CommandLineParser(args);
TinyResponse rsp = new TinyResponse();
try
{
tinyHelper.StartRemoteService(tp);
rsp = tinyHelper.ExecuteCommand(tp);
}
finally
{
try
{
// Ignore error in stopping service error:
tinyHelper.StopService(tp);
}
catch (Exception ex)
{
_log.Error(string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, ErrorMessage: {4}",
deliveredIPorMachineName, installerLocation, commandLine, executeResult.ExecuteTaskId,
ex.Message));
}
}
int exitCode = rsp.CmdRetCode == ? rsp.TinyRetCode : rsp.CmdRetCode; // delete the temperary installer if it exists
try
{
if (File.Exists(remoteLocationToDelete))
File.Delete(remoteLocationToDelete);
}
catch { } if (ExitCodeHelper.IsSucess(exitCode))
{
executeResult.State = ExecuteStatusEnum.Successed;
}
else
{
executeResult.State = ExecuteStatusEnum.Failed;
executeResult.Message =
string.Format(
"Failed on install targetIPorMachineName: {0}, installerLocation: {1}, commandLine: {2}, taskId: {3}, Exit code: {4}",
deliveredIPorMachineName, installerLocation, commandLine, executeResult.ExecuteTaskId,
ExitCodeHelper.GetExitCodeFormatedMessage(exitCode));
_log.Error(executeResult.Message);
}
} private string GetCurrentMachineName()
{
string currentName = Dns.GetHostName();
return currentName.Contains(".") ? currentName.Substring(, currentName.IndexOf(".")) : currentName;
} }
}
WCF项目的架构设计的更多相关文章
- Redis缓存项目应用架构设计二
一.概述 由于架构设计一里面如果多平台公用相同Key的缓存更改配置后需要多平台上传最新的缓存配置文件来更新,比较麻烦,更新了架构设计二实现了缓存配置的集中管理,不过这样有有了过于中心化的问题,后续在看 ...
- python-django电商项目-需求分析架构设计数据库设计_20191115
python-django电商项目需求分析 1.用户模块 1)注册页 注册时校验用户名是否已被注册. 完成用户信息的注册. 给用户的注册邮箱发送邮件,用户点击邮件中的激活链接完成用户账户的激活. 2) ...
- Redis缓存项目应用架构设计一
一些项目整理出的项目中引入缓存的架构设计方案,希望能帮助你更好地管理项目缓存,作者水平有限,如有不足还望指点. 一.基础结构介绍 项目中对外提供方法的是CacheProvider和MQProvider ...
- vue项目的架构设计完善详解
vue项目构建vuex+mock层 vue项目添加jsBridge(与原生交互的) vue项目添加代码格式化
- 架构设计(ASP.NET MVC+Knockout+Web API+SignalR)
最近忙于重构项目的架构设计,没有时间发博客,也没有时间回复邮件及博文评论,忘各位见谅: 今天先发布架构设计图,同样没有时间写相关的介绍也没有时间回复评论,所以就不发在首页,希望给看到的朋友一些参考,同 ...
- 微信小程序全面实战,架构设计 && 躲坑攻略(小程序入门捷径教程)
最近集中开发了两款微信小程序,分别是好奇心日历(每天一条辞典+一个小投票)和好奇心日报(轻量版),直接上图: Paste_Image.png 本文将结合具体的实战经验,主要介绍微信小程序的基础知识.开 ...
- 架构设计的UML图形思考
本篇紧接着上一篇 基本OOP知识 ,介绍高焕堂老师的第二讲. 架构设计的UML图形思考.本篇最重要的是三个词语:图形.思考.UML. 架构师的作用体现主要在项目开发前期.在整个项目还没有完毕的时 ...
- APP和服务端-架构设计(一)
架构因人而异,不同的架构师大多会有不同的看法:架构也因项目而异,不同的项目需求不同,相应的架构也会不同.然而,有些东西还是通用的,是所有架构师都需要考虑的,也是所有项目都会有的需求,比如API如何设计 ...
- 基于WCF大型分布式系统的架构设计
在大型系统中应用中,一个架构设计较好的应用系统,其总体功能肯定是由很多个功能模块所组成的,而每一个功能模块所需要的数据对应到数据库中就是一个或多个表.而在架构设计中,各个功能模块相互之间的交互点 越统 ...
随机推荐
- React 在服务端渲染的实现
原文地址:Server-Side React Rendering 原文作者:Roger Jin 译者:牧云云 React 在服务端渲染的实现 React是最受欢迎的客户端 JavaScript 框架, ...
- 6.解决AXIOS的跨域问题
在服务端加上: response.addHeader("Access-Control-Allow-Origin", "*"); response.addHead ...
- Linux内核的基本概念
Linux内核学习,推荐的书籍: <linux设备驱动开发详解第二版>.<Linux内核设计与实现第三版>.<嵌入式Linux应用开发完全手册> 第一篇:讲解Lin ...
- tp框架为什么验证码加载不出来?----- ob_clean() 可解决
在用tp做验证码时,代码逻辑都正确,但就是加载不出图片来,如何解决呢?在创建验证码之前加上 ob_clean(); public function haha(){ ob_clean(); $v = n ...
- 快学Scala之继承
## 1. 继承 Scala语言通过 extends 关键字来继承类. 那么继承一个类有什么好处呢? 子类除了拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的), 还可 ...
- Chrome浏览器扩展开发系列之十一:NPAPI插件的使用
在Chrome浏览器扩展中使用HTML和JavaScript非常容易,但是如何重用已有的非JavaScript遗留系统代码呢?答案是将NPAPI插件绑定到Chrome浏览器扩展,从而实现在Chrome ...
- 使用gulp实现文件压缩及浏览器热加载
一.安装gulp 首先,你要安装过nodejs,如果没有安装过的同学请自行下载. 先再命令行里输入 npm install gulp -g 下载gulp 二.创建gulp项目 创建一个你需要 ...
- Struts 之 通配符 路径匹配 常量用法 配置默认值
Struts 框架学习 Action的开发的几种方式 方式1 : 继承ActionSupport 如果使用Struts校验功能,必须继承此类 方式2 : 实现Action接口 方式3 :不继承 ...
- java 重载与重写 【转】
首先我们来讲讲:重载(Overloading) (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态 ...
- Bootstrap提示框
前面的话 提示框是一个比较常见的功能,一般来说是鼠标移动到特定元素上时,显示相关的提示语.本文将详细介绍Bootstrap提示框 基本用法 Bootstrap框架中的提示框,结构非常简单,常常使用的是 ...