public static void Initialize(TestContext context) { ODInitialize.IsRunningInUnitTest = true; //Causes FormFriendlyException to throw rather than displaying a MessageBox. ODInitialize.Initialize(); if (!UnitTestsCore.DatabaseTools.SetDbConnection(UnitTestDbName, "localhost", "3306", "root", "", false)) //Put this in a config file in the future. { UnitTestsCore.DatabaseTools.SetDbConnection("", "localhost", "3306", "root", "", false); DatabaseTools.FreshFromDump("localhost", "3306", "root", "", false); //this also sets database to be unittest. } else { //Clear the database before running the unittests (instead of after) for two reasons //1- if the cleanup is done using [TestCleanup], the cleanup will not be run if the user cancels in the middle of a test while debugging //2- if a test fails, we may want to look at the data in the db to see why it failed. UnitTestsCore.DatabaseTools.ClearDb(); } if (!ODBuild.IsDebug()) { throw new Exception("Active solution configuration must be set to Debug for running unit tests."); } CreateAndSetUnitTestUser(); RevertMiddleTierSettingsIfNeeded(); //Set initial connection }
static void Main(string[] args) { if (ODBuild.IsWeb()) { //allows open dental to run in a web browser Web.Start(); //allows open dental to send data to the browser ODCloudClient.SendDataToBrowser = OpenDental.Thinfinity.Browser.SendData; } //Application.EnableVisualStyles() uses version 6 of comctl32.dll instead of version 5. See https://support.microsoft.com/en-us/kb/2892345 //See also http://stackoverflow.com/questions/8335983/accessviolationexception-on-tooltip-that-faults-comctl32-dll-net-4-0 Application.EnableVisualStyles(); //This line fixes rare AccessViolationExceptions for ToolTips on our ValidDate boxes, ValidDouble boxes, etc... try { ODInitialize.Initialize(); Security.CurComputerName = Environment.MachineName; } catch (Exception e) { FriendlyException.Show("Critical Error: " + e.Message, e, "Quit"); return; } //Register an EventHandler which handles unhandled exceptions. //AppDomain.CurrentDomain.UnhandledException+=new UnhandledExceptionEventHandler(OnUnhandeledExceptionPolicy); bool isSecondInstance = false; //or more. Process[] processes = Process.GetProcesses(); for (int i = 0; i < processes.Length; i++) { if (processes[i].Id == Process.GetCurrentProcess().Id) { continue; } //we have to do it this way because during debugging, the name has vshost tacked onto the end. if (processes[i].ProcessName.StartsWith("OpenDental")) { isSecondInstance = true; break; } } /* * if(args.Length>0) {//if any command line args, then we will attempt to reuse an existing OD window. * if(isSecondInstance){ * FormCommandLinePassOff formCommandLine=new FormCommandLinePassOff(); * formCommandLine.CommandLineArgs=new string[args.Length]; * args.CopyTo(formCommandLine.CommandLineArgs,0); * Application.Run(formCommandLine); * return; * } * }*/ Application.SetCompatibleTextRenderingDefault(false); //designer uses new text rendering. This makes the exe use matching text rendering. Before this was added, it was common for labels to be longer in the running program than they were in the designer. Application.EnableVisualStyles(); //changes appearance to XP Application.DoEvents(); string[] cla = new string[args.Length]; args.CopyTo(cla, 0); FormOpenDental formOD = new FormOpenDental(cla); Exception submittedException = null; Action <Exception, string> onUnhandled = new Action <Exception, string>((e, threadName) => { //Try to automatically submit a bug report to HQ. string displayMsg = ""; try { //We want to submit a maximum of one exception per instance of OD. if (submittedException == null) { submittedException = e; BugSubmissions.SubmitException(e, out displayMsg, threadName, FormOpenDental.CurPatNum, formOD.GetSelectedModuleName()); } } catch (Exception ex) { ex.DoNothing(); } FriendlyException.Show((displayMsg.IsNullOrEmpty()) ? "Critical Error: " + e.Message : displayMsg, e, "Quit"); formOD.ProcessKillCommand(); }); CodeBase.ODThread.RegisterForUnhandledExceptions(formOD, onUnhandled); formOD.IsSecondInstance = isSecondInstance; Application.AddMessageFilter(new ODGlobalUserActiveHandler()); Application.ThreadException += new ThreadExceptionEventHandler((object s, ThreadExceptionEventArgs e) => { onUnhandled(e.Exception, "ProgramEntry"); }); Application.Run(formOD); }
///<summary>Pass in a serialized dto. It returns a dto which must be deserialized by the client. ///Set serverMapPath to the root directory of the OpenDentalServerConfig.xml. Typically Server.MapPath(".") from a web service. ///Optional parameter because it is not necessary for Unit Tests (mock server).</summary> public static string ProcessDto(string dtoString, string serverMapPath = "") { try { #region Normalize DateTime if (!_isMiddleTierInitialized) { //If this fails, the exception will throw and be serialized and sent to the client. ODInitialize.Initialize(); //Because Security._curUserT is a thread static field, we need to make sure that any new threads that are spawned have that field set. ODThread.AddInitializeHandler <Userod>(() => Security.CurUser.Copy(), user => Security.CurUser = user); //Same thing for PasswordTyped. ODThread.AddInitializeHandler <string>(() => Security.PasswordTyped, password => Security.PasswordTyped = password); //Ditto for CurComputerName ODThread.AddInitializeHandler <string>(() => Security.CurComputerName, computerName => Security.CurComputerName = computerName); //Calling CDT.Class1.Decrypt will cause CDT to verify the assembly and then save the encryption key. This needs to be done here because //if we later call CDT.Class1.Decrypt inside a thread, we won't we able to find OpenDentalServer.dll in the call stack. ODException.SwallowAnyException(() => CDT.Class1.Decrypt("odv2e$fakeciphertext", out _)); _isMiddleTierInitialized = true; } #endregion #region Initialize Database Connection //Always attempt to set the database connection settings from the config file if they haven't been set yet. //We use to ONLY load in database settings when Security.LogInWeb was called but that is not good enough now that we have more services. //E.g. We do not want to manually call "Security.LogInWeb" from the CEMT when all we want is a single preference value. if (string.IsNullOrEmpty(DataConnection.GetServerName()) && string.IsNullOrEmpty(DataConnection.GetConnectionString())) { RemotingClient.RemotingRole = RemotingRole.ServerWeb; //the application virtual path is usually /OpenDentalServer, but may be different if hosting multiple databases on one IIS server string configFilePath = ""; if (!string.IsNullOrWhiteSpace(HostingEnvironment.ApplicationVirtualPath) && HostingEnvironment.ApplicationVirtualPath.Length > 1) { //There can be multiple config files within a physical path that is shared by multiple IIS ASP.NET applications. //In order for the same physical path to host multiple applications, they each need a unique config file for db connection settings. //Each application will have a unique ApplicationVirtualPath which we will use to identify the corresponding config.xml. configFilePath = ODFileUtils.CombinePaths(serverMapPath, HostingEnvironment.ApplicationVirtualPath.Trim('/') + "Config.xml"); } if (string.IsNullOrWhiteSpace(configFilePath) || !File.Exists(configFilePath)) //returns false if the file doesn't exist, user doesn't have permission for file, path is blank or null { //either configFilePath not set or file doesn't exist, default to OpenDentalServerConfig.xml configFilePath = ODFileUtils.CombinePaths(serverMapPath, "OpenDentalServerConfig.xml"); } Userods.LoadDatabaseInfoFromFile(configFilePath); } #endregion DataTransferObject dto = DataTransferObject.Deserialize(dtoString); DtoInformation dtoInformation = new DtoInformation(dto); if (dtoInformation.FullNameComponents.Length == 3 && dtoInformation.FullNameComponents[2].ToLower() == "hashpassword") { return(dtoInformation.GetHashPassword()); } //Set Security.CurUser so that queries can be run against the db as if it were this user. Security.CurUser = Userods.CheckUserAndPassword(dto.Credentials.Username, dto.Credentials.Password , Programs.UsingEcwTightOrFullMode()); Security.PasswordTyped = dto.Credentials.Password; //Set the computer name so securitylog entries use the client's computer name instead of the middle tier server name //Older clients might not include ComputerName in the dto, so we need to make sure it's not null. Security.CurComputerName = dto.ComputerName ?? ""; Type type = dto.GetType(); #region DtoGetTable if (type == typeof(DtoGetTable)) { DataTable dt = (DataTable)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(XmlConverter.TableToXml(dt)); } #endregion #region DtoGetTableLow else if (type == typeof(DtoGetTableLow)) { DataTable dt = Reports.GetTable((string)dtoInformation.ParamObjs[0]); return(XmlConverter.TableToXml(dt)); } #endregion #region DtoGetDS else if (type == typeof(DtoGetDS)) { DataSet ds = (DataSet)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(XmlConverter.DsToXml(ds)); } #endregion #region DtoGetSerializableDictionary else if (type == typeof(DtoGetSerializableDictionary)) { Object objResult = dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); Type returnType = dtoInformation.MethodInfo.ReturnType; return(XmlConverterSerializer.Serialize(returnType, objResult)); } #endregion #region DtoGetLong else if (type == typeof(DtoGetLong)) { long longResult = (long)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(longResult.ToString()); } #endregion #region DtoGetInt else if (type == typeof(DtoGetInt)) { int intResult = (int)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(intResult.ToString()); } #endregion #region DtoGetDouble else if (type == typeof(DtoGetDouble)) { double doubleResult = (double)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(doubleResult.ToString()); } #endregion #region DtoGetVoid else if (type == typeof(DtoGetVoid)) { dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return("0"); } #endregion #region DtoGetObject else if (type == typeof(DtoGetObject)) { if (dtoInformation.ClassName == "Security" && dtoInformation.MethodName == "LogInWeb") { dtoInformation.Parameters[2] = new DtoObject(serverMapPath, typeof(string)); //because we can't access this variable from within OpenDentBusiness. RemotingClient.RemotingRole = RemotingRole.ServerWeb; //We just changed the number of parameters so we need to regenerate ParamObjs. dtoInformation.ParamObjs = DtoObject.GenerateObjects(dtoInformation.Parameters); } Object objResult = dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); Type returnType = dtoInformation.MethodInfo.ReturnType; if (returnType.IsInterface) { objResult = new DtoObject(objResult, objResult?.GetType() ?? returnType); returnType = typeof(DtoObject); } return(XmlConverterSerializer.Serialize(returnType, objResult)); } #endregion #region DtoGetString else if (type == typeof(DtoGetString)) { string strResult = (string)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(XmlConverter.XmlEscape(strResult)); } #endregion #region DtoGetBool else if (type == typeof(DtoGetBool)) { bool boolResult = (bool)dtoInformation.MethodInfo.Invoke(null, dtoInformation.ParamObjs); return(boolResult.ToString()); } #endregion else { throw new NotSupportedException("Dto type not supported: " + type.FullName); } } catch (Exception e) { DtoException exception = new DtoException(); if (e.InnerException == null) { exception = GetDtoException(e); } else { exception = GetDtoException(e.InnerException); } return(exception.Serialize()); } }