How to detect properly Windows, Linux & Mac operating systems - c#

I could not found anything really efficient to detect correctly what platform (Windows / Linux / Mac) my C# progrma was running on, especially on Mac which returns Unix and can't hardly be differenciated with Linux platforms !
So I made something less theoretical, and more practical, based on specificities of Mac.
I'm posting the working code as an answer. Please, comment if it works well for you too / can be improved.
Thanks !
Response :
Here is the working code !
public enum Platform
{
Windows,
Linux,
Mac
}
public static Platform RunningPlatform()
{
switch (Environment.OSVersion.Platform)
{
case PlatformID.Unix:
// Well, there are chances MacOSX is reported as Unix instead of MacOSX.
// Instead of platform check, we'll do a feature checks (Mac specific root folders)
if (Directory.Exists("/Applications")
& Directory.Exists("/System")
& Directory.Exists("/Users")
& Directory.Exists("/Volumes"))
return Platform.Mac;
else
return Platform.Linux;
case PlatformID.MacOSX:
return Platform.Mac;
default:
return Platform.Windows;
}
}

Maybe check out the IsRunningOnMac method in the Pinta source:

Per the remarks on the Environment.OSVersion Property page:
The Environment.OSVersion property does not provide a reliable way to
identify the exact operating system and its version. Therefore, we do
not recommend that you use this method. Instead: To identify the
operating system platform, use the RuntimeInformation.IsOSPlatform
method.
RuntimeInformation.IsOSPlatform worked for what I needed.
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
// Your OSX code here.
}
elseif (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// Your Linux code here.
}

Related

Turn on Airplane mode using AccessibilityService Class in Xamarin

I want to turn on or off airplane mode using AccessibilityService.
Any idea how we can do it?
Yes, you can't change it from app that target bigger than Android 4.2. But you can open the settings page instead if you want:
if (Android.OS.Build.VERSION.SdkInt < BuildVersionCodes.JellyBeanMr1)
{
try
{
Intent intentAirplaneMode = new Intent(Android.Provider.Settings.ActionAirplaneModeSettings);
intentAirplaneMode.SetFlags(ActivityFlags.NewTask);
Context.StartActivity(intentAirplaneMode);
}
catch (ActivityNotFoundException e)
{
Log.Error("exception", e + "");
}
}
else
{
Intent intent1 = new Intent("android.settings.WIRELESS_SETTINGS");
intent1.SetFlags(ActivityFlags.NewTask);
Context.StartActivity(intent1);
}
}
And AccessibilityService can used with dependency service.
Kamal you’re not going to be able to do it.
It doesn’t seem like you’re doing iOS, but iOS has a lot of limitations due to privacy and security purposes that won’t allow you to do this. You can see more details here stackoverflow.com/q/20469425/11104068
Also android blocked being able to do this from Android 4.2 onwards. Only system apps can make changes to Airplane mode, as you can see here stackoverflow.com/a/5533943/11104068
Since it doesn’t seem you’re creating a system app that gets installed with the operating system, and not through the Play Store, you won’t be able to get permissions. It will give you an error /exception even if you implement everything

How to set the WebBrowser object in the .NET Framework to use whatever highest version of IE is installed on the users system

