Call specific function from perl module from PowerShell or C# - c#

I've a perl script file (.pm) which has many functions like below
sub check_row {
my ($class, %args) = #_;
.......
sub find_value {
my ($class, %args) = #_;
.......
Is there any way I can call specific function either via C# or Powershell? I am not allowed to make any change in the .pm file. I am clueless as the tutorial I see on internet talks only about running perl module but not calling any specific function and passing and retrieving value.

You can't use Perl modules (your_module.pm) directly from PowerShell or C#. You need to run a Perl script (your_script.pl) that uses the module:
#!/usr/bin/env perl
use strict;
use warnings;
use Your::Module qw(find_value);
find_value ...;
or at least pass the code string as a commandline argument to the Perl interpreter, as Mathias R. Jessen pointed out in the comments:
perl.exe -w -MYour::Module -e 'find_value ...;'

For further research you might have a look at Win32-PowerShell-IPC-0.02. The documentation states the following:
This module fires up a captive child PowerShell process to which you can submit commands, and receive the results. It's all text for now, but Perl excels at messy stuff like this.

Related

Running the PowerShell Script from the c#

I am trying to call PowerShell ISE Script from the C#.
I have command that I am running it on the PowerShell
. .\Commands.ps1; Set-Product -bProduct 'Reg' -IPPoint 'ServerAddress' -Location 'testlocation' -Terminal 3
Now I am trying to create the Command with the c# I have wrote some code Like this.
//Set Execution Policy to un restrict
powershell.AddCommand("Set-ExecutionPolicy");
powershell.AddArgument("unrestricted");
powershell.Invoke();
powershell.Commands.Clear();
powershell.AddScript("K:\\Auto\\Cases\\Location\\Commands.ps1", false);
powershell.AddArgument("Set-Product").AddParameter("bProduct ", "Reg").
AddParameter("IPPoint", "ServerAddress").
AddParameter("Location", "testlocation").AddParameter("Terminal", 3);
powershell.Invoke();
I can see its running fine. But its not updating values in my xml file. It suppose to update my values in file. When I try to run it with powershell It does run and works file. But c# code does not work.
Any hint or clue will be appreciated.
Mind the semicolon, so this is basically two statements:
1.) Dot-sourcing the script Commands.ps1
. .\Commands.ps1
2.) Invoking the cmdlet Set-Product
Set-Product -bProduct 'Reg' -IPPoint 'ServerAddress' -Location 'testlocation' -Terminal 3
So, you have to treat them as such. Also, AddScript expects code, not a file name.
powershell
// dot-source the script
.AddScript(#". 'K:\Auto\Cases\Location\Commands.ps1'")
// this is the semicolon = add another statement
.AddStatement()
// add the cmdlet
.AddCommand("Set-Product")
.AddParameter("bProduct", "Reg")
.AddParameter("IPPoint", "ServerAddress")
.AddParameter("Location", "testlocation")
.AddParameter("Terminal", 3)
// invoke all statements
.Invoke();
(Alternatively to AddStatement() you can of course split this up in two calls and call Invoke() twice.)

Changing the current working directory of cmd (from a child process)

So I am trying to write a cd -like program that can be executed using cmd and after it exits the working directory of the calling cmd process should be changed.
Now before this post is flagged as a duplicate: I am aware of this and this question that were asked for pretty much this exact problem but using Linux instead of Windows as well as being pretty broad and unspecific, and I am aware that similar limitations apply to Windows as well (changing the working directory of my process will not change the parent’s working directory).
There is actually is a working solution to this for linux. However it is using gdb for this, and I would like to achieve this task using only built-in Windows utilities (WinAPI, dotNET, etc.).
What I have tried so far
I did manage to use Cheat Engine and the OpenProcess() / WriteProcessMemory() WinAPI funtions to successfully override cmd's working directory. However this solution feels sloppy and doesn't work well (or at least requires more work to be put into.)
My question
Is there a different (maybe simpler?) way on Windows to achieve this? Like a way to invoke/inject code to the cmd process to execute cd whatever\directory\I\want directly without overriding its memory? I have seen the CreateRemoteThread() functions however I didn't manage to find a way to put them to use.
FYI: I am mainly using C# but C/C++ solutions should help too as long as they are based on the native Microsoft libraries.
This post describes a Windows implementation of a function that launches a child process, creates pipes to stdin and stdout from which a command is sent, and a response is returned. Finally, once all response is captured the child process is terminated. If this sounds familiar it is similar in concept to Linux's popen() function with the exception that this implementation was specifically created to capture the response into a buffer of any command that returns one. (Also included is a variant for use when no-response is expected or needed.)
The full source can be adapted for use within a standalone executable, or as an API. (.dll) Either way, the resulting functions accept and process any command using standard Windows CMD syntax. The function cmd_rsp(...) returns the Windows response via stdout into a self-sizing buffer.
The exported prototypes are:
int __declspec(dllexport) cmd_rsp(const char *command, char **chunk, unsigned int size);
int __declspec(dllexport) cmd_no_rsp(const char *command);
A simple use case when capturing a response:
#include "cmd_rsp.h"
int main(void)
{
char *buf = {0};
buf = calloc(100, 1);//initialize to some initial size
if(!buf)return 0;
cmd_rsp("dir /s", &buf, 100);//buffer will grow to accommodate response as needed.
printf("%s", buf);
free(buf);
return 0;
}
A simple use case when response is not needed:
#include "cmd_rsp.h"
int main(void)
{
cmd_no_rsp("cd C:\\dir1\\dir2");
return 0;
}
A detailed description of purpose and usage is described in the link provided above. To illustrate, here are a few sample command inputs, each in this case change the working directory, then execute a command from that directory:
A command to change to sqlite directory, then execute a query:
cd c:\\tempExtract\\sqlite\\Tools\\sqlite-tools-win32-x86-3250300 && sqlite3.exe .\\extract.db \"select * from event, eventdata where eventType=38 and eventdata .eventid=event.eventid\
A command to change to teraterm directory, then execute a script:
"c:\\Program Files (x86)\\teraterm\" && ttpmacro c:\\DevPhys\\LPCR_2\\play\\Play.ttl
A command to change directory then execute a command to send multiple digital acquisition channel settings.
cd C:\\Dir1\\Dir2\\Dir3\\support\\Exes\\WriteDigChannel && .\\WriteDigChannel.exe P1_CH0 1 && .\\WriteDigChannel.exe P1_C H0 0 && .\\WriteDigChannel.exe P1_CH0 1
A recursive directory search from a specified location:
cd C:\\dir1\\dir2 && dir /s /b
I got it working. As was suggested SendInput finally did the trick.
I used a combination of WinAPI calls to GetForegroundWindow() / SetForegroundWindow() and the Windows Forms System.Windows.Forms.SendKeys.SendWait() Method to achieve what I wanted:
Upon calling my cd-wrapper program (sd.exe) and providing my custom target directory (~/ home) it generates the corresponding command along with the "Enter-Pressed-Event" to be sent to it's parent cmd process.
Here's the complete C# code:
if (args.Length != 1)
{
Console.WriteLine(Directory.GetCurrentDirectory());
return;
}
string targetDirectory = args[0];
string command = string.Empty;
if (targetDirectory.Equals("~"))
{
command = #"pushd C:\Users\fred\Desktop";
}
else if (!Directory.Exists(targetDirectory))
{
Console.WriteLine("I/O Error: No such file or directory.");
return;
}
else
{
command = #"cd " + targetDirectory;
}
Target target = Target.Create(Process.GetCurrentProcess().GetParentProcess());
target.SendKeys(command + "{ENTER}", true);
Note that I kind of started to write a complete Framework for this and similar problems alongside this project that contains all my different approaches to this question and the low level WinAPI calls as well as the Extension methods to get the parent process :D
As it would be a bit overkill to paste all of it's code in this answer, here's the GitHub. If I can find the time I'll go ahead and optimize the code, but for now this'll do. Hope this helps anyone encountering a similar problem :)
Edit:
An even "cleaner" way is to use dll injection to directly make cmd switch it's working directory. While it is a lot harder to get working it has the advantage of not littering the cmd command history as compared to the approach described above. In addition to that cmd seems to be aware of any changes to it's current working directory, so it automatically updates the prompt text. Once I have a fully working example, that allows to dynamically specify the target directory I will post it here :)

