I am working on an app for an Okuma lathe.
I would like to be able to put the lathe into an alarm state from the app. I am not getting any errors and the app runs on the machine, but it doesn't go into an NC alarm state.
The line before it does change the text of alarmLabel.
I am using alarmLabel for troubleshooting.
Can anyone provide an example of SetUserAlarm in C#?
Does anyone see what is wrong with my code?
alarmLabel.Text = "Alarm ON";
objCMDMachine.SetUserAlarm(
Okuma.CLCMDAPI.Enumerations.UserAlarmEnum.C,
"Test Alarm",
Okuma.CLCMDAPI.Enumerations.UserAlarmSubSystemEnum.All
);
Your example code there looks okay to me.
To successfully generate a machine alarm, the API must have the licensed feature UserAlarm.
(Okuma.Lathe.UserAlarm in the okuma.api.lic license file).
You can confirm that a machine has this option by using the SCOUT library:
UserAlarmLathe = Okuma.Scout.LicenseChecker.License_UserAlarm_L;
if (UserAlarmLathe.Status == Enums.LicenseStatus.Valid)
{
// ...
}
Additionally, the machine on which the API resides must also have the THiNC ALARM option.
If your machine does not have the option, it can be ordered by contacting your Okuma Distributor and asking for option code " :911-0010 - THiNC ALARM "
The presence of this option can be confirmed by checking the Lathe Spec Code NC-B No. 4, Bit 3. You can check this spec code in your application using either THINC API or SCOUT.
Using THINC API:
Okuma.CLDATAPI.DataAPI.CSpec SpecCodeClass = new Okuma.CLDATAPI.DataAPI.CSpec();
bool THiNK_ALARM = SpecCodeClass.GetBSpecCode(4, 3);
if (THiNK_ALARM)
{
// ...
}
Using SCOUT:
if (Okuma.Scout.SpecCode.NCB.MachineSpecCodeFileExists)
{
if (Okuma.Scout.SpecCode.NCB.SpecFileIsValid)
{
bool THiNK_ALARM = Okuma.Scout.SpecCode.NCB.Bit(
Okuma.Scout.Enums.NCBSpecGroup.NCB1MG, 4, 3);
if (THiNK_ALARM)
{
// ...
}
}
}
Related
I've been using this C# library wrapper for the darksky API:
https://github.com/amweiss/dark-sky-core
In my implementation I poll once every 3 minutes to get the forecast, which I use in my home thermostat network:
async void GetForecast()
{
// https://darksky.net/dev/docs#forecast-request
float Temp, DewPoint, WindSpeed, WindChill, Humidity, HeatIndex;
var client = new DarkSkyService("user-api-key");
try
{
Forecast fc = await client.GetWeatherDataAsync(38.329444, -87.412778);
Temp = (float)Math.Floor(fc.Currently.Temperature);
PublishTemp(Temp);
// for database, get temp, dewpoint, calculate windchill, calculate heatindex
DewPoint = (float)fc.Currently.DewPoint;
WindSpeed = (float)fc.Currently.WindSpeed;
Humidity = (float)fc.Currently.Humidity; // range: 0-1
WindChill = (float)CalculateWindChill(Temp, WindSpeed);
HeatIndex = (float)CalculateHeatIndex(Temp, Humidity);
SaveToDatabase(Temp, DewPoint, WindChill, HeatIndex);
RxForecast = true;
if (DateTime.Now.Hour != LastForecastHour)
{
LatestForecast = fc;
LastForecastHour = DateTime.Now.Hour;
PublishForecasts();
}
}
catch (Exception s) {
RxForecast = false;
}
ForecastWaitTime = RxForecast ? FAST_FORECAST_CYCLE : SLOW_FORECAST_CYCLE;
}
This has worked fine for about 4 months before it abruptly stopped working a week ago. Darksky support said that they have recently implemented security updates and no longer support most common TLS ciphers (quoting):
- TLS 1.0
- TLS 1.1
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA256
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_256_GCM_SHA384
- TLS_RSA_WITH_AES_256_CBC_SHA256
- TLS_RSA_WITH_AES_256_CBC_SHA
You can definitively determine whether your app works with the new SSL permissions by testing against
https://api.darksky.net:4433/. If you decide to update SSL on your end, you can test the API by sending a request here: https://api.darksky.net:4433/v1/status.txt.
Note that we will be making additional security-related updates in the coming weeks so there will be more changes in the near future. We don't have a notification system for alerting users to changes made on our backend but we do offer a feed for our status page, which often includes information about updates that have been or will be made (https://status.darksky.net/). We'll do our very best to make sure we communicate them as we're able to. Additionally, to avoid future disruptions we strongly recommend switching to one of the following, which should carry you through any of the additional security updates that will be applied in the near future:
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
I have no idea what changes I need to make to this code to 'update TLS', and I can't seem to get any more information from darksky. In the meantime, my alarm system is at a standstill.
One thing I don't understand is that, if I type this URL in a browser:
https://api.darksky.net/forecast/my-api-key/38.329444, -87.412778
It works fine, and immediately returns a huge JSON forecast string. Trying this with HttpWebRequest, HttpClient, or WebClient, in code results in different "errors occurred" exceptions. Overall, I'd rather use the library for the returned Forecast object that is easy to interpret.
Is this TLS update something I do at the system level, outside the devlopment environment?
Or, are there any alternatives to darksky that I could switch to?
You have two options:
1: update the library you are using and recompile. This issue was reported on its github page:
https://github.com/jcheng31/DarkSkyApi/issues/28
2: It's a bit of work but you could move the forecast module to Linux/Raspberry Pi, where TLS12 is already configured. You will have to rewrite the routine in Python to do this. I verified this approach would work on my own PI network.
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..
I have a strange problem. I have a kiosk application (running as device owner, set by dpm) that is attempting to perform a self upgrade from an apk file that has already been downloaded. The file is downloaded correctly and the upgrade appears to work correctly. The application quits, the system gives a notification that the application has been upgraded by the device owner before the application relaunches.
When the application has relaunched, the version number is reporting as the new version, but none of the modified functionality in the app is present. On the initial login form I added a label with the version number hardcoded into it to compare to the version pulled using Xamarin.Essentials.AppInfo.Version.ToString(). The hardcoded version does not update, but the software version shows correctly.
The device is a Samsung Galaxy Tab A.
I have added a toast on exception which is showing no error messages. I have tried changing the PackageInstallMode to InheritExisting, this didn't seem to make any difference.
The method used for the upgrade is here.
public void UpgradeFromLocalFile(string downloadedFile)
{
try
{
if (MainActivity.Instance.CheckSelfPermission(Manifest.Permission.WriteExternalStorage) == Permission.Denied)
{
MainActivity.Instance.RequestPermissions(new string[] { Manifest.Permission.WriteExternalStorage }, 0);
}
if (MainActivity.Instance.CheckSelfPermission(Manifest.Permission.ReadExternalStorage) == Permission.Denied)
{
MainActivity.Instance.RequestPermissions(new string[] { Manifest.Permission.ReadExternalStorage }, 0);
}
if (MainActivity.Instance.CheckSelfPermission(Manifest.Permission.InstallPackages) == Permission.Denied)
{
MainActivity.Instance.RequestPermissions(new string[] { Manifest.Permission.InstallPackages }, 0);
}
var installer = MainActivity.Instance.PackageManager.PackageInstaller;
var parameters = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
parameters.SetAppPackageName("my.package.name");
var sessionid = installer.CreateSession(parameters);
var session = installer.OpenSession(sessionid);
var fis = File.OpenRead(downloadedFile);
using (var outputstream = session.OpenWrite("my.package.name", 0, -1))
{
fis.CopyTo(outputstream);
session.Fsync(outputstream);
outputstream.Close();
outputstream.Dispose();
fis.Close();
fis.Dispose();
GC.Collect();
}
var pendingIntent = PendingIntent.GetBroadcast(MainActivity.Instance, sessionid, new Intent(Intent.ActionInstallPackage), 0);
session.Commit(pendingIntent.IntentSender);
}
catch(Exception ex)
{
Toast.MakeText(MainActivity.Instance.ApplicationContext, string.Format("Update failed, you may not have full device admin privileges. Error - {0}", ex.ToString()), ToastLength.Long).Show();
}
}
I'd expect the software version to change as well as the actual executable version. Does anyone have any clues as to what I'm doing wrong.
Ok, after much stuffing around and inspecting install logs with logcat, it seems the apk I was generating by deploy is incomplete. I had to set up a keystore to sign my app and then create a complete archive.
Right click the android proj -> archive.. -> Distribute -> Ad Hoc
This allowed me to self update properly.
Phew. Was bashing my head against it for days. Hope this saves someone else some time.
Is there any API for writing a C# program that could interface with Windows update, and use it to selectively install certain updates?
I'm thinking somewhere along the lines of storing a list in a central repository of approved updates. Then the client side applications (which would have to be installed once) would interface with Windows Update to determine what updates are available, then install the ones that are on the approved list. That way the updates are still applied automatically from a client-side perspective, but I can select which updates are being applied.
This is not my role in the company by the way, I was really just wondering if there is an API for windows update and how to use it.
Add a Reference to WUApiLib to your C# project.
using WUApiLib;
protected override void OnLoad(EventArgs e){
base.OnLoad(e);
UpdateSession uSession = new UpdateSession();
IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher();
uSearcher.Online = false;
try {
ISearchResult sResult = uSearcher.Search("IsInstalled=1 And IsHidden=0");
textBox1.Text = "Found " + sResult.Updates.Count + " updates" + Environment.NewLine;
foreach (IUpdate update in sResult.Updates) {
textBox1.AppendText(update.Title + Environment.NewLine);
}
}
catch (Exception ex) {
Console.WriteLine("Something went wrong: " + ex.Message);
}
}
Given you have a form with a TextBox this will give you a list of the currently installed updates. See http://msdn.microsoft.com/en-us/library/aa387102(VS.85).aspx for more documentation.
This will, however, not allow you to find KB hotfixes which are not distributed via Windows Update.
The easiest way to do what you want is using WSUS. It's free and basically lets you setup your own local windows update server where you decide which updates are "approved" for your computers. Neither the WSUS server nor the clients need to be in a domain, though it makes it easier to configure the clients if they are. If you have different sets of machines that need different sets of updates approved, that's also supported.
Not only does this accomplish your stated goal, it saves your overall network bandwidth as well by only downloading the updates once from the WSUS server.
If in your context you're allowed to use Windows Server Update Service (WSUS), it will give you access to the Microsoft.UpdateServices.Administration Namespace.
From there, you should be able to do some nice things :)
P-L right. I tried first the Christoph Grimmer-Die method, and in some case, it was not working. I guess it was due to different version of .net or OS architecture (32 or 64 bits).
Then, to be sure that my program get always the Windows Update waiting list of each of my computer domain, I did the following :
Install a serveur with WSUS (may save some internet bandwith) : http://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=5216
Add all your workstations & servers to your WSUS server
Get SimpleImpersonation Lib to run this program with different admin right (optional)
Install only the administration console component on your dev workstation and run the following program :
It will print in the console all Windows updates with UpdateInstallationStates.Downloaded
using System;
using Microsoft.UpdateServices.Administration;
using SimpleImpersonation;
namespace MAJSRS_CalendarChecker
{
class WSUS
{
public WSUS()
{
// I use impersonation to use other logon than mine. Remove the following "using" if not needed
using (Impersonation.LogonUser("mydomain.local", "admin_account_wsus", "Password", LogonType.Batch))
{
ComputerTargetScope scope = new ComputerTargetScope();
IUpdateServer server = AdminProxy.GetUpdateServer("wsus_server.mydomain.local", false, 80);
ComputerTargetCollection targets = server.GetComputerTargets(scope);
// Search
targets = server.SearchComputerTargets("any_server_name_or_ip");
// To get only on server FindTarget method
IComputerTarget target = FindTarget(targets, "any_server_name_or_ip");
Console.WriteLine(target.FullDomainName);
IUpdateSummary summary = target.GetUpdateInstallationSummary();
UpdateScope _updateScope = new UpdateScope();
// See in UpdateInstallationStates all other properties criteria
_updateScope.IncludedInstallationStates = UpdateInstallationStates.Downloaded;
UpdateInstallationInfoCollection updatesInfo = target.GetUpdateInstallationInfoPerUpdate(_updateScope);
int updateCount = updatesInfo.Count;
foreach (IUpdateInstallationInfo updateInfo in updatesInfo)
{
Console.WriteLine(updateInfo.GetUpdate().Title);
}
}
}
public IComputerTarget FindTarget(ComputerTargetCollection coll, string computername)
{
foreach (IComputerTarget target in coll)
{
if (target.FullDomainName.Contains(computername.ToLower()))
return target;
}
return null;
}
}
}
In my current C# code I'm able to lock a Windows user session programmatically (same as Windows + L).
Since the app would still be running, is there any way to unlock the session from that C# program. User credentials are known. The app is running on Windows 7.
You'll need a custom windows credential provider to log in for you. Also, you'll need to save the user's credentials somewhere to log in. There are some samples in Windows SDK 7 https://www.microsoft.com/en-us/download/details.aspx?id=8279
There's a bunch of projects to get you started under Samples\security\credentialproviders.
To unlock the screen:
set the username / password in CSampleCredential::Initialize
set autologin to true in CSampleCredential::SetSelected
search the hardware provider sample for WM_TOGGLE_CONNECTED_STATUS message to see how to trigger the login
build some way to communicate with your app to trigger the unlock (local tcp server for example)
It's a pain in the ass, but it works.
Here is some hackery to do that: http://www.codeproject.com/Articles/16197/Remotely-Unlock-a-Windows-Workstation
Didn't test it myself though.
Not for .NET part, but you could also make your own custom Logon UI and inject some mechanism there. It can easily become security problem though.
var path = new ManagementPath();
path.NamespacePath = "\\ROOT\\CIMV2\\Security\\MicrosoftVolumeEncryption"; path.ClassName = "Win32_EncryptableVolume";
var scope = new ManagementScope(path, new ConnectionOptions() { Impersonation = ImpersonationLevel.Impersonate });
var management = new ManagementClass(scope, path, new ObjectGetOptions());
foreach (ManagementObject vol in management.GetInstances())
{
Console.WriteLine("----" + vol["DriveLetter"]);
switch ((uint)vol["ProtectionStatus"])
{
case 0:
Console.WriteLine("not protected by bitlocker");
break;
case 1:
Console.WriteLine("unlocked");
break;
case 2:
Console.WriteLine("locked");
break;
}
if ((uint)vol["ProtectionStatus"] == 2)
{
Console.WriteLine("unlock this driver ...");
vol.InvokeMethod("UnlockWithPassphrase", new object[] { "here your pwd" });
Console.WriteLine("unlock done.");
}
}
Note: this only works if you run Visual Studio as an administrator.
No, there is no way to do this, by design. What's your scenario and why do you need to lock/unlock the workstation?
Of course you can't unlock it. Unlocking a session requires the user physically be there to enter their account credentials. Allowing software to do this, even with saved credentials, would be a security issue for many of the other situations where workstation locking is used.