本文將介紹以WCF開(kāi)發(fā)項(xiàng)目為主的架構(gòu)設(shè)計(jì),主要從類(lèi)庫(kù)的分類(lèi)和代碼的結(jié)構(gòu)。
下面將以一個(gè)WCF實(shí)例做具體的介紹。此項(xiàng)目底層是一個(gè)Windows Service,WCF服務(wù)Hosted在此Windows Service上,WCF向外暴露REST接口供第三方調(diào)用,僅為單向通訊。
項(xiàng)目的目錄結(jié)構(gòu)如下圖:
?
項(xiàng)目介紹:
***CentralService: Windows service 項(xiàng)目,它是一個(gè)windows service的殼,同時(shí)定義關(guān)于此服務(wù)的權(quán)限、介紹、名稱(chēng)等內(nèi)容,里面會(huì)調(diào)用OnStart和OnStop事件,分別關(guān)聯(lián)Windows服務(wù)的啟動(dòng)和停止事件。具體的工作在下面的***StartEngine項(xiàng)目中,之所以分離開(kāi)有以下兩方面原因: 1.為方便調(diào)試,除在Windows服務(wù)中可以啟動(dòng)整個(gè)程序,一般會(huì)新建一個(gè)Console程序啟動(dòng)整個(gè)程序以便調(diào)試,所以啟動(dòng)程序最好是一個(gè)操作單元(unit,即***StartEngine項(xiàng)目) 2.OnStart和OnStop默認(rèn)有一個(gè)超時(shí)時(shí)間(timeout),所以在啟動(dòng)服務(wù)時(shí)為了避免不超時(shí)一般采用另起一個(gè)新線程啟動(dòng)整個(gè)程序,單獨(dú)做一個(gè)操作單元會(huì)很方便新線程調(diào)用
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();}}
} View Code ?
***StartEngine: 整個(gè)項(xiàng)目的啟動(dòng)單元
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 =
8889 ; 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 =
0 ; 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. " );}}
} View Code ?
***WCFRestContract: WCF服務(wù)的接口項(xiàng)目,包含如下內(nèi)容以方便其他項(xiàng)目調(diào)用本項(xiàng)目的主要功能是: 1.定義WCF服務(wù)的接口 2.整個(gè)程序中用到的公共實(shí)體(Entity) 3.整個(gè)程序中用到的公共方法
?
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();}
} View Code ?
?
***WcfRestService: WCF服務(wù)的具體實(shí)現(xiàn),真正服務(wù)的實(shí)現(xiàn)和處理都在這個(gè)項(xiàng)目中。 本項(xiàng)目的所有方法一般只是個(gè)殼,具體的業(yè)務(wù)實(shí)現(xiàn)需調(diào)用***CentralServiceCore,目的是保證整個(gè)項(xiàng)目的穩(wěn)定。 為了項(xiàng)目的穩(wěn)定(windows service或client程序),在這里的每個(gè)方法都要做try catch,捕獲所有從底層服務(wù)或本方法拋出的異常。 一般底層服務(wù)不再需要try catch異常,因?yàn)闀?huì)一直拋到最上層被這個(gè)項(xiàng)目給抓住,多線程調(diào)用的底層方法需自己捕獲并處理異常。 主要功能如下: 1.catch住整個(gè)程序的所有異常 2.記錄異常等日志信息 3.記錄方法調(diào)用日志信息
?
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! " ;}}
} View Code ?
***CentralServiceCore: 這個(gè)項(xiàng)目是具體的業(yè)務(wù)實(shí)現(xiàn),***WcfRestService中的服務(wù)一般調(diào)用***CentralServiceCore里的方法,以方便處理異常。本項(xiàng)目的內(nèi)容一般不需捕獲異常,出了問(wèn)題直接拋給了***WcfRestService,復(fù)雜的邏輯一般在這里處理。多線程的調(diào)用需要在這里做異常處理。
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 =
0 ; 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 +
1 );} 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 ==
0 ?
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 +
1 );} 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 ==
0 ?
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(
0 , currentName.IndexOf(
" . " )) : currentName;}}
} View Code ?
轉(zhuǎn)載于:https://www.cnblogs.com/zhengshuangliang/p/4243935.html
總結(jié)
以上是生活随笔 為你收集整理的WCF项目的架构设计 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。