Skip to content

Commit 0f92c41

Browse files
authored
Close and delete Intellisense database after generating project files (#566)
* Try to mitigate stalls in NativeHandles.GetAllFileHandlesAsync * Close and delete Intellisense database after generating project files This ensures that 'uet generate' clears out any corrupt Intellisense database files (that prevent Intellisense from working).
1 parent 8387f67 commit 0f92c41

4 files changed

Lines changed: 86 additions & 11 deletions

File tree

UET/Redpoint.Windows.HandleManagement/NativeHandles.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44

55
namespace Redpoint.Windows.HandleManagement
66
{
7-
using System.ComponentModel;
8-
using System.Runtime.InteropServices;
9-
using System.Runtime.Versioning;
10-
using System.Threading.Tasks;
7+
using global::Windows.Wdk.Foundation;
8+
using global::Windows.Wdk.System.SystemInformation;
119
using global::Windows.Win32;
1210
using global::Windows.Win32.Foundation;
13-
using Redpoint.Windows.VolumeManagement;
1411
using Redpoint.Collections;
12+
using Redpoint.Windows.VolumeManagement;
13+
using System.ComponentModel;
1514
using System.Linq;
16-
using global::Windows.Wdk.System.SystemInformation;
17-
using global::Windows.Wdk.Foundation;
15+
using System.Runtime.InteropServices;
16+
using System.Runtime.Versioning;
17+
using System.Threading.Tasks;
18+
using System.Xml.Linq;
1819

1920
/// <summary>
2021
/// Static API methods for querying and closing handles on Windows.
@@ -240,6 +241,28 @@ internal static GetPathResultCode GetPathForHandle(SYSTEM_HANDLE targetHandle, b
240241
}
241242
throw new NTSTATUSException(status);
242243
}
244+
if (PInvoke.GetFileType((HANDLE)duplicatedHandle) != global::Windows.Win32.Storage.FileSystem.FILE_TYPE.FILE_TYPE_DISK)
245+
{
246+
PInvoke.CloseHandle((HANDLE)duplicatedHandle);
247+
return GetPathResultCode.NotSupported;
248+
}
249+
HANDLE mapFile;
250+
unsafe
251+
{
252+
fixed (char* mapFileTemporaryName = "TestFileMap")
253+
{
254+
mapFile = PInvoke.CreateFileMapping((HANDLE)duplicatedHandle, null, global::Windows.Win32.System.Memory.PAGE_PROTECTION_FLAGS.PAGE_READONLY, 0, 1024, mapFileTemporaryName);
255+
}
256+
}
257+
if (!mapFile.IsNull)
258+
{
259+
PInvoke.CloseHandle(mapFile);
260+
}
261+
else if (Marshal.GetLastWin32Error() == 193)
262+
{
263+
PInvoke.CloseHandle((HANDLE)duplicatedHandle);
264+
return GetPathResultCode.NotSupported;
265+
}
243266
try
244267
{
245268
unsafe

UET/Redpoint.Windows.HandleManagement/NativeMethods.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ NtQuerySystemInformation
33
UNICODE_STRING
44
CloseHandle
55
OpenProcess
6-
GetCurrentProcess
6+
GetCurrentProcess
7+
GetFileType
8+
CreateFileMapping

UET/Redpoint.Windows.HandleManagement/NtQueryObjectPool.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,13 @@ public NTSTATUS NtQueryObject(
118118
{
119119
// NtQueryObject has stalled. Kill the thread and restart it.
120120
Debug.WriteLine($"Stalled requesting handle from process ID: {processId}");
121-
cts.Cancel();
121+
cts.CancelAfter(10);
122122
var i = Array.IndexOf(_threads, request.Thread);
123-
_threads[i] = new Thread(NtQueryObjectLoop);
124-
_threads[i].Start();
123+
if (i >= 0 && i < _threads.Length)
124+
{
125+
_threads[i] = new Thread(NtQueryObjectLoop);
126+
_threads[i].Start();
127+
}
125128
returnLength = 0;
126129
return (NTSTATUS)NTSTATUSException.NT_STATUS_CANCELLED;
127130
}

UET/uet/Commands/Generate/GenerateCommand.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Redpoint.Uet.Commands.ParameterSpec;
99
using Redpoint.Uet.CommonPaths;
1010
using Redpoint.Uet.SdkManagement;
11+
using Redpoint.Windows.HandleManagement;
1112
using System;
1213
using System.Collections.Generic;
1314
using System.CommandLine;
@@ -355,6 +356,52 @@ public async Task<int> ExecuteAsync(ICommandInvocationContext context)
355356
if (exitCode == 0)
356357
{
357358
_logger.LogInformation($"Project generation finished successfully. The generated project files are located in: {outputFolder}");
359+
360+
var vsDirectory = Path.Combine(workingDirectory, ".vs");
361+
if (Directory.Exists(vsDirectory))
362+
{
363+
if (OperatingSystem.IsWindowsVersionAtLeast(6, 2))
364+
{
365+
try
366+
{
367+
await foreach (var handle in NativeHandles.GetAllFileHandlesAsync(context.GetCancellationToken()))
368+
{
369+
if (handle.FilePath.StartsWith(vsDirectory, StringComparison.OrdinalIgnoreCase) &&
370+
(handle.FilePath.Contains("Browse.VC.db", StringComparison.OrdinalIgnoreCase) ||
371+
handle.FilePath.Contains("Browse.VC.opendb", StringComparison.OrdinalIgnoreCase)))
372+
{
373+
_logger.LogInformation($"Trying to close handle to Intellisense database file at: {handle.FilePath}");
374+
await NativeHandles.ForciblyCloseHandleAsync(handle, context.GetCancellationToken());
375+
}
376+
}
377+
}
378+
catch
379+
{
380+
}
381+
}
382+
foreach (var browseFile in new DirectoryInfo(vsDirectory).GetFiles("Browse.VC.*db*", SearchOption.AllDirectories))
383+
{
384+
_logger.LogInformation($"Trying to clear Intellisense database file at: {browseFile.FullName}");
385+
try
386+
{
387+
browseFile.Delete();
388+
}
389+
catch
390+
{
391+
}
392+
if (browseFile.Exists)
393+
{
394+
try
395+
{
396+
browseFile.MoveTo(browseFile.FullName + ".old");
397+
}
398+
catch
399+
{
400+
}
401+
}
402+
}
403+
}
404+
358405
if (open)
359406
{
360407
if (OperatingSystem.IsWindows())

0 commit comments

Comments
 (0)