Calling query results from Powershell into C# - c#

I am new to Powershell.
I am trying to insert the query results of this Powershell code into C# variable called "results".
I got the C# sample code from here to get the result of Powershell into C#.
var results = ps.Invoke();
foreach (var psobject in results)
{
var myInteger = Convert.ToInt32(psobject.Members["SomeField"].Value);
}
By looking at this Powershell code, on line 39 and 40,
# results of query
[Intacct.SDK.Xml.OnlineResponse]$Response = $task.Result
the object name for the query results seems to be [Intacct.SDK.Xml.OnlineResponse]$Response.
Is it?
1) What would be expression to get the result of this Powershell and put inside C#?
2) Do I have to install PowerShell Tool into Visual Studio to see the "PowerShell" object to be recognized (shows up without an error)?
And, why is this extension trial version?
I am trying to understand how powershell code works within C# solution.
3) Do I just create ps1 code like this and add to the solution?
Thank you.

Related

Running a powershell script from C# ends in error

I want to trigger a site design from powershell. It works here but when I try to run it through c# I get this error:
Cannot convert value "param" to type
"Microsoft.Online.SharePoint.PowerShell.SPOSiteDesignPipeBind". Error:
"Guid should contain 32 digits with 4 dashes
(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
I have tested several versions of the addScript string but none have worked. This is the code I'm trying to run. And it works fine in powershell.
PowerShellInstance.AddScript("Invoke-SPOSiteDesign -Identity param($paramSiteDesignId) -WebUrl param($paramUrl)");
PowerShellInstance.AddParameter("paramSiteDesignId", "176d2af0-1772-41b2-9ad7-acfceefc8851");
PowerShellInstance.AddParameter("paramUrl", "https://TenantName.sharepoint.com/sites/TMVTest13");
Any help pointing me in the right direction is very appreciated.
I found a way doing it directly in C# with Tenant.ApplySiteDesign. It works great see link for more info https://laurakokkarinen.com/the-ultimate-guide-to-sharepoint-site-designs-and-site-scripts/#applying-site-designs-programmatically
As you can see on learn.microsoft.com, AddParameter doesn't work by replacing placeholders the way you are doing it, but instead works by adding parameter/value pairs to the given command as parameters.
Your code probably results in something like this:
Invoke-SPOSiteDesign -Identity param($paramSiteDesignId) -WebUrl param($paramUrl) -paramSiteDesignId 176d2af0-1772-41b2-9ad7-acfceefc8851 -paramUrl https://TenantName.sharepoint.com/sites/TMVTest13
According to the documentation, this should do what you want:
PowerShellInstance = PowerShellInstance.AddScript("Invoke-SPOSiteDesign");
PowerShellInstance = PowerShellInstance.AddParameter("Identity", "176d2af0-1772-41b2-9ad7-acfceefc8851");
PowerShellInstance = PowerShellInstance.AddParameter("WebUrl", "https://TenantName.sharepoint.com/sites/TMVTest13");```

Is there any way to convert PSObject to string in C# while working with Powershell Api

I need to convert PSObject to String(). Is there any standard way available to do this task? Somehow powershell also does ToString() or spits out a readable stream on ISE console.
I used PSSerializer.Serialize(PSObject) but it serializes everything. I want in my application seemlessly everything shown in a way the way Powershell does.
Is there anyway to convert PSObject to a.readable string. At the moment when I use following line of code
PSObject.ToString()
or
PSObject.BaseObject.ToString()
both just print out complete type name. ( e.g. "System.Collection.HashTable" )
But I want complete displayed contents to see the way powershell exposes.C#
You could get PowerShell to format it for you.
foreach (PSObject obj in myPsObjects)
{
var formattedObj =
System.Management.Automation.PowerShell
.Create()
.AddCommand("Write-Output").AddArgument(obj)
.AddCommand("Out-String")
.Invoke();
string message = string.Join(" ", formattedObj);
Console.Write(message);
}

Call PS Script, Save String Returned

My PS script returns a string.
Function GetData {
Param(
[string]$id
)
Process
{
return "Value is $id"
}
GetData -id $arg
The below is the C# that calls the PS script:
PowerShell ps = PowerShell.Create();
string psScript = "GetData.ps1";
ps.AddScript(psScript);
// only takes one parameter
ps.AddParameter("25");
Collection<PSObject> results = ps.Invoke();
foreach (PSObject r in results)
{
Console.WriteLine(r.ToString());
}
Console.ReadLine();
Nothing returns.
I double checked the script and it does return a value when I pass in the path manually when calling the script directly in PowerShell. I also made sure that in the Properties of the project the Platform target is x64 (based on another question's error). I also tried to directly save the result in the Invoke method, but it gave an error, which showed that I have to actually save it in a collection, even though it's one record.
Forgot, also tried:
psParam = "25";
string psScript = "GetData.ps1 -arg'" + psParam + "'";
And no result on the console.
Tested this:
PowerShell ps = PowerShell.Create();
string psScript = ".\\GetData.ps1";
ps.AddCommand(psScript);
ps.AddArgument("25");
Collection<PSObject> results = ps.Invoke();
foreach (PSObject r in results)
{
Console.WriteLine(r.ToString());
}
Console.ReadLine();
And used most of the above and this errors because it says GetData.ps1 is not recognized as the name of a cmdlet, function, script file, or operable program. If I point directly to it by placing it on my C drive (C:\GetData.ps1), it does nothing.
Double check; inside the script I am calling the function on the last line:
GetData -id $arg
Is this correct?
Pay attention to your function. It gets an open curly brace '{', but not the matching close curly brace '}'. Your defective PowerShell code will emit an error not caught by your code.
After you correct this simple error, notice how you're calling your function. What is $arg? I assure you it's not any automatic variable. Have a look in about_automatic_variables...
P.S.: you'd better off asking enormously difficult questions like this one in social . technet . microsoft . com / Forums / windowsserver / en-US / home?forum=winserverpowershell . If you ha did it, the answer would have been posted many hours ago.
The problem is that "return" is not what you think.
In Powershell, the "return value" is the last value on the stack when execution ends. In your case, just omit the "return" keyword, and the string will come out as you expect.
Function return value in PowerShell
Alternatively, you can use Write-Output which would explicitly send the data to the output like a C-style return statement.
Note: Do NOT use Write-Host, as it writes directly to the powershell host, skipping the pipeline and never giving you a chance to see the value.

Calling COM object from c#

I am currently calling the following com object using Powershell but am having trouble converting the code over to c#. I know this should be pretty straightforward and may be a dumb question, so I apologize if I look like a moron.
Powershell:
$nDeviceId=517
$wug = New-Object -ComObject CoreAsp.EventHelper
$wug.SendChangeEvent(2,$nDeviceId,1)
Current C# Attempt:
Type type = TypeDelegator.GetTypeFromProgID("CoreAsp.EventHelper");
Object application = Activator.CreateInstance(type);
pplication.GetType().InvokeMember("SendChangeEvent", BindingFlags.InvokeMethod, null, application, new object[]{2,517,1});
I appreciate any help!
Update:
When I run the c# code I do not receive any errors.
If you're using .NET 4 and don't mind late-binding (no intellisense, ...), you could use a dynamic object:
Type type = Type.GetTypeFromProgID("CoreAsp.EventHelper");
dynamic application = Activator.CreateInstance(type);
application.SendChangeEvent(...);
I'm not familiar with that COM-object, but in general COM-components are accessed by adding them as a reference in your c# project (select the com-tab in the add reference-dialog) and by using the classes they provide.
Best way to access COM objects from C#
Working off of Frode's answer, I found a DLL named CoreASP.dll and tried to import this into my project but received an error that the library was invalid.
I was able to use the "Type Library Importer" tool in visual studio to convert the COM type library into equivalent definitions.
command: tlbimp.exe CoreAsp.dll\1
This created another DLL "CoreAspiLib.dll" that I was able to import into my Visual Studio project.
Thank you Frode for leading me in the right direction.
Update:
So this method SOMETIMES works, it seems like I would have to call the command 3-4 times to get it to work as expected. To avoid the headache I ended up calling powershell from c#, making sure to hold the runspace open so that I don't have to reload it for subsequent commands (I may be calling this function 50+ times per minute).
Example of calling the script 1000 times:
Runspace runspace = RunspaceFactory.CreateRunspace();
string scriptText =
"$wug = New-Object -ComObject CoreAsp.EventHelper;" +
"$wug.SendChangeEvent(2,519,1)";
runspace.Open();
for (int x = 0; x < 1000; x++)
{
Console.WriteLine("Running Event "+(x+1).ToString());
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
pipeline.Commands.Add("Out-String");
pipeline.Invoke();
Thread.Sleep(1000);
}
runspace.Close();
This seems to work 100% of the time.
Joe I also tried your method and ended up with the same result as my first test, no errors but the function did not run as expected.

How do I call a specific Method from a Python Script in C#?

I'm wondering if there is a possibility to call a specific Method from a Python script over a C# project.
I have no code... but my idea is:
Python Code:
def SetHostInfos(Host,IP,Password):
Work to do...
def CalcAdd(Numb1,Numb2):
Work to do...
C# Code:
SetHostInfos("test","0.0.0.0","PWD")
result = CalcAdd(12,13)
How can I call one of the Methods, from this Python script, over C#?
You can host IronPython, execute the script and access the functions defined within the script through the created scope.
The following sample shows the basic concept and two ways of using the function from C#.
var pySrc =
#"def CalcAdd(Numb1, Numb2):
return Numb1 + Numb2";
// host python and execute script
var engine = IronPython.Hosting.Python.CreateEngine();
var scope = engine.CreateScope();
engine.Execute(pySrc, scope);
// get function and dynamically invoke
var calcAdd = scope.GetVariable("CalcAdd");
var result = calcAdd(34, 8); // returns 42 (Int32)
// get function with a strongly typed signature
var calcAddTyped = scope.GetVariable<Func<decimal, decimal, decimal>>("CalcAdd");
var resultTyped = calcAddTyped(5, 7); // returns 12m
I found a similar way to do it, the call of the method is much easier with it.
C# Code goes as follows:
IDictionary<string, object> options = new Dictionary<string, object>();
options["Arguments"] = new [] {"C:\Program Files (x86)\IronPython 2.7\Lib", "bar"};
var ipy = Python.CreateRuntime(options);
dynamic Python_File = ipy.UseFile("test.py");
Python_File.MethodCall("test");
So basically I submit the Dictionary with the Library path which I want to define in my python file.
So the PYthon Script looks as follows:
#!/usr/bin/python
import sys
path = sys.argv[0] #1 argument given is a string for the path
sys.path.append(path)
import httplib
import urllib
import string
def MethodCall(OutputString):
print Outputstring
So The method call is now much easier from C#
And the argument passing stays the same.
Also with this code you are able to get a custom library folder
for the Python file which is very nice if you work in a network
with a lot of different PC's
You could make your python program take arguments on the command line then call it as a command line app from your C# code.
If that's the way to go then there are plenty of resources:
How do I run a Python script from C#?
http://blogs.msdn.com/b/charlie/archive/2009/10/25/hosting-ironpython-in-a-c-4-0-program.aspx

Categories

Resources