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大型分布式系统的架构设计
在大型系统中应用中,一个架构设计较好的应用系统,其总体功能肯定是由很多个功能模块所组成的,而每一个功能模块所需要的数据对应到数据库中就是一个或多个表.而在架构设计中,各个功能模块相互之间的交互点 越统 ...
随机推荐
- H5个性三级联动日期插件(一)
1. 先看效果:如图 2.如果跟你的需求一样的话,那就抓紧down(当)起来吧! 首先你的页面可能需要很多的开发需求文件: jquery,mobiscroll 等js框架插件等 自己参照官方的demo ...
- CSS3学习系列之背景相关样式(一)
新增属性: background-clip:指定背景的显示范围 background-origin:指定绘制背景图像时的起点 background-size:指定背景中图像的尺寸 background ...
- CSS学习笔记05 display属性
HTML标记一般分为块标记和行内标记两种类型,它们也称块元素和行内元素. 块元素 每个块元素通常都会独自占据一整行或多整行,可以对其设置宽度.高度.对齐等属性,常用于网页布局和网页结构的搭建.并且块级 ...
- ReactiveCocoa源码解析(四) Signal中的静态属性静态方法以及面向协议扩展
上篇博客我们聊了Signal的几种状态.Signal与Observer的关联方式以及Signal是如何向关联的Observer发送事件的.本篇博客继续上篇博客的内容,来聊一下Signal类中静态的ne ...
- 在线SVN仓库实现:金山快盘+TortoiseSVN(Win)+SCPlugin(Mac)
前段时间一直在研究SVN在线托管,也尝试了网上推荐的免费托管网站. 但毕竟是是免费的,还是要受到比如空间大小.私有性等这样那样的限制,感觉有些麻烦. 而且,比较心疼自己在本地开发的时候积累的更新日志, ...
- HDFS Java API的使用举例
HDFS是Hadoop应用程序使用的主要分布式存储.HDFS集群主要由管理文件系统元数据的NameNode和存储实际数据的DataNodes组成,HDFS架构图描述了NameNode,DataNode ...
- iOS- 解决iOS10 App启动时放大铺满App Icon的问题
0.前言 iOS10 App启动时放大铺满App图标 iPad Application shows app icon as launch screen in iOS 10 如图,点击APP后APP图标 ...
- 读书共享 Primer Plus C-part 7
第十章 数组和指针 1.关于二维数组跟指针 #include<stdio.h> int main() { ][]={{,,,},{,,,},{,,,}}; ; ;i< ;i++) ...
- kbengine 常见问题汇总
Q: KBEngine是什么,能用来做什么?A: KBEngine是一个通用网络游戏服务器引擎,适合绝大多数中心拓扑结构的网络游戏,包括但不限于即时和回合制MMORPG.副本类.房间类.卡牌.棋牌等. ...
- Wireshark初步入门
第一次捕获数据包 为了能让Wireshark得到一些数据包,你可以开始你的第一次数据包捕获实验了.你可能会想:"当网络什么问题都没有的时候,怎么能捕获数据包呢?" 首先,网络总是有 ...