Is there any tool that can do c# code to powershell - c#

I was wondering if there is an online tool that can convert c# code to powershell cmdlet code. I have following code that i need to have it powershell. I dont have visual studio to turn this into an exe or dll. any help or ideas would be great.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
namespace CopyUsersBetweenGroupsInSharepointByRR
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("This tool will copy the users from one group to another group");
Console.WriteLine("Please enter the URL of the site where your groups are available");
String siteUrl = Console.ReadLine();
using (SPSite site = new SPSite(siteUrl))
{
try
{
SPWeb web = site.OpenWeb();
Console.WriteLine("Please enter the name of the source group");
String sourceGroupName = Console.ReadLine();
Console.WriteLine("Please enter the name of the destination group");
String destinationGroupName = Console.ReadLine();
SPGroup sourceGroup = web.Groups[sourceGroupName];
SPGroup destinationGroup = web.Groups[destinationGroupName];
SPUserCollection sourceUsers = sourceGroup.Users;
SPUserInfo[] sourceUserInfoArray = new SPUserInfo[sourceUsers.Count];
for (int i = 0; i < sourceUsers.Count; i++)
{
sourceUserInfoArray[i] = new SPUserInfo();
sourceUserInfoArray[i].LoginName = sourceUsers[i].LoginName;
sourceUserInfoArray[i].Name = sourceUsers[i].Name;
}
destinationGroup.Users.AddCollection(sourceUserInfoArray);
destinationGroup.Update();
web.Update();
Console.WriteLine("Operation Completed Successfully");
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
}
}

It's comments like those above that are turning people away from SO in droves. The OP's question was unambiguous and displayed genuine need.
There are several ways to achieve this. Rewriting your entire C# code repository is not one of them.
As already discussed, as of PS 2 you are able to either run C# (or most any other language) inline, or refer to well-formed external file. I've had mixed success with this and I don't believe it's what the OP was really after.
If you genuinely want to convert code (particularly compiled assemblies) then a decompiler like Reflector is able to do this and - with the PowerShell addon - is also able to convert it on-the-fly.
http://blog.lekman.com/2011/10/converting-c-to-powershell.html
If you want your input and output to take place within the PS console then you'd still have to perform some obvious re-writes. But this method has proved incredibly useful to me.

The fastest way to do it is to write the PowerShell code yourself.
Below is how the code will look in PowerShell, i would say that most C# developers should be able to grasp the concepts of converting C# code to PowerShell in a very short time.
Functions can be a little odd at the beginning, since the usual PS syntax is
myFunction Parameter1 Parameter2
Also you really should install PowerShell 3.0 and use the Windows PowerShell ISE tool to develop the code.
Anyways it should not take you more than 1-2 hours to get your C# code running along in PowerShell.
[System.Reflection.Assembly]::LoadWithPartialName(”Microsoft.SharePoint”)
Write-Host "This tool will copy the users from one group to another group"
Write-Host "Please enter the URL of the site where your groups are available"
[string] $siteUrl = [Console]::ReadLine()
$site = new-object Microsoft.SharePoint.SPSite($siteUrl)
try
{
$web = $site.OpenWeb()
Write-Host "Please enter the name of the source group"
[string] $sourceGroupName = [Console]::ReadLine()
Write-Host "Please enter the name of the destination group"
[string] $destinationGroupName = [Console]::ReadLine()
$sourceUsers = $web.Groups[$sourceGroupName]
(and so on)
}
catch
{
Write-Error ("Failed to copy sharepoint users." + $_)
}

I doubt there is anything remotely like that, however Visual Studio is not required to compile c# code. You could compile an exe without VS. The compiler (csc.exe) and msbuild are included as part of framework. They are located in C:\Windows\Microsoft.NET\Framework\{version}.
If you really want to call this from powershell, have a look at the Add-Type cmdlet. You provide it the source code and it will compile the source on the fly, then load the assembly into your session.

Not sure about online tools, but download the free Visual Studio Express & follow this tutorial should have you creating a cmdlet in no time

Related

What is the best way to check PowerShell Execution Policy in C#?

