I want to connect to the OpcUa server through the APP on HoloLens and read the node's data. It works on Unity and works fine, but it can't connect to the OpcUa server in HoloLens. I use the OpcUaHelper plugin, which has a simple OpcUa client and supports .Net Core and .Net Standard 2.0.
Unity's settings are:
Scripting Runtime Version: .Net 4.X Equivalent
Scripting Backend: IL2CPP
Api Compatibility Level : .Net 4.X
My code are shown below.
Does anyone know what the reason is?
Or have anyone tried to connect the Opc Ua server in HoloLens?
The version of the software I am using is:
1.Unity 2018 3.11f
2.Mixed Reality Toolkit v2.0.0 RC1
3.Visual Studio 2017
using System;
using UnityEngine;
using UnityEngine.UI;
using Microsoft.MixedReality.Toolkit.Input;
using OpcUaHelper;
using Opc.Ua;
using System.Collections;
using System.Collections.Generic;
public void OpcUaConnector()
{
OpcUaClient m_OpcUaClient = new OpcUaClient();
//m_OpcUaClient.UserIdentity = new UserIdentity("user", "password");
string OpcUa_Test = "opc.tcp://118.24.36.220:62547/DataAccessServer";
m_OpcUaClient.ConnectServer(string.Format("{0}", OpcUa_Test));
try
{
//Read the same type of data from multiple nodes
List<NodeId> nodeIds = new List<NodeId>();
nodeIds.Add(new NodeId("ns=2;s=Machines/Machine A/Name"));
nodeIds.Add(new NodeId("ns=2;s=Machines/Machine B/Name"));
nodeIds.Add(new NodeId("ns=2;s=Machines/Machine C/Name"));
List<DataValue> dataValues = m_OpcUaClient.ReadNodes(nodeIds.ToArray());
AnlagenName_A.text = string.Format("{0}", dataValues[0]);
AnlagenName_B.text = string.Format("{0}", dataValues[1]);
AnlagenName_C.text = string.Format("{0}", dataValues[2]);
//foreach (string tag in Tags)
//{
// string value = m_OpcUaClient.ReadNode<string>(tag);
//}
}
// //Read data from a single node
// //string value = m_OpcUaClient.ReadNode<string>("ns=2;s=Machines/Machine B/Name");
// //Console.WriteLine("{0}", value);
// //Console.ReadKey();
//}
catch
{
Debug.Log("Connected Failed");
}
}
I hope to successfully connect to the OpcUa server and read the node data.
Related
I have a Windows Forms application that uses Selenium. I have multiple production clients that need to run this application and I’ve noticed that in every new client (and also when I need to update the webdriver) I need to copy and paste the .exe to the [PATH] location (%USERPROFILE%\AppData\Local\Microsoft\WindowsApps) and I want to automate that with the setup file that gets generated by Visual Studio every time I publish the application.
I’ve found that you can install an extension called “Microsoft Visual Studio Installer Project”, include the .exe file on it and either make a new Form that’ll check if the webdriver is in place and if it’s not to copy it, or I can change the [PATH] of my IWebDriver object in order to reflect the new path of this file. As a bonus you can also add the the desktop icon.
But first I want to know if there’s a way to publish this webdriver.exe file to it’s proper address through the “Publish wizard” parameters before I start looking for workarounds.
This worked for my use case, for context, I'm using a windows forms project targeting .NET (framework) 4.7.1. these are snippets from my events "load" and "show" formated as a different function. I only included the logic behind the file check, download and unzip with overwite. Since the System.IO.Compression.ZipFile class for this version of .NET doesn't natively support overwrite files, I used Ionic's DotNetZip package downloaded from NuGet.
using Ionic.Zip;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
private void DriverCheck(){
string edge, edgeVersion, edgeDriverPath, edgeDriver, edgeDriverVersion;
edge = #"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe";
edgeVersion = FileVersionInfo.GetVersionInfo(edge).FileVersion;
edgeDriverPath = Environment.GetEnvironmentVariable("LocalAppData") + "\\Microsoft\\WindowsApps\\";
edgeDriver = edgeDriverPath + "msedgedriver.exe";
try
{
edgeDriverVersion = FileVersionInfo.GetVersionInfo(edgeDriver).FileVersion;
}
catch
{
edgeDriverVersion = null;
}
if (!File.Exists(edgeDriver) || edgeVersion != edgeDriverVersion)
{
try
{
using (var client = new WebClient())
{
string winver;
if (Environment.Is64BitProcess)
{
winver = "64";
}
else
{
winver = "32";
}
string zipPath = edgeDriverPath + "edgedriver_win64.zip";
client.DownloadFile("https://msedgedriver.azureedge.net/" + edgeVersion + "/edgedriver_win" + winver + ".zip", zipPath);
using (ZipFile zip = ZipFile.Read(zipPath))
{
foreach (ZipEntry temp in zip)
{
temp.Extract(edgeDriverPath, ExtractExistingFileAction.OverwriteSilently);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error downloading webdriver:\n" + ex.Message);
Application.Exit();
}
}
}
Mac OS, .Net6, C# 10.0.
I always created console clients for MS Dynamics 365 on .Net Framework Platform without problems. But now I need to do the same on .Net Core or newer platform (because I need to put it into Docker container later). At this case I try to use .Net6.
I created new console application and added the NuGet packages:
Microsoft.PowerPlatform.Dataverse.Client v0.6.6
System.Configuration.ConfigurationManager v6.0.0
System.ServiceModel.Primitives v4.9.0
My simple Program.cs file:
using System.Net;
using System.ServiceModel.Description;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;
namespace ConsoleAppExample
{
internal class Program
{
static void Main(string[] args)
{
Console.Title = "CRM console client";
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var orgServiceUrl = "http://dev-crm-app02/MyCompany/XRMServices/2011/Organization.svc";
var crmUserLogin = "myLogin";
var crmUserPassword = "myPassword";
var credentials = new ClientCredentials();
credentials.UserName.UserName = crmUserLogin;
credentials.UserName.Password = crmUserPassword;
try
{
using (var orgService = new OrganizationServiceProxy(new Uri(orgServiceUrl),
null, credentials, null))
{
RetrieveVersionRequest versionRequest = new RetrieveVersionRequest();
RetrieveVersionResponse versionResponse =
(RetrieveVersionResponse) orgService.Execute(versionRequest);
WhoAmIRequest whoAmIRequest = new WhoAmIRequest();
WhoAmIResponse whoAmIResponse = (WhoAmIResponse) orgService.Execute(whoAmIRequest);
Console.WriteLine($"\nOrganizationService: {orgServiceUrl}");
Console.WriteLine($"CRM version: {versionResponse.Version}");
Console.WriteLine($"User login: {crmUserLogin}");
Console.WriteLine($"\nOrganizationId: {whoAmIResponse.OrganizationId}");
Console.WriteLine($"BusinessUnitId: {whoAmIResponse.BusinessUnitId}");
Console.WriteLine($"UserId: {whoAmIResponse.UserId}");
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message); // Xrm.Sdk WSDL
if (ex.InnerException != null)
{
Console.WriteLine(ex.InnerException.Message);
}
Console.ResetColor();
}
Console.WriteLine("\nPress ENTER for exit...");
Console.ReadLine();
}
}
}
But when I run my application I get the error:
Xrm.Sdk WSDL
Why does it happen and how can I solve it?
Organization service client is deprecated and is not supported directly on net core.
When connecting using the dataverse serviceclient, connection string or serviceclient constructor is the only supported way.
That said onprem is not well supported due to the changes I the underlying authentication stack.
Best currently possible supported feature is to use oAuth via adfs on prem with a custom auth handler.
There is an extension written by a user of the dataverse service client that adds AD and WSTrust support for net core, but it is not part of the MS distribution.
You can find a link to it on the dataverse serviceclient GitHub site issues board under the AD onPrem support topic
https://github.com/microsoft/PowerPlatform-DataverseServiceClient/issues/110
I have a .NET Core 2.2 API running on IIS on a Windows Server 2012 R2 Datacenter machine. It uses the DLLs from Nuget package Microsoft.SharePointOnline.CSOM. But it throws exception One or more errors occurred. (The process has no package identity. (Exception from HRESULT: 0x80073D54)) when calling method ClientContext.ExecuteQueryAsync().
I have followed the following guide: https://rajujoseph.com/getting-net-core-and-sharepoint-csom-play-nice/ . I have tried two solutions. The first was creating a .NET Core Console solution that calls the DLL containing the SharePoint CSOM code. Then I tried calling the DLL from a .NET Core 2.2 API running on IIS on a Windows Server 2012 R2 Datacenter machine. But both solutions throw the same exception as mentioned above One or more errors occurred. (The process has no package identity. (Exception from HRESULT: 0x80073D54)).
The SharePointHelper.dll code:
using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Text;
namespace SharePointHelper
{
public class SharePointHelper
{
public SharePointHelper() { }
public void WriteFilesAndFolders(string siteUrl, string listName, string username, string password)
{
using (var context = new ClientContext(siteUrl))
{
context.Credentials = new SharePointOnlineCredentials(username, password);
var folder = context.Web.GetFolderByServerRelativeUrl(listName);
var subFolders = folder.Folders;
var files = folder.Files;
context.Load(folder);
context.Load(subFolders);
context.Load(files);
if (context.HasPendingRequest)
context.ExecuteQueryAsync().Wait();
var subFolderEnumorator = subFolders.GetEnumerator();
var filesEnumerator = files.GetEnumerator();
PrintValues(subFolderEnumorator);
PrintValues(filesEnumerator);
}
}
private void PrintValues(IEnumerator<Folder> enumerator)
{
while (enumerator.MoveNext())
Console.WriteLine(enumerator.Current.Name);
}
private void PrintValues(IEnumerator<File> enumerator)
{
while (enumerator.MoveNext())
Console.WriteLine(enumerator.Current.Name);
}
}
}
The .NET Core 2.2 service code calling the method in the SharePointHelper.dll:
public void SharePointTest()
{
string siteUrl = #"https://somecompany.sharepoint.com/sites/Test";
string listName = "Documents";
string username = "myemail#somecompany.com";
string password = "mypassword";
var sharePointHelper = new SharePointHelper.SharePointHelper();
sharePointHelper.WriteFilesAndFolders(siteUrl, listName, username, password);
}
I expect the SharePointHelper.dll to connect and get a response from SharePoint. But exception One or more errors occurred. (The process has no package identity. (Exception from HRESULT: 0x80073D54)) is thrown.
You can solve this problem to use SharePoint with .NET Core by simply installing the TTCUE.NetCore.SharepointOnline.CSOM Nuget package. No reason to follow the linked guide unless you want to understand how to do the workaround in depth.
I've been browsing for a good hour and have yet to find something that would help with this. I'm working on opening AutoCAD from the .NET API in VS2013 using C#, but for some reason, I can never get AutoCAD to actually launch. I'm using the following code:
using System;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
namespace IOAutoCADHandler
{
public static class ACADDocumentManagement
{
[CommandMethod("ConnectToAcad")]
public static void ConnectToAcad()
{
AcadApplication acAppComObj = null;
// no version number so it will run with any version
const string strProgId = "AutoCAD.Application";
// Get a running instance of AutoCAD
try
{
acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId);
}
catch // An error occurs if no instance is running
{
try
{
// Create a new instance of AutoCAD
acAppComObj = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true);
}
catch //// STOPS HERE
{
// If an instance of AutoCAD is not created then message and exit
// NOTE: always shows this box and never opens AutoCAD
System.Windows.Forms.MessageBox.Show("Instance of 'AutoCAD.Application'" +
" could not be created.");
return;
}
}
// Display the application and return the name and version
acAppComObj.Visible = true;
System.Windows.Forms.MessageBox.Show("Now running " + acAppComObj.Name +
" version " + acAppComObj.Version);
// Get the active document
AcadDocument acDocComObj;
acDocComObj = acAppComObj.ActiveDocument;
// Optionally, load your assembly and start your command or if your assembly
// is demandloaded, simply start the command of your in-process assembly.
acDocComObj.SendCommand("(command " + (char)34 + "NETLOAD" + (char)34 + " " +
(char)34 + #"C:\Users\Administrator\Documents\All Code\main-libraries\IOAutoCADHandler\bin\Debug\IOAutoCADHandler.dll" + (char)34 + ") ");
acDocComObj.SendCommand("DRAWCOMPONENT");
}
}
Unfortunately, it always stops at the nested catch statement and always displays the popup box without opening AutoCAD. Any suggestions on how to at least make AutoCAD open for me?
EDIT: Error message
The issue is you're coding (correctly) to the AutoCAD interop interface. I recommend against that (due to potential version changes).
The other issue is that the documentation for AutoCAD plugins using the newer .net api is for plugins when AutoCAD is already running.
Final issue could be that the program Id of AutCAD is a mystery. I have resorted to making that a configurable setting, but default to "AutoCAD.Application", which will take the currently registered AutoCAD.Application on the production machine. If there are multiple versions installed on the machine and you want to be specific, then you could append the version number (which you'll need to research) to the ProgID like: "AutoCAD.Application.19", or "AutoCAD.Application.20" for 2015.
For the first issue, one technique is to use dynamics for the autoCad objects, particularly for creating instances. I have used the ObjectARX api for creating my application in a dummy project, and then switching to dynamics when I'm happy with the properties and method names.
In a standalone .Net application that starts AutoCAD you could use something like:
// I comment these out in production
//using Autodesk.AutoCAD.Interop;
//using Autodesk.AutoCAD.Interop.Common;
//...
//private static AcadApplication _application;
private static dynamic _application;
static string _autocadClassId = "AutoCAD.Application";
private static void GetAutoCAD()
{
_application = Marshal.GetActiveObject(_autocadClassId);
}
private static void StartAutoCad()
{
var t = Type.GetTypeFromProgID(_autocadClassId, true);
// Create a new instance Autocad.
var obj = Activator.CreateInstance(t, true);
// No need for casting with dynamics
_application = obj;
}
public static void EnsureAutoCadIsRunning(string classId)
{
if (!string.IsNullOrEmpty(classId) && classId != _autocadClassId)
_autocadClassId = classId;
Log.Activity("Loading Autocad: {0}", _autocadClassId);
if (_application == null)
{
try
{
GetAutoCAD();
}
catch (COMException ex)
{
try
{
StartAutoCad();
}
catch (Exception e2x)
{
Log.Error(e2x);
ThrowComException(ex);
}
}
catch (Exception ex)
{
ThrowComException(ex);
}
}
}
When there are several versions of AutoCAD installed on a computer, creating an instance with the ProgID "AutoCAD.Application" will run the latest version started on this computer by the current user. If the version of the Interop assemblies used does not match the version that is starting, you'll get a System.InvalidCastException with an HRESULT 0x80004002 (E_NOINTERFACE).
In your specific case, the {070AA05D-DFC1-4E64-8379-432269B48B07} IID in your error message is the GUID for the AcadApplicationinterface in R19 64-bit (AutoCAD 2013 & 2014). So there is an AutoCAD 2013 or 2014 that is starting, and you cannot cast this COM object to a 2015 type because 2015 is R20 (not binary compatible).
To avoid that, you can add a specific version to your ProgID (like "AutoCAD.Application.20" for AutoCAD 2015 (R20.0) to 2016 (R20.1)) to start the version matching your Interop assemblies or you can use late binding (eg. remove your references to Autodesk.AutoCAD.Interop* and use the dynamic keyword instead of the AutoCAD types).
In the last case, you will lost autocompletion, but your program will work with all the versions of AutoCAD.
Check also 32-bit vs 64-bit because TypeLib/Interop assemblies are not the same.
I open the application in a much straight-forward way. First, be sure to reference the correct type library. The one I am using is AutoCAD 2014 Type Library, located at:
c:\program files\common files\autodesk shared\acax19enu.tlb
To initialize the application:
using AutoCAD;
namespace test
{
class Program
{
static void Main(string[] args)
{
AutoCAD.AcadApplication app;
app = new AcadApplication();
app.Visible = true;
Console.Read();
}
}
}
Try this:
"sourcefile" is the original file
"newfile" is the new file
[CommandMethod("ModifyAndSaveas", CommandFlags.Redraw | CommandFlags.Session)]
public void ModifyAndSaveAs()
{
Document acDoc = Application.DocumentManager.Open(sourcefile);
Database acDB = acDoc.Database;
Transaction AcTran = acDoc.Database.TransactionManager.StartTransaction();
using (DocumentLock acLckDoc = acDoc.LockDocument())
{
using (AcTran)
{
BlockTable acBLT = (BlockTable)AcTran.GetObject(acDB.BlockTableId, OpenMode.ForRead);
BlockTableRecord acBLTR = (BlockTableRecord)AcTran.GetObject(acBLT[BlockTableRecord.ModelSpace], OpenMode.ForRead);
var editor = acDoc.Editor;
var SelectionSet = editor.SelectAll().Value;
foreach (ObjectId id in SelectionSet.GetObjectIds())
{
Entity ent = AcTran.GetObject(id, OpenMode.ForRead) as Entity;
//modify entities
}
AcTran.Commit();
}
}
acDB.SaveAs(newfile, DwgVersion.AC1021);
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Tekkit
{
class Program
{
static void Main(string[] args)
{
//make sure to add last 2 using statements
ProcessStartInfo start = new ProcessStartInfo("calc.exe");
Process.Start(start);//starts the process
}
}
}
I am new to working with Accumulo. I need to read/write data from a remote Accumulo through C#.
The only code sample/documentation for C#, I have found is -
Accumulo createBatchScanner range not working as expected
I attempted to compile the code in Xamarin Studio, on a Mac.
The issue I am encountering is with this line:
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
Error CS0246: The type or namespace name AccumuloProxy' could not be found. Are you missingorg.apache.accumulo.proxy.thrift' using directive? (CS0246) (AccumuloIntegratorPrototype)
Where can I find the DLLs to add to my CSharp project related to AccumuloProxy client?
Is there a way I can generate the same?
Here is a code fragment:
namespace AccumuloIntegratorPrototype
{
class MainClass
{
static byte[] GetBytes(string str)
{
return Encoding.ASCII.GetBytes(str);
}
static string GetString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
public static void Main (string[] args)
{
try
{
/** connect **/
TTransport transport = new TSocket("xxx.xx.x.xx", 42424);
transport = new TFramedTransport(transport);
TCompactProtocol protocol = new TCompactProtocol(transport);
transport.Open();
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
Thanks to all for the pointers.
Was able to complete my project.
These are my notes.
A. Versions:
Accumulo 1.5
Thrift 0.90
Mono 3.2.5
B. Strategy/option used to connect to Accumulo from C#:
Accumulo Proxy API
C. Accumulo Proxy with C# bindings:
Performed the following actions on a node running Accumulo
1. Installed Mono 3.2.5
2. Installed Thrift 0.90
3. Configured Accumulo proxy service
Modified the file $ACCUMULO_HOME/proxy/proxy.properties;
Specifically updated the instance name, and zookeeper
4. Started the proxy daemon-
${ACCUMULO_HOME}/bin/accumulo proxy -p ${ACCUMULO_HOME}/proxy/proxy.properties
5.Generated the c# bindings, using the proxy.thrift IDL file
thrift --gen csharp $ACCUMULO_HOME/proxy/thrift/proxy.thrift
This resulted in the creation of a directory called gen-csharp under ${ACCUMULO_HOME}/proxy/thrift/
6. The files under gen-csharp are needed in the C# project, in section D, below.
7. Thrift.dll, is also needed.
D. C# project - Accumulo Client:
1. Created a project of type library.
2. Added the files under gen-csharp in step C5, above to the library
3. Added reference to thrift.dll
4. Built the library
E. Connecting to Accumulo from C#
In the C# project that reads/writes to Accumulo,
1. Added reference - thrift.dll
2. Added reference to the library built in section D, above
3. On the Accumulo server, started the proxy (refer step C4, above)
Here is some sample code, to read data, to try this functionality out..
using System;
using System.Text;
using System.Collections.Generic;
using Thrift.Protocol;
using Thrift.Transport;
namespace AccumuloIntegratorPrototype
{
class MainClass
{
static byte[] GetBytes(string str)
{
return Encoding.ASCII.GetBytes(str);
}
static string GetString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
public static void Main (string[] args)
{
try
{
String accumuloProxyServerIP = "xxx.xxx.x.xx";//IP
int accumuloProxyServerPort = 42424;//Port Number
TTransport transport = new TSocket(accumuloProxyServerIP, accumuloProxyServerPort);
transport = new TFramedTransport(transport);
TCompactProtocol protocol = new TCompactProtocol(transport);
transport.Open();
String principal = "root";//Application ID
Dictionary<string, string> passwd = new Dictionary<string,string>();
passwd.Add("password", "xxxxx");//Password
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
byte[] loginToken = client.login(principal, passwd);//Login token
//{{
//Read a range of rows from Accumulo
var bScanner = new BatchScanOptions();
Range range = new Range();
range.Start = new Key();
range.Start.Row = GetBytes("d001");
//Need the \0 only if you need to get a single row back
//Otherwise, its not needed
range.Stop = new Key();
range.Stop.Row = GetBytes("d001\0");
bScanner.Ranges = new List<Range>();
bScanner.Ranges.Add(range);
String scanId = client.createBatchScanner(loginToken, "departments", bScanner);
var more = true;
while (more)
{
var scan = client.nextK(scanId, 10);
more = scan.More;
foreach (var entry in scan.Results)
{
Console.WriteLine("Row = " + GetString(entry.Key.Row));
Console.WriteLine("{0} {1}:{2} [{3}] {4} {5}", GetString(entry.Key.Row), GetString(entry.Key.ColFamily), GetString(entry.Key.ColQualifier), GetString(entry.Key.ColVisibility), GetString(entry.Value),(long)entry.Key.Timestamp);
}
}
client.closeScanner(scanId);
client.Dispose();
transport.Close();
}catch (Exception e)
{
Console.WriteLine(e);
}
//}}
}
}
}
Adding Thrift to C# project involves two steps:
Add the C# code that has been generated by means of the Thrift compiler
Build Thrift.DLL and add it as a reference to your project. Alternatively, it is possible to link the code into your project, however not recommended.
The C# code for step 1 is generated from a Thrift IDL file, which is typically part of the project. In your case, the IDL files are located under proxy/src/main/thrift in the Accumulo tree.
The Thrift compiler and library can be downloaded from http://thrift.apache.org. Note that some projects are using a older version of Apache Thrift, which is not necessarily the latest stable. As elserj mentioned in the comments, Accumulo 1.4.x depends on Thrift 0.6.1, Accumulo 1.5.x and greater depend on Thrift 0.9.0.