microsoft / windows-rs

Rust for Windows
https://kennykerr.ca/rust-getting-started/
Apache License 2.0
10.41k stars 489 forks source link

Are you using the Windows crate? #1285

Closed kennykerr closed 2 years ago

kennykerr commented 2 years ago

Hi folks, we're trying to gauge adoption and understand how we can best serve the Rust community with the Windows crate. In order to do this, I would love to hear from you! How has the Windows crate influenced your decision making? Did it help you decide to use Rust or target Windows? Is Rust replacing another language for a product you've previously shipped?

Feel free to leave a response here or email me directly to keep things private: kenny.kerr@microsoft.com

If the Windows crate matters to you, don't miss this opportunity to let me know and help influence the future of Rust on Windows.

Berrysoft commented 2 years ago

Two problems I've found:

I'm also looking forward to the ability of authoring XAML UWP or WinUI3 applications. Is there any plan of providing an XAML compiler?

samlh commented 2 years ago

I currently only use Rust for personal projects - that being said, windows-rs has made me comfortable trying out the Win32 API in earnest for the first time. At this point, I'm very happy with the developer experience using window-rs with prebuilt bindings.

My next project is to find a usable native-feeling UI framework I can use from Rust - if I'm able to get WinUI 3 to work, I expect I'll be implementing all of my projects for the foreseeable future in Rust. Note that I don't feel blocked on a XAML compiler - I'm hoping to build the UI using api calls.

kennykerr commented 2 years ago

@Berrysoft thanks for the feedback, but please create new issues to report any problems you may have. Here I'm really just trying to collect feedback on who is using the Windows crate and how it is helping you build software for Windows. (ARM64 support shipped in 0.25 for MSVC and namespace refactoring is an ongoing process here.)

Jasper-Bekkers commented 2 years ago

Hi Kenny,

Ever since https://github.com/microsoft/windows-rs/issues/432 got resolved, we've started the process on our side of switching over to windows-rs since for us this seems to be the way forward.

For we're mostly waiting on the rest of the ecosystem to slowly catch up, I think other then our own code winit is probably the biggest dependency we have on the old winapi crate. Though this also includes things like libloading, notify, ntapi, parking_lot, rand, ring, time, tokio, walkdir and lots more.

One thing that could be helpful also to speed up ecosystem adoption would be to publish a rustsec advisory stating that winapi is/will be deprecated. At the moment it's hardly maintained and windows-rs seems to be the way forward.

Additionally it could be extremely helpful if Microsoft would help evangelize the windows-rs adoption throughout the ecosystem, either by doing some of the heavily lifting itself on some of the very foundational crates, or by filing issues on larger repo's and making project maintainers aware and potentially advising on the switch.

