Passing an argument from .NET MVC APP into .NET Console APP - c#

I have an MVC app in which I have integrated a .net console app. Now I want to pass a value that is returned from a method in MVC Model and pass it as an argument in the console app MAIN method.
I want that the "hexString" that is being returned from "PinBlock" function is passed as an argument in the Main Method in the console application.
**MVC Model Function**
public string PinBlock()
{
// PAN Code without first 3 characters and last character
string str1 = Convert.ToString(PAN).Remove(0, 3);
string str2 = str1.Remove(str1.Length - 1, 1);
// Adding 4 0s at the start of the remaining PAN Number
int count = 4;
char someChar = '0';
string AlgoA = str2.PadLeft(count + str2.Length, someChar);
Console.WriteLine("ALgoA: " + AlgoA);
//Finding the length of the pin code and adding it to the pin code wth 10 'F's
string PinLength = Convert.ToString(APIN);
PinLength = PinLength.ToString();
string result = String.Format("{0,2:X2}", PinLength.Length);
string AlgoB = result + APIN + "FFFFFFFFFF";
Console.WriteLine("ALgoB: " + AlgoB);
long dec1 = Convert.ToInt64(AlgoA, 16);
long dec2 = Convert.ToInt64(AlgoB, 16);
long res = dec1 ^ dec2;
string hexResult = res.ToString("X");
PIN = hexResult;
return hexResult;
}
**MVC Function that attaches Console app with the MVC app**
public string Onclick(string hexResult)
{
using (var process = new Process())
{
process.StartInfo.FileName = #"..\ABL-ESB-DCA\bin\Debug\net6.0\encrypt\ConsoleApp1.exe"; // relative path. absolute path works too.
process.StartInfo.Arguments = hexResult;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += (sender, data) =>
{
Console.WriteLine(data.Data);
};
process.ErrorDataReceived += (sender, data) => Console.WriteLine(data.Data);
Console.WriteLine("starting");
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var exited = process.WaitForExit(1000 * 10); // (optional) wait up to 10 seconds
Console.WriteLine($"exit {exited}");
}
// ProcessInfo.Start(#"C:\Users\Talha\Desktop\New folder\linkedin\server.exe");
return "BUTTON ONCLICK";
}
**Console app**
internal class Program
{
static void Main(string[] args)
{
ClassLibrary1.Class1 class1 = new ClassLibrary1.Class1(); ;
class1.Perform();
}

In the console app we just need to output the first argument as:
Console.WriteLine(arg[0]);
static void Main(string[] args)
{
foreach(string arg in args)
{
Console.WriteLine(arg[0]);
}
ClassLibrary1.Class1 class1 = new ClassLibrary1.Class1(); ;
class1.Perform();

Related

find numbers and save to string

I am trying to make a ui that gets the session id of a computer on the network. I want to take this session id and save it to a string to be used later.
private void button1_Click(object sender, EventArgs e)
{
string ComputerName = ComputerNameBox.Text;
string Username = UserNameBox.Text;
Process Process = new Process();
Process.StartInfo.FileName = "CMD.exe";
Process.StartInfo.Arguments = "/K" + "qwinsta /server:" + ComputerName + " " + Username;
Process.StartInfo.CreateNoWindow = true;
Process.StartInfo.UseShellExecute = false;
Process.StartInfo.RedirectStandardOutput = true;
Process.Start();
Process.OutputDataReceived += new DataReceivedEventHandler(SortOutputHandler);
Process.BeginOutputReadLine();
while (!Process.HasExited)
{
Application.DoEvents();
}
}
private void SortOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (MessagePop.InvokeRequired)
{
MessagePop.BeginInvoke(new DataReceivedEventHandler(SortOutputHandler), new[] { sendingProcess, outLine });
}
else
{
MessagePop.AppendText(Environment.NewLine + outLine.Data);
}
}
This code runs and inputs the computername and username of the computer/person you want the session ID for. The username and ID will likely be different every time so I can't hard code it.
SESSIONNAME USERNAME ID STATE TYPE DEVICE
console mlynch 9 Active
This is the output I get in the textbox, I want to get the 9 and save it to a string, however, the number can be something like 10 or higher so I will need to be able to get both numbers. How do I do this?
Please try this:
var textBoxData =
"SESSIONNAME USERNAME ID STATE TYPE DEVICE\r\nconsole mlynch 9 Active";
var stringCollection = textBoxData.Split(new[] { Environment.NewLine, " " }, StringSplitOptions.RemoveEmptyEntries);
var finalCollection = new List<int>();
foreach (var s1 in stringCollection)
{
int n;
if (int.TryParse(s1, out n))
{
finalCollection.Add(n);
}
}
(or) create a function which takes in text box data and return int colleciton:
public List<int> GetData(string textBoxData)
{
var stringCollection = textBoxData.Split(new[] { Environment.NewLine, " " }, StringSplitOptions.RemoveEmptyEntries);
var finalCollection = new List<int>();
foreach (var s1 in stringCollection)
{
int n;
if (int.TryParse(s1, out n))
{
finalCollection.Add(n);
}
}
}
and then use it as
var intCollection = GetData(textBox1.Text);
I get in trouble for linking to my open source project UltimateHelper, but just pretend Word is a string.
public static List<Word> GetWords(string sourceText, char[] delimiters = null)
{
// initial value
List<Word> words = new List<Word>();
// typical delimiter characters
char[] delimiterChars = { ' ', '-', '/', ',', '.', ':', '\t' };
// if the delimiters exists
if (delimiters != null)
{
// use the delimiters passedin
delimiterChars = delimiters;
}
// verify the sourceText exists
if (!String.IsNullOrEmpty(sourceText))
{
// Get the list of strings
string[] strings = sourceText.Split(delimiterChars);
// now iterate the strings
foreach (string stringWord in strings)
{
// verify the word is not an empty string or a space
if (!String.IsNullOrEmpty(stringWord))
{
// Create a new Word
Word word = new Word(stringWord);
// now add this word to words collection
words.Add(word);
}
}
}
// return value
return words;
}
I have this in a class called WordParser, so to call it:
Edit: If you need to parse each line, there is also a method:
List<TextLine> textLines = WordParser.GetTextLines(text);
In your case, you want to parse on just space, so set Delimiters to this:
char[] delimiterChars = { ' ' };
List<Word> words = WordParser.GetWords(text, delimiterChars);
// Here is the full example using DataJuggler.Core.UltimateHelper Nuget package
if ((ListHelper.HasOneOrMoreItems(words)) && (words.Count >= 3))
{
Word idWord = Words[2];
int idValue = NumericHelper.ParseInteger(idWord.Text, 0, -1);
}
idValue will be the Id if it parses, 0 if it can't be parsed, and -1 if an error occurs trying to parse it.
I hope I didn't offend anyone by not posting all the classes used, but if it does I will post the full class for each, but kind of overkill to demonstrate a 3 line of code solution.
Hope it helps.
The full code is here:
https://github.com/DataJuggler/UltimateHelper/tree/master/UltimateHelper
And Word Parser:
https://github.com/DataJuggler/UltimateHelper/blob/master/UltimateHelper/WordParser.cs
Word class:
https://github.com/DataJuggler/UltimateHelper/blob/master/UltimateHelper/Objects/Word.cs
List Helper:
https://github.com/DataJuggler/UltimateHelper/blob/master/UltimateHelper/ListHelper.cs
And Numeric Helper:
https://github.com/DataJuggler/UltimateHelper/blob/master/UltimateHelper/NumericHelper.cs
I figured out how to do what I needed.
Process GetSessionID = new Process();
GetSessionID.StartInfo.FileName = "CMD.exe";
GetSessionID.StartInfo.Arguments = "/C" + "for /f \"skip=1 tokens=3\" %1 in ('query user " + Username + "/server:" + ComputerName + "') do #echo %1";
GetSessionID.StartInfo.RedirectStandardOutput = true;
GetSessionID.StartInfo.UseShellExecute = false;
GetSessionID.StartInfo.CreateNoWindow = true;
GetSessionID.Start();
SessionIDOutput = GetSessionID.StandardOutput.ReadToEnd();
GetSessionID.WaitForExit();
DoAllTheThingsTextBox.Text = SessionIDOutput;
if (GetSessionID.HasExited == true)
{
var digitArray = DoAllTheThingsTextBox.Text.Where(Char.IsDigit).ToArray();
SessionID = new String(digitArray);
if (MouseControlCheck.Checked == true)
{
Process Process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/C" + "mstsc /shadow:" + SessionID + " /v " + ComputerName + " /control");
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
Process = Process.Start(startInfo);
}
else
{
Process Process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo("CMD.exe", "/C" + "mstsc /shadow:" + SessionID + " /v " + ComputerName);
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
Process = Process.Start(startInfo);
}
}

c# - How to asynchronously stream output from ffmpeg

I created a method to call ffmpeg binaries and do stuff for me. It worked perfectly fine on a standard console application. I am trying to make a Windows Form Application version but there are few problems. The app freezes (but the progress bar is still updating) when the ffmpeg process is still running. The textboxes are not being updated. I cannot move the app window. I suspect this is because of the loop and I googled some stuff and found out that I might need to do this asynchronously but how do I do that exactly.
public void ffmpeg(string ffmpeg_exe, string args)
{
Process p = new Process();
p.StartInfo.FileName = ffmpeg_exe;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;
p.Start();
StreamReader reader = p.StandardError;
string line;
string size = "", current_duration = "", duration = "";
while ((line = reader.ReadLine()) != null)
{
if (!string.IsNullOrEmpty(line))
{
if (line.Contains("Duration") && line.Contains("bitrate") && line.Contains("start"))
{
duration = RemoveWhitespace(Between(line, "Duration:", ", start"));
totaltime.Text = duration;
}
if (line.Contains("frame=") && line.Contains("size=") && line.Contains("time="))
{
size = RemoveWhitespace(Between(line, "size=", " time"));
current_duration = RemoveWhitespace(Between(line, "time=", " bitrate"));
progressBar_main.Value = Convert.ToInt32(Math.Round(TimeSpan.Parse(current_duration.Substring(0, current_duration.Length -3)).TotalSeconds * 100 / TimeSpan.Parse(duration.Substring(0,duration.Length-3)).TotalSeconds, 3));
current_time.Text = current_duration;
filesize.Text = size;
}
}
}
p.Close();
current_time.Text = "";
filesize.Text = "";
totaltime.Text = "";
progressBar_main.Value = 0;
}
Try using Task like this :
Action action = () =>
{
//Do your streaming here
};
Then start it :
Task t2 = Task.Factory.StartNew(action);
Hope this was useful.

C# Get Session Processes Without Showing CMD Prompt

Current attempt at WTSEnumerateProcesses:
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern Int32 WTSEnumerateProcesses(
IntPtr serverHandle, // Handle to a terminal server.
Int32 reserved, // must be 0
Int32 version, // must be 1
ref IntPtr ppProcessInfo, // pointer to array of WTS_PROCESS_INFO
ref Int32 pCount // pointer to number of processes
);
public struct WTS_PROCESS_INFO
{
public int SessionID;
public int ProcessID;
// This is spointer to a string...
public IntPtr ProcessName;
public IntPtr userSid;
}
public static void ListProcs(String ServerName)
{
IntPtr serverHandle = IntPtr.Zero;
List<string> resultList = new List<string>();
serverHandle = OpenServer(ServerName);
IntPtr ProcessInfoPtr = IntPtr.Zero;
Int32 processCount = 0;
Int32 retVal = WTSEnumerateProcesses(serverHandle, 0, 1, ref ProcessInfoPtr, ref processCount);
Int32 dataSize = Marshal.SizeOf(typeof(WTS_PROCESS_INFO));
Int32 currentProcess = (int)ProcessInfoPtr;
uint bytes = 0;
if (retVal != 0)
{
WTS_PROCESS_INFO pi = (WTS_PROCESS_INFO)Marshal.PtrToStructure((System.IntPtr)currentProcess, typeof(WTS_PROCESS_INFO));
currentProcess += dataSize;
for (int i = 0; i < processCount; i++)
{
MessageBox.Show(pi.ProcessID.ToString());
}
WTSFreeMemory(ProcessInfoPtr);
}
}
I am obviously missing something pretty crucial here, as my listProcs method just returns the same ID over and over again. I need to read up on C APIs and work out what WTSEnumeratEProcesses is actually doing, and how I can query these processes.
Possible solution example code (top answer)
I am creating a self-help IT app for my organisation, where users have the ability to log off their own session as well as display all active processes and select one to terminate.
Users have no problem logging off, but I am having an issue when enumerating processes. Due to the fact that I am using a log in name and password to query active processes, the CMD window is displayed briefly every time this occurs. I can't find any solution to this in the documentation, and was hoping someone could point me in the right direction.
The code is below:
using System.Drawing;
using System;
using System.ComponentModel;
using System.Security;
using System.Diagnostics;
using System.DirectoryServices;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ITHelp
{
class funcs
{
///////////////////////////////////////////////////// GET SERVERS
public static List<string> get_Servers()
{
// Get servers using AD directory searcher
List<string> serverList = new List<string>();
DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
string domainContext = rootDSE.Properties["defaultNamingContext"].Value as string;
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://OU=XA76-2012,OU=Servers,OU=XenApp,dc=MYDOMAINNAME1,dc=co,dc=uk");
using (DirectorySearcher searcher = new DirectorySearcher(
searchRoot,
"(&(objectClass=computer)(!(cn=*MASTER*)))",
new string[] { "cn" },
SearchScope.Subtree))
{
foreach (SearchResult result in searcher.FindAll())
{
foreach (string server in result.Properties["cn"])
{
serverList.Add(server);
}
}
}
return serverList;
}
///////////////////////////////////////////////////// GET SESSION
public static string[] get_Session(List<string> servers, string name)
{
string[] sessionDetails = new string[3];
// Iterate through serverList to find the correct connection - then add this to the sessionDetails array
string current = "";
for (int i = 0; i < servers.Count; i++)
{
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/c QUERY SESSION " + name + " /SERVER:" + servers[i] + ".MYDOMAINNAME1.co.uk ")
{
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
Process getsess = Process.Start(startInfo);
getsess.OutputDataReceived += (x, y) => current += y.Data;
getsess.BeginOutputReadLine();
getsess.WaitForExit();
if (current.Length != 0)
{
// Session ID
// Better to use this as an identifer than session name, as this is always available
sessionDetails[0] = current.Substring(119, 4);
// Server Name
sessionDetails[1] = servers[i] + ".MYDOMAINNAME1.co.uk";
// Session Name (ica-)
// This is only available if the session is not disconnected
//sessionDetails[2] = current.Substring(76, 11);
// Removed this as it is not used - BUT COULD BE HELPFUL FOR CHECKING SESSION EXISTENCE/DETAILS
break;
}
}
return sessionDetails;
}
///////////////////////////////////////////////////// GET PROCESSES
public static Dictionary<string, string> getProc(string server, string sessID)
{
var ss = new SecureString();
ss.AppendChar('M');
ss.AppendChar('y');
ss.AppendChar('p');
ss.AppendChar('a');
ss.AppendChar('s');
ss.AppendChar('s');
ss.AppendChar('w');
ss.AppendChar('o');
ss.AppendChar('r');
ss.AppendChar('d');
ss.MakeReadOnly();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C tasklist /S " + server + " /FI \"SESSION eq " + sessID + "\" /FO CSV /NH")
{
WindowStyle = ProcessWindowStyle.Minimized,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
WorkingDirectory = #"C:\windows\system32",
Verb = "runas",
Domain = "MYDOMAINNAME1",
UserName = "XATest",
Password = ss
};
List<string> procList = new List<string>();
Process proc = Process.Start(startInfo);
proc.OutputDataReceived += (x, y) => procList.Add(y.Data);
proc.BeginOutputReadLine();
proc.WaitForExit();
// Create a new ditionary ...
Dictionary<string, string> procDict = new Dictionary<string, string>();
for (int i = 0; i < procList.Count - 1; i++)
{
if (procDict.ContainsKey(procList[i].Split(',')[0].Trim('"')))
{
// Do nothing
}
else
{
procDict.Add(procList[i].Split(',')[0].Trim('"'), procList[i].Split(',')[1].Trim('"'));
}
}
return procDict;
}
///////////////////////////////////////////////////// RESET SESSION
public static void reset_Session(string sessID, string servName, string name)
{
// Ensure the sesion exists
if (sessID != null)
{
// Log session off
logoff_Session(sessID, servName);
// While isLoggedIn returns true, wait 1 second (checks 50 times)
for (int i = 0; i < 50; i++)
{
if (isLoggedIn(name, servName) == true)
{
System.Threading.Thread.Sleep(1000);
}
else
{
break;
}
}
// Wait here to prevent starting a session while still logged in
System.Threading.Thread.Sleep(3000);
}
// Finally, start the session (Outlook)
start_Session(name);
}
///////////////////////////////////////////////////// LOGOFF SESSION
public static void logoff_Session(string sessID, string servName)
{
Process logoff = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C LOGOFF " + sessID + " /SERVER:" + servName;
logoff.StartInfo = startInfo;
logoff.Start();
}
///////////////////////////////////////////////////// START SESSION
public static void start_Session(string name)
{
// Start Outlook
Process.Start("C:\\Users\\" + name + "\\AppData\\Roaming\\Citrix\\SelfService\\Test_Outlook2013.exe");
}
///////////////////////////////////////////////////// IS LOGGED IN
private static bool isLoggedIn(string name, string server)
{
string current = " ";
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/c QUERY SESSION " + name + " /SERVER:" + server)
{
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
Process logcheck = Process.Start(startInfo);
logcheck.OutputDataReceived += (x, y) => current += y.Data;
logcheck.BeginOutputReadLine();
logcheck.WaitForExit();
if (current.Contains(userName()))
{
return true;
}
else
{
return false;
}
}
///////////////////////////////////////////////////// USERNAME
public static string userName()
{
// Get userName
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
userName = userName.Remove(0, 8);
return userName;
}
///////////////////////////////////////////////////// KILL PROCESS
public static void killProc(string server, string procid)
{
var ss = new SecureString();
ss.AppendChar('M');
ss.AppendChar('y');
ss.AppendChar('p');
ss.AppendChar('a');
ss.AppendChar('s');
ss.AppendChar('s');
ss.AppendChar('w');
ss.AppendChar('o');
ss.AppendChar('r');
ss.AppendChar('d');
ss.MakeReadOnly();
ProcessStartInfo startInfo = new ProcessStartInfo("cmd", "/C taskkill /S " + server + " /PID " + procid + " /F")
{
WorkingDirectory = #"C:\windows\system32",
Verb = "runas",
Domain = "MYDOMAINNAME1",
UserName = "XATest",
Password = ss,
WindowStyle = ProcessWindowStyle.Minimized,
UseShellExecute = false,
CreateNoWindow = true
};
Process proc = Process.Start(startInfo);
proc.WaitForExit();
}
///////////////////////////////////////////////////// KILL BUSYLIGHT
public static void killBL()
{
foreach (KeyValuePair<string, string> entry in Program.proclist)
{
if (entry.Key == "Busylight.exe")
{
killProc(Program.servName, entry.Value);
System.Threading.Thread.Sleep(3000);
Process.Start("C:\\Users\\" + Program.name + "\\AppData\\Roaming\\Citrix\\SelfService\\Test_Busylight.exe");
return;
}
// Start BUSYLIGHT - the above method should close the application instantly
}
}
///////////////////////////////////////////////////// KILL LYNC
public static void killLync()
{
foreach (KeyValuePair<string, string> entry in Program.proclist)
{
if (entry.Key == "lync.exe")
{
killProc(Program.servName, entry.Value);
Process.Start("C:\\Users\\" + Program.name + "\\AppData\\Roaming\\Citrix\\SelfService\\Test_SkypeforBusiness.exe");
System.Threading.Thread.Sleep(3000); /////////////////////////////////////////////////////////
return;
}
}
}
///////////////////////////////////////////////////// CHECK RUNNING
public static bool checkRunning(string procName)
{
var ss = new SecureString();
ss.AppendChar('M');
ss.AppendChar('y');
ss.AppendChar('p');
ss.AppendChar('a');
ss.AppendChar('s');
ss.AppendChar('s');
ss.AppendChar('w');
ss.AppendChar('o');
ss.AppendChar('r');
ss.AppendChar('d');
ss.MakeReadOnly();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C tasklist /S " + Program.servName + " /FI \"SESSION eq " + Program.sessID + "\" /FO CSV /NH";
startInfo.WorkingDirectory = #"C:\windows\system32";
startInfo.Verb = "runas";
startInfo.Domain = "MYDOMAINNAME1";
startInfo.UserName = "XATest";
startInfo.Password = ss;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.CreateNoWindow = true;
string strCheck = " ";
Process proc = Process.Start(startInfo);
proc.OutputDataReceived += (x, y) => strCheck += y.Data;
proc.BeginOutputReadLine();
proc.WaitForExit();
if (strCheck.Contains(procName))
{
return true;
}
else
{
return false;
}
}
}
}
Any suggestions or feedback on this much appreciated!
Many thanks
The Remote Desktop Services APIs can certainly do all the things you want. However I'm not sure whether non-admin users are allowed to manipulate their own sessions on other machines.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa383464%28v=vs.85%29.aspx
WTSOpenServer to get a handle to a particular server.
WTSEnumerateProcesses to get a list of processes.
WTSEnumerateSessions to get a list of sessions.
WTSLogoffSession to logoff a specific session.
WTSTerminateProcess to kill a specific process.
Here's some example code using the APIs to enumerate sessions. This is using the constant WTS_CURRENT_SESSION to open the current server, but you can use WTSOpenServer to talk to some other remote server. This is code I hacked out of a live app so it won't compile as-is.
If you program C# long enough you will come across APIs that just don't exist in C# and you have to pinvoke the C versions of the API. I suggest you have a look at http://pinvoke.net if you want help learning how to pinvoke C APIs.
public const int WTS_CURRENT_SESSION = -1;
[StructLayout(LayoutKind.Sequential)]
public struct WTS_SESSION_INFO
{
public Int32 SessionID;
public IntPtr pWinStationName;
public WTS_CONNECTSTATE_CLASS State;
}
[DllImport("wtsapi32.dll")]
public static extern bool WTSEnumerateSessions(
IntPtr hServer,
Int32 Reserved,
Int32 Version,
ref IntPtr ppSessionInfo,
ref Int32 pCount);
[DllImport("wtsapi32.dll")]
public static extern void WTSFreeMemory(IntPtr pMemory);
IntPtr pSessions = IntPtr.Zero;
int count = 0;
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, ref pSessions, ref count))
{
unsafe
{
WTS_SESSION_INFO* pHead = (WTS_SESSION_INFO*)pSessions.ToPointer();
for (int i = 0; i < count; ++i)
{
WTS_SESSION_INFO* pCurrent = (pHead + i);
var session = new Session(pCurrent->SessionID, pCurrent->State);
_activeSessions[pCurrent->SessionID] = session;
session.Id, session.IsConnected, session.IsLoggedOn, session.User.UserName);
}
}
WTSFreeMemory(pSessions);
}
From MSDN site on ProcessStartInfo.CreateNoWindow Property :
Remarks
If the UseShellExecute property is true or the UserName and Password
properties are not null, the CreateNoWindow property value is ignored
and a new window is created.
There is no workaround or resolution mentioned, and I have been unable to find one anywhere.
I have had to resort to me application briefly displaying CMD windows when running certain processes (The CreateNoWindow property works when not using UserName and Password).
Found another solution to this.
As Donovan mentioned, this can be done using WTSEnumerateProcesses.
However, if someone wanted to list remote processes (for a specific session) without marshalling c++ methods, you could also use qprocess:
qprocess /id:10 /server:servername
This lists all processes running on that session.
For more details see here

