How to determine tcp port used by Windows process in C# - c#

Is there a managed class/method that would provide the TCP port number(s) used by a particular Windows processes?
I'm really looking for a .NET equivalent of the following CMD line:
netstat -ano |find /i "listening"

Except for PID, take a look this:
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] endPoints = ipProperties.GetActiveTcpListeners();
TcpConnectionInformation[] tcpConnections =
ipProperties.GetActiveTcpConnections();
foreach (TcpConnectionInformation info in tcpConnections)
{
Console.WriteLine("Local: {0}:{1}\nRemote: {2}:{3}\nState: {4}\n",
info.LocalEndPoint.Address, info.LocalEndPoint.Port,
info.RemoteEndPoint.Address, info.RemoteEndPoint.Port,
info.State.ToString());
}
Console.ReadLine();
Source: Netstat in C#
A bit more research bring this: Build your own netstat.exe with c#. This uses P/Invoke to call GetExtendedTcpTable and using same structure as netstat.

See here for an equivalent of netstat in C#: http://towardsnext.wordpess.com/2009/02/09/netstat-in-c/
Update: Link is broken, but here's an equivalent: http://www.timvw.be/2007/09/09/build-your-own-netstatexe-with-c
Update: The original page has been archived at the Wayback Machine.

Related

How to get the ports that are in "ESTABLISHED" state in C#

I am new to the .NET framework.
Currently working on a program that checks if the port is ready to use.
I have used IPGlobalProperties to get the port info which was specified here
IPGlobalProperties ipGP = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] tcpEndPoints= ipGP.GetActiveTcpListeners();
IPEndPoint[] updEndPoints = ipGP.GetActiveUdpListeners();
// port validation
Since "ESTABLISHED" & "LISTENING" states refer to open ports
as per this post
I also need a solution to get the port that is in the "ESTABLISHED" state.
Is there a way to get the ports that are in the "ESTABLISHED" state in C#
Not sure what you want to see exactly, but this will show you all the active local established sockets and ports
var active = result.GetActiveTcpConnections().Where(c => c.State == TcpState.Established);
active.Select(c => $"{c.LocalEndPoint.Address} {c.LocalEndPoint.Port}")
.ToList()
.ForEach(Console.WriteLine);

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 :)

Adding a network printer with C#

I've been building a program to easily configure newly imaged computers (setting DNS servers, IP address, gateway, adding to AD, adding optional printers, etc). I had it working in PowerShell, but I've been trying to port it to C#, mainly to combine lots of small scripts in one, add a nice user interface, and as practice to get better at C#. It's been going well so far, but I've been having some trouble with adding a printer.
Here's the PowerShell script I was using to configure the network printer:
Add-PrinterPort -name ESDPRT500 -PrinterHostAddress $ReceiptPrinterIP
Set-Printer -Name "EPSON TM-T88IV Receipt" -PortName ESDPRT500
I've been looking at the following C# code, but it appears to only set a printer by TCP/IP port, whereas I believe my port is under "EPSON Port Handler"?
ManagementClass portClass = new ManagementClass("Win32_TCPIPPrinterPort");
ManagementObject portObject = portClass.CreateInstance();
portObject["Name"] = portName;
portObject["HostAddress"] = "174.30.164.15";
portObject["PortNumber"] = portNumber;
portObject["Protocol"] = 1;
portObject["SNMPCommunity"] = "public";
portObject["SNMPEnabled"] = true;
portObject["SNMPDevIndex"] = 1;
PutOptions options = new PutOptions();
options.Type = PutType.UpdateOrCreate;
portObject.Put(options);
Could anyone point me in the right direction given how my printer is configured? I've found examples for installing drivers and adding printers via TCP/IP port #s, but haven't had much luck with this. Thanks!

Automating Netcat file transfer from C# application - Windows & Raspberry Pi

