@@ -50,6 +50,61 @@ internal class CxToolbar
5050 public Func < List < State > , Dictionary < MenuItem , State > > CreateStateMenuItems { get ; set ; }
5151
5252 private static bool initPolling = false ;
53+
54+ public static bool IsValidSourceProject ( string sourcePath )
55+ {
56+ if ( string . IsNullOrEmpty ( sourcePath ) )
57+ {
58+ return false ;
59+ }
60+
61+ try
62+ {
63+ string searchPath ;
64+ if ( System . IO . File . Exists ( sourcePath ) )
65+ {
66+ searchPath = System . IO . Path . GetDirectoryName ( sourcePath ) ;
67+ }
68+ else if ( System . IO . Directory . Exists ( sourcePath ) )
69+ {
70+ searchPath = sourcePath ;
71+ }
72+ else
73+ {
74+ return false ;
75+ }
76+
77+ string [ ] projectExtensions = { "*.sln" , "*.csproj" } ;
78+
79+ foreach ( string extension in projectExtensions )
80+ {
81+ var files = System . IO . Directory . GetFiles ( searchPath , extension , System . IO . SearchOption . AllDirectories ) ;
82+ if ( files . Any ( file => IsValidProjectFile ( file ) ) )
83+ return true ;
84+ }
85+
86+ return false ;
87+ }
88+ catch ( Exception ex )
89+ {
90+ UpdateStatusBar ( "Checkmarx: Error validating project directory" + ex . Message ) ;
91+ return false ;
92+ }
93+ }
94+
95+
96+ private static bool IsValidProjectFile ( string filePath )
97+ {
98+ try
99+ {
100+ var fileInfo = new System . IO . FileInfo ( filePath ) ;
101+ return fileInfo . Exists && fileInfo . Length > 0 ;
102+ }
103+ catch
104+ {
105+ return false ;
106+ }
107+ }
53108 private const string DevOrTestFilterName = "SCA Dev & Test Dependencies" ;
54109
55110
@@ -286,6 +341,13 @@ public async Task ScanStart_ClickAsync()
286341 return ;
287342 }
288343
344+ if ( ! IsValidSourceProject ( dte . Solution . FullName ) )
345+ {
346+ CxUtils . DisplayMessageInInfoWithLinkBar ( Package , CxConstants . NOT_A_VALID_PROJECT , KnownMonikers . StatusError , "Project Error" , "" , false ) ;
347+ ScanStartButton . IsEnabled = true ;
348+ return ;
349+ }
350+
289351 var currentGitBranch = await GetCurrentGitBranchAsync ( dte ) ;
290352 var checkmarxBranch = SettingsUtils . GetToolbarValue ( Package , SettingsUtils . branchProperty ) ;
291353 var matchProject = await ASTProjectMatchesWorkspaceProjectAsync ( dte ) ;
@@ -322,6 +384,9 @@ private static async Task<string> GetCurrentGitBranchAsync(EnvDTE.DTE dte)
322384 try
323385 {
324386 string workingDir = System . IO . Path . GetDirectoryName ( dte . Solution . FullName ) ;
387+ if ( string . IsNullOrEmpty ( workingDir ) || ! System . IO . Directory . Exists ( workingDir ) )
388+ return null ;
389+
325390 RepositoryInformation repository = RepositoryInformation . GetRepositoryInformation ( workingDir ) ;
326391
327392 if ( repository == null )
@@ -341,9 +406,9 @@ private static async Task<string> GetCurrentGitBranchAsync(EnvDTE.DTE dte)
341406
342407 private static async Task < bool > ASTProjectMatchesWorkspaceProjectAsync ( EnvDTE . DTE dte )
343408 {
344- if ( ResultsTreePanel . currentResults == null || ! ResultsTreePanel . currentResults . results . Any ( ) )
409+ if ( ResultsTreePanel . currentResults == null | ResultsTreePanel . currentResults . results == null || ResultsTreePanel . currentResults . results . Any ( ) )
345410 {
346- return true ;
411+ return false ;
347412 }
348413
349414 List < Result > astResults = ResultsTreePanel . currentResults . results ;
@@ -434,6 +499,13 @@ private async Task StartScanAsync()
434499
435500 string currentPath = await GetCurrentWorkingDirAsync ( ) ;
436501
502+ // Check if a valid project/solution was found
503+ if ( string . IsNullOrEmpty ( currentPath ) )
504+ {
505+ UpdateStatusBar ( CxConstants . NOT_A_VALID_PROJECT ) ;
506+ return ;
507+ }
508+
437509 Dictionary < string , string > parameters = new Dictionary < string , string >
438510 {
439511 { CxCLI . CxConstants . FLAG_SOURCE , currentPath } ,
@@ -462,14 +534,91 @@ private static async Task<string> GetCurrentWorkingDirAsync()
462534 await ThreadHelper . JoinableTaskFactory . SwitchToMainThreadAsync ( ) ;
463535
464536 DTE2 dte = ( DTE2 ) ServiceProvider . GlobalProvider . GetService ( typeof ( DTE ) ) ;
537+ var solutionExplorer = dte ? . ToolWindows ? . SolutionExplorer ;
538+
539+ // Try to get directory from solution or active projects
540+ string directory = null ;
541+
542+ if ( ! string . IsNullOrEmpty ( dte ? . Solution ? . FullName ) )
543+ {
544+ // Solution is loaded - get its directory or use the path itself if it's a directory
545+ if ( System . IO . File . Exists ( dte . Solution . FullName ) )
546+ {
547+ directory = System . IO . Path . GetDirectoryName ( dte . Solution . FullName ) ;
548+ }
549+ else if ( System . IO . Directory . Exists ( dte . Solution . FullName ) )
550+ {
551+ directory = dte . Solution . FullName ;
552+ }
553+ }
554+ else if ( solutionExplorer ? . DTE ? . ActiveSolutionProjects is Array projects && projects . Length > 0 )
555+ {
556+ // Try to get directory from first active project
557+ var firstProject = projects . GetValue ( 0 ) as EnvDTE . Project ;
558+ if ( firstProject != null && ! string . IsNullOrEmpty ( firstProject . FullName ) )
559+ {
560+ directory = System . IO . Path . GetDirectoryName ( firstProject . FullName ) ;
561+ }
562+ }
563+
564+ // If we still don't have a directory, try current directory
565+ if ( string . IsNullOrEmpty ( directory ) )
566+ {
567+ try
568+ {
569+ directory = System . IO . Directory . GetCurrentDirectory ( ) ;
570+ }
571+ catch
572+ {
573+ return null ;
574+ }
575+ }
465576
466- var solutionExplorer = dte . ToolWindows . SolutionExplorer ;
577+ // Now search for .sln or .csproj in the directory
578+ if ( ! string . IsNullOrEmpty ( directory ) && System . IO . Directory . Exists ( directory ) )
579+ {
580+ return FindSolutionFileOrDirectory ( directory ) ;
581+ }
582+
583+ return null ;
584+ }
585+
586+ private static string FindSolutionFileOrDirectory ( string directory )
587+ {
588+ if ( string . IsNullOrEmpty ( directory ) || ! System . IO . Directory . Exists ( directory ) )
589+ {
590+ return null ;
591+ }
592+
593+ // Look for .sln file in the directory
594+ var slnFiles = System . IO . Directory . GetFiles ( directory , "*.sln" , System . IO . SearchOption . TopDirectoryOnly ) ;
595+ if ( slnFiles . Length > 0 )
596+ {
597+ // Return the first valid .sln file
598+ foreach ( var slnFile in slnFiles )
599+ {
600+ if ( IsValidProjectFile ( slnFile ) )
601+ {
602+ return directory ;
603+ }
604+ }
605+ }
467606
468- if ( ( solutionExplorer . DTE . ActiveSolutionProjects as Array ) ? . Length > 0 )
607+ // If no .sln found, look for .csproj files
608+ var csprojFiles = System . IO . Directory . GetFiles ( directory , "*.csproj" , System . IO . SearchOption . TopDirectoryOnly ) ;
609+ if ( csprojFiles . Length > 0 )
469610 {
470- return System . IO . Path . GetDirectoryName ( dte . Solution . FullName ) ;
611+ foreach ( var csprojFile in csprojFiles )
612+ {
613+ if ( IsValidProjectFile ( csprojFile ) )
614+ {
615+ return directory ;
616+ }
617+ }
471618 }
472- return "." ;
619+
620+ // No valid .sln or .csproj found - return null to trigger error
621+ return null ;
473622 }
474623
475624 private async Task PollScanStartedAsync ( )
0 commit comments