We're eagerly awaiting the namespace changes to come through since right now we're having a bit of trouble keeping our feature set lean (for example we need to enable Win32_Graphics_Direct3D11 even though we're exclusively using Dx12).

One thing I'm worried about going forward is build times; right now only leaf nodes in our dependency tree are depending on windows-rs, which means that the parallel builds can hide quite a big chunk of the windows-rs build times on our heavy threadrippers. However, on smaller machines, or if window-rs gets pushed closer to the root of the dependency tree, I'm worried this may become a problem again.

mwgabby-li commented 2 years ago

How has the Windows crate influenced your decision making?

Official support from Microsoft on their platform has given me a lot more confidence in being able to create a robust Rust application on Windows. I am much more likely to use this crate for Windows interfacing thanks to the official support from Windows.

Did it help you decide to use Rust or target Windows?

No, because I was already planning to use Rust.

Is Rust replacing another language for a product you've previously shipped?

No. But it seems likely to start replacing languages like C and C++ in future projects.

Alovchin91 commented 2 years ago

Hi Kenny,

First of all, thank you for all the hard work you're doing! 🌷

Right now, there are basically two things that I'm waiting on to start adopting windows-rs:

I also hope that the future of Rust on Windows is not under question, given the record of Microsoft not allocating enough resources to a project and then killing it over the lack of adoption... 😬

joshtriplett commented 2 years ago

I'm really enthusiastic about the windows crate. I'm looking forward to being able to use it with raw-dylib, which will allow linking Windows applications without needing all the libraries around.

I would love to find the right combination of "make Rust compile faster" and "ship pre-compiled indexes of interfaces" and "make the compiler smarter about compiling only the used subset of a crate" to allow people to just use windows without having to set feature flags for the APIs they want to use.

LGUG2Z commented 2 years ago

I was a pretty early adopter of this crate, I've been using it in my tiling window manager since 0.3.

Before starting this project, I had zero familiarity with the Windows development ecosystem (and honestly, outside of this crate, I still don't), and I don't think I would have started this project if this crate was not available because I was not interested in learning C#, C++ or having a workflow centered around Visual Studio.

The only real pain point for me has been keeping up to date with the breaking changes between the updates (quite a few between 0.3 and 0.25 😅). I appreciate the changelog, but more often than not, when updating this crate results in a broken build, I have to diff through the examples and create a mental 'migration guide'.

Something like Rocket's migration guide for breaking changes would be a welcome addition whenever there is a new release with potentially build-breaking changes.

nothingismagick commented 2 years ago

We had the pleasure of working with @wravery on integrating windows-rs over at the Tauri ecosystem.

https://github.com/tauri-apps/tao/blame/next/Cargo.toml#L76

On a sidenote, tao started out as a winit fork, but the next branch is now using windows-rs; not sure if this addresses @Jasper-Bekkers concerns - because we have added general features that the winit maintainers felt were out of scope (like accelerators and menus)...

Definitely agree with @LGUG2Z about more strict change management.

wravery commented 2 years ago

We had the pleasure of working with @wravery on integrating windows-rs over at the Tauri ecosystem.

Coincidentally, I'm testing an update which will bump Tauri to windows-rs v0.25.0 and webview2-com to a version which matches. The latest windows-rs includes pre-compiled library support, which greatly simplifies the dependencies since the consumer can reference types directly in the windows crate instead of needing to build them all into an intermediate bindings crate. The webview2-com crate doesn't need to include everything its consumers might reference, and the Tao crate itself doesn't need to depend on webview2-com anymore since it can get those types directly from windows.

The only downside is that the windows::runtime::build macro doesn't yet point types referenced in another winmd file back to the pre-compiled libraries. I have to unwrap and rewrap a few types (e.g. windows::Win32::Foundation::HWND and windows::Win32::Foundation::RECT) when passing values through WebView2 APIs/callbacks. For Tauri, I also had to cast (i.e. QueryInterface) between a webview2_com::Win32::System::Com::IStream and windows::Win32::System::Com::IStream, as well as aliasing the types to disambiguate them.

yozhgoor commented 2 years ago

I use the Windows crate in two co-dependent projects, I created a lib (in-progress) to create a subprocess from a command string given by the user. I cannot use std::process because i would need to split the user input string into arguments (not trivial). I'm not a Windows user and i have a minimal setup to test the code but so far it was an interesting experience.

The differences between Rust and the API was a bit frustrating at first, it wasn't easy to find the appropriate documentation about the functions I was looking for but it's really easy to get started with the crate itself.

I also ran into an issue about the implementation of Copy on a struct passed as a mutable reference in argument. When creating a new ChildProcess I was trying to move a PROCESS_INFORMATION twice (since i write in it) but i was moving a copy and all others attempt to handle the ChildProcess failed silently.

We talked a bit about this on Twitter: https://twitter.com/CecileTonglet/status/1457760102228893696?s=20

MarijnS95 commented 2 years ago

I also ran into an issue about the implementation of Copy on a struct passed as a mutable reference in argument. When creating a new ChildProcess I was trying to move a PROCESS_INFORMATION twice (since i write in it) but i was moving a copy and all others attempt to handle the ChildProcess failed silently.

We talked a bit about this on Twitter: https://twitter.com/CecileTonglet/status/1457760102228893696?s=20

This seems to be a more general issue that could also be applied to primitives. What if I were to write (analogous to that fn create_process() implementation):

fn get_the_thing(thing: u32) {
    self.something.get(&mut thing)
}

Even if there's no copying going on at the caller, there should be a lint or warning that thing is unused after being mutably passed to a function, which is usually not intended.

rlabrecque commented 2 years ago

I jumped to this crate pretty early on some small personal projects, the only issues I've hit have been unimplemented stuff (with progress being made on all fronts since I hit those).

I'll echo some other opinions here that one area which needs to continue to evolve is the overall size of the package, including/disabling aspects of it, and the resulting build time of it.

Documentation on usage will be important too, it would be great if you could get some people dedicated towards documentation on the project. There were a handful of windows-rs specific patterns that I could only really figure out by looking at third party code doing similar things.

Overall this crate is hugely important to the Rust ecosystem, and I hope it continues to grow in a positive way!

kennykerr commented 2 years ago

I'm really enthusiastic about the windows crate. I'm looking forward to being able to use it with raw-dylib, which will allow linking Windows applications without needing all the libraries around.

I would love to find the right combination of "make Rust compile faster" and "ship pre-compiled indexes of interfaces" and "make the compiler smarter about compiling only the used subset of a crate" to allow people to just use windows without having to set feature flags for the APIs they want to use.

@joshtriplett Now you're talking!

I can't wait for raw-dylib to stabilize so I can throw away all those lib crates.

Making the Rust compiler faster is my top ask. On average, the Rust compiler seems about 10x slower than the C++ compiler: https://github.com/microsoft/windows-rs/issues/1292#issuecomment-965805621

kyleshay commented 2 years ago

Adopted at v0.10.0 - it's been a really fun ride seeing the advancements coming in all of the recent work. It's gotten so, so much easier! Thank you!!

We're relying on this crate to do (among other small things) screen shots and screen recording. The documentation has been excellent and easy to use. I've really liked that even back at 0.10.0 we could do everything we needed, it felt mostly feature-complete. It's also been satisfying to delete some of the extra boilerplate though the releases.

We're also using wasapi-rs for the audio side of things, over at Dropbox on our Capture project.

Here's a higher level article with a call out to the Windows crate! https://dropbox.tech/application/why-we-built-a-custom-rust-library-for-capture

Would love to chat more (with @robmikh as well, thank you for your projects! 🙌)

HEnquist commented 2 years ago

I'm using this in my CamillaDSP project. I was using the CPAL library before, but wanted direct access to wasapi. So when I found the windows crate I decided to go for it. That then became my wasapi-rs crate. I wasn't aware that it had found use in other projects than my own :)

I haven't worked with any windows API before starting with this. The windows crate (together with the excellent documentation at msdn) made it very easy to get started. Altogether it's been a very positive experience.

The one thing I'm missing is a way to have documentation for my wasapi-rs crate published to docs.rs. I realize this is not easy to solve, and it may not be worth the trouble. It works ok to just put it on GitHub pages.

EDIT: I haven't checked in a while and just noticed that the docs(.rs) for my latest few release built just fine! https://docs.rs/wasapi/0.7.0/wasapi/ Only problem I have left now is that the new windows-rs versions are coming so fast that I'm struggling to keep up :)