When you run Get-ExecutionPolicy in PowerShell, it gets the effective execution policy. I need to know the best way to get that information in C#. I don't need to know how to change it like many other questions about PowerShell Execution Policy, I just need to know how to get it in C#.
Note:
PowerShell execution policies apply only on Windows.
With respect to Windows, the answer below covers both PowerShell editions.
It can be inferred from the docs that boxdog pointed to in a comment, but to spell it out:
using System;
using System.Management.Automation;
namespace demo
{
class ConsoleApp {
static void Main() {
using (var ps = PowerShell.Create()) {
var effectivePolicy = ps.AddCommand("Get-ExecutionPolicy").Invoke()[0].ToString();
ps.Commands.Clear();
Console.WriteLine("Effective execution policy: " + effectivePolicy);
}
}
}
}
Note:
The above assumes that you're using the PowerShell SDK - see this answer for the appropriate NuGet package to add to your project.
If you're using a PowerShell (Core) 7+ SDK, additional considerations apply:
On Unix-like platforms, execution policies fundamentally do not apply (Unrestricted is reported, though in effect it is Bypass), so the following applies to Windows only:
The LocalMachine scope of any - by definition install-on-demand - PowerShell (Core) 7+ version does not apply; only - if defined - the CurrentUser and GPO-based policies (which preempt the former) do.
On Windows:
In the absence of a relevant execution policy being defined, Restricted is the default, which categorically prevents execution of script files (.ps1).
If your application needs to execute .ps1 files when hosting the PowerShell SDK, for predictable behavior it is best to set the execution policy, for the current process only, as shown in this answer.
The most elegant solution would probably be to get the ExecutionPolicy registry key in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell. For this solution to work, your program needs to be running on the same architecture (x64 or x86) as the operating system it's running on or it won't be able to see the registry key. Code to do this would look something like this:
using Microsoft.Win32
...
string executionPolicy = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell", "ExecutionPolicy", null)?.ToString();
If for any reason you can't do the first solution, the second way I would recommend is by using the System.Management.Automation.PowerShell NuGet package. This method would look something like this:
using(var ps = PowerShell.Create()){
ps.AddScript("Get-ExecutionPolicy");
Collection<PSObject> output = ps.Invoke();
Console.WriteLine($"Execution policy is {output[0]}")
}
If you really don't want to add an extra NuGet package to your project, there is another, but quite a bit messier way of doing this using System.Diagnostics.Process and it's output stream. It would look something like this:
var procInfo = new ProcessStartInfo("powershell.exe", "-Command \"Get-ExecutionPolicy\"")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
var proc = new Process
{
StartInfo = procInfo
};
proc.OutputDataReceived += Proc_OutputDataReceived;
proc.Start();
proc.BeginOutputReadLine();
Console.ReadLine();
...
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Data))
Console.WriteLine($"Execution policy is {e.Data}");
}

.xmla deployment to SQL using C#

I use Invoke-ASCmd in PowerShell right now to create a database in SQL Server, like this:
Invoke-ascmd -Query $MyScript -Server $ASServer
Where $MyScript is a string holding the contents of an .xmla file that I read in previously.
This works great. Now I need to do something similar in C#, but am unable to find a simple solution like the one that exists in PowerShell.
I see some people using a Microsoft DLL called Microsoft.AnalysisServices.XMLA.dll, but it's not supported, and the class in question is "internal", so I can't even reference it.
I found this DLL Microsoft.AnalysisServices.AdomdClient.dll while searching around, but don't see any of the classes being relevant to what I need: https://learn.microsoft.com/en-us/dotnet/api/microsoft.analysisservices.adomdclient?view=analysisservices-dotnet
using Microsoft.AnalysisServices.AdomdClient;
try
{
var xmlaFileContents = File.ReadAllText("path/to/your/file.xmla");
using (AdomdCommand cmd = conn.CreateCommand())
{
cmd.CommandText = xmlaFileContents;
cmd.ExecuteNoQuery();
}
}
catch(Exception)
{
}
** please note that I have not run this code **
As the AdomdConnection is inherited from IDbConnection, it's pretty similar to how the SqlConnection works, and therefor, similar syntax can be used, as #jogi presented for you.
I wrote a PS function a few years back which we use in TFS builds. It uses the .NET assemblies rather than the PS layer, so I figured since you seem savvy in PS, you can perhaps get something out of it. Still essentially the same as what #jogi wrote, only wrapped in PS.
function Invoke-XmlaScript {
[CmdletBinding()] param (
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$ServerInstance,
[Parameter(Mandatory=$true)][ValidateNotNullOrEmpty()][string]$XmlaScript
)
process {
$connection = New-Object Microsoft.AnalysisServices.AdomdClient.AdomdConnection("Data Source=$ServerInstance;Provider=MSOLAP.4;Integrated Security=SSPI;Impersonation Level=Impersonate;")
$connection.Open()
try {
$command = $connection.CreateCommand()
$command.CommandTimeout = 20000
$command.CommandType = [System.Data.CommandType]::Text
$command.CommandText = $Xmla
$reader = $command.ExecuteXmlReader()
if($reader.Read()) {
Write-Output $reader.ReadOuterXml()
}
}
catch { }
$connection.Dispose()
}
}

How do I run an external python script that's importing 3rd party library himself, in C#?

