-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OS version information #14294
Comments
This seems like a reasonable addition to me. I know we are nervous to add back version properties, but some way to figure out if you are on Linux/OSX/Windows seems reasonable. |
Thank you 👍 |
I've seen a similar request for ARM32 vs other platforms, checking pointer size is not good enough in that situation. |
I would have upvoted this issue if it were possible =) I have a project that uses quite a few |
I think we do need to expose something like the Platform your are running on (Linux/Windows/Mac) and the processor. For example, Kestrel does the following to figure out if they are running on windows or not: public static bool IsWindows()
{
#if DNXCORE50
return true;
#else
var p = (int)Environment.OSVersion.Platform;
return (p != 4) && (p != 6) && (p != 128);
#endif
} Which is completely busted when you want to run .NET Core on CoreCLR. If we don't provide an API I can imagine the next best thing being just trying to P/Invoke to random Windows or Unix APIs and determine the answer that way. I have also seen cases where parts of ASP.NET vNext sniff PROCESSOR_ARCHIECTURE environment variable to detect x86 vs x64. I have been moving that code to use IntPtr.Size, but as David says, there's no way to figure out ARM or not with that. |
Exposing the desktop types in cloud platform, is not desired, as we need to keep adding support back to desktop. A good way to go will be to create a new contract, with the following api-definition: namespace System.XPlatform
{
public struct OSName
{
public OSName(string osName) { }
public static OSName Windows { get; }
public static OSName Linux { get; }
public static OSName OSX { get; }
}
public static class RuntimeInfo
{
public static bool IsOSPlatform(OSName osName) { return default(bool); }
}
} cc @KrzysztofCwalina @ellismg @weshaggard @davkean @stephentoub : If this api design is agreeable i'll start implementing this. |
Can you help me understand that conclusion? Adding enum values to .NET Framework ("desktop") is extremely easy, especially given NET Framework will never have to return them or plumb them through. In fact, it already contains the values (Unix/Linux, MacOS and Win32NT) that currently we're planning to port to. Adding this into a new assembly is even more problematic, and we're now forced to introduce a new library (with one type!) that we'll need to build for each platform, even though we're already building mscorlib/CoreCLR for each one and it already contains the APIs. I believe we should stick with the previous plan and expose the existing APIs. cc @terrajobst @nguerrera @jaredpar @ericstj the rest of the Framework Design Core. |
The BSD port of CoreCLR is underway by the community now and they are making good progress. I assume as soon as they are done, we will want to be answer the question "am I running on BSD". So we would have to version the contract anyway. With the above design we can say call RuntimeInfo.IsOSPlatform(new OSName("BSD")) even if we can't quickly rev the contract.
Not having a dependency on the runtime when possible feels like a win to me. I don't understand the pushback about having to build multiple times. We're already going to be in that boat for many pieces of CoreFX. I also see no reason why long term the implementation of the contract could not be a façade over the runtime itself, if we find that that's the correct factoring. |
For every port to a new OS, the runtime is going to have to rev, so I'm not understanding that concern. It's not just building multiple times; it's creating the contract, the multiple projects, NuGet packages, etc. It feels like we're adding complexity to an area that is not needed. The APIs already exist and given the large amount of code already in mscorlib that probably needs to do something similar, we'd probably need to keep them around anyway - or put these new APIs into mscorib.
You can achieve the same thing with enums |
@Priya91 I really like what you have here. My only piece of feedback is around the namespace. Could we use something like |
@ellismg : Yes, system.runtime.interopservices sounds good. Since these apis relate to runtime environment information how about System.Runtime.Environment.. |
I like that a lot! |
(Side note that will clash with Environment class in the System namespace) |
@davkean What clashes? If the contract is called System.Runtime.Environment? |
Ah, I thought you were talking about the namespace. |
Ok, sounds like we have reached a conclusion with the latest proposal. I'll mark the issue with accepting PRs. Going along with the API review process @blobor: will you be providing PR, or only contributing the issue? |
The API looks good overall to me as well but I was curious about why you need the OSName struct? Is there a particular reason that is necessary instead of just using a string? We could still use OSName as a place holder for predefined sets. |
@weshaggard : Any string parsing that has to be done, can be abstracted in OSName instead of IsOSPlatform, moreover, we expect a string that represents an OSName, instead of any string. |
It also helps with discoverability. You know you need an OSName and that guides you to the static properties. |
How is this supposed to work under the hood, i.e. will it end up calling Just to confirm I understand this correctly: this can't be put into |
The current thinking is we would provide a different implementation assembly for each platform, which would hard-code the result, so we wouldn't call uname. We don't have current plans to expose something like Distro information from this type, but that's more because we don't understand the scenarios where one might want to do that. We are hesitant, however, to do something like expose a Version of the OS your are running on.
Yeah, that is the basic problem. |
@Priya91 For now, only contributing the issue. |
I'd vote for just exposing the existing |
@justinvp wanted to avoid the use of |
@jaredpar For reasons I still don't understand. :) |
I also don't fully grok why all of this is necessary. @ellismg can you summarize the problems again? |
Frankly, I don't see how the proposed API is better than the old one. From the readability point of view, And a separate obscure class somewhere in |
Sorry, my post was a bit tongue in cheek. I know the deeper problem is complex. We discussed the complex issue many time and could not come up with a great small dunk solution. If we can come up with something great in this thread, it would be great. But for this, the discussion needs to focus on the deeper (scenario) problems, not on whether the thing is an enum, int, expanded acronym or not, etc. |
@whoisj I'm personally satisfied with the scenarios that you and @HellBrick gave. Certainly, we could make a longer list. @Priya91 is the one to say if she has enough requirements to make an update to her design. Do you have any comments on whether the current design is adequate or not? @KrzysztofCwalina Agree with you. The core issue is not the metadata representation of the API. |
Other than I prefer to not use Otherwise, I'm happy as this as a starting point. I like to get general agreement that there's a lot more information that needs to be surfaced to make the API truely useful (see mentioned above about file system case sensitivity and preservation, etc). |
I meant something a bit different, which I didn't properly ask. Oops. There is a q much higher in the thread about how one would do checks on Android. Would that be "Linux" or "Android" or would both be true? That's not an implementation detail. I'm interested in exploring the scenarios where the currently simple API might fall down. Android is also interesting because there is the Dalvik / ART divide. That's divide won't be relevant for .NET Core. The interesting thing is that scenario. If .NET Core had 5 years of apps on Android, would people have had to do checks for runtime, or would that have been handled by the Java APIs? I assume so. It's still relevant for this discussion. |
@richlander : The primary use case for this feature arose from the x-plat work that we have been doing in corefx. Code specific to different platforms has been organized into separate files that are conditionally included during compile time in product. Writing tests for the product is a scenario that consumes the product and implements the different use-cases of this product. Now while writing tests, we had this problem where there was just this one line of code that differs between the different platforms. Of the ways that we could solve the problem at that time was to have different compilation for different platforms, which is too much effort for a single line of code. Having different compilation to test a single line of code leads to defining different pre-processor symbols and changes to build script to automate building for different platforms. All of this for a single line of code, and given the examples from @HellBrick it is evident the same kind of workarounds are being applied for simple scenarios. Another solution one might propose is to have a custom runtime platform detection, which is the temporary solution used in corefx here. So in essence people are coming up with creative ways to fill this void, when we should provide a good way to solve this problem in .NET Core, this being a common scenario. On Linux: Right now Linux implies desktop OS (we are not differentiating between different distros, and we may provide support for this later, note, that itself is another issue, what are the distros to be supported, etc). If we ever supported .NET core apps on android (mobile platform), we would add another value to the OSPlatform for Android. If this is confusing as to why Linux is not returning true for Android, then what would be a good name to differentiate linux desktop OS with android? |
@Priya91 What you wrote is not a use-case. That's mechanically how the feature is used. It doesn't help me understand if your proposal satisfies your need. I was thinking of Linux as a kernel, similar to this thread: http://www.linux.org/threads/the-linux-kernel-android.5459/. My understanding is that Android uses the standard Linux kernel. Is that right? |
@richlander Forgive my ignorance, but can you define what you are expecting by use-case. This is what i think you are expecting: Scenario: Develop a wallpaper changer app that runs on linux and windows, a very basic code sample: namespace MyApp
{
internal enum OSEnum
{
Windows,
Linux
}
public class WallpaperChanger
{
private void ChangeWindowsWallpaper() { }
private void ChangeLinuxWallpaper() { }
private OSEnum DetectOS()
{
/*In the absence of .NET Core platform detection API, I will have some custom logic here.*/
return default(OSEnum);
}
internal void ShowImagesFromWeb() { }
public void StartApp()
{
ShowImagesFromWeb();
/*Wait for image select event to fire*/
switch(DetectOS())
{
case OSEnum.Linux:
ChangeLinuxWallpaper();
break;
case OSEnum.Windows:
ChangeWindowsWallpaper();
break;
default:
throw new PlatformNotSupportedException();
}
}
}
} |
@Priya91 These examples from @HellBrick are what I was looking for: https://github.com/dotnet/corefx/issues/1017#issuecomment-107797361.They describe actual platform differences that one must workaround. I'm sure that there are others. Your example, while appreciated, displays a particular technique for differentiating behavior for an OS, but isn't really a use-case, since I cannot see the code that needs to differ. If I could see that, then it would be more clear which patterns and APIs would satisfy it. As it stands, I just have to trust you that the coding pattern that you chose is the right one. |
@richlander : In the previous example, to set the wallpaper i will have to interop into the linux/windows specific library and call the native api to actually do the change. The actual code that changes the wallpaper is irrelevant here, the focus should be on which library you are going to choose to interop to based on the platform. Those platform specific differences given by @HellBrick should be answered by the various framework apis that manipulate that data, for example, filesystem has path.directoryseparatorchar which will give the right path, similarly process.start to handle the differences, etc. I wouldn't even need to use this api for such scenarios, when i can directly call the cross plat .net framework api for that. It is in examples like above that this API is actually useful. |
But so is this. That's exactly my point. Just because it's hidden behind enums and classes instead of strings doesn't make the conceptual intent of the API any different. It would be better to have a "platform string" and admit where a kludge is a kludge than to have an enum which is out of date or provides a misleading API. ([edit] The point here being that an enum would have to be provided by corefx and I don't think the BCL should have any notion of what platforms it can run on.)
Yes, that is in fact exactly what I have been arguing. |
Thank you :) These are the examples @HellBrick provided, all of which (IMO) need a different and specific check.
You want something like
If this is a concern you should just do this universally to avoid the problem altogether. Clearly you need some
Seems like this should be a property of a cross-platform file interaction API. Also isn't this a Posix API? Does OSX care about the executable bit?
Available universally on any Linux distro? (if so, then yes, valid use-case for this feature!)
This should absolutely be handled by some API, you shouldn't have to pass strings around like this.
Admittedly an edge case and not recommended behavior, no? |
@Priya91 I know this was a quick example you just tossed together, so don't take this personally, but that is the sort of code that everyone should be moving away from. One's code should not be littered with platform checks. It shouldn't even be lightly dusted with platform checks. You would want some |
Coming into the discussion a bit late, but it seems like the main use case we are aiming to enable (and correct me if I'm wrong) is letting a library developer create implementations for multiple platforms without multiple compilations, and therefore without multiple release binaries. To me, that seems to be the one "thing" this library is aiming to solve. Apologies if this seems obvious, I thought I'd mention it anyways to try to get some clarity/consensus on that point. So to me, the use case is: "Creating a cross-platform library which uses platform-specific logic, without shipping platform-specific binaries" or even simpler: "Use platform-specific logic within a platform-agnostic assembly" A few more thoughts that pop to my mind:
@nexussays brings up a very good point regarding the potential usages of the library. When you are pivoting around file paths or file names, you are really trying to make a decision based on the machine's file system behavior, not the name of the operating system. By pivoting on the operating system name, you are relying on your prior knowledge of OS and filesystem differences. From an API purity and usage standpoint, that is not ideal. It would be awesome if the libraries could abstract these important differences in a more meaningful and user-friendly way, but that's obviously not an easy problem in all cases. |
@Priya91 Your point is also my point. You and @nexussays say that most of the platform-specific operations would be covered by platform-agnostic facades, with platform-specific implementations, provided by .NET Core. That's definitely what we want. So, your use case then is:
Without seeing the actual P/Invokes, it was hard to see what the scenario was. My question, then, is what the other scenarios are. I'm wondering if there are some cases where .NET Core APIs return results that are platform-specific that require differentiated handling. |
@mellinoe (I doubt anyone minds you jumping in late. I jumped in like a week ago and now I'm trying to hijack the thread :)) That seems like a very good explanation; working off of that, my pushback is on the "use platform-specific logic" part, in which I will continuously ask: what logic? and why? We should consider any time you need to "break out" of .NET and use platform-specific logic to be a "hole" in CoreFX. Could be it's an edge case that no one has addressed, could be it's too expensive, maybe it's already an open issue. Point being we ("we" the community) should address each such case individually and figure out what .NET Core API can provide for this platform-specific functionality.
I agree, but I'm saying show me those cases; specifically, enumerate what those cases are and then we can address them individually. Once we come across some platform-specific functionality that stumps this question then we can say ok, so we can't integrate this use-case into .NET, what's the next level of abstraction up that we can implement. We've basically started at the highest possible level of abstraction with some abstract notion of "Operating System" in which Linux is a singular entity. That's my objection. |
Not exactly. The concept is similar, but the folders that we use are specific to our system and
I'm with you on this one; like I said earlier, something like
I don't know if this flag is important to OSX, since we only use Windows and Linux servers. But come to think of it, I've never tested what will happen if I try to append Executable attribute to a file on Windows. If it works fine, then the platform check isn't really needed here.
We deploy this dependency with our app, both Windows and Ubuntu versions, and then choose one in runtime to avoid managing 2 separate builds and deployments. I'm not really sure if it works on the other distros, but even if it doesn't, it's hard to imagine scenario where we would choose to use two different Linux distros simultaneously in our cluster. Worst-case scenario, we could be forced to replace the platform type check with a distro check here, but I really don't think it will ever come to this.
Sorry, I don't get your point here. We're just launching a child process, and on different platforms we use different executables that obviously have slightly different argument strings. Some better API to manage argument strings would obviously be of help here, but it has nothing to do with the platform-dependent choice we're discussing here.
It sure it is an edge case, but this is still a good example of a completely unpredictable yet real problem the platform check could help with. In case of this specific bug checking the platform is way easier than analyzing the types loaded into the current app domain to detect we're running on Mono, since in our case we're running on Mono if and only if we're running on Linux. |
A simple use-case for knowing what platform you're on (Linux, Mac, or Windows): scanning the file system to compare files present with a list of expected files present. On Mac and/or Linux you're best off grabbing a bunch of strings (paths) then The logic is different, it simply has to be or one platform will suffer performance penalties and have unhappy users. Can this be hidden behind some API facade? Sure - does it need to be? No. Will there be plenty of other topics like this? Yes. Is this API sufficient? No. Is it a start in the right direction? I think so, but I'd like to see if flushed out more before we proceed. |
@nexussays do you mind providing some pseudo code? I think your point is no different from what @Priya91 says. The actual logic to change the wallpaper is abstracted. It could be a native call or some IsA kind implementation. The jist is that you need to identify which of the descendants or the native API to call based on the current platform.
I am sorry if I didn't understand your point. May I please request you to elaborate a bit more? |
Having listened to the API review (thanks for hosting it !), I'm wondering if
Also using uname, you may lack information, you may lack flexibility (won't be able to hack your own values in), you may lack enum niceties, but you can't make it wrong (on Unix). I'm not 100% sure on this one, and I don't like the fact that it'd be an simple wrapper over the OS, but given the uncertainty/confusion around the topic during the review (flags/exclusive or not, versions or not, feature/capability or not), I can't help thinking than something else will fail. |
We've reviewed this proposal today. It has been approved with feedback. |
Please also consider these use cases if
The API can only test if we are running on a given platform, but there is no way to retrieve the current platform. |
Closing this issue, as the scope of this issue was to get a query api into corefx to query for the underlying os platform. |
- Adds a new dependency to System.Runtime.InteropServices.RuntimeInformation. More info can be found - On this issue: https://github.com/dotnet/corefx/issues/1017 - On this PR: dotnet/corefx#1999
…. Using OperationSystem is not sufficient, e.g. it returns just "fedora" on Fedora Linux. See also https://github.com/dotnet/corefx/issues/1017.
* Use RuntimeInformation.IsOSPlatform to determine the runtime platform. Using OperationSystem is not sufficient, e.g. it returns just "fedora" on Fedora Linux. See also https://github.com/dotnet/corefx/issues/1017. * Remove whitespaces.
I want to write cross-platform class library based on .NET Core. I need to invoke native libraries in Windows (kernel32) and in UNIX (libc).
Currently Environment class is missing OSversion property. Is there some way to determine in what OS currently my assembly is running?
The text was updated successfully, but these errors were encountered: