Wymagane jest dla określonego zadania wyliczenie wszystkich uchwytów w systemie. Najlepszym podejściem, jakie do tej pory znalazłem, jest używanie nieudokumentowanego NtQuerySystemInformation
z flagą SystemHandleInformation
dla parametru klasy.Preferowane podejście do kompilacji warunkowej dla wersji 32-bitowych i 64-bitowych typów
Jak dotąd tak dobrze. Jednak uruchomienie go w trybie 32-bitowym na 64-bitowym systemie Windows, wymagana struktura jest następująca:
// 32-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public uint ProcessID;
public byte ObjectTypeNumber;
public byte Flags;
public ushort Handle;
public uint Object_Pointer;
public UInt32 GrantedAccess;
}
A dla 64-bitowych systemów Windows (x64, nie przetestować Itanium, które mam nadzieję, że nie jest inaczej. ..), których struktura jest następująca:
// 64-bit version
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct SYSTEM_HANDLE_INFORMATION
{
public int Reserved; // unknown, no documentation found
public uint ProcessID;
public byte ObjectTypeNumber;
public byte Flags;
public ushort Handle;
public long Object_Pointer;
public UInt32 GrantedAccess;
}
teraz należy zmienić Object_Pointer
do IntPtr
. Miałem nadzieję, że przez chwilę będę mógł zrobić to samo z ProcessId
, było odniesienie mówiąc, że faktycznie był to HANDLE
, który jest w rzeczywistości wartością 64-bitową. Jednak Reserved
ma zawsze wartość zero, więc nie mogę tego scalić w taki sam sposób.
Prawdopodobnie nie jest to jedyny scenariusz, w którym tak się dzieje. Szukam praktyka sposób radzenia sobie z takimi różnicami najlepiej:
- przy stałej jak
#if WIN32
(używany wewnętrznie w źródle referencyjnym IntPtr) nie będzie tu pracować, chyba że chcą utrzymać oddzielne pliki binarne. - Potrafię napisać dwie różne funkcje i dwie różne struktury, utworzyć opakowanie i użyć kodu
if IntPtr.Size ==4
. Działa to dla funkcji zewnętrznych, ale nie działa dobrze z typami. - Mogę przeciążać
GetType
, ale nie jestem pewien, gdzie to prowadzi (może pomóc w Marshalling?). - Coś jeszcze?
Żadne z nich nie wydaje się idealne, ale jak na razie jedyną niezawodną metodą wydaje się być smalenie mojego systemu za pomocą instrukcji if IsWin64()
. Chciałbym usłyszeć lepsze podejście niż moje.
Ten rodzaj kodu jest jak seks nastoletnich, jeden błąd i będziesz go wspierać przez resztę swojego życia. Użyj klasy Process, aby uruchomić narzędzie Handle.exe SysInternals, przynajmniej możesz poprosić kogoś innego, aby to wspierał. –
@HansPassant: LOL! Tak, rozważałem użycie dowolnego narzędzia SysInternal, ale nie, nie pasuje do mojego scenariusza. Dzięki za wskaźnik. – Abel