示例#1
0
        ///<summary>Launches a splash screen with a progressbar that will listen specifically for ODEvents with the passed in name.
        ///Returns an ODProgressWindow that has a Close method that should be invoked whenever the progress window should close.
        ///eventName should be set to the name of the ODEvents that this specific progress window should be processing.</summary>
        ///<param name="currentForm">The form to activate once the progress is done. If you cannot possibly pass in a form, it is okay to pass in null.
        ///</param>
        public static ODProgressWindow ShowProgressSplash(string eventName, Form currentForm)
        {
            //Create a splash form with a progress bar on a separate thread to avoid UI lockups
            bool       isFormClosed = false;
            FormSplash FormS        = new FormSplash(eventName);

            FormS.FormClosed += new FormClosedEventHandler((obj, e) => {
                isFormClosed = true;
            });
            ODThread odThread = new ODThread(new ODThread.WorkerDelegate((ODThread o) => {
                //From this point forward, the only way to kill FormSplash is with a DEFCON 1 message via an ODEvent with the corresponding eventName.
                FormS.ShowDialog();
            }));

            odThread.SetApartmentState(ApartmentState.STA);
            odThread.AddExceptionHandler(new ODThread.ExceptionDelegate((Exception e) => { }));            //Do nothing.
            odThread.Name = "ProgressSplashThread_" + eventName;
            odThread.Start(true);
            return(new ODProgressWindow(new Action(() => {
                //For progress threads, there is a race condition where the DEFCON 1 event will not get processed.
                //This is due to the fact that it took the thread longer to instantiate FormProgressStatus than it took the calling method to invoke this action.
                //Since we don't have access to FormProgressStatus within the thread from here, we simply flag odThread's Tag so that it knows to die.
                if (odThread != null)
                {
                    odThread.Tag = true;
                }
                //Send the phrase that closes the window in case it is processing events.
                SplashProgressEvent.Fire(new ODEventArgs(eventName, "DEFCON 1"));
                if (currentForm != null)
                {
                    //When the form closed on the other thread it was sometimes causing the application to go behind other applications. Calling Activate()
                    //brings the application back to the front or causes it to flash in the taskbar.
                    DateTime start = DateTime.Now;
                    while (!isFormClosed && (DateTime.Now - start).TotalSeconds < 1)                   //Wait till the form is closed or for one second
                    {
                        Thread.Sleep(1);
                    }
                    if (!currentForm.IsDisposed)
                    {
                        currentForm.Activate();
                    }
                }
            })));
        }
示例#2
0
 ///<summary></summary>
 public FormOpenDental(string[] cla)
 {
     Logger.openlog.Log("Initializing Open Dental...",Logger.Severity.INFO);
     CommandLineArgs=cla;
     Splash=new FormSplash();
     if(CommandLineArgs.Length==0) {
         Splash.Show();
     }
     InitializeComponent();
     SystemEvents.SessionSwitch+=new SessionSwitchEventHandler(SystemEvents_SessionSwitch);
     //toolbar
     ToolBarMain=new ODToolBar();
     ToolBarMain.Location=new Point(51,0);
     ToolBarMain.Size=new Size(931,25);
     ToolBarMain.Dock=DockStyle.Top;
     ToolBarMain.ImageList=imageListMain;
     ToolBarMain.ButtonClick+=new ODToolBarButtonClickEventHandler(ToolBarMain_ButtonClick);
     this.Controls.Add(ToolBarMain);
     //outlook bar
     myOutlookBar=new OutlookBar();
     myOutlookBar.Location=new Point(0,0);
     myOutlookBar.Size=new Size(51,626);
     myOutlookBar.ImageList=imageList32;
     myOutlookBar.Dock=DockStyle.Left;
     myOutlookBar.ButtonClicked+=new ButtonClickedEventHandler(myOutlookBar_ButtonClicked);
     this.Controls.Add(myOutlookBar);
     //contrAppt
     ContrAppt2=new ContrAppt();
     ContrAppt2.Visible=false;
     ContrAppt2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrAppt2);
     //contrFamily
     ContrFamily2=new ContrFamily();
     ContrFamily2.Visible=false;
     ContrFamily2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrFamily2);
     //contrFamilyEcw
     ContrFamily2Ecw=new ContrFamilyEcw();
     ContrFamily2Ecw.Visible=false;
     //ContrFamily2Ecw.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrFamily2Ecw);
     //contrAccount
     ContrAccount2=new ContrAccount();
     ContrAccount2.Visible=false;
     ContrAccount2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrAccount2);
     //contrTreat
     ContrTreat2=new ContrTreat();
     ContrTreat2.Visible=false;
     ContrTreat2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrTreat2);
     //contrChart
     ContrChart2=new ContrChart();
     ContrChart2.Visible=false;
     ContrChart2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrChart2);
     //contrImages
     ContrImages2=new ContrImages();
     ContrImages2.Visible=false;
     ContrImages2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrImages2);
     //contrManage
     ContrManage2=new ContrStaff();
     ContrManage2.Visible=false;
     ContrManage2.PatientSelected+=new PatientSelectedEventHandler(Contr_PatientSelected);
     this.Controls.Add(ContrManage2);
     //userControlTasks
     userControlTasks1=new UserControlTasks();
     userControlTasks1.Visible=false;
     userControlTasks1.GoToChanged+=new EventHandler(userControlTasks1_GoToChanged);
     GotoModule.ModuleSelected+=new ModuleEventHandler(GotoModule_ModuleSelected);
     this.Controls.Add(userControlTasks1);
     panelSplitter.ContextMenu=menuSplitter;
     menuItemDockBottom.Checked=true;
     phoneSmall=new UserControlPhoneSmall();
     phoneSmall.GoToChanged += new System.EventHandler(this.phoneSmall_GoToChanged);
     phoneSmall.Visible=false;
     this.Controls.Add(phoneSmall);
     //phonePanel=new UserControlPhonePanel();
     //phonePanel.Visible=false;
     //this.Controls.Add(phonePanel);
     //phonePanel.GoToChanged += new System.EventHandler(this.phonePanel_GoToChanged);
     Logger.openlog.Log("Open Dental initialization complete.",Logger.Severity.INFO);
     //Plugins.HookAddCode(this,"FormOpenDental.Constructor_end");//Can't do this because no plugins loaded.
 }
