Output Path in Visual Studio - c#

I want to output my C# project into a user defined folder.
Therefore I tried the following:
1. Setting the output path in the properties
Setting Output path in properties for all configs and any CPU
I built in Debug|x64 mode the C# project.
The solution contains a second project in C++ which has a config type of DLL. Goal is to use the DLL in C++ in my C# project.
C++ Project properties
Property Page for C++ Project
Here is the respective code for:
C# Project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace ConsoleApp
{
class Program
{
[DllImport("NativeLibrary.dll")]
public static extern void HelloWorld();
static void Main(string[] args)
{
HelloWorld();
Console.ReadLine();
}
}
}
C++ Project
#include <iostream>
// Expose function
extern "C" __declspec(dllexport) void HelloWorld();
void HelloWorld()
{
std::cout << "Hello World" << std::endl;
}
The problem now is:
When I build both projects there are no errors.
When running the project, the C++ DLL cannot be found. This, I found out is because of the incorrect build pathes.
Whereas the C++ correctly resolves the environment variables I set, the C# project doesn't. It creates folders named as the variable name itself, instead of building into the resolved path name.
The build for the C++ file resolves correctly the output path
Output C++ build
The build for the C# project doesn't
Output C# build
I just cannot figure out how to resolve this issue, but I am also fairly new to this. Can you help me out?
Regards
Sebastian

Related

Sharing environment variables across languages

I'm writing an application composed by several modules written in different languages (i.e. Java, C#, C++).
I'm experiencing an odd behavior where the environment variables that I set in one module (e.g. C#) are not propagated to other modules.
As far as I understand, the problem is due to the fact that environment variables in Windows are accessed via the _environ struct in the runtime library, rather than via the process descriptor, hence libraries using different runtimes have different environment variables.
For C# in particular, this problem seems to occur only if I compile and run the code in Release, whereas compiling the code in Debug works just fine.
The code below reproduce the issue with two very simple modules written in C# and C++. I compiled the code with VS2015 Professional. C# code was compiled with runtime v4.0 and .NET framework v4.5.2
C# executable
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("cpp_lib.dll", CharSet = CharSet.Unicode)]
public static extern void print_path();
static void Main(string[] args)
{
var path = Environment.GetEnvironmentVariable("PATH");
path += ";D:\\Temp";
Environment.SetEnvironmentVariable("PATH", path);
// Print the path from C#
Console.WriteLine("Path from C#: " + Environment.GetEnvironmentVariable("PATH"));
// Print the path from c++
print_path();
}
}
}
C++ library
#include <iostream>
#include <Windows.h>
extern "C" {
__declspec(dllexport) void print_path() {
std::cout << "PATH seen in C++: " << getenv("PATH") << std::endl;
}
}
As stated before, running the code in Debug the same path is printed from C# and C++, but running the code in Release results in the PATH printed from c++ missing the D:\Temp folder
User Environment variables are per-process and changes are not propagated to other processes.
To change system environment variables in your example PATH. You need to modify the value under the registry key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment and then broadcast a WM_SETTINGCHANGE message. Applications wishing to see the change will have to handle the broadcast.
Source: https://learn.microsoft.com/en-us/windows/win32/procthread/environment-variables
It turns out Windows provide more functions to get environment variables.
From the documentation "getenv and _putenv use the copy of the environment pointed to by the global variable _environ to access the environment." whereas GetEnvironmentVariable "Retrieves the contents of the specified variable from the environment block of the calling process."
From these statements GetEnvironmentVariable looks like the safest alternative and replacing getenv with GetEnvironmentVariable indeed resolve the problem.
References:
https://social.msdn.microsoft.com/Forums/en-US/c27a6623-6f57-4c7e-be9b-6dd35d362872/sharing-environment-variables-across-languages?forum=windowsgeneraldevelopmentissues
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getenv-wgetenv?view=vs-2019
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getenvironmentvariable

Python calling C++/CLI dll function using pythonnet

I've compiled a dll from a C++/CLI project in Visual Studio.
The code looks like:
#include "stdafx.h"
#include "api209.h"
using namespace System;
using namespace api209;
namespace CDK_net {
public ref class CDK_wrapper
{
public:
CDK_wrapper::CDK_wrapper(){};
public:
void init(){
//some magic
}
};
}
So this dll references a few other native C++ dlls and libraries, and does some stuff in the init() function.
If I create a C# project, reference this dll, the CDK_wrapper.init() works perfectly fine.
Now I want to reference this dll from a python script. So I have Python 2.7.15 and pythonnet to allow me to do this.
If I create a simple script:
import sys
import clr
dlldir = "C:\\dir\\of\\dll\\"
dllname = "CDK_net"
sys.path.append(dlldir)
clr.AddReference(dllname)
from CDK_net import CDK_wrapper
cdk = CDK_wrapper()
#works fine until here
cdk.init()
I get the following error when running it in Python:
Traceback (most recent call last):
File "test_script.py", line 33, in <module>
cdk.init()
System.Runtime.InteropServices.SEHException: External component has thrown an exception.
at api209.model.open(model* , SByte* , Repository* )
at CDK_net.CDK_wrapper.init() in d:\(...)cdk_net.h:line 21
So the error traces back to function in a C++ library which is referenced by my C++/CLI managed dll.
My question is; whatever is happening in the init() function in my dll, if it works when being called by a C# application, is there any reason why it shouldn't work when being called by python using pythonnet?