kennykerr commented 2 years ago

Thanks so much for all the responses thus far - keep it coming! I have read and re-read every one and am so grateful for your support. This is a huge help in planning. ♥

phuongtran7 commented 2 years ago

I'm using this for a small personal project that manipulates the window position, like starting up processes and resizing/moving to correct monitor. Previously I did this with a simple Autohotkey script, but after starting to learn Rust, I figure this would be a great way to try.

My main problem is from lacking Rust and Win API understanding, not from the crate itself. For example, the CreateProcessA function, when I read the doc to try and see how to use it, there isn't much there. I had to look up how to use the C++ version of that, then try and use it in Rust. Took a bit of time but I'm very happy with the result.

The crate is really great, even with my limited usage.

crlf0710 commented 2 years ago

When i made my own gdi-based minesweeper clone in rust, i made my own wrappers - apiw which is winapi-based WinAPI wrapper, and resw(https://github.com/crlf0710/resw-rs) which is a build-time windows resource script generator. (See https://github.com/crlf0710/charlesmine-rs/blob/7914458567421b0cf1d0cefab772985a5b5395d6/build.rs for its usage!)

I'm interested in the Windows crate and indeed thinking about migration. Though i'd really really like to see something as a replacement for my resw crate first... Please consider creating something in the place of that so i can retire it!

rlabrecque commented 2 years ago

With the announcement of windows-sys, I think that's a great step. Now I do wonder if there actually needs to be a third layer eventually?

  1. windows-sys - raw bindings
  2. windows-rs - core foundation (usually unsafe usage, some niceties but still a pretty raw form of the API)
  3. ? - Safe rust wrapper, code calling this should never need unsafe blocks.

I bring this up because of @crlf0710's comment about apiw. On my project I also had to create a wrapper on top of windows-rs to expose it in a safer way to my other code. The Windows API is so complicated that I know for a fact that my wrapper is unsound though, and I wish that layer was provided.

For what it's worth this is kind of what I ended up doing on Steamworks.NET, the 3 layered approach, with bindings, then a foundational layer with basically a 1:1 api with the underlying C++ based API, then layer on top of that which does things like let you pass in C# arrays to functions that take a pointer and length under the hood.

To add to @phuongtran7's point about the documentation since that was my primary pain point as well, despite knowing win32 fairly well, the issue I had was the magic incantation of getting the correct type to behave in the correct way when calling windows-rs functions. Using CreateProcessA as the example again, the way it's often used in C/++ ends up being throwing a bunch of NULL's or 0's in various arguments, well that usually doesn't work as well in Rust and you tend to need something like SomeSpecificNullableType::create_null(), then pass it in with ref mut* what ever. And figuring out that was by far the hardest part for me.

crlf0710 commented 2 years ago

@rlabrecque While i do think there's need for the third layer, as a API user actually i need a platform neutral third layer, and i hope it can work across major desktop platforms, and taking some consideration into supporting Web page+Webassembly and mobile platforms too, so i think it will be out-of-scope for windows-rs project itself. (Unless microsoft wants to create a rust version of maui or something)

That being said, windows-rs and windows-sys provides very solid foundation for the windows platform implementation, and provided support for working with very windows-specific functionalities. I'm very grateful for microsoft creating and maintaining this crate.

carey commented 2 years ago

As well as learning more about Win32, I wanted to call some APIs that didn't seem to have any easy way to do so from PowerShell, whether from .NET or ActiveX, and Add-Type -MemberDefinition seemed a bit too hacky. This resulted in these small tools:

What’s missing seems to me to be:

(Before this, I also learnt a lot of about COM and Rust FFI by trying to use a bit of IDispatch from scratch. Never again.)

main-- commented 2 years ago

So far my experience has been good. Thank you for this crate!

I encountered two major pain points:

I highly appreciate the error handling, but if I had‘t found it by accident while trying to figure out how to convert a BOOL to bool, I would still be out here trying to mess with std::io::Error::last_os_error() 😆. I think ideally there needs to be a book about this crate to show the patterns (like serde has) or at least a very detailed top-level documentation.

Zingam commented 2 years ago

I just found this crate. The documentation is a bit sketchy or basically missing. Currently docs.rs/windows is almost empty. What are these widows vs windows-sys bindings?

[dependencies.windows-sys]
version = "0.28.0"
features = [
    "Win32_Foundation",
    "Win32_Security",
    # "Win32_System_Threading",
    "Win32_UI_WindowsAndMessaging",
]

What is Win32_Foundation, Win32_Security? Why do I need it for MessageBoxA. We need answers. In any case what I see is enough for me to re-start my next big project in Rust rather than in C++. I needed a really good excuse for that and I think I found it, particularly because I need to use the Win32 APIs.

Also some links on this site are broken: https://docs.microsoft.com/en-us/windows/dev-environment/rust/ and the information seems outdated now but overall it was a great introduction.

knopp commented 2 years ago

Using windows-rs for NativeShell (Experimental embedder for Flutter). Started with 0.3 I think, It's been a bit bumpy ride keeping up, since almost every windows-rs update broke things, but I really don't mind because the changes were always for the better. Going for hand written COM implementation to #[implement felt amazing :) Currently upgrading to 0.28. Thank you for your work!

qdot commented 2 years ago

We're using it over in https://github.com/deviceplug/btleplug for our windows bluetooth access. Seems to mostly work for our needs.

Nocturem commented 2 years ago

The documentation is a bit sketchy or basically missing.

Have to second this and not too sure why @Berrysoft downvoted it. The documentation https://microsoft.github.io/windows-docs-rs/doc/windows is a good quick reference but lacks overviews or even links back out to them yet which makes it a fair bit more of a detective process to track down relevant examples than it need be.

Berrysoft commented 2 years ago

@Nocturem If you ask my opinion, I don't think the doc is missing. Actually I think the documentation is all there. If you want the usage of an API, just go to MSDN. If you want to search where it is, just search with ILSpy. If you don't know the difference between windows and windows-sys, read README carefully. If you don't know why you need MessageBoxA, you don't need it.

Nocturem commented 2 years ago

Well Zingam and myself aren't particularly alone I would note rlabrecque, phuongtran7, & main-- also mentioned documentation pain so mostly that comes off as an unproductive denial of others experiences.

Berrysoft commented 2 years ago

You need not to change my mind, right? That's just my personal opinion. If there's someone don't agree with me, it's OK.

tim-weis commented 2 years ago

@Berrysoft Here's a small challenge then: Can you spot the bug?

unsafe fn foo() -> Result<()> {
    GetClientRect( /* arguments */ ).ok()?;
    LineTo( /* arguments */ ).ok()?;
    Ok(())
}
Berrysoft commented 2 years ago

LineTo doesn't report error messages with GetLastError.

tim-weis commented 2 years ago

Correct. Now the follow-up question: Did you find the bug by looking at the available documentation exclusively, or did you have to dig into this crate's source code? I know I had to go looking there.

The documentation does indeed currently lack a good overview, ideally easily accessible from root level module documentation. Things I'd like to see documented:

Though I've been following this project since before it was a thing, and using it ever since, I still frequently find myself having to browse the source code. A bit more documentation would indeed help. This isn't asking for exhaustive documentation, just a bit more introductory/overview-type material.

Berrysoft commented 2 years ago

@tim-weis OK, it's fair to say that it's a documentation problem. However, I'd rather think it's an API design problem. There are at least 3 different BOOL in winapi (the 3rd one is ShowWindow), but they are the same in the metadata, and therefore it leads to the same BOOL here. If the metadata is designed much more exactly, it shouldn't be a bug in your example.

The core APIs that handle the interop with Windows API and Rust is simple, and the signatures mostly follow the std names. That's why I don't think it's missing doc.

You're right that sometimes I need to look through the source code to find the answers. But I don't think it is polite to simply ask for the answers and don't try to find them (oh, maybe found them and felt angry to the missing docs, I guess? My fault.). That's all and I don't want to argue whether the documentation is really missing. Anyway I'm not the maintainer or contributer, but only a user. You are free to ask for the docs, and even free to open pull requests. :)