I was trying to combine a Python code with C#, to use all those cool libraries like Speech Recognition inside my C# application.
I made two different projects one for python (IronPython) where I've included the module I need (Speech Recognition) through the python environment in VS2017 and the other one is just a console application where I want to call this app.
I thought the point was to change the searchPaths of Ironpython and afterwards it'll work.
Maybe I'm doing something wrong or maybe it just shouldn't work anyway?
C# Code Main.cs:
using IronPython.Hosting;
using System.Collections.Generic;
private static void Main(string[] args)
{
//Using Iron python
var engine = IronPython.Hosting.Python.CreateEngine();
System.Console.WriteLine("Search paths:");
ICollection<string> searchPaths = engine.GetSearchPaths();
foreach (string path in searchPaths)
{
System.Console.WriteLine(path);
}
System.Console.WriteLine();
searchPaths.Add("..\\..");
///Trying to add a searchPath for the place with the module I need
searchPaths.Add(#"C:\Program Files (x86)\Microsoft Visual
Studio\Shared\Anaconda3_64\Lib\site-packages");
engine.SetSearchPaths(searchPaths);
var res = engine.CreateScriptSourceFromFile(
#"D:\Python\Projects\TestSpeechRecognition
\TestForNETinPython\TestForNETinPython.py"
);
engine.ImportModule("speech_recognition");
var result = res.Execute();
}
Python code
import speech_recognition as sr
r = sr.Recognizer()
with sr.Microphone() as source:
print ("Hello: ")
audio = r.listen(source)
try:
print ("I said: " + r.recognize_google(audio))
except sr.UnknownValueError:
print ("Cant't rec")
except sr.RequestError as e:
print ("Can't connect: (0)".format(e))
Exception:
Unhandled Exception:
IronPython.Runtime.Exceptions.ImportException: no module named speech_recognition
at IronPython.Hosting.PythonService.ImportModule(ScriptEngine engine, String name)
at IronPython.Hosting.Python.ImportModule(ScriptEngine engine, String moduleName)
at Test.Program.Main(String[] args) in D:\Python\Projects\TestSpeechRecognition\Test\Program.cs:line 26
I even read some literature about creating the modules like this one http://www.needfulsoftware.com/IronPython/IronPythonCS2 or this one it's for pythonnet and a little bit creepy, but I guess it may be useful (NoteBook).
Hope someone can use it to solve the problem.

Communication between Python and C#

I have a Python backend running machine learning algorithms. I want to use the same backend for both an Excel plugin (C#) and a website. I want both interfaces to send my training data (thousands of lines of numbers in arrays) to the same Python application and retrieve the results in the form of another array up to a few thousand lines.
The website would fetch data from a SQL database and send that data to Python, while the Excel plugin would take the data that is in the current worksheet and send that data to Python. I need to be able to create numpy arrays in Python before continuing to process the data. Note that the website would be running on the same machine where the Python application resides. I still haven't decided what I will use to code the website, but I was leaning towards Node.js.
I have done some research and found a few options:
1- Named pipes
2- Sockets
3- RPC server such as gRPC or XML-RPC.
4- Writing the data to a file and reading it back in Python
5- Web Service
Note: I would need the Python "server" to be stateful and keep the session running between calls. So I would need to have a kind of daemon running, waiting for calls.
Which one would you experts recommend and why? I need flexibility to handle several parameters and also large arrays of numbers. Using IronPython is not an option because I am running Keras on Python, which apparently does not support IronPython.
I had the same problem recently.
I used a named pipe to transport data from python to my c# server, hope it helps you.
Python:
import win32pipe, win32file
class PipeServer():
def __init__(self, pipeName):
self.pipe = win32pipe.CreateNamedPipe(
r'\\.\pipe\\'+pipeName,
win32pipe.PIPE_ACCESS_OUTBOUND,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
1, 65536, 65536,
0,
None)
#Carefull, this blocks until a connection is established
def connect(self):
win32pipe.ConnectNamedPipe(self.pipe, None)
#Message without tailing '\n'
def write(self, message):
win32file.WriteFile(self.pipe, message.encode()+b'\n')
def close(self):
win32file.CloseHandle(self.pipe)
t = PipeServer("CSServer")
t.connect()
t.write("Hello from Python :)")
t.write("Closing now...")
t.close()
For this code to work you need to install pywin32 (best choice is from binarys): https://github.com/mhammond/pywin32
C#-Server:
using System;
using System.IO;
using System.IO.Pipes;
class PipeClient
{
static void Main(string[] args)
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "CSServer", PipeDirection.In))
{
// Connect to the pipe or wait until the pipe is available.
Console.Write("Attempting to connect to pipe...");
pipeClient.Connect();
Console.WriteLine("Connected to pipe.");
Console.WriteLine("There are currently {0} pipe server instances open.",
pipeClient.NumberOfServerInstances);
using (StreamReader sr = new StreamReader(pipeClient))
{
// Display the read text to the console
string temp;
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("Received from server: {0}", temp);
}
}
}
Console.Write("Press Enter to continue...");
Console.ReadLine();
}
}
You can use Python for .NET (Python.NET). It may require some changes to your code, but then it should work very well, once everything is in good shape.
Python.NET allows two-way communication between CPython and CLR.
Let me give you a neat and quick recipe, in the form of example code.
There are basically two ways to tie python in the backend of C# (or a C# winform app or gui or something similar).
Method1: Iron Python. In this method you install a .net package in your visual studio called IronPython. I would not prefer this, because assuming your machine learning model uses keras or a lot of other libraries. It would be another quest to get you installations ready and working in IronPython. And most importantly, it is not as good as your common virtual env or conda environment.
Method2: (The Good Method): Create a Custom Process in your C# that takes arguments from your GUI, knows the path to your script and your python env. Using all these things, it calls your python code exactly the way you would call it in your terminal and pass arguments to it.
Now the tasty example code (I have used this simple trick and it always helps make my black screen python stuff look good with the cover of C# apps).
Python Part
import sys
a = sys.argv[1]
b = sys.argv[2]
print("The Sum = ", float(a)+float(b))
The C# Part
So here is the python process/function that you need to call on the click event of your sum button in the application
static void PythonProcess()
{
//1) Create Process Info
var psi = new ProcessStartInfo();
//Conda Env Path
psi.FileName = #"C:\Users\jd\.conda\pkgs\py\python.exe";
//2) Provide Script and the Arguments
var script = #"C:\Users\jd\Desktop\script.py";
var a = "15";
var b = "18";
psi.Arguments = $"\"{script}\" \"{a}\" \"{b}\"";
//3) Process Configuration
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
//4) Execute Process and get Output.
var errors = "";
var results = "";
using(var process = Process.Start(psi))
{
errors = process.StandardError.ReadToEnd();
results = process.StandardOutput.ReadToEnd();
}
//5) Display Output
Console.WriteLine("ERRORS: ");
Console.WriteLine(errors);
Console.WriteLine();
Console.WriteLine("RESULTS: ");
Console.WriteLine(results);
}
Calling Python from C# is easily possible via Pyrolite where your Python code is running as a Pyro4 server. It should be fast enough to handle "large arrays of numbers" however you didn't specify any performance constraints.
I had the same issue and seem to end up with named pipes. Here is a nice example of how to set it up to talk C# => Python, assuming C# is the server.
It can use the same way to talk back or just Python.net to call directly through CLR as shown here. I use the latter.

Import math fails in IronPyhton

I am trying to use IronPython log function in C#. Idea is user would write a mathematical script this would be evaluated and answer would be displayed in UI. When I use this method for simple mathematics(addition, subtraction etc.) it works fine. When I need to use log function I try to import math module it fails. My code is:
public double Calculate(string script)
{
ScriptEngine engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromString("import math" + System.Environment.NewLine + script, SourceCodeKind.AutoDetect);
return source.Execute<double>();
}
When I run this code I get exception 'IronPython.Runtime.Exceptions.ImportException No Module named math.
I am calling method as
Calculate("math.log(10)")`
Am I missing any import or dll?
I tried to replicate your issue, however I did not have IronPython installed yet, so I installed the latest stable version (2.7.4) from here. I am not sure if you are using the same version...
When creating a solution, I knew I needed to add some references. My guess is, that this is the source of your 'evil'.
I have added the references 'IronPython' and 'Microsoft.Scripting', which come along with the installation of IronPython. The exact versions are v4.0.30319 (both IronPython and Microsoft Scripting).
So my Windows Forms application has one textBox and one button (it's just a test after all) and I copied in your example method called Calculate, in order to make sure we have the same, here is my version:
public double Calculate(string script)
{
ScriptEngine engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromString("import math" + Environment.NewLine + script, Microsoft.Scripting.SourceCodeKind.AutoDetect);
return source.Execute<double>();
}
In the eventhandler of my button I have placed the following code:
private void button1_Click(object sender, EventArgs e)
{
try
{
double outcome = Calculate("math.log(10)");
tbOutcome.Text = string.Format("Outcome of log(10): {0}", outcome);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error occured...", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
When executing my application, the program does not show an error as yours, but it shows the an outcome that I did expect when calculating log(10) (assuming you are calculating a natural logarithm). My textBox contains:
Outcome of log(10): 2,30258509299405
So there is only one hint, try to find out if you have different versions of your ScriptEngine installed (I know there are a few more than just Microsoft.Scripting) and look at the references in your solution.
Hope it helps!
Python is case sensitive, and, there is no class named just Math.. only System.Math
so to get what you want, you need to use this import statement: from System import Math or import System.Math as Math
both would get you the same result...

Categories

Resources