c# how to import a powershell module from a string

I'm using c# and I want to use import-module to import a powershell script. However I don't want to have a .psm1 file on disk. I want to have it hardcoded on my code, like in a string and then import it.
Is that possible?
All the example I can find are something like:
pipeline.Commands.Add("Import-Module");
var command = pipeline.Commands[0];
command.Parameters.Add("Name", #"G:\PowerShell\PowerDbg.psm1")
or something like:
var ps = PowerShell.Create(myRS);
ps.Commands.AddCommand("Import-Module").AddArgument(#"g:\...\PowerDbg.psm1")
ps.Invoke()
However as I said above I don't want to read a file from disk. I want it hardcoded to avoid multiple files. I want everything on an exe and that's it. I couldn't find a way, any help is appreciated.
The reason I want to use import-module is because after importing the module I want to do something like:
get-command -module <whatever>
and get a list of all its functions.
Any other way to list functions from a script might be helpful too.
Thanks.
You're looking for New-Module; it does exactly what you're asking for.
From the TechNet page (paraphrased):
New-Module -ScriptBlock {
$SayHelloHelp="Type 'SayHello', a space, and a name."
function SayHello ($name) {
"Hello, $name"
}
Export-ModuleMember -function SayHello -Variable SayHelloHelp
} -Name PowerDbg
C# Example (not tested):
string moduleContents = #"...";
pipeline.Commands.Add("New-Module");
var command = pipeline.Commands[0];
command.Parameters.Add("ScriptBlock", moduleContents);
command.Parameters.Add("Name", "PowerDbg");
pipeline.Invoke();

Redirect the standard input and output of .net program

I am writing a test script for a C/S system in python. And right now, we only have a test client written in C#. It is a command line based client. I want to control the input and get the output of the client in my python script. How could I make it?
Thanks!
Use the subprocess module as follows:
import subprocess
proc = subprocess.Popen("cat", stdin = subprocess.PIPE, stdout = subprocess.PIPE)
out, err = proc.communicate(input)
The process ends after the last call. If you want to do some input iteratively, you can use proc.stdin.write, but you have to call communicate(None) at the end to finish the process.
Use subprocess.Popen.

FilePaths in C# and VB.NET (via WCF)

I have a WCF which I can call from a VB.NET application like this:
Dim tcp As New TCPService2.Service1Client
ExStreamPath = "C:\Program Files\Exstream\Dialogue 6.1\Engine.exe"
datPath = "-FILEMAP=DataFile,\\Dev-srv1\Exstream\LetterWriterApp\Input Files\Data Files\SAVEezkazivaftf40s452ndayb45.dat"
optPath = "-CONTROLFILE=C:\Exstream\Development\LetterWriter\ControlFiles\Letter.opt"
tcp.StartExStream(datPath, optPath, ExStreamPath)
The previous code kicks off a subroutine in a WCF (written in VB.NET), which uses the process object to start a 3rd party executable (with the arguments listed above). The code works great.
But, I'm having problems making the same type of call with C#. I think it might have something to do with a VB WCF being passed C# filepaths (the whole double-\\ thing), but I'm not sure. When trying to run the following code, I'm getting a 'File Not Found' error. The paths have been copied and pasted, so I know the paths are identical. Here's the C#:
tcpExstream.Service1Client MyTCP = new tcpExstream.Service1Client();
string ExStreamPath;
string datPath;
string optPath;
ExStreamPath = #"C:\Program Files\Exstream\Dialogue 6.1\Engine.exe";
datPath = #"-FILEMAP=DataFile,\\Dev-srv1\Exstream\LetterWriterApp\Input Files\Data Files\SAVEezkazivaftf40s452ndayb45.dat";
optPath = #"-CONTROLFILE=C:\Exstream\Development\LetterWriter\ControlFiles\Letter.opt";
MyTCP.StartExStream(ExStreamPath, datPath, optPath);
Any ideas?
Thanks in advance,
Jason
Your arguments appear in a different order between the two.
Compare:
tcp.StartExStream(datPath, optPath, ExStreamPath)
With:
MyTCP.StartExStream(ExStreamPath, datPath, optPath);

Categories