Interestingly, the Rust windows crate is generated from an MSIL assembly. And same metadata might be used to generate C# bindings thanks to cswin32 [1] project. The meta-assembly generation (Win32 metadata project) is based on clangsharp and it's fairly straightforward to generate interop code for native Windows libraries. Some time ago I described this process on my blog for the detours library [2]
I understand the burden that too much notes may take on you. I am a software troubleshooter and I used to keep my raw notes of all the interesting cases I encountered. However, with time, this set became hard to navigate. Additionally, when I was rereading my notes, they seemed chaotic and hard to follow. I now prefer to create a succinct summary of a closed case, explaining the taken steps, my thinking, and the solution, so that my future self could understand it :)
I do a lot of Windows troubleshooting and still thinking about incorporating AI in my work. The posted project looks interesting and it's impressive how fast it was created. Since it's using MCP it should be possible to bind it with local models. I wonder how performant and effective it would be. When working in the debugger, you should be careful with what you send to the external servers (for example, Copilot). Process memory may contain unencrypted passwords, usernames, domain configuration, IP addresses, etc. Also, I don’t think that vibe-debugging will work without knowing what eax registry is or how to navigate stack/heap. It will solve some obvious problems, such as most exceptions, but for anything more demanding (bugs in application logic, race conditions, etc.), you will still need to get your hands dirty.
I am actually more interested in improving the debugger interface. For example, AI assistant could help me create breakpoint commands that nicely print function parameters when you only partly know the function signature and do not have symbols. I used Claude/Gemini for such tasks and they were pretty good at it.
As a side note, I recall Kevin Gosse also implemented a WinDbg extension [1][2] which used OpenAI API to interpret the debugger command output.
I've been using bpftrace -lv to examine available trace points. But the bpftrace output won't show you the complex types definitions and this tool can do it. Great work!
There is also Sysmon for Linux [1]. I work often with Windows systems that's how I know it (it's a popular choice on Windows to analyze Sysmon logs for suspicious events), but it's probably niche in Linux world.
Have you tried running it on wine? [1] I use it this way on Linux and, after adjusting my commands for running editors and start menu tools, everything runs smoothly.
I feel that nowadays Rust is the language to go when you are doing system programming, but C# is not a bad choice either. With .NET 9 being released in a few weeks we will get NativeAOT (compilation to a native single binary) for x86 (x64 and ARM64 are already available). At work, I'm writing patches for legacy apps and needed to use C++ for most of my tasks. Nowadays, I'm doing more and more stuff in C# and enjoying it. For WinAPI there is a fantastic cswin32 [1] project that generates FFIs signatures on the fly. And it's fairly simple to extend it for other Windows libraries (I did it for detours [2], for example). And using pointers or working with native memory blocks is straightforward and intuitive for people with C/C++ background.
Although NativeAOT sounds cool and it's better than nothing: I don't like that it comes with a bunch of limitations[1]. I would have loved this if you could just use it without any changes, but I'm very worried that at some point I used something that prevents me from getting it to work and I have to figure out which limitation I just walked into. Correct me if I'm wrong.
Those limitations are often obvious. With AOT, you don't have the VM around, you can't load new bytecode or introspect the objects. I would focus on writing working code, and try to go AOT close to the end. If it fails and it's not fixable, tough luck, but it works on the standard runtime.
Technically speaking, there is VM (you could also consider GC to be a part of it, but in HN understanding it's an umbrella term that can mean many things). Because the type system facilities are there which is what allows reflection to work.
The main source of confusion as to why some believe that NativeAOT prohibits this are libraries which perform unbound reflection in a way that isn't statically analyzable (think accessing a method by a computed string that the compiler cannot see and not annotating with attributes the exact members you would like to keep and compile the code for) or libraries which rely on reflection emit. But even reflection emit works for limited scenarios where runtime compilation is not actually required like constructing a generic method where argument is a class - there could only be a single generic instantiation of __Canon argument in this case, which can be emitted at compile time. You can even expect the reflection to work faster under NativeAOT - it uses a more modern pure C# implementation and does not need to deal with the fact that types can be added or removed at runtime.
That's interesting - I would have thought targeting aot at the outset and then switching away only when the design became incompatible would be more effective, only because by going for aot at the end I'd probably have introduced some code or dependency that isn't aot compatible and yet too much work to replace
With source generation, I'd say that its biggest limitation is rapidly diminishing. Even ASP.NET Core is embracing it, allowing for better support for json deserialization and eventually MVC.
Apart from search customizations, I also use the bang searches (a few mine and many from https://github.com/kagisearch/bangs). I also recently switched to ultimate and created a few assistants with system prompts for my various needs (coding, learning chemistry, etc.)
[1] https://github.com/microsoft/CsWin32
[2] https://lowleveldesign.org/2023/11/23/generating-c-bindings-...