riverar commented 2 years ago

Great feedback on all sides. We're aware the docs fall short in all areas. Should start to see more of that come online soon, stay tuned.

MrGibus commented 2 years ago

I've been sporadically working with this crate for window management. The docs could always be improved, but I've generally been able to achieve everything I wanted so far using what is provided and the MSDN.

General suggestions for improvement.

Appreciate the work.

Zingam commented 2 years ago

Great feedback on all sides. We're aware the docs fall short in all areas. Should start to see more of that come online soon, stay tuned.

How are these https://docs.rs/windows-sys/0.28.0/windows_sys/ and https://docs.rs/windows/0.28.0/windows/ (version 0.28.0) where there is literally nothing related to https://microsoft.github.io/windows-docs-rs/doc/windows/ (version 0.26.0). This got me confused, particularly because I was searching for the latest docs and I'm new to the ecosystem. As a noob I expected to find everything on docs.rs.

UPDATE: It looks like docs are not yet published: https://github.com/microsoft/windows-rs/issues/1358 :)

craftlinks commented 2 years ago

I'm using this crate to learn win32 programming using Rust, I'm having a blast so far! The example code has been surprisingly useful to get me unstuck on multiple occasions too.

Josh015 commented 2 years ago

I've been following this crate's progress in the hopes that I can help other crates port from winapi-rs to windows-rs when it's stable.