Running two exe files in one c# project

I'm trying to write a program which executes 2 different .exe files and outputs their results to a text file. When I execute them separately, they work fine, but when I try to execute them both, the second process doesn't run. Can anyone help?
Here is the code. Player1.exe and Player2.exe are console applications returning 0 or 1.
static void Main(string[] args)
{
Process process1 = new Process();
process1.StartInfo.FileName = "C:/Programming/Tournament/Player1.exe";
process1.StartInfo.Arguments = "";
process1.StartInfo.UseShellExecute = false;
process1.StartInfo.RedirectStandardOutput = true;
process1.Start();
var result1 = process1.StandardOutput.ReadToEnd();
process1.Close();
Process process2 = new Process();
process2.StartInfo.FileName = "C:/Programming/Tournament/Player2.exe";
process2.StartInfo.Arguments = "";
process2.StartInfo.UseShellExecute = false;
process2.StartInfo.RedirectStandardOutput = true;
process2.Start();
string result2 = process2.StandardOutput.ReadToEnd().ToString();
process2.Close();
string resultsPath = "C:/Programming/Tournament/Results/Player1vsPlayer2.txt";
if (!File.Exists(resultsPath))
{
StreamWriter sw = File.CreateText(resultsPath);
sw.WriteLine("Player1 " + "Player2");
sw.WriteLine(result1 + " " + result2);
sw.Flush();
}
}
1.
you wrote in a comment: "The program doesn't even reach to process2. I tested that by putting a breakpoint."
process1.Start() may be throwing an exception. Rather than setting a breakpoint at process2, step through the lines and find the exception. Or better yet, add a try/catch block and report an error.
2.
Another possibility is that ReadToEnd is not behaving as expected. You can Peek and see if there is more data to read by looping like this:
var result1 = new StringBuilder()
while (process1.StandardOutput.Peek() > -1)
{
result1.Append(process1.StandardOutput.ReadLine());
}
3.
If these processes don't immediately provide data and end, then you need to get them both started before you begin waiting on their StandardOutput. Call Start() on each process before doing the reads.
I don't know too much about using process, but I use this approach when I need separate things to run at once. I didn't pull in the bottom portion of your project, but check this out to see if it helps in any way.
class Program
{
static void Main(string[] args)
{
Process process1 = new Process();
process1.StartInfo.FileName = "C:/Programming/Tournament/Player1.exe";
process1.StartInfo.Arguments = "";
process1.StartInfo.UseShellExecute = false;
process1.StartInfo.RedirectStandardOutput = true;
Process process2 = new Process();
process2.StartInfo.FileName = "C:/Programming/Tournament/Player2.exe";
process2.StartInfo.Arguments = "";
process2.StartInfo.UseShellExecute = false;
process2.StartInfo.RedirectStandardOutput = true;
Thread T1 = new Thread(delegate() {
doProcess(process1);
});
Thread T2 = new Thread(delegate() {
doProcess(process2);
});
T1.Start();
T2.Start();
}
public static void doProcess(Process myProcess)
{
myProcess.Start();
var result1 = myProcess.StandardOutput.ReadToEnd();
myProcess.Close();
}
}