'csc' is not recognized as an internal or external command, operable program or batch file [duplicate]

This question already has answers here:
How to get csc.exe path?
(10 answers)
Closed 5 years ago.
I'm fairly new to C# and I'm trying to use cmd to compile a basic hello world file called test.cs. It contains the following:
// Similar to #include<foo.h> in C++, includes system namespaces in a program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// A name space declaration, a class is a group of namespaces
namespace Program1
{
class Hello // my class here, classes can contain multiple functions called methods which define it's behavior
{
static void Main(string[] args) // main method, just like in C/C++ it's the starting point for execution cycle
{
Console.WriteLine("Hello World");
Console.ReadKey(); // similar to _getch() in C++ waits for user to input something before closing
}
}
}
/*
* Other notes, .cs is a c# file extension
* cs files can be built via terminal by using csc foo.cs to generate foo.exe run it with foo
*/
When I try to run the line csc test.cs I get the following output:
Locate the path of csc.exe and add it your PATH environment variable.
In my case, the path for 64-bit C# compiler is C:\Windows\Microsoft.NET\Framework64\v4.0.30319.
Similarly, you can look for 32-bit C# compiler in C:\Windows\Microsoft.NET\Framework under different .NET framework version directories
There will be csc.exe for all versions like v2.0.XXXXX and v3.5. Select the one with the highest version in Framework64/Framework directory depending on your requirement.
Copy the path of csc.exe and add it to the PATH system environment variable.
Quit the cmd, and then launch again and run the program. That'd work.

Using a C++CLI .dll as an assembly in Powershell

I want to use a C++CLI (Managed C++) .dll to interface between Powershell v3 x86 and a (Unmanaged) C++ application.
I've tried to load a very simple "Hello World" program written in C++CLI using both Add-Type and [System.Reflection.Assembly]::LoadWithPartialName() in powershell but I get the error: "Could not load file or assembly"
I then wrote a C# wrapper for the C++CLI class, successfully loaded it into Powershell using the same method, but when I make a call that references the C++CLI code I get the same error. The C# code itself seems to not take any issue with calls to the C++CLI .dll, but Powershell does.
Accessor.h:
using namespace System;
namespace Accessor {
static public ref class Greeting
{
public:
static void HelloWorld();
};
}
Accessor.cpp:
#include "Accessor.h"
void Accessor::Greeting::HelloWorld()
{
Console::WriteLine("Hello World!\n");
}
Wrapper.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Accessor;
namespace AccessWrap
{
static public class Wrapper
{
static public void HelloWorld()
{
Greeting.HelloWorld();
}
}
}
What is the correct way to accomplish this? I've tried many other methods I've found online but none have worked for me.
Edit:
This is the exact error I get when trying to load the C++CLI .dll directly:
http://imgur.com/HF5VRkf
I was accidentally using 64 bit powershell, not x86 like I thought. I switched to x86 and it works fine.
Thanks for everyone's help.

csharp to java JNI porting call to run on ubuntu

I getting bug: crash happened outside the Java Virtual Machine in native code. whenever i run with class file with native library and .net module file it works fine.
but when i try to run alone class file and native library it gets crash .please clarify my mistake i have done, please review my code.
for your reference with parameter
==========================================
public class Sum
{
public int add(int a, int b)
{
return a + b;
}
}
===========================================
save as Sum.cs and compile it to module
using cmd:
csc /t:module sum.cs
Create Java File to test
===========================================
public class test{
public native int add(int a,int b);
static {
System.loadLibrary("JSample");
}
public static void main (String[] args) {
System.out.println(new test().add(10,15));
}
}
==========================================
save it as test.java compile as
javac test.java
create native header file
javah -jni test
it will create test.h
create win32 project using visual studio (I used VS2010)
Choose project name as JSample
include header and C#.net module
write header for manged C++ conversion
==============================================
#using <mscorlib.dll>
#using "Sum.netmodule"
using namespace System;
public __gc class SumC
{
public:
Sum __gc *t;
SumC()
{
t = new Sum();
}
int callCSharpSum(int a,int b)
{
return t->add(a,b);
}
};
===========================================
save it as sum.h
create sum.cpp file
============================================
#include <jni.h>
#include "test.h"
#include "sum.h"
JNIEXPORT jint JNICALL Java_test_add
(JNIEnv *, jobject, jint a, jint b)
{
SumC* t = new SumC();
return t->callCSharpSum(a ,b );
}
=============================================
optimize compiler to build /clr:oldSyntax
Include Jdk/Include directory path
build the project.
we will Get JSample DLL
run the project
with C#.net module,Native DLL file and class file at the same folder.
java test
25
but whenever i run the code with dll file and class file alone.
it shows bug report The crash happened outside the Java Virtual Machine in native code.
please clarify how to port managed code C# into C++ (Win32 Un-Managed code). library file.
To use .NET assemblies from Java, I strongly suggest you look at IKVM, which is a Java VM that bridges to .NET Runtime.
I've used this back in (I think) 2004 for production software and it worked nicely. The project is actively maintained and recieves support for .NET 4 and Java 7 these days.
You have a choice of
running the Java code in IKVM so you can use .NET libraries
run a .NET program that loads java libraries (e.g. jars)
Both ways, there is a preprocessing step to translate the jars to DLLS or viceversa.
See http://ikvm.net

Categories