public int InsertUpdateDevProject(DevProjPath item) { if (string.IsNullOrWhiteSpace(item.DevProjectName)) { Debug.WriteLine("DevProjectName is empty"); return(-1); } using (var cmd = new SqlCommand("DevTrkr..InsertUpdateDevProject")) { cmd.Parameters.AddWithValue("@ID", item.ID); cmd.Parameters.AddWithValue("@DevProjectName", item.DevProjectName); cmd.Parameters.AddWithValue("@DevProjectPath", item.DevProjectPath); cmd.Parameters.AddWithValue("@Machine", item.Machine); cmd.Parameters.AddWithValue("@UserName", item.UserName); cmd.Parameters.AddWithValue("@IDEAppName", item.IDEAppName); cmd.Parameters.AddWithValue("@CreatedDate", item.CreatedDate); if (item.CompletedDate != null && item.CompletedDate > item.CreatedDate) { cmd.Parameters.AddWithValue("@CompletedDate", item.CompletedDate); } cmd.Parameters.AddWithValue("@DatabaseProject", item.DatabaseProject); cmd.Parameters.AddWithValue("@SyncID", item.SyncID); cmd.Parameters.AddWithValue("@ProjFileExt", item.ProjFileExt); cmd.Parameters.AddWithValue("@DevSLNPath", item.DevSLNPath); cmd.Parameters.AddWithValue("@GitURL", item.GitURL); return(UpdateDatabase(cmd)); } }
public DevProjPath GetDevDBProjectByName(string devProjectName) { using (var cmd = new SqlCommand("DevTrkr..GetDevDBProjectByName")) { cmd.Parameters.AddWithValue("@DevProjectName", devProjectName); var dt = GetDataTable(cmd); if (dt.Rows.Count.Equals(0)) { return(null); } DataRow dr = dt.Rows[0]; DevProjPath item = new DevProjPath { ID = dr["ID"].ToString(), DevProjectName = (string)dr["DevProjectName"], DevProjectPath = dr["DevProjectPath"] == DBNull.Value ? string.Empty : (string)dr["DevProjectPath"], Machine = dr["Machine"] == DBNull.Value ? string.Empty : (string)dr["Machine"], UserName = dr["UserName"] == DBNull.Value ? string.Empty : (string)dr["UserName"], IDEAppName = dr["IDEAppName"] == DBNull.Value ? string.Empty : (string)dr["IDEAppName"], CreatedDate = dr["CreatedDate"] == DBNull.Value ? DateTime.Now : (DateTime)dr["CreatedDate"], CompletedDate = dr["CompletedDate"] == DBNull.Value ? DateTime.Now : (DateTime)dr["CompletedDate"], DatabaseProject = dr["DatabaseProject"] == DBNull.Value ? false : (bool)dr["DatabaseProject"], SyncID = dr["SyncID"] == DBNull.Value ? string.Empty : dr["SyncID"].ToString(), ProjFileExt = dr["ProjFileExt"] == DBNull.Value ? string.Empty : (string)dr["ProjFileExt"], DevSLNPath = dr["DevSLNPath"] == DBNull.Value ? string.Empty : (string)dr["DevSLNPath"], GitURL = dr["GitURL"] == DBNull.Value ? string.Empty : (string)dr["GitURL"] }; return(item); } }
public int UpdateSLNPathInDevProject(DevProjPath item) { using (var cmd = new SqlCommand("DevTrkr..UpdateSLNPathInDevProject")) { cmd.Parameters.AddWithValue("@ID", item.ID); cmd.Parameters.AddWithValue("@DevSLNPath", item.DevSLNPath); return(UpdateDatabase(cmd)); } }
public int UpdateDevProjectsWithSyncIDAndGitURL(DevProjPath item) { using (var cmd = new SqlCommand("DevTrkr..UpdateDevProjectsWithSyncIDAndGitURL")) { cmd.Parameters.AddWithValue("@ID", item.ID); cmd.Parameters.AddWithValue("@SyncID", item.SyncID); cmd.Parameters.AddWithValue("@GitURL", item.GitURL); return(UpdateDatabase(cmd)); } }
public int CheckForInsertingNewProjectPath(DevProjPath item) { using (var cmd = new SqlCommand("DevTrkr..CheckForInsertingNewProjectPath")) { cmd.Parameters.AddWithValue("@DevProjectName", item.DevProjectName); cmd.Parameters.AddWithValue("@DevProjectPath", item.DevProjectPath); cmd.Parameters.AddWithValue("@Machine", item.Machine); cmd.Parameters.AddWithValue("@UserName", item.UserName); cmd.Parameters.AddWithValue("@IDEAppName", item.IDEAppName); cmd.Parameters.AddWithValue("@DatabaseProject", item.DatabaseProject); return(UpdateDatabase(cmd)); } }
/// <summary> /// NOTE: You can put breakpoints in here, but if you do, then writing becomes iffy in spite of /// all that I have done to queue and thread, there are still issues in debugging /// b/c stopping in here changes the window event /// </summary> public WindowEvents() { WinEventProcesss wep; TopOfCode: try { // get a queue item if it exists while (true) { lock (Globals.SyncLockObject) { if (Globals.WinEventQueue.Count.Equals(0)) { Globals.WindowEventThreadRunning = false; return; } wep = Globals.WinEventQueue.Peek(); Globals.WinEventQueue.Dequeue(); break; } } var now = wep.Starttime; // time window changed var title = wep.MyWindowEvent.WindowTitle; if (string.IsNullOrWhiteSpace(title)) { return; } var accessDenied = false; var moduleName = wep.MyWindowEvent.ModuleName; string displayName = wep.MyWindowEvent.UserDisplayName; var devPrjName = string.Empty; var syncId = string.Empty; // We set some properties so the file watcher knows who is running _currentApp = wep.MyWindowEvent.AppName.ToLower(); bool writeDB = false; /* make project extraction generic with regex */ // new code ***** NOTE: THE ideMATCHES TABLE SHOULD ONLY HAVE IDES AND SSMS (DBMGRs) **** // **** WE ARE DOING THIS FOR SSMS THO NOT AN IDE B/C SO MUCH TIME IS SPENT THERE // **** AND EVEN GROUPING BY A SERVER.DBNAME MAY GIVE A CLUE TO THE DEV PROJECT IDEMatch ideMatchObject = null; // ssms failing to update project name here and the reason is that ide.DBUnknown is // likely not set b/c ide switches when window changes, .^. some switch must reside in globals // that will persist between window changes.. and cache updates // i think that is what the index in the match table was // about and then I forgot its purpose and removed it //NOTE: cfp.GetProjectName also sets writeDB base on multiple checks // including the config option RECORDAPPS so the decision whether // to record this window is made there var cfp = new CheckForProjectName(); Tuple <string, IDEMatch, bool, string> cfpObject = cfp.GetProjectName(title, accessDenied, _currentApp, writeDB); devPrjName = cfpObject.Item1; writeDB = cfpObject.Item3; ideMatchObject = cfpObject.Item2; wep.MyWindowEvent.SyncID = cfpObject.Item4; // if we are writing this window, and devProjectName not set yet // see if a known project name is being worked on by a non IDE if (writeDB) { // check to see if the window title contains a known project name if (string.IsNullOrWhiteSpace(devPrjName)) { Tuple <string, string> prjObject = cfp.IsProjectInNonIDETitle(title); if (prjObject != null) { devPrjName = prjObject.Item1; wep.MyWindowEvent.SyncID = prjObject.Item2; } } } else { // one or more goto TopOfCode; } // try to get syncId from DevProjects var hlpr = new DHWindowEvents(); if (/*ideMatchObject != null && !ideMatchObject.IsDBEngine && */ !string.IsNullOrWhiteSpace(devPrjName)) { MaintainProject mp = new MaintainProject(); // bypass next line until we get fw debugged if (string.IsNullOrWhiteSpace(wep.MyWindowEvent.SyncID)) { wep.MyWindowEvent.SyncID = mp.GetProjectSyncIDForProjectName(devPrjName); //, _currentApp); } // here we should update any WindowEvents that have been created by this appname // and for this project w/o a syncid if (!string.IsNullOrWhiteSpace(wep.MyWindowEvent.SyncID)) { hlpr.UpdateWindowEventsWithSyncID(devPrjName, _currentApp, wep.MyWindowEvent.SyncID); } } /* Here, we are going to record the window in db * there are other threads, FileWatcher, changing this object * and we want no conflict */ WindowEvent item = wep.MyWindowEvent; if (item.AppName == "ApplicationFrameHost" && item.WindowTitle.Contains("Solitaire")) { item.AppName = item.WindowTitle; } if (!string.IsNullOrWhiteSpace(item.DevProjectName) && item.DevProjectName.Equals("devenv")) { _ = new LogError($"WindowEvent, Bad Project Name of 'devenv' from Title: {item.WindowTitle}", false, "WindowEvents.ctor"); } if (ideMatchObject != null && devPrjName == "DevTracker" && ideMatchObject.AppName == "ssms") { _ = new LogError($"WindowEvents, 'Devtracker' should not be the project name for ssms, Title: {item.WindowTitle}", false, "WindowEvent.ctor"); } //NOTE: 4 / 27 / 2020 discontinued this doing anything...except writing bad data notes // Window events does not have devpath and therefore is not qualified to insert a project if (ideMatchObject != null && !ideMatchObject.IsIde && !devPrjName.ToLower().Contains(".sql")) { // if next line true if (/*(!string.IsNullOrWhiteSpace(ideMatchObject.AlternateProjName) && devPrjName == ideMatchObject.AlternateProjName) || */ devPrjName == ".") { _ = new LogError($"WindowEvents, Bad Project Name: {devPrjName} from Title: {item.WindowTitle}", false, "WindowEvents.ctor"); } else { // this is a check for convoluted name going to DevProjectName if ("Connect.to_Repor._DevTrack.".Contains(devPrjName) || devPrjName.EndsWith(".")) { _ = new LogError($"WindowEvents bad project name = {devPrjName} from Title: {item.WindowTitle}", false, "WindowEvents.ctor"); } //NOTE: we should not set an unknown value in the devproject table // the way the sproc is written, this call will insert a new project with unknown path // if the project does not exist, and if it does exist, this call will not update // the path b/c this call is passing xxUnknown as the the path, // if this is the way a project gets created in DevProjects, it will only get the correct path // from the save of a project file, which only get done when a new project is created else if (string.IsNullOrWhiteSpace(devPrjName) || string.IsNullOrWhiteSpace(ideMatchObject.UnknownValue)) { _ = new LogError($"WindowEvents, Missing Data, Project: {devPrjName} Path: {ideMatchObject.UnknownValue} from Title: {item.WindowTitle}", false, "WindowEvents.ctor"); } else { // we create projects for database servers here for two reasons // 1) they don't have a path // 2) they will get no files saved with any relation to a path so FileAnalyzer won't create the project // when development of DevTracker was begun, windowevents // was the only way we had of possibly getting the project // name, but it did not, nor does it now have a way to get // the path. FileAnalyzer on the other hand has an exact way of // deriving the path to the projectFile .xxproj so Les has made // the decision of stopping what is at best doing half the job // except for database projects //Debug.WriteLine($"**** Would have checked for writing {devPrjName} to DevProjects"); if (ideMatchObject != null && ideMatchObject.IsDBEngine && devPrjName != ideMatchObject.AlternateProjName) { var mp = new MaintainProject(); DevProjPath dpp = new DevProjPath { DevProjectName = devPrjName, DevProjectPath = ideMatchObject.UnknownValue, IDEAppName = item.AppName, DatabaseProject = ideMatchObject.IsDBEngine, CountLines = false, ProjFileExt = "sql", DevSLNPath = string.Empty, GitURL = devPrjName, Machine = Environment.MachineName, UserName = Environment.UserName, CreatedDate = DateTime.Now }; item.SyncID = mp.CheckForInsertingNewProjectPath(dpp); } } } } if (item.AppName == "ssms" && item.DevProjectName == "Microsoft") { _ = new LogError($"WindowEvents, Bad Project name 'Microsoft' from Title: {item.WindowTitle}", false, "WindowEvents.ctor"); } item.DevProjectName = devPrjName; hlpr = new DHWindowEvents(); int rows = hlpr.InsertWindowEvent(item); goto TopOfCode; // check for more queue entries } catch (Exception ex) { _ = new LogError(ex, false, "WindowEvents.ctor"); } goto TopOfCode; }
public FileAnalyzer() { try { FileChange fc; // get instance of Project/File handler MaintainProject mp = new MaintainProject(); TopOfCode: // get a queue item while (true) { // this lock is local to this machine, and protects the Queue // b/c we are multithreaded and multiple cores (processing) lock (Globals.SyncLockObject) { if (Globals.FileChangeQueue.Count.Equals(0)) { Globals.FileAnalyzerThreadRunning = false; return; } fc = Globals.FileChangeQueue.Peek(); Globals.FileChangeQueue.Dequeue(); break; } } //NOTE: the original reason for the FileWatcher is not to record files being manipulated, // Rather it is to help maintain the DevProjects Table with the best information posssible // so that the WindowEvents class can charge the project and to report back to the windowevents // LastWindowEvent the project being worked on by the currentapp string syncID = null; var ext = Path.GetExtension(fc.FullPath).Replace(".", string.Empty).ToLower(); var devPath = string.Empty; var devProject = string.Empty; var relativeFileName = string.Empty; // filename past the pathname // but we should check to see if the file being saved is a .xxproj file, // we check for "CheckForInsertingNewProjectPath" var projFileObject = Globals.NotableFiles.Find(x => x.Extension == ext); var ideMatch = Globals.IDEMatches.Find(x => x.AppName == fc.CurrentApp); // HERE, app is ide and we are Manupulating the Project File (.xxproj) if (ideMatch != null && ideMatch.IsIde && projFileObject != null && !string.IsNullOrWhiteSpace(projFileObject.IDEProjectExtension) && projFileObject.IDEProjectExtension.Equals(ext)) { // yes, we are manipulating a development language project or sln file // therefore the path is where the project file is saved and // by definition, the filename is the name of the project fc.ProjectName = Path.GetFileNameWithoutExtension(fc.FullPath); devPath = Path.GetDirectoryName(fc.FullPath); // if devPath not in DevProjects path insert it, else update the pathname DevProjPath dpp = new DevProjPath { DevProjectName = fc.ProjectName, DevProjectPath = devPath, IDEAppName = fc.CurrentApp, DatabaseProject = ideMatch.IsDBEngine, CountLines = projFileObject.CountLines, ProjFileExt = projFileObject.IDEProjectExtension }; dpp.DevSLNPath = mp.FindSLNFileFromProjectPath(dpp); dpp.SyncID = syncID = mp.CheckForInsertingNewProjectPath(dpp, fc.FullPath); // the .sln may or may not be in the project table at the time the // project is created, in fact it may never be there for a number of reasons, // e.g., DLL project, etc., but a project may get a .sln at later time // here we do not know whether the code above wrote to DevProjects if (ext.Equals("sln")) { mp.UpdateSLNPathInProject(dpp); } // since project files (.cs,.vb, etc.) could be created before // the project file (.xxproj), now that we know for sure the // name and path, update all the files that may be missing them //NOTE: also, other project files will be saved after this but // we will not update them here until all files are are saved in the // project and the project file .xxproj get saved again which is // unless we get a method to update all the files in a project .xxproj file // which I just did so instead of the call below, we need to // 1. Get a list of all files from the project file. // 2. Loop thru the list of files from step 1. // 3. Call InsertUpdateFileActivity(with fa.Filename = each file from step 2) // We can do this without being concerned about time b/c this class runs on separate thread // from the FileWatcher and is processing files in sequence as they are queued // by FileWatcher class } else if (ideMatch != null && ideMatch.IsIde && projFileObject != null && !string.IsNullOrWhiteSpace(projFileObject.IDEProjectExtension)) { // this is an ide, but not saving a .xxproj file, but we know what the extension of the project file is // here we are addressing the issue of existing projects when this application is installed // look at FileAnalyzer saving code files for a project that has xxUnknown for a path // it could try to find the project name and path by enhancing GetProjectPath() to look for the // project file in the path somewhere // NOTE: changing logic here to something more reliable 04/17/2020 DevProjPath pp = mp.IsFileInADevProjectPath(fc.FullPath); // if pp not null, we have a known project // **** and the following lines is not doing anything... // b/c the project is already in devprojects and ChkforInsert..will do nothing if (pp != null) { fc.ProjectName = pp.DevProjectName; devPath = pp.DevProjectPath; syncID = mp.CheckForInsertingNewProjectPath(new DevProjPath { DevProjectName = fc.ProjectName, DevProjectPath = devPath, IDEAppName = fc.CurrentApp, DatabaseProject = ideMatch.IsDBEngine, CountLines = projFileObject.CountLines, ProjFileExt = projFileObject.IDEProjectExtension }, fc.FullPath); } else { // NOTE: if GetProjectPath returns project name and path it // found the .xxproj file so we are sure that we can check for inserting // a new project in DevProjects table Tuple <string, string, string> tuple = mp.GetProjectFromDevFileSave(fc.FullPath, Globals.NotableFiles, ext); if (tuple == null || string.IsNullOrWhiteSpace(tuple.Item1)) { goto TopOfCode; } else { //NOTE: if devenv is installing something don't let it fool // us into creating a project if ((fc.CurrentApp == "devenv" && tuple.Item2.ToLower().Contains("program files")) || tuple.Item1.ToLower().Contains("install")) { goto TopOfCode; } fc.ProjectName = tuple.Item1; devPath = tuple.Item2; syncID = mp.CheckForInsertingNewProjectPath( new DevProjPath { DevProjectName = tuple.Item1, DevProjectPath = tuple.Item2, IDEAppName = fc.CurrentApp, DatabaseProject = ideMatch.IsDBEngine, CountLines = projFileObject.CountLines, ProjFileExt = projFileObject.IDEProjectExtension }, fc.FullPath); } } } else if (fc.FullPath.ToLower().EndsWith(@"\.git\config")) { // we can try to get the project file name from git config file // the config file will not get a URL until the local repo is pushed to the server var url = mp.GetGitURLFromConfigFile(fc.FullPath); if (string.IsNullOrWhiteSpace(url)) { goto TopOfCode; } // get the repo name from the url, should be a projectname, may not be var m = Regex.Match(url, @".*/(?<PrjName>.*?)\.git"); var trialProjName = m.Success && !string.IsNullOrWhiteSpace(m.Groups["PrjName"].Value) ? m.Groups["PrjName"].Value : string.Empty; // if the url does not contain a projectname quit if (string.IsNullOrWhiteSpace(trialProjName)) { goto TopOfCode; } var exten = Globals.NotableFiles.Find(x => x.Extension == "config"); if (exten == null) { goto TopOfCode; } Tuple <string, string, string> projObj = mp.GetProjectFromGitConfigSaved(fc.FullPath, Globals.NotableFiles); if (projObj == null) { goto TopOfCode; } fc.ProjectName = projObj.Item1; devPath = projObj.Item2; syncID = mp.CheckForInsertingNewProjectPath( new DevProjPath { DevProjectName = projObj.Item1, DevProjectPath = projObj.Item2, IDEAppName = fc.CurrentApp, DatabaseProject = false, // above code found vs project extension CountLines = true, ProjFileExt = projObj.Item3 }, fc.FullPath); } else { // current app is not an IDE, or we don't have a projectFileExt type, // so see if file is saved in // a known current devprojectpath for this machine and user DevProjPath pp = mp.IsFileInADevProjectPath(fc.FullPath); if (pp == null) { goto TopOfCode; } // if this is a .sln file, check for updating the sln path in pp if (ext == "sln" && string.IsNullOrWhiteSpace(pp.DevSLNPath)) { pp.DevSLNPath = Path.GetDirectoryName(fc.FullPath); mp.UpdateSLNPathInProject(pp); } // yes, this file is project file of a known DevProjects project fc.ProjectName = pp.DevProjectName; devPath = pp.DevProjectPath; syncID = pp.SyncID; pp.CountLines = projFileObject.CountLines; // we update files only here b/c we are not calling mp.CheckForInsertingProject // as we do when we have an IDE above... mp.UpdateProjectFiles(pp, fc.FullPath, new DHMisc()); } // NOTE: if we get here we have a file that is being updated // in a known development path, else we would have ignored the file before getting here // if devProject is not empty, update the windowevent so that the app that caused this // FW event can be charged to the project if (!string.IsNullOrWhiteSpace(devPath)) { lock (Globals.LastWindowEvent) { var hlpr2 = new DHWindowEvents(); if (Globals.LastWindowEvent.ID == fc.CurrentWindowID && string.IsNullOrWhiteSpace(Globals.LastWindowEvent.DevProjectName)) { Globals.LastWindowEvent.DevProjectName = fc.ProjectName; Globals.LastWindowEvent.SyncID = string.IsNullOrWhiteSpace(syncID) ? string.Empty : syncID; } else { // since the ID has changed in the last window event // that means the current window changed before we could get // here (somewhat unlikely), so the window event that saved the // current file has already been written to database and the // projName is incorrect, it should be the last row // but not necessarily WindowEvent we = hlpr2.GetLastWindowEventWritten(fc.CurrentWindowID); if (we != null && string.IsNullOrWhiteSpace(we.DevProjectName)) { // update the window event that was current when this file was modified // with the correct proj name so work on this file gets charged hlpr2.UpadateProjAndPathInWindowEvent(fc.CurrentWindowID, fc.ProjectName, string.IsNullOrWhiteSpace(syncID) ? string.Empty : syncID); } } //update syncid in window events if syncid is known if (!string.IsNullOrWhiteSpace(syncID)) { hlpr2.UpdateWindowEventsWithSyncID(fc.ProjectName, fc.CurrentApp, syncID); } } } goto TopOfCode; } catch (Exception ex) { _ = new LogError(ex, false, "FileAnalyzer.ctor"); Globals.FileAnalyzerThreadRunning = false; } }