kirawi commented 2 years ago

Not sure if this was already mentioned here (I didn't read), but I'm dissuaded by the long search times w/ the docs compared to winapi.

estokes commented 2 years ago

I just finished implementing an RTD server for Excel using this crate and the com crate. I had initially prototyped in C++ and also in C#. Even though there are a lot of things that could improve rust is still my preferred solution by far. I'll just bullet some areas that could improve.

Still, even dealing with VARIANT and SAFEARRAY doesn't look that different from doing it in C++, so while that specific part of the code isn't much improved, many other areas are vastly better. For example, while the com crate could certainly be better, I find it already much nicer than using atl, midl, C++, and that complex dance of macros and header files and idl files. I know from reading the issue stack that all these problems are already on your radar, so keep up the great work!

skeletor-spills commented 2 years ago

Currently writing a WinUSB-ish program. We'd like to use a sanctioned Win32 bindings crate and this one seems to be the right one. It is far and away better to program against Win32 in rust vs C/C++. Though the API isn't all that different. Working with the rust language and its perks outweighs even the warts of the crate.

As @MrGibus stated the one thing on our wishlist currently is some things that are macro definitions Win32 C/C++ code either aren't in the rust bindings or are opaque and not easily found. Things like the RGB macro (https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-rgb) I can't seem to locate easily. We can implement a similar typesafe rust macro ourselves, but would rather not if something is available.

All around stellar work though and keep it up. Thanks.

luqmana commented 2 years ago

I finally got around to trying out writing a WireGuard UWP VPN plugin with the windows crate, and a couple warts aside it just worked! My biggest ask would probably be IVector[View] support out-of-the-box. For now I just have a half-implemented version that works for few cases I need.

Otherwise, awesome work! It's definitely come very far compared to the first time I tried implemented COM/WinRT interfaces in Rust.

pjmlp commented 2 years ago

Not much, beyond some toy projects.

Microsoft still isn't committed to Rust on Visual Studio (not Code) and to be honest, the WIP state of C++/WinRT tooling doesn't make us look forward into similar efforts in Rust.

So for us Windows remains focused on .NET, C++ when we aren't given an option to access Windows APIs from .NET directly, and Rust is left for hobby coding, mostly on POSIX platforms.

RivenSkaye commented 9 months ago

I've only used this crate for one project at work where I decided to use Rust for its emphasis on safety and fearless concurrency. For me the major blockers for doing more with it are the amount of unsafe required to get some pretty basic stuff done (references and mutable borrows could be handed over instead of raw pointers) and the three steps required to get through documentation. It's kinda annoying to have to find the C++ function you want, then find its definition and then check the Rust equivalent and any pitfalls there might be. E.g. CreateFileMapping -> CreateFileMapping<A|W> -> 1 IntoParam<Handle>, 1 PCSTR (constructable only with a macro or unsafe), and it returns a HANDLE that is different from the one in std (but I presume it's not yet off the table to fix that).

That said, the crate definitely does motivate me to play with it more in personal projects. And as evidenced by the issue I opened last week, I'm willing to help make working with it easier. I'm currently busy setting up the snippets repo and I'm working on a small crate to safely work with Memory Mapped Files as an option for Windows IPC that doesn't break when more than one client wants to read the same data. (for context, this is capturing a camera feed, and named pipes do not like 5MB frames being pushed to clients that may or may not read them).

Would love to see what the future brings for these crates and how the projections in general could grow to provide more safety mechanisms. I did notice a lot of them are unsafe purely because of raw pointers or due to returning a value indicating errors; that seems fixable right?