I have the following problem when using standard C# code and command:
Uri.EscapeUriString("[]")
I get :
"[]"
but when I'm using PowerShell:
[Uri]::EscapeUriString("[]")
I get
"%5B%5D"
Could someone please explain me what the differences are in those method calls?
And why am I getting different results? How to force PowerShell to return the same results as standard c#?
Thanks in advance
This seems to be .NET version related. Your C# code probably uses a more recent version.
C#
// .NET 4.0
Uri.EscapeUriString("[]"); // OUTPUT: "%5B%5D"
// .NET 4.5
Uri.EscapeUriString("[]"); // OUTPUT: "[]"
PowerShell
# v5
[Uri]::EscapeUriString("[]") # OUTPUT: "%5B%5D"
# for reference
Add-Type "
using System;
namespace PowerShell
{
public static class Uri
{
public static string EscapeUriString(string stringToEscape)
{
return System.Uri.EscapeUriString(stringToEscape);
}
}
}"
[PowerShell.Uri]::EscapeUriString("[]") # OUTPUT: "%5B%5D"
There is no "Standard C#". The solution would be to make sure both are using the same .NET version, or implement your own escape method.
Alternatively, use System.Net.WebUtility.UrlEncode which seems to return "%5B%5D" in both cases.
Related
I create a .NET Standard F# library with F# 4.3.4 (I also tested with 4.5) with the following code:
namespace ClassLibrary2
module Say =
let a = "国".Length.ToString()
let b = sprintf "%A" ("国".ToCharArray() |> Array.map int)
let c = "国"
When referencing that library from another project (.net core or .net framework):
Console.WriteLine(Say.a); // F# .net standard
Console.WriteLine(Say.b);
Console.WriteLine(Say.c == "国");
I get the following output:
2
[|65533; 65533|]
False
The equivalent C# .NET Standard library:
using System;
using System.Linq;
namespace ClassLibrary1
{
public static class Class1
{
public static string a = "国".Length.ToString();
public static string b = String.Join(", ", "国".ToCharArray().Select(i => ((int)i).ToString()));
public static string c = "国";
}
}
gives the expected output:
1
22269
True
Here's a repo showing the issue: https://github.com/liboz/Kanji-Bug.
This looks likely to be a bug, but I was wondering what would be a reasonable workaround for this problem? Specifically, I want to be able to be able to check equality for strings with something like Say.c = "国" where I might be using non-English characters while using a .NET Standard library.
So, the issue appears to be that the first file that the dotnet cli generates in an F# library does not use Unicode for its encoding. So, when creating a .NET Standard F# library that file for me was generated with Shift-JIS encoding, likely due to region settings on my own computer. Therefore, the solution to my issue was to simply save the default Library1.fs file with UTF-8 encoding manually so that it would have the same encoding as all the other files.
I know it is possible to call C# code from the PowerShell script by loading an assembly. But is there any way to pass and receive a value in between both C# code and PowerShell script.
Let's say I have a $path variable in my power script. I want to pass it to my c# code. And C# code will use the $path. After doing some stuff in the c# code it will return some value to the script. Is this possible? If it is, how can I do it? I must load a third party dll in my power shell and all one or two public methods on that dll to complete some task.
My PowerShell script code:
$scriptpath = $MyInvocation.MyCommand.Path;
$cureentDir = Split-Path $scriptpath;
$isSasDir = $cureentDir -match "mydir";
$requiredFile = "Core.dll";
$myPowersehllVal = "has value for c# code";
My C# code:
$Source = #"
using System.Net;
public class ExtendedWebClient : WebClient
{
String myPowersehllVal;
public int Timeout;
protected override WebRequest GetWebRequest(System.Uri address)
{
}
}
"#;
For getting PS values into C#
https://stackoverflow.com/a/22384009/3546415
In a more general sense, System.Management.Automation (Nuget Required) looks promising, in particular, Runspace and Pipeline.
Here are some good examples of usage:
https://msdn.microsoft.com/en-us/library/ee706576(v=vs.85).aspx
Something like this one seems similar to what you want.
Or maybe just use the PowerShell Class to execute PS commands from your C# module to set PS variable values.
Alternatively, without worrying about interop, you can kind of hack this by working through the file system and/or environmental variables. Following this paradigm, you could even use a memory mapped file and share variables with a broader set of applications. Powershell side would be something like this. For objects, serialization.
i've got a third party c# dll which has been created in dot net 4.5 and has a platform target of x86. I would like to import this into a python script and I've started off with Rob Deary's answer here. However I can't get his example to work. I'm using python version 2.7.6 and I get an AttributeError as shown below.
File "C:\Python27\Lib\ctypes\__init__.py", line 378, in __getattr__
func = self.__getitem__(name)
File "C:\Python27\Lib\ctypes\__init__.py", line 383, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'add' not found
Please note that I am aware of Ironpython and Python for dot net but I need to get this working specifically with C python. Here's my sample code which generates the custom c# library: ClassLibrary1.dll
using System;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
class Test
{
[DllExport("add", CallingConvention = CallingConvention.Cdecl)]
public static int TestExport(int a, int b)
{
return a + b;
}
}
And here's the python script that generates the error
import ctypes
lib = ctypes.cdll.LoadLibrary('ClassLibrary1.dll')
lib.add(3,5)
When I use the line below, this is the output i get. So at least I know that it is loading the dll, but i'm not sure why the function can't be found.
>>> lib.__dict__
{'_FuncPtr': <class 'ctypes._FuncPtr'>, '_handle': 254476288, '_name': 'ClassLibrary1.dll'}
>>>
Any help will be appreciated. Thanks
As the RGiesecke.DllExport documentation states, you need to target a specific architecture (x86 or x64) when building your code. Leaving it set to Any CPU (the default) will not work.
I'm trying to use an embedded python interpreter from C# using pythonnet (the python3 compatible version found at https://github.com/renshawbay/pythonnet)
My interpreter is located in D:\src\scratch\TestPythonNet\TestPythonNet\PythonRuntime and has the "Lib" and "Libs" folder from the python distribution.
I've tested using the following code:
<!-- language: c# -->
PythonEngine.PythonHome = #"D:\src\scratch\TestPythonNet\TestPythonNet\PythonRuntime";
PythonEngine.ProgramName = "PythonRuntime";
PythonEngine.Initialize();
using (Py.GIL())
{
PythonEngine.RunSimpleString("print(1)");
}
But, it doesn't work. I get a "SystemError: PyEvalCodeEx: NULL globals". Everytime I try to get an object from python, the code fails.
What am I doing wrong?
I think I've found the answer. If I add a reference to the "clr" module provided by pythonnet, it does work
PythonEngine.PythonHome = #"D:\src\scratch\TestPythonNet\TestPythonNet\PythonRuntime";
PythonEngine.ProgramName = "PythonRuntime";
PythonEngine.Initialize();
// ==>
PyObject a = PythonEngine.ImportModule("clr");
using (Py.GIL())
{
PythonEngine.RunSimpleString("print(1)");
}
I'm trying to use Leonardo B's litjson library from PowerShell. The entry point to the library I need to use is a static method. I can load the assembly with add-type, no problem. Trying to use the static method though gives this error:
PS C:\Users\david>[litjson.jsonmapper]::toobject("{`"foo`":`"bar`"}")
format-default : The JsonData instance has to be initialized first
+ CategoryInfo : NotSpecified: (:) [format-default], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.FormatDefaultCommand
I though that what was happening was that the static constructor for this class didn't run, but Lars Truijens corrected that misunderstanding. The error is an exception from the JsonData class. Although the same line of code works correctly in VS2012 (targeting .net 3.5) it won't run in powershell.
UPDATE:
This unit test passes in visual studio 2012:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using LitJson;
namespace litjsonTest
{
[TestClass]
public class TestJsonMapper
{
[TestMethod]
public void TestMethod1()
{
var obj = LitJson.JsonMapper.ToObject("{\"foo\":\"bar\"}");
Assert.IsNotNull(obj);
}
}
}
That would totally break .Net. I doubt that. Even more since the error is from the JsonData class and is because a type field is not set from the (non static) constructor of that class. See http://couchbrowse.googlecode.com/svn/trunk/LitJson/JsonData.cs Are you sure your LitJson code is correct? Does this exact code work in a C# program?
UPDATE
Are you sure your Json is correct? The example you posted isn't. There should be double quotes. Try escaping use the back tick or use a here-string
[litjson.jsonmapper]::toobject("{`"foo`":`"bar`"}")