Interfacing Microsoft .NET ( C# / F# ) with SWI-Prolog - c#

I have problem with connecting Prolog to C#.
Visual Studio gives this following error :
"An unhandled exception of type 'System.IO.FileNotFoundException'
occurred in SwiPlCs.dll"
and I really don't know how to handle this.
I think it came from the path I gave in the code :
using System;
using SbsSW.SwiPlCs;
namespace ptest
{
class Program
{
static void Main(string[] args)
{
//Environment.SetEnvironmentVariable(#"C:\Program Files\swipl", #"C:\Program Files\swipl\boot64.prc"); // or boot64.prc
var curPath = Environment.GetEnvironmentVariable("C:\\Program Files\\swipl\\bin");
Environment.SetEnvironmentVariable(#"C:\Program Files\swipl\bin", #"C:\Program Files\swipl\boot;C:\Program Files\swipl;" + curPath);
if (!PlEngine.IsInitialized)
{
String[] param = { "-q" }; // suppressing informational and banner messages
PlEngine.Initialize(param);
PlQuery.PlCall("assert(father(martin, inka))");
PlQuery.PlCall("assert(father(uwe, gloria))");
PlQuery.PlCall("assert(father(uwe, melanie))");
PlQuery.PlCall("assert(father(uwe, ayala))");
using (var q = new PlQuery("father(P, C), atomic_list_concat([P,' is_father_of ',C], L)"))
{
foreach (PlQueryVariables v in q.SolutionVariables)
Console.WriteLine(v["L"].ToString());
Console.WriteLine("all children from uwe:");
q.Variables["P"].Unify("uwe");
foreach (PlQueryVariables v in q.SolutionVariables)
Console.WriteLine(v["C"].ToString());
}
PlEngine.PlCleanup();
Console.WriteLine("finshed!");
}
}
}
}
Please Help me. Thank you very much.

I think its a problem with latest versions of SWI_Prolog. Try installing older version of SWI-Prolog 6.6.1 for Microsoft Windows (32 bit) in C:/Program Files (x86) and use SwiPlCs_1.1.60301.0.zip. Add reference to SwiPlCs.dll in Visual Studio. It will work IA :)

Related

xsd to class (C#) in visual studio 2019

I am following a tutorial, in one step it opens "VS2012 arm cross tools command prompt" and executes
xsd file.xsd /classes
I can't find "VS2012 arm cross tools command prompt" on my computer (my guess it's because I'm using VS2019) so I open the "Developer command prompt for VS 2019" instead, but when I run the command, I get an error:
"xsd" is not recognized as an internal or external command, program or executable batch file
Can someone tell me how I can create a class from an xsd file in VS 2019? Thank you for your time.
Once you have installed the Windows SDK. The following could be of help to you...it is .NET Core. Browse to the xsd.exe and add a reference to it in VS 2019.
class Program
{
static void Main(string[] args)
{
var rgs = new string[]
{
#"PathToYourDLL\My.dll",
"/type:ClassNameToGen"
};
AppDomain.CurrentDomain.FirstChanceException += (s, e) =>
{
string error = e.Exception.ToString();
var typeLoadException = e.Exception as ReflectionTypeLoadException;
if (typeLoadException != null)
{
foreach (var exception in typeLoadException.LoaderExceptions)
{
error += Environment.NewLine + Environment.NewLine + exception.ToString();
}
}
Console.WriteLine(error);
};
XsdTool.Xsd.Main(rgs);
Console.ReadLine();
}
}

ERROR: HRESULT: 0x8007007E System.IO.FileNotFoundException on Prolog and C# integration

I'm trying to call Prolog script file from C# program using SWI Prolog. I downloaded the code package from github (using this link). But, when I'm trying to run the HelloWorldDemo program the following error occurs:
System.IO.FileNotFoundException: 'The specified module could not be found. (Exception from HRESULT: 0x8007007E)'
on Line 105 on the following code:
private static void LoadUnmanagedLibrary(string fileName)
{
if (_hLibrary == null)
{
_hLibrary = NativeMethods.LoadDll(fileName);
if (_hLibrary.IsInvalid)
{
int hr = Marshal.GetHRForLastWin32Error();
Marshal.ThrowExceptionForHR(hr); //here the error occurs
}
}
}
I tried many solutions on the Internet, for example, provide the swi path on setenviromentvariable but the error still same.
Here is the code of HelloWorldDemo.cs:
static void Main(string[] args)
{
Environment.SetEnvironmentVariable("SWI_HOME_DIR", #"C:\Program Files\swipl\"); // I also used C:\Program Files\swipl\bin and didn't help too
if (!PlEngine.IsInitialized)
{
String[] param = { "-q" }; // suppressing informational and banner messages
PlEngine.Initialize(param);
PlQuery.PlCall("assert(father(martin, inka))");
PlQuery.PlCall("assert(father(uwe, gloria))");
PlQuery.PlCall("assert(father(uwe, melanie))");
PlQuery.PlCall("assert(father(uwe, ayala))");
using (var q = new PlQuery("father(P, C), atomic_list_concat([P,' is_father_of ',C], L)"))
{
foreach (PlQueryVariables v in q.SolutionVariables)
Console.WriteLine(v["L"].ToString());
Console.WriteLine("all children from uwe:");
q.Variables["P"].Unify("uwe");
foreach (PlQueryVariables v in q.SolutionVariables)
Console.WriteLine(v["C"].ToString());
}
PlEngine.PlCleanup();
Console.WriteLine("finshed!");
}
}
So, how can I fix this issue?
Note: I'm using Win10 x64, visual studio 2017 community.

C# - Compiling C# code at runtime results in errors that is "nonexistent"

I'm trying to compile multiple C# files into one executable at runtime and I keep getting compiler errors that aren't present if I run this code from Visual Studio.
The specific errors I'm getting from my runtime compiler is "; expected" and "Method must have a return type" at line 7 in 'Program.cs'. Obviously, I would fix these if there was something to fix.
So the code. Here's the actual compiler code: (with some parts removed, like the actual error reporting)
private CSharpCodeProvider provider = new CSharpCodeProvider();
private CompilerParameters parameters = new CompilerParameters();
private void RunOption_Click(object sender, RoutedEventArgs e)
{
parameters.GenerateInMemory = false;
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Path + "/builds/debug/bot.exe";
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Threading.Tasks.dll");
parameters.CompilerOptions = "/optimize";
parameters.WarningLevel = 3;
parameters.TreatWarningsAsErrors = false;
string[] filesToCompile = Directory.GetFiles(Path + "\\src\\", "*.cs");
CompilerResults results = provider.CompileAssemblyFromFile(parameters, filesToCompile);
}
And here are the two files it's trying to compile.
Program.cs
using System.Threading.Tasks;
namespace MyBot
{
class Program
{
static void Main(string[] args) => new MyBot().RunAsync().GetAwaiter().GetResult();
}
}
MyBot.cs
using System;
using System.Threading.Tasks;
namespace MyBot
{
public class MyBot
{
public async Task RunAsync()
{
Console.Title = "MyBot";
Console.Read();
}
}
}
What am I missing here? As mentioned, if I run the code from 'Program.cs' and 'MyBot.cs' in Visual Studio, everything works fine, so there are no errors in the actual code.
As Eric Lippert pointed out, I was using a newer .NET version than the compiler. So I simply changed the compiler to the new Roslyn compiler that supports C# 6, which I just what I need. So lesson learned: Always make sure you target the right framework version.
OLD ANSWER
Welp, I'm going to declare myself idiot once again. Better to do it myself before anyone else does.
I got it working by changing the Program.cs file.
Instead of
static void Main(string[] args) => new MyBot().RunAsync().GetAwaiter().GetResult();
I did
static void Main(string[] args)
{
new MyBot().RunAsync().GetAwaiter().GetResult();
}
But I still have no idea why it didn't work in the first place since it worked in Visual Studio.

Facing error "System.IO.FileNotFoundException:"

I am a C guy and new to C#, I have to debug an error in my project code.
Need help from C# experts, I read some articles on SO, but was not able to find solution.
I installed SQL 2012 express edition on my Windows 2012 server machine and was trying to run the below code.
Used Visual Studio 2010.
using System;
using System.Management;
public class Example
{
public static void Main()
{
ManagementScope scope = new ManagementScope(#"\\" + Environment.MachineName + #"\root\Microsoft\SQLServer\ComputerManagement11");
string instanceName, ipAddressName, propertyName, protocolName;
using (ManagementClass networkProtocolMan = new ManagementClass(scope, new ManagementPath("ServerNetworkProtocolProperty"), null))
{
networkProtocolMan.Get();
Console.WriteLine("" + networkProtocolMan.Path);
ManagementObjectCollection moCollection = networkProtocolMan.GetInstances(); //Class gets filled with error here
//used debugger to look inside moCollection
Console.WriteLine(""+moCollection.Count); //Error is getting printed on console here
ManagementObject mo;
ManagementObject protocolProperty = null; ;
}
return;
}
}
The error which I get is:
System.IOFileNotFoundException:
at
System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR
at System.Management.ManagementObjectCollection.ManagementObjectEnumeration.moveNext<>
at System.Management.ManagementObjectCollection.get_Count<>
After putting breakpoints I see that in moCollection->Count value is
'moclooection.Count' threw an exception of type 'System.IO.FileNotFound'
and type is: int{System.IO.FileNotFoundException}
I was not able to post the debugger screenshot here, so I tried it to describe as above. Please guide me to resolve this error.

How can I open AutoCAD 2015 through the .NET API

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
}
}
}

Categories