示例#3
0
 private void FormOpenDental_Load(object sender, System.EventArgs e)
 {
     Splash.Dispose();
     Version versionOd=Assembly.GetAssembly(typeof(FormOpenDental)).GetName().Version;
     Version versionObBus=Assembly.GetAssembly(typeof(Db)).GetName().Version;
     if(versionOd!=versionObBus) {
         MessageBox.Show("Mismatched program file versions. Please run the Open Dental setup file again on this computer.");//No MsgBox or Lan.g() here, because we don't want to access the database if there is a version conflict.
         Application.Exit();
         return;
     }
     allNeutral();
     string odUser="";
     string odPassHash="";
     string webServiceUri="";
     YN webServiceIsEcw=YN.Unknown;
     string odPassword="";
     string serverName="";
     string databaseName="";
     string mySqlUser="";
     string mySqlPassword="";
     if(CommandLineArgs.Length!=0) {
         for(int i=0;i<CommandLineArgs.Length;i++) {
             if(CommandLineArgs[i].StartsWith("UserName="******"');
             }
             if(CommandLineArgs[i].StartsWith("PassHash=") && CommandLineArgs[i].Length>9) {
                 odPassHash=CommandLineArgs[i].Substring(9).Trim('"');
             }
             if(CommandLineArgs[i].StartsWith("WebServiceUri=") && CommandLineArgs[i].Length>14) {
                 webServiceUri=CommandLineArgs[i].Substring(14).Trim('"');
             }
             if(CommandLineArgs[i].StartsWith("WebServiceIsEcw=") && CommandLineArgs[i].Length>16) {
                 if(CommandLineArgs[i].Substring(16).Trim('"')=="True") {
                     webServiceIsEcw=YN.Yes;
                 }
                 else {
                     webServiceIsEcw=YN.No;
                 }
             }
             if(CommandLineArgs[i].StartsWith("OdPassword="******"');
             }
             if(CommandLineArgs[i].StartsWith("ServerName=") && CommandLineArgs[i].Length>11) {
                 serverName=CommandLineArgs[i].Substring(11).Trim('"');
             }
             if(CommandLineArgs[i].StartsWith("DatabaseName=") && CommandLineArgs[i].Length>13) {
                 databaseName=CommandLineArgs[i].Substring(13).Trim('"');
             }
             if(CommandLineArgs[i].StartsWith("MySqlUser="******"');
             }
             if(CommandLineArgs[i].StartsWith("MySqlPassword="******"');
             }
         }
     }
     YN noShow=YN.Unknown;
     if(webServiceUri!=""){//a web service was specified
         if(odUser!="" && odPassword!=""){//and both a username and password were specified
             noShow=YN.Yes;
         }
     }
     else if(databaseName!=""){
         noShow=YN.Yes;
     }
     FormChooseDatabase formChooseDb=new FormChooseDatabase();
     formChooseDb.OdUser=odUser;
     formChooseDb.OdPassHash=odPassHash;
     formChooseDb.WebServiceUri=webServiceUri;
     formChooseDb.WebServiceIsEcw=webServiceIsEcw;
     formChooseDb.OdPassword=odPassword;
     formChooseDb.ServerName=serverName;
     formChooseDb.DatabaseName=databaseName;
     formChooseDb.MySqlUser=mySqlUser;
     formChooseDb.MySqlPassword=mySqlPassword;
     formChooseDb.NoShow=noShow;//either unknown or yes
     formChooseDb.GetConfig();
     formChooseDb.GetCmdLine();
     while(true) {//Most users will loop through once.  If user tries to connect to a db with replication failure, they will loop through again.
         if(formChooseDb.NoShow==YN.Yes) {
             if(!formChooseDb.TryToConnect()) {
                 formChooseDb.ShowDialog();
                 if(formChooseDb.DialogResult==DialogResult.Cancel) {
                     Application.Exit();
                     return;
                 }
             }
         }
         else {
             formChooseDb.ShowDialog();
             if(formChooseDb.DialogResult==DialogResult.Cancel) {
                 Application.Exit();
                 return;
             }
         }
         Cursor=Cursors.WaitCursor;
         Splash=new FormSplash();
         if(CommandLineArgs.Length==0) {
             Splash.Show();
         }
         if(!PrefsStartup()){//looks for the AtoZ folder here, but would like to eventually move that down to after login
             Cursor=Cursors.Default;
             Splash.Dispose();
             Application.Exit();
             return;
         }
         if(ReplicationServers.Server_id!=0 && ReplicationServers.Server_id==PrefC.GetInt(PrefName.ReplicationFailureAtServer_id)) {
             MsgBox.Show(this,"This database is temporarily unavailable.  Please connect instead to your alternate database at the other location.");
             formChooseDb.NoShow=YN.No;//This ensures they will get a choose db window next time through the loop.
             ReplicationServers.Server_id=-1;
             continue;
         }
         break;
     }
     if(Programs.UsingEcwTight()) {
         Splash.Dispose();//We don't show splash screen when bridging to eCW.
     }
     //We no longer do this shotgun approach because it can slow the loading time.
     //RefreshLocalData(InvalidType.AllLocal);
     List<InvalidType> invalidTypes=new List<InvalidType>();
     invalidTypes.Add(InvalidType.Prefs);
     invalidTypes.Add(InvalidType.Defs);
     invalidTypes.Add(InvalidType.Providers);//obviously heavily used
     invalidTypes.Add(InvalidType.Programs);//already done above, but needs to be done explicitly to trigger the PostCleanup
     invalidTypes.Add(InvalidType.ToolBut);//so program buttons will show in all the toolbars
     if(Programs.UsingEcwTight()) {
         lightSignalGrid1.Visible=false;
     }
     else{
         invalidTypes.Add(InvalidType.Signals);//so when mouse moves over light buttons, it won't crash
     }
     Plugins.LoadAllPlugins(this);//moved up from right after optimizing tooth chart graphics.  New position might cause problems.
     //It was moved because RefreshLocalData()=>RefreshLocalDataPostCleanup()=>ContrChart2.InitializeLocalData()=>LayoutToolBar() has a hook.
     RefreshLocalData(invalidTypes.ToArray());
     FillSignalButtons(null);
     ContrManage2.InitializeOnStartup();//so that when a signal is received, it can handle it.
     //Lan.Refresh();//automatically skips if current culture is en-US
     //LanguageForeigns.Refresh(CultureInfo.CurrentCulture);//automatically skips if current culture is en-US
     DataValid.BecameInvalid += new OpenDental.ValidEventHandler(DataValid_BecameInvalid);
     signalLastRefreshed=MiscData.GetNowDateTime();
     if(PrefC.GetInt(PrefName.ProcessSigsIntervalInSecs)==0) {
         timerSignals.Enabled=false;
     }
     else {
         timerSignals.Interval=PrefC.GetInt(PrefName.ProcessSigsIntervalInSecs)*1000;
         timerSignals.Enabled=true;
     }
     timerTimeIndic.Enabled=true;
     myOutlookBar.Buttons[0].Caption=Lan.g(this,"Appts");
     myOutlookBar.Buttons[1].Caption=Lan.g(this,"Family");
     myOutlookBar.Buttons[2].Caption=Lan.g(this,"Account");
     myOutlookBar.Buttons[3].Caption=Lan.g(this,"Treat' Plan");
     //myOutlookBar.Buttons[4].Caption=Lan.g(this,"Chart");//??done in RefreshLocalData
     myOutlookBar.Buttons[5].Caption=Lan.g(this,"Images");
     myOutlookBar.Buttons[6].Caption=Lan.g(this,"Manage");
     foreach(MenuItem menuItem in mainMenu.MenuItems){
         TranslateMenuItem(menuItem);
     }
     if(CultureInfo.CurrentCulture.Name=="en-US"){
         //for the business layer, this functionality is duplicated in the Lan class.  Need for SL.
         CultureInfo cInfo=(CultureInfo)CultureInfo.CurrentCulture.Clone();
         cInfo.DateTimeFormat.ShortDatePattern="MM/dd/yyyy";
         Application.CurrentCulture=cInfo;
         //
         //if(CultureInfo.CurrentCulture.TwoLetterISOLanguageName=="en"){
         menuItemTranslation.Visible=false;
     }
     if(!File.Exists("Help.chm")){
         menuItemHelpWindows.Visible=false;
     }
     if(Environment.OSVersion.Platform==PlatformID.Unix){//Create A to Z unsupported on Unix for now.
         menuItemCreateAtoZFolders.Visible=false;
     }
     if(!PrefC.GetBool(PrefName.ADAdescriptionsReset)) {
         ProcedureCodes.ResetADAdescriptions();
         Prefs.UpdateBool(PrefName.ADAdescriptionsReset,true);
     }
     Splash.Dispose();
     //Choose a default DirectX format when no DirectX format has been specified and running in DirectX tooth chart mode.
     //ComputerPref localComputerPrefs=ComputerPrefs.GetForLocalComputer();
     if(ComputerPrefs.LocalComputer.GraphicsSimple==DrawingMode.DirectX && ComputerPrefs.LocalComputer.DirectXFormat=="") {
         //MessageBox.Show(Lan.g(this,"Optimizing tooth chart graphics. This may take a few minutes. You will be notified when the process is complete."));
         ComputerPrefs.LocalComputer.DirectXFormat=FormGraphics.GetPreferredDirectXFormat(this);
         if(ComputerPrefs.LocalComputer.DirectXFormat=="invalid") {
             //No valid local DirectX format could be found.
             //Simply revert to OpenGL.
             ComputerPrefs.LocalComputer.GraphicsSimple=DrawingMode.OpenGL;
         }
         ComputerPrefs.Update(ComputerPrefs.LocalComputer);
         ContrChart2.InitializeOnStartup();
         //MsgBox.Show(this,"Done optimizing tooth chart graphics.");
     }
     if(Security.CurUser==null) {//It could already be set if using web service because login from ChooseDatabase window.
         if(Programs.UsingEcwTight() && odUser!="") {//only leave it null if a user was passed in on the commandline.  If starting OD manually, it will jump into the else.
             //leave user as null
         }
         else {
             if(odUser!="" && odPassword!=""){//if a username and password were passed in
                 Userod user=Userods.GetUserByName(odUser,Programs.UsingEcwTight());
                 if(user!=null){
                     if(Userods.CheckTypedPassword(odPassword,user.Password)){//password matches
                         Security.CurUser=user.Copy();
                         if(RemotingClient.RemotingRole==RemotingRole.ClientWeb){
                             string pw=odPassword;
                             if(Programs.UsingEcwTight()) {//ecw requires hash, but non-ecw requires actual password
                                 pw=Userods.EncryptPassword(pw,true);
                             }
                             Security.PasswordTyped=pw;
                         }
                         //TasksCheckOnStartup is one thing that doesn't get done because login window wasn't used
                     }
                 }
             }
             if(Security.CurUser==null) {//normal manual log in process
                 Userod adminUser=Userods.GetAdminUser();
                 if(adminUser.Password=="") {
                     Security.CurUser=adminUser.Copy();
                 }
                 else {
                     FormLogOn_=new FormLogOn();
                     FormLogOn_.ShowDialog(this);
                     if(FormLogOn_.DialogResult==DialogResult.Cancel) {
                         Cursor=Cursors.Default;
                         Application.Exit();
                         return;
                     }
                 }
             }
         }
     }
     if(userControlTasks1.Visible) {
         userControlTasks1.InitializeOnStartup();
     }
     myOutlookBar.SelectedIndex=Security.GetModule(0);//for eCW, this fails silently.
     if(Programs.UsingEcwTight()) {
         myOutlookBar.SelectedIndex=4;//Chart module
         //ToolBarMain.Height=0;//this should force the modules further up on the screen
         //ToolBarMain.Visible=false;
         LayoutControls();
     }
     if(Programs.UsingOrion) {
         myOutlookBar.SelectedIndex=1;//Family module
     }
     myOutlookBar.Invalidate();
     LayoutToolBar();
     SetModuleSelected();
     Cursor=Cursors.Default;
     if(myOutlookBar.SelectedIndex==-1){
         MsgBox.Show(this,"You do not have permission to use any modules.");
     }
     Bridges.Trojan.StartupCheck();
     FormUAppoint.StartThreadIfEnabled();
     Bridges.ICat.StartFileWatcher();
     if(PrefC.GetBool(PrefName.DockPhonePanelShow)){
         #if !DEBUG
             if(Process.GetProcessesByName("WebCamOD").Length==0) {
                 try {
                     Process.Start("WebCamOD.exe");
                 }
                 catch { }//for example, if working from home.
             }
         #endif
     }
     #if !TRIALONLY
         if(PrefC.GetDate(PrefName.BackupReminderLastDateRun).AddMonths(1)<DateTime.Today) {
             FormBackupReminder FormBR=new FormBackupReminder();
             FormBR.ShowDialog();
             if(FormBR.DialogResult==DialogResult.OK){
                 Prefs.UpdateDateT(PrefName.BackupReminderLastDateRun,DateTime.Today);
             }
             else{
                 Application.Exit();
                 return;
             }
         }
     #endif
     FillPatientButton(0,"",false,"",0);
     ThreadCommandLine=new Thread(new ThreadStart(Listen));
     if(!IsSecondInstance) {//can't use a port that's already in use.
         //js We can't do this yet.  I tried it already, and it consumes nearly 100% CPU.  Not while testing, but later.
         //So until we really need to do it, it's easiest no just not start the thread for now.
         //ThreadCommandLine.Start();
     }
     //if(CommandLineArgs.Length>0) {
     ProcessCommandLine(CommandLineArgs);
     //}
     try {
         Computers.UpdateHeartBeat(Environment.MachineName);
     }
     catch { }
     string dllPathEHR=ODFileUtils.CombinePaths(Application.StartupPath,"EHR.dll");
     if(PrefC.GetBoolSilent(PrefName.ShowFeatureEhr,false)) {
         #if EHRTEST
             FormEHR=new FormEHR();
             ContrChart2.InitializeLocalData();//because toolbar is now missing the EHR button.  Only a problem if a db conversion is done when opening the program.
         #else
             FormEHR=null;
             AssemblyEHR=null;
             if(File.Exists(dllPathEHR)) {//EHR.dll is available, so load it up
                 AssemblyEHR=Assembly.LoadFile(dllPathEHR);
                 Type type=AssemblyEHR.GetType("EHR.FormEHR");//namespace.class
                 FormEHR=Activator.CreateInstance(type);
             }
         #endif
     }
     dateTimeLastActivity=DateTime.Now;
     timerLogoff.Enabled=true;
     timerReplicationMonitor.Enabled=true;
     Plugins.HookAddCode(this,"FormOpenDental.Load_end");
 }
示例#4
0
		private void FormOpenDental_Load(object sender,System.EventArgs e) {
			_isStartingUp=true;//Halts mobile synch during updates.
			Splash.Dispose();
			allNeutral();
			string odUser="";
			string odPassHash="";
			string webServiceUri="";
			YN webServiceIsEcw=YN.Unknown;
			bool isSilentUpdate=false;
			string odPassword="";
			string serverName="";
			string databaseName="";
			string mySqlUser="";
			string mySqlPassword="";
			if(CommandLineArgs.Length!=0) {
				for(int i=0;i<CommandLineArgs.Length;i++) {
					if(CommandLineArgs[i].StartsWith("UserName="******"');
					}
					if(CommandLineArgs[i].StartsWith("PassHash=") && CommandLineArgs[i].Length>9) {
						odPassHash=CommandLineArgs[i].Substring(9).Trim('"');
					}
					if(CommandLineArgs[i].StartsWith("WebServiceUri=") && CommandLineArgs[i].Length>14) {
						webServiceUri=CommandLineArgs[i].Substring(14).Trim('"');
					}
					if(CommandLineArgs[i].StartsWith("WebServiceIsEcw=") && CommandLineArgs[i].Length>16) {
						if(CommandLineArgs[i].Substring(16).Trim('"')=="True") {
							webServiceIsEcw=YN.Yes;
						}
						else {
							webServiceIsEcw=YN.No;
						}
					}
					if(CommandLineArgs[i].StartsWith("OdPassword="******"');
					}
					if(CommandLineArgs[i].StartsWith("ServerName=") && CommandLineArgs[i].Length>11) {
						serverName=CommandLineArgs[i].Substring(11).Trim('"');
					}
					if(CommandLineArgs[i].StartsWith("DatabaseName=") && CommandLineArgs[i].Length>13) {
						databaseName=CommandLineArgs[i].Substring(13).Trim('"');
					}
					if(CommandLineArgs[i].StartsWith("MySqlUser="******"');
					}
					if(CommandLineArgs[i].StartsWith("MySqlPassword="******"');
					}
					if(CommandLineArgs[i].StartsWith("IsSilentUpdate=") && CommandLineArgs[i].Length>15) {
						if(CommandLineArgs[i].Substring(15).Trim('"').ToLower()=="true") {
							isSilentUpdate=true;
						}
						else {
							isSilentUpdate=false;
						}
					}
				}
			}
			YN noShow=YN.Unknown;
			if(webServiceUri!="") {//a web service was specified
				if(odUser!="" && odPassword!="") {//and both a username and password were specified
					noShow=YN.Yes;
				}
			}
			else if(databaseName!="") {
				noShow=YN.Yes;
			}
			//Users that want to silently update MUST pass in the following command line args.
			if(isSilentUpdate && (odUser.Trim()==""
					|| (odPassword.Trim()=="" && odPassHash.Trim()=="")
					|| serverName.Trim()==""
					|| databaseName.Trim()==""
					|| mySqlUser.Trim()==""
					|| mySqlPassword.Trim()=="")) 
			{
				ExitCode=104;//Required command line arguments have not been set for silent updating
				Application.Exit();
				return;
			}
			Version versionOd=Assembly.GetAssembly(typeof(FormOpenDental)).GetName().Version;
			Version versionObBus=Assembly.GetAssembly(typeof(Db)).GetName().Version;
			if(versionOd!=versionObBus) {
				if(isSilentUpdate) {
					ExitCode=105;//File versions do not match
				}
				else {//Not a silent update.  Show a warning message.
					//No MsgBox or Lan.g() here, because we don't want to access the database if there is a version conflict.
					MessageBox.Show("Mismatched program file versions. Please run the Open Dental setup file again on this computer.");
				}
				Application.Exit();
				return;
			}
			FormChooseDatabase formChooseDb=new FormChooseDatabase();
			formChooseDb.OdUser=odUser;
			formChooseDb.OdPassHash=odPassHash;
			formChooseDb.WebServiceUri=webServiceUri;
			formChooseDb.WebServiceIsEcw=webServiceIsEcw;
			formChooseDb.OdPassword=odPassword;
			formChooseDb.ServerName=serverName;
			formChooseDb.DatabaseName=databaseName;
			formChooseDb.MySqlUser=mySqlUser;
			formChooseDb.MySqlPassword=mySqlPassword;
			formChooseDb.NoShow=noShow;//either unknown or yes
			formChooseDb.GetConfig();
			formChooseDb.GetCmdLine();
			while(true) {//Most users will loop through once.  If user tries to connect to a db with replication failure, they will loop through again.
				if(formChooseDb.NoShow==YN.Yes) {
					if(!formChooseDb.TryToConnect()) {
						if(isSilentUpdate) {
							ExitCode=106;//Connection to specified database has failed
							Application.Exit();
							return;
						}
						formChooseDb.ShowDialog();
						if(formChooseDb.DialogResult==DialogResult.Cancel) {
							Application.Exit();
							return;
						}
					}
				}
				else {
					formChooseDb.ShowDialog();
					if(formChooseDb.DialogResult==DialogResult.Cancel) {
						Application.Exit();
						return;
					}
				}
				Cursor=Cursors.WaitCursor;
				//theme
				try {
					ODToolBar.UseBlueTheme=PrefC.GetBool(PrefName.ColorTheme);
					ODGrid.UseBlueTheme=PrefC.GetBool(PrefName.ColorTheme);
				}
				catch {
					//try/catch in case you are trying to convert from an older version of OD and need to update the DB.
				}
				this.Invalidate();//apply them at next repaint.
				Plugins.LoadAllPlugins(this);//moved up from near RefreshLocalData(invalidTypes). New position might cause problems.
				Splash=new FormSplash();
				if(CommandLineArgs.Length==0) {
					Splash.Show();
				}
				if(!PrefsStartup(isSilentUpdate)) {//looks for the AtoZ folder here, but would like to eventually move that down to after login.  In Release, refreshes the Pref cache if conversion successful.
					Cursor=Cursors.Default;
					Splash.Dispose();
					if(ExitCode==0) {
						//PrefsStartup failed and ExitCode is still 0 which means an unexpected error must have occured.
						//Set the exit code to 999 which will represent an Unknown Error
						ExitCode=999;
					}
					Application.Exit();
					return;
				}
				if(isSilentUpdate) {
					//The db was successfully updated so there is nothing else that needs to be done after this point.
					Application.Exit();//Exits with ExitCode=0
					return;
				}
				if(ReplicationServers.Server_id!=0 && ReplicationServers.Server_id==PrefC.GetInt(PrefName.ReplicationFailureAtServer_id)) {
					MsgBox.Show(this,"This database is temporarily unavailable.  Please connect instead to your alternate database at the other location.");
					formChooseDb.NoShow=YN.No;//This ensures they will get a choose db window next time through the loop.
					ReplicationServers.Server_id=-1;
					continue;
				}
				break;
			}
			if(Programs.UsingEcwTightOrFullMode()) {
				Splash.Dispose();//We don't show splash screen when bridging to eCW.
			}
			RefreshLocalData(InvalidType.Prefs);//should only refresh preferences so that SignalLastClearedDate preference can be used in ClearOldSignals()
			Signalods.ClearOldSignals();
			//We no longer do this shotgun approach because it can slow the loading time.
			//RefreshLocalData(InvalidType.AllLocal);
			List<InvalidType> invalidTypes=new List<InvalidType>();
			//invalidTypes.Add(InvalidType.Prefs);//Preferences were refreshed above.  The only preference which might be stale is SignalLastClearedDate, but it is not used anywhere after calling ClearOldSignals() above.
			invalidTypes.Add(InvalidType.Defs);
			invalidTypes.Add(InvalidType.Providers);//obviously heavily used
			invalidTypes.Add(InvalidType.Programs);//already done above, but needs to be done explicitly to trigger the PostCleanup 
			invalidTypes.Add(InvalidType.ToolBut);//so program buttons will show in all the toolbars
			if(Programs.UsingEcwTightMode()) {
				lightSignalGrid1.Visible=false;
			}
			else{
				invalidTypes.Add(InvalidType.Signals);//so when mouse moves over light buttons, it won't crash
			}
			//Plugins.LoadAllPlugins(this);//moved up from right after optimizing tooth chart graphics.  New position might cause problems.
			//It was moved because RefreshLocalData()=>RefreshLocalDataPostCleanup()=>ContrChart2.InitializeLocalData()=>LayoutToolBar() has a hook.
			//Moved it up again on 10/3/13
			RefreshLocalData(invalidTypes.ToArray());
			FillSignalButtons(null);
			ContrManage2.InitializeOnStartup();//so that when a signal is received, it can handle it.
			//Lan.Refresh();//automatically skips if current culture is en-US
			//LanguageForeigns.Refresh(CultureInfo.CurrentCulture);//automatically skips if current culture is en-US
			DataValid.BecameInvalid += new OpenDental.ValidEventHandler(DataValid_BecameInvalid);
			signalLastRefreshed=MiscData.GetNowDateTime();
			if(PrefC.GetInt(PrefName.ProcessSigsIntervalInSecs)==0) {
				timerSignals.Enabled=false;
			}
			else {
				timerSignals.Interval=PrefC.GetInt(PrefName.ProcessSigsIntervalInSecs)*1000;
				timerSignals.Enabled=true;
			}
			timerTimeIndic.Enabled=true;
			myOutlookBar.Buttons[0].Caption=Lan.g(this,"Appts");
			myOutlookBar.Buttons[1].Caption=Lan.g(this,"Family");
			myOutlookBar.Buttons[2].Caption=Lan.g(this,"Account");
			myOutlookBar.Buttons[3].Caption=Lan.g(this,"Treat' Plan");
			//myOutlookBar.Buttons[4].Caption=Lan.g(this,"Chart");//??done in RefreshLocalData
			myOutlookBar.Buttons[5].Caption=Lan.g(this,"Images");
			myOutlookBar.Buttons[6].Caption=Lan.g(this,"Manage");
			foreach(MenuItem menuItem in mainMenu.MenuItems){
				TranslateMenuItem(menuItem);
			}
			if(CultureInfo.CurrentCulture.Name=="en-US") {
				//for the business layer, this functionality is duplicated in the Lan class.  Need for SL.
				CultureInfo cInfo=(CultureInfo)CultureInfo.CurrentCulture.Clone();
				cInfo.DateTimeFormat.ShortDatePattern="MM/dd/yyyy";
				Application.CurrentCulture=cInfo;
				//
				//if(CultureInfo.CurrentCulture.TwoLetterISOLanguageName=="en"){
				menuItemTranslation.Visible=false;
			}
			else {//not en-US
				CultureInfo cInfo=(CultureInfo)CultureInfo.CurrentCulture.Clone();
				string dateFormatCur=cInfo.DateTimeFormat.ShortDatePattern;
				//The carrot indicates the beginning of a word.  {2} means that there has to be exactly 2 y's.  [^a-z] means any character except a through z.  $ means end of word.
				if(Regex.IsMatch(dateFormatCur,"^y{2}[^a-z]")
					|| Regex.IsMatch(dateFormatCur,"[^a-z]y{2}$")) 
				{
					//We know there are only two y's in the format.  Force there to be four.
					cInfo.DateTimeFormat.ShortDatePattern=dateFormatCur.Replace("yy","yyyy");
					Application.CurrentCulture=cInfo;
				}
			}
			//For EHR users we want to load up the EHR code list from the obfuscated dll in a background thread because it takes roughly 11 seconds to load up.
			if(PrefC.GetBool(PrefName.ShowFeatureEhr)) {
				try {
					Thread threadPreloadEhrCodeList=new Thread((ThreadStart)EhrCodes.UpdateList);//Background loading of the EHR.dll code list.
					threadPreloadEhrCodeList.Start();
				}
				catch { 
					//This should never happen.  It would most likely be due to a corrupt dll issue but I don't want to stop the start up sequence.
					//Users could theoretically use Open Dental for an entire day and never hit the code that utilizes the EhrCodes class.
					//Therefore, we do not want to cause any issues and the worst case scenario is the users has to put up with the 11 second delay (old behavior). 
				}
			}
			if(!File.Exists("Help.chm")){
				menuItemHelpWindows.Visible=false;
			}
			if(Environment.OSVersion.Platform==PlatformID.Unix){//Create A to Z unsupported on Unix for now.
				menuItemCreateAtoZFolders.Visible=false;
			}
			if(!PrefC.GetBool(PrefName.ProcLockingIsAllowed)) {
				menuItemProcLockTool.Visible=false;
			}
			if(!PrefC.GetBool(PrefName.ADAdescriptionsReset)) {
				ProcedureCodes.ResetADAdescriptions();
				Prefs.UpdateBool(PrefName.ADAdescriptionsReset,true);
			}
			#region Start OpenDent Services
			//If this is the designated update server, make sure that all "OpenDent..." services are up and running.
			//This is mainly to increase the odds that critical services required for e-Services are always running.
			if(PrefC.GetString(PrefName.WebServiceServerName)!="" && ODEnvironment.IdIsThisComputer(PrefC.GetString(PrefName.WebServiceServerName))) {
				List<ServiceController> listServices=ODEnvironment.GetAllOpenDentServices();
				for(int i=0;i<listServices.Count;i++) {
					//Only attempt to start services that are of status stopped or stop pending.
					//If we do not do this, an InvalidOperationException will throw that says "An instance of the service is already running"
					if(listServices[i].Status!=ServiceControllerStatus.Stopped && listServices[i].Status!=ServiceControllerStatus.StopPending) {
						continue;
					}
					try {
						listServices[i].Start();//We will not wait for the service to start so that loading OD does not take any longer that usual.
					}
					catch {
						//An InvalidOperationException can get thrown if the service could not be started.  E.g. current user is not running Open Dental as an administrator.
						//We do not want to halt the startup sequence here.  If we want to notify customers of a downed service, there needs to be an additional monitoring service installed.
					}
				}
			}
			#endregion
			Splash.Dispose();
			//Choose a default DirectX format when no DirectX format has been specified and running in DirectX tooth chart mode.
			//ComputerPref localComputerPrefs=ComputerPrefs.GetForLocalComputer();
			if(ComputerPrefs.LocalComputer.GraphicsSimple==DrawingMode.DirectX && ComputerPrefs.LocalComputer.DirectXFormat=="") {
				//MessageBox.Show(Lan.g(this,"Optimizing tooth chart graphics. This may take a few minutes. You will be notified when the process is complete."));
				ComputerPrefs.LocalComputer.DirectXFormat=FormGraphics.GetPreferredDirectXFormat(this);
				if(ComputerPrefs.LocalComputer.DirectXFormat=="invalid") {
					//No valid local DirectX format could be found.
					//Simply revert to OpenGL.
					ComputerPrefs.LocalComputer.GraphicsSimple=DrawingMode.Simple2D;
				}
				ComputerPrefs.Update(ComputerPrefs.LocalComputer);
				ContrChart2.InitializeOnStartup();
				//MsgBox.Show(this,"Done optimizing tooth chart graphics.");
			}
			if(ODEnvironment.IsRunningOnDbServer(MiscData.GetODServer()) && PrefC.GetBool(PrefName.ShowFeatureEhr)) {//OpenDental has EHR enabled and is running on the same machine as the mysql server it is connected to.*/
				_threadTimeSynch=new Thread(new ThreadStart(ThreadTimeSynch_Synch));
				_threadTimeSynch.Start();
			}
			_isStartingUp=false;//Used to allow Mobile Synch to continue
			if(Security.CurUser==null) {//It could already be set if using web service because login from ChooseDatabase window.
				if(Programs.UsingEcwTightOrFullMode() && odUser!="") {//only leave it null if a user was passed in on the commandline.  If starting OD manually, it will jump into the else.
					//leave user as null
				}
				else {
					if(odUser!="" && odPassword!=""){//if a username and password were passed in
						//Userod user=Userods.GetUserByName(odUser,Programs.UsingEcwTight());
						Userod user=Userods.GetUserByName(odUser,Programs.UsingEcwTightOrFullMode());
						if(user!=null){
							if(Userods.CheckTypedPassword(odPassword,user.Password)){//password matches
								Security.CurUser=user.Copy();
								if(RemotingClient.RemotingRole==RemotingRole.ClientWeb){
									string pw=odPassword;
									//if(Programs.UsingEcwTight()) {//ecw requires hash, but non-ecw requires actual password
									if(Programs.UsingEcwTightOrFullMode()) {//ecw requires hash, but non-ecw requires actual password
										pw=Userods.EncryptPassword(pw,true);
									}
									Security.PasswordTyped=pw;
								}
								//TasksCheckOnStartup is one thing that doesn't get done because login window wasn't used
							}
						}
					}
					if(Security.CurUser==null) {//normal manual log in process
						Userod adminUser=Userods.GetAdminUser();
						if(adminUser.Password=="") {
							Security.CurUser=adminUser.Copy();
							SecurityLogs.MakeLogEntry(Permissions.UserLogOnOff,0,"User: "******" has logged on.");
						}
						else {
							FormLogOn_=new FormLogOn();
							FormLogOn_.ShowDialog(this);
							if(FormLogOn_.DialogResult==DialogResult.Cancel) {
								Cursor=Cursors.Default;
								Application.Exit();
								return;
							}
						}
					}
				}
			}
			if(userControlTasks1.Visible) {
				userControlTasks1.InitializeOnStartup();
			}
			myOutlookBar.SelectedIndex=Security.GetModule(0);//for eCW, this fails silently.
			//if(Programs.UsingEcwTight()) {
			if(Programs.UsingEcwTightOrFullMode()
				|| (HL7Defs.IsExistingHL7Enabled() && !HL7Defs.GetOneDeepEnabled().ShowAppts)) {
				myOutlookBar.SelectedIndex=4;//Chart module
				//ToolBarMain.Height=0;//this should force the modules further up on the screen
				//ToolBarMain.Visible=false;
				LayoutControls();
			}
			if(Programs.UsingOrion) {
				myOutlookBar.SelectedIndex=1;//Family module
			}
			myOutlookBar.Invalidate();
			LayoutToolBar();
			//If clinics are enabled, we will set the public ClinicNum variable
			//If the user is restricted to a clinic(s), and the computerpref clinic is not one of the user's restricted clinics, the user's clinic will be selected
			//If the user is not restricted, or if the user is restricted but has access to the computerpref clinic, the computerpref clinic will be selected
			//The ClinicNum will determine which view is loaded, either from the computerpref table or from the userodapptview table
			if(!PrefC.GetBool(PrefName.EasyNoClinics) && Security.CurUser!=null) {//If block must be run before SetModuleSelected() so correct clinic filtration occurs.
				List<Clinic> listClinics=Clinics.GetForUserod(Security.CurUser);
				bool isCompClinicAllowed=false;
				for(int i=0;i<listClinics.Count;i++) {
					if(listClinics[i].ClinicNum==ComputerPrefs.LocalComputer.ClinicNum) {
						isCompClinicAllowed=true;
						break;
					}
				}
				if(Security.CurUser.ClinicIsRestricted && !isCompClinicAllowed) {//user is restricted and does not have access to the computerpref clinic
					ClinicNum=Security.CurUser.ClinicNum;
				}
				else {//the user is either not restricted to a clinic(s) or the user is restricted but has access to the computerpref clinic
					ClinicNum=ComputerPrefs.LocalComputer.ClinicNum;
				}
				RefreshMenuClinics();
			}
			SetModuleSelected();
			Cursor=Cursors.Default;
			if(myOutlookBar.SelectedIndex==-1){
				MsgBox.Show(this,"You do not have permission to use any modules.");
			}
			Bridges.Trojan.StartupCheck();
			FormUAppoint.StartThreadIfEnabled();
			Bridges.ICat.StartFileWatcher();
			Bridges.TigerView.StartFileWatcher();
			if(PrefC.GetBool(PrefName.DockPhonePanelShow)) {
				menuItemResellers.Visible=true;
				menuItemXChargeReconcile.Visible=true;
				#if !DEBUG
					if(Process.GetProcessesByName("WebCamOD").Length==0) {
						try {
							Process.Start("WebCamOD.exe");
						}
						catch { }//for example, if working from home.
					}
				#endif
				ThreadVM=new Thread(new ThreadStart(this.ThreadVM_SetLabelMsg));
				ThreadVM.Start();//It's done this way because the file activity tends to lock the UI on slow connections.
				ThreadHqMetrics=new Thread(new ThreadStart(PhoneWebCamTickWorkerThread));
				ThreadHqMetrics.Start();						
			}
			#if !TRIALONLY
				if(PrefC.GetDate(PrefName.BackupReminderLastDateRun).AddMonths(1)<DateTime.Today) {
					FormBackupReminder FormBR=new FormBackupReminder();
					FormBR.ShowDialog();
					if(FormBR.DialogResult==DialogResult.OK){
						Prefs.UpdateDateT(PrefName.BackupReminderLastDateRun,DateTimeOD.Today);
					}
					else{
						Application.Exit();
						return;
					}
				}
				//==tg  Commented out on 04/24/2014 after discussion deciding it was not necessary to synchronize time on start-up. Timeouts and other errors were causing complaints from customers.
				//if(PrefC.GetBool(PrefName.ShowFeatureEhr) && !_isTimeSynchThreadRunning) {
				//	FormEhrTimeSynch FormEhrTS = new FormEhrTimeSynch();
				//	FormEhrTS.IsAutoLaunch=true;
				//	if(!FormEhrTS.TimesInSynchFast()) {
				//		FormEhrTS.ShowDialog();
				//	}
				//}
			#endif
			FillPatientButton(null);
			//ThreadCommandLine=new Thread(new ThreadStart(Listen));
			//if(!IsSecondInstance) {//can't use a port that's already in use.
			//	//js We can't do this yet.  I tried it already, and it consumes nearly 100% CPU.  Not while testing, but later.
			//	//So until we really need to do it, it's easiest no just not start the thread for now.
			//	//ThreadCommandLine.Start();
			//}
			//if(CommandLineArgs.Length>0) {
			ProcessCommandLine(CommandLineArgs);
			//}
			try {
				Computers.UpdateHeartBeat(Environment.MachineName,true);
			}
			catch { }
			//string dllPathEHR=ODFileUtils.CombinePaths(Application.StartupPath,"EHR.dll");
			//if(PrefC.GetBoolSilent(PrefName.ShowFeatureEhr,false)) {
			//	#if EHRTEST
			//		FormEHR=new FormEHR();
			//		ContrChart2.InitializeLocalData();//because toolbar is now missing the EHR button.  Only a problem if a db conversion is done when opening the program.
			//	#else
			//		ObjFormEhrMeasures=null;
			//		AssemblyEHR=null;
			//		if(File.Exists(dllPathEHR)) {//EHR.dll is available, so load it up
			//			AssemblyEHR=Assembly.LoadFile(dllPathEHR);
			//			Type type=AssemblyEHR.GetType("EHR.FormEHR");//namespace.class
			//			ObjFormEhrMeasures=Activator.CreateInstance(type);
			//		}
			//	#endif
			//}
			Text=PatientL.GetMainTitle(Patients.GetPat(CurPatNum),ClinicNum);
			dateTimeLastActivity=DateTime.Now;
			timerLogoff.Enabled=true;
			timerReplicationMonitor.Enabled=true;
			ThreadEmailInbox=new Thread(new ThreadStart(ThreadEmailInbox_Receive));
			ThreadEmailInbox.Start();
			StartEServiceMonitoring();
			Plugins.HookAddCode(this,"FormOpenDental.Load_end");
		}