I am trying to receive a file through Netcat from a Linux based server (Raspberry Pi).
On the sender side (Raspberry Pi) I run a small Python script, that just packs up some files and sends them into the pipeline. This works great, and has been tested a lot.
On the receiver side (Windows 8.1 Pro), I use Netcat to turn the incoming stream into a file. If I do this by hand in cmd.exe, it works great:
nc -l -p <port> > C:\file.gz
My file arrives as planned.
However when I try to automate this process on the receiver side with a C# script (.Net 4.5), the file simply doesn't arrive. My code looks like this:
public void StartListeningToNetcat()
{
Process ncProcess = new Process();
ncProcess.StartInfo.UseShellExecute = false;
ncProcess.StartInfo.CreateNoWindow = false;
ncProcess.StartInfo.RedirectStandardOutput = true;
ncProcess.StartInfo.RedirectStandardInput = true;
ncProcess.StartInfo.FileName = "cmd.exe";
ncProcess.StartInfo.Arguments = #"C:\...\nc -l -p <port> > C:\file.gz";
ncProcess.Start();
}
I am aware, that running nc through cmd.exe is a detour, but calling netcat directly like this:
ncProcess.StartInfo.FileName = "C:\...\nc.exe";
ncProcess.StartInfo.Arguments = #"-l -p <port> > C:\file.gz";
...returns the error: ">: forward host lookup failed: h_errno 11001: HOST_NOT_FOUND". Anyway, I wouldn't mind ignoring this error and going for the "inelegant" way to call cmd.exe.
Assuming that it could be a security measure by windows to not allow applications to write incoming files on my hard drive I tried turning of my firewall and using:
ncProcess.StartInfo.Verb = "runas";
with no success.
Could somebody point me in the right direction?
I was just able to resolve this issue myself:
Instead of executing "cmd.exe" with the arguments to run netcat, or calling Netcat itself, I create a batch file upfront, which I can later call in my C# script.
public void StartListenToNetcat()
{
string batchPath = CreateNetcatBatchFile();
Process.Start(batchPath);
}
public string CreateNetcatBatchFile()
{
Streamwriter w = new StreamWriter("C:\runNC.bat");
w.WriteLine("C:\...\nc -l -p 22 > C:\file.gz");
w.Close();
return "C:\runNC.bat";
}
Still I don't actually understand the necessity of this detour. Comments for clarifaction would be greatly appreciated.

Getting wrong serial-port names from bluetoothdevice (c#)

To get all avaliable Serialports from the system i use the following command.
SerialPort.GetPortNames
It works fine for the mainboard serial port, but with the bluetooth device i get the wrong portnames.
For Example: Instead of COM7 i get sometimes COM70 or COM7ö. Its always 1 letter to much.
any suggestens?
PS: I am using newest Visual Studio Express in Windows 7
PPS: The dirty hack to cut the last letter didn't work because i don't know which one is the bluetooth serial port (with various bluetoothstick or devices it changes the number of the comport) and after trying various sticks i reached COM10, ergo COM100 or COM10f
EDIT: the code i am using right now. reading the regestry, but still the same problem.
RegistryKey myRegistry = Registry.LocalMachine.OpenSubKey("Hardware\\DeviceMap\\SerialComm");
foreach (string valuename in myRegistry.GetValueNames())
{
if (myRegistry.GetValue(valuename) is String)
{
if (valuename.Contains("BthModem"))
{
richTextBox1.AppendText(">" + myRegistry.GetValue(valuename) + "<" + Environment.NewLine);
}
}
}
Normally the second or third request is working with a result like
COM11ᯋ<
COM10S<
COM11<
COM10<
COM11<
COM10<
how can that be?
This has been reported as a bug with non-null terminated strings:
Can you manually walk the registry?
HKLM\Hardware\DeviceMap\SerialComm
You can utilize WMI to query the system for serial ports, including those that are added by bluetooth devices and USB-To-Serial devices. Maybe that way you won't encounter this issue. See at CodeProject.
I have the same issue. SerialPort.GetPortNames basically uses the registry anyway- both of those methods don't seem to work with bluetooth.
The workaround I'm currently using is to loop through the first X com ports and see if they exist, which is hardly elegant. MS: FAIL.

Categories