@@ -336,6 +336,12 @@ public static bool RemoveRecentProject(string projectPathToRemove)
336336 {
337337 bool result = false ;
338338
339+ if ( RemoveProjectFromUnityHubJson ( projectPathToRemove ) )
340+ {
341+ //Console.WriteLine("Deleted Unity Hub project item: " + projectPathToRemove);
342+ result = true ;
343+ }
344+
339345 var hklm = RegistryKey . OpenBaseKey ( RegistryHive . CurrentUser , RegistryView . Registry64 ) ;
340346
341347 // check each version path
@@ -397,10 +403,115 @@ public static bool RemoveRecentProject(string projectPathToRemove)
397403 result = true ;
398404 }
399405
400-
401406 return result ;
402407 } // RemoveRecentProject()
403408
409+ private static bool RemoveProjectFromUnityHubJson ( string projectPathToRemove )
410+ {
411+ string hubProjectsFile = Path . Combine (
412+ Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) ,
413+ "UnityHub" , "projects-v1.json" ) ;
414+
415+ if ( ! File . Exists ( hubProjectsFile ) )
416+ return false ;
417+
418+ string json ;
419+
420+ try
421+ {
422+ json = File . ReadAllText ( hubProjectsFile ) ;
423+ }
424+ catch
425+ {
426+ return false ;
427+ }
428+
429+ string wantedPath = NormalizeProjectPath ( projectPathToRemove ) ;
430+
431+ int dataIndex = json . IndexOf ( "\" data\" :" ) ;
432+ if ( dataIndex == - 1 )
433+ return false ;
434+
435+ int dataStart = json . IndexOf ( '{' , dataIndex + 7 ) ;
436+ if ( dataStart == - 1 )
437+ return false ;
438+
439+ int searchFrom = dataStart + 1 ;
440+
441+ while ( true )
442+ {
443+ int entryStart = json . IndexOf ( '{' , searchFrom ) ;
444+ if ( entryStart == - 1 )
445+ break ;
446+
447+ int entryEnd = JsonParser . FindMatchingBrace ( json , entryStart ) ;
448+ if ( entryEnd == - 1 )
449+ break ;
450+
451+ string entry = json . Substring ( entryStart , entryEnd - entryStart + 1 ) ;
452+ string projectPath = JsonParser . GetStringValue ( entry , "path" ) ;
453+
454+ if ( ! string . IsNullOrEmpty ( projectPath ) )
455+ {
456+ projectPath = NormalizeProjectPath ( projectPath ) ;
457+
458+ if ( string . Equals ( projectPath , wantedPath , StringComparison . OrdinalIgnoreCase ) )
459+ {
460+ int removeStart = entryStart ;
461+ int removeEnd = entryEnd + 1 ;
462+
463+ // Prefer removing comma after this object.
464+ int i = removeEnd ;
465+ while ( i < json . Length && char . IsWhiteSpace ( json [ i ] ) )
466+ i ++ ;
467+
468+ if ( i < json . Length && json [ i ] == ',' )
469+ {
470+ removeEnd = i + 1 ;
471+ }
472+ else
473+ {
474+ // Otherwise remove comma before this object.
475+ i = removeStart - 1 ;
476+ while ( i >= 0 && char . IsWhiteSpace ( json [ i ] ) )
477+ i -- ;
478+
479+ if ( i >= 0 && json [ i ] == ',' )
480+ removeStart = i ;
481+ }
482+
483+ json = json . Remove ( removeStart , removeEnd - removeStart ) ;
484+
485+ try
486+ {
487+ File . WriteAllText ( hubProjectsFile , json ) ;
488+ return true ;
489+ }
490+ catch
491+ {
492+ return false ;
493+ }
494+ }
495+ }
496+
497+ searchFrom = entryEnd + 1 ;
498+ }
499+
500+ return false ;
501+ }
502+
503+ private static string NormalizeProjectPath ( string path )
504+ {
505+ if ( string . IsNullOrEmpty ( path ) )
506+ return "" ;
507+
508+ return path
509+ . Replace ( @"\\" , "/" )
510+ . Replace ( "\\ " , "/" )
511+ . Trim ( )
512+ . TrimEnd ( '/' ) ;
513+ }
514+
404515 } // class
405516} // namespace
406517
0 commit comments