So the title says it all, I would like C# code (so please, PLEASE make sure it isn't Visual Basic code). And that is all I want to ask. I have tried the web browser built in to the .NET framework, but it looks like some old version of IE (if I am right or not). And if you answered, well thanks I guess! I need this for a small project where a bot would just log on to a website (its a base for future projects).
By default it's IE7. You can bang a registry entry in to make it later:
public static void EnsureBrowserEmulationEnabled(string exename = "YourAppName.exe", bool uninstall = false)
{
try
{
using (
var rk = Registry.CurrentUser.OpenSubKey(
#"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", true)
)
{
if (!uninstall)
{
dynamic value = rk.GetValue(exename);
if (value == null)
rk.SetValue(exename, (uint)11001, RegistryValueKind.DWord);
}
else
rk.DeleteValue(exename);
}
}
catch
{
}
}
Code courtesy of this blog
The values you can use in place of 11001 can be found in MSDN
Alternatively; can you do what you want by using WebClient/HttpWebRequest rather than poking at a web browser control to navigate around? Or can you find some web service/api version of the site that will respond with JSON rather than trying to manipulate html?
I was mildly curious why you'd care what a page looks like if it's a bot that is using it, but perhaps you're hitting a "your IE is too old" from the server..

Android's - performHapticFeedback vs Vibrator - documentation and use

TL;DR:
Would appreciate any extra information on Android's
abstract class Vibrator
vs
performHapticFeedback
Preferably avoiding the use of the Vibrator class and prioritising performHapticFeedback to circumvent having to ask the user for permissions, and rely only on their system's preference.
Scenario:
I'm working with Xamarin trying to implement Haptic Feedback for Android and iOS.
Now, whereas the iOS documentation has a short explanation, which I've implemented as the following:
void Platform.Vibrate(HapticsIntensity HapticsIntensity)
{
UIKit.UIImpactFeedbackGenerator ImpactFeedbackGenerator;
switch (HapticsIntensity)
{
case HapticsIntensity.Light:
ImpactFeedbackGenerator = new UIKit.UIImpactFeedbackGenerator(UIKit.UIImpactFeedbackStyle.Light);
break;
case HapticsIntensity.Medium:
ImpactFeedbackGenerator = new UIKit.UIImpactFeedbackGenerator(UIKit.UIImpactFeedbackStyle.Medium);
break;
case HapticsIntensity.Heavy:
ImpactFeedbackGenerator = new UIKit.UIImpactFeedbackGenerator(UIKit.UIImpactFeedbackStyle.Heavy);
break;
default:
ImpactFeedbackGenerator = null;
break;
};
if (ImpactFeedbackGenerator != null)
{
ImpactFeedbackGenerator.Prepare();
ImpactFeedbackGenerator.ImpactOccurred();
}
}
The Android documentation for Haptic Feedback states that the method performHapticFeedback expects a HapticFeedbackConstant as a parameter.
public boolean performHapticFeedback (int feedbackConstant)
The available feedbackConstant's are here, but they seem to have no difference between them.
Calling:
LongPress
Engine.AndroidActivity.Window.DecorView.PerformHapticFeedback(Android.Views.FeedbackConstants.LongPress);
has the same effect as
VirtualKey
Engine.AndroidActivity.Window.DecorView.PerformHapticFeedback(Android.Views.FeedbackConstants.VirtualKey);
or
KeyboardTap
Engine.AndroidActivity.Window.DecorView.PerformHapticFeedback(Android.Views.FeedbackConstants.KeyboardTap);
moreover, some of the FeedbackConstants don't even result in haptic feedback.
Does anyone know where I could find any more documentation around this matter?
The reason why I ask is that I am implementing an abstract layer over Xamarin with Invention where my intention is to have my method calls like:
Vibrate(HapticsIntensity.Light);
Vibrate(HapticsIntensity.Medium);
Vibrate(HapticsIntensity.Heavy);
This works today, but where on iOS I get the tactile feedback of Light, Medium and Heavy vibration, on Android, I can't differentiate between them.
Now, I know Android has a Vibrate class (see here), which allows for granular control; however, to use this I need to add to my manifest or ask for specific permissions for my app (android.permission.VIBRATE), and that is not optimal.
Also, if I add the android.permission.VIBRATE permission to my manifest, it seems like (if the device has Haptic Feedback enabled in its settings), I don't even need to add the Vibrate() method call to my buttons` onClick; and they will already provide the tactile feedback (BZZZTT!!1!).
It totally depends upon if the device OEM has altered ASOP code and the vibration timing arrays in com.android.internal.R.array resource to enable a special haptic feedback "engine" that they are using on their device.
By default, the hardware OEMs are only required to support (in hardware) a standard on/off vibration (linear actuator, weighted rotary, etc..), not a "true" haptic feedback one which is normally based upon waveforms.
In comparison to the newer iOS devices (7|8+?), they are using the "Taptic Engine" (fancy speak for an "advanced linear actuator") for haptic feedback and only recently are Android devices "catching" up on the hardware side (new OnePlus, Pixel 3s, etc...) are starting to include more advanced haptic/vibration hardware (whether are not the OEM has done any special with that new hardware, you decide...)
So if you look at ASOP's PhoneWindowManager.java you will find that most of the HapticFeedbackConstants get lumped into a few VibrationEffects constants such as:
~~~
VibrationEffect.EFFECT_TICK
VibrationEffect.EFFECT_CLICK
VibrationEffect.EFFECT_HEAVY_CLICK
~~~
Look at the source if you want to see what the ASOP default VibrationEffects would be for a specific HapticFeedbackConstants:
PhoneWindowManager.java
If you have to provide manual-based haptic for your app for some reason, you can use the Vibrator API and provide the byte array for your on/off timing and then special case it for phone devices at offer more hardware features.

Issues with VNCSharpWpf for WPF in Microsoft Surface

first of all, I have been learning Microsoft Surface for about 1-2 months now and my project requires me to look into incorporating the use of a VNC viewer into my Surface Application.
I have looked into VNCSharp and VNCSharpWpf from VNC control for WPF application and I'm currently using VNCSharpWpf as it has better user interaction in the WPF environment although the performance is somewhat lacking compared to the viewers out there.
Here is my question, is there any difference between Microsoft Surface WPF and the default WPF in how they handle framebuffer/threads ?
I noticed that when the client attempts to draw the rectangle in the Surface environment, it will cause an exception where by the rectangle to be updated has 0 width and height.
However, when I test it on the sample code the author of VNCSharpWPF provides (WPF on Window ), the error never occur.
I tried to workaround by setting and if clause to only draw if the width and height of the rectangle decoded is not 0. Although it prevents the application from crashing, it will results in dead pixel around the screen whenever there are changes in the screen in the server-end.
I've been stuck with this situation for 1-2 weeks already and have ran out of ideas and is in need of some guidance on where I should look into
Or is there is any cool VNC viewer/server out there that I can use for my Surface project that I've missed out ?
I've been having the same issue with VNCSharp WPF on a PC, and when tested VNC Sharp for WinForms, then it worked OK.
Furthermore, When I've tested VNCSharp for WPF on Debug, then it works OK, but failed on Release.
I've wasted several hours debugging it (I've learned some parts of the VNC protocol for that matter, since I've found out that it somehow reads the width and the height of the remote device from the wrong location in the netowrk stream).
The bug is related to floats comparison. It depends on the machine you have (it might work well on some machines and on others it might not)
Please look at VncClient, Line 349:
if (rfb.ServerVersion == 3.8) rfb.ReadSecurityFailureReason();
If you, while debugging, put a breakpoint there, you will see that rfb.ServerVersion is 3.8f
ServerVersion returns a calcualted float:
public float ServerVersion {
get {
return (float) verMajor + (verMinor * 0.1f);
}
}
You should expect that since ServerVersion is 3.8, then it will execute
ReadSecurityFailureReason which reads some extra bytes that are needed for the code to work, but on Release (Ctrl+F5, since in Visual Studio Release, while the code is being debugged, it will probably work OK) those extra bytes will not be read, so the width and height will be read from the wrong location on the stream, causing it to be 0px over 0px
For demontrating my point, please take the following code, and compile it as x86 (I'm assuming that you have an x64 machine and an x64 OS, since this is the situation here):
class Program
{
static void Main(string[] args)
{
SomeVersion someVersion = new SomeVersion(3, 8);
if (someVersion.Version == 3.8f)
{
Console.WriteLine("Version is 3.8");
}
Console.ReadLine();
}
}
public class SomeVersion
{
private int _major;
private int _minor;
public SomeVersion(int major, int minor)
{
_major = major;
_minor = minor;
}
public float Version
{
get
{
return (float)_major + (_minor * 0.1f);
}
}
}
Run the code in Debug x86 (both with visual studio debugger and with Ctrl+F5)
You should see that you get the message: "Version is 3.8" on both cases.
Now change it to Release x86... Run it with F5. You should get the message.
Now run it with Ctrl + F5... WTF??, no message!
In order to fix the bug in the Vnc Sharp WPF, I've took the class RfcProtocol, and added another function:
public bool CompareVersion(int major, int minor)
{
return major == verMajor && minor == verMinor;
}
Now on VNC Client (both line 188 and 349), I've changed the code so it will compare using the new function, instead of comparing 2 floats.

What is the best way for a WinForms application to determine exactly which Windows operating system it is running on?

I have a WinForms application that needs to behave in specific ways (specifically shell to a certain installer) based on the operating system on which it is running.
I am using the System.OperatingSystem class, and combining the PlatFormID, Major, Minor and Build numbers which gets you most of the way there.
Unfortunately, the properites of an OperatinSystem object, do not allow you to distinguish precisely between some platforms. E.g. Vista and Windows Server 2008, or Vista 32 bit and Vista 64 bit. Likewise, XP 64 bit Professional seems to have the same versioning info as Server 2003.
So is it possible to determine exactly which Windows operating system you are running on, from a WinForms App (using c#)?
The easiest way to distinguish between 32bit and 64bit is through environmental variable PROCESSOR_ARCHITECTURE.
string value = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE");
if you run this code on 32bit Windows, value will be either "x86" or empty. On 64bit Windows I assume it will be set to anything but "x86". Kind of messy but so far it works on all versions of Windows where you can execute .NET program.
You can also use more modern WMI to query practically all information about operating system you can imagine but this will only work on Windows 2000 or newer. If you can live with that, check this blog post for some examples.
You can use WMI to retrieve information for the Win32_OperatingSystem management class.
Code generated with WMI Code Creator :
using System;
using System.Management;
using System.Windows.Forms;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_OperatingSystem");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_OperatingSystem instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("BuildNumber: {0}", queryObj["BuildNumber"]);
Console.WriteLine("Caption: {0}", queryObj["Caption"]);
Console.WriteLine("OSArchitecture: {0}", queryObj["OSArchitecture"]);
Console.WriteLine("OSLanguage: {0}", queryObj["OSLanguage"]);
Console.WriteLine("Version: {0}", queryObj["Version"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
}
}
This was something i did about a year ago for a legacy app at my company... I don't know that it is the most current method, but it certainly worked.
If Environment.OSVersion.Platform = PlatformID.Win32NT Then
If major <= 4 Then
ret = "Windows NT 4.0"
_usingNT4 = True
ElseIf major > 6 Then
ret = "Windows Vista"
ElseIf major = 5 And minor = 0 Then
ret = "Windows 2000"
Else
ret = "Windows XP"
End If
Else
If major > 4 Or (major = 4 And minor >= 90) Then
ret = "Windows ME"
ElseIf (major = 4 And minor >= 10 And minor < 90) Then
ret = "Windows 98"
Else
ret = "Windows 95"
End If
End If
If you really need all the details, I guess you still can use the good-old GetVersionEx of Win32 API.
In fact this is not .NET (strictly speaking), but usable in a .NET application. See here.
Here's a simpler way:
string os = Environment.OSVersion.VersionString;
... For my OS, the above returns the following:
Microsoft Windows NT 6.1.7600.0
Hope this helps.

Categories