command line output validation in c#

My output in the actual command prompt looks like this:
Name: My Software
Version: 1.0.1
Installed location: c:\my folder
I am trying to get this output via c# code
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/c " + "my command to execute");
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
string[] lines = result.Split(new string[] { System.Environment.NewLine, }, System.StringSplitOptions.None);
foreach (string tmp in lines)
{
if (tmp.Contains("Version"))
{
isAvailable= true;
}
}
I don't want to just check a version tag, I am trying to get the version value and do a compare, for example if the value is 1.0.1, i would want that value and do a comparison with 2.0.0.
I can use indexof(like result.IndexOf("Version:");) - But that doesn't get me the value of the version
Any thoughts will be helpful.
You should use the .NET Version class and it's CompareTo(Object) method to do your comparison.
var input = new Regex(#"(?<=Version:)\s*(.*)").Matches(#"Name: My Software
Version: 1.0.1
Installed location: c:\my folder")[0].Value.Trim();
var a = new Version(input);
var b = new Version("2.0.0");
int comparison = a.CompareTo(b);
if(comparison > 0)
{
Console.WriteLine(a + " is a greater version.");
}
else if(comparison == 0)
{
Console.WriteLine(a + " and " + b +" are the same version.");
}
else
{
Console.WriteLine(b + " is a greater version.");
}
Try like below... it will help you...
Instead of Contains check the word by using IndexOf...
if (tmp.IndexOf("Version") != -1)
{
isAvailable = true;
string[] info = tmp.Split(':');
string version = info[1].Trim();
Console.WriteLine(version);
}
string versionText;
var stuff = tmp.Split(":");
if(stuff[0].Trim() == "Version")
{
isAvailable = true;
versionText = stuff[1].Trim();
}
if(versionText == expectedVersionText) // Do something specfic.
You might want to use Regular Expressions:
^Version:\s*(.*)$
should match the version number inside the parentheses.
string sought = "Version:";
foreach (string tmp in lines)
{
if (tmp.Contains(sought))
{
int position = tmp.IndexOf(sought) + sought.Length;
string version = tmp.Substring(tmp.IndexOf(sought) + sought.Length);
string[] versionParts = version.Split('.');
VersionCompare(versionParts, new string[]{"2", "0", "0"});
}
}
/// <summary>Returns 0 if the two versions are equal, else a negative number if the first is smaller, or a positive value if the first is larder and the second is smaller.</summary>
private int VersionCompare(string[] left, string[] right)
{
for(int i = 0; i < Math.Min(left.Length, right.Length); ++i)
{
int leftValue = int.Parse(left[i]), rightValue = int.Parse(right[i]);
if(leftValue != rightValue) return leftValue - rightValue;
}
return left.Length - right.Length;
}

Categories

Resources