Powershell script as a Topshelf/Windows service - c#

I'd like to get notified when a specific pattern occurs in some text file so I wrote a simple PowerShell script:
Get-Content 'C:\\testfile.txt' -Wait -Tail 50 | Select-String -Pattern 'Sample pattern'
I'd rather run it as a topshelf service. I've already produced the following code:
public class MyService
{
private string doWork;
public string Path
{
get
{
return #"C:\\testfile.txt";
}
}
public void Start()
{
while (this.doWork)
{
var script = $"Get-Content '{Path}' -Wait -Tail 50 | Select-String -Pattern 'Sample pattern'";
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript(script);
var PSOutput = PowerShellInstance.Invoke();
foreach (PSObject outputItem in PSOutput)
{
if (outputItem != null)
{
Console.WriteLine(outputItem.BaseObject + "\n");
}
}
if (PowerShellInstance.Streams.Error.Count > 0)
{
Console.Write.Write("Error");
}
}
}
}
public void Stop()
{
this.doWork = false;
}
}
public class Program
{
static void Main(string[] args)
{
var rc = HostFactory.Run(
x =>
{
x.Service<MyService>(
s =>
{
s.ConstructUsing(name => new MyService());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.StartAutomatically();
x.SetDescription("Sample Topshelf Host");
x.SetDisplayName("Sample display name");
x.SetServiceName("Sample service name");
});
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());
Environment.ExitCode = exitCode;
}
}
The solutions builds fine.I ran it in a debug mode, but for some reason I don't see the expected output on the console so I assume that there is some problem which I tried to figure out myself but without effect.
Is there any way to make this program working as expected? If anyone could provide some guidance or even proper solution I'd be grateful.

Related

How to get my account's balance using binance.net

Below codes purpose for get my balances using binance.net
but in console, just only "True" emitted.
How can I get my balance through c#?
namespace BinanceAPI
{
class Program
{
static async Task Main(string[] args)
{
BinanceClient.SetDefaultOptions(new BinanceClientOptions()
{
ApiCredentials = new ApiCredentials("my_API", "my_secret"),
});
using (var client = new BinanceClient())
{
var balanceData = await client.UsdFuturesApi.Account.GetBalancesAsync();
Console.WriteLine(balanceData);
}
}
}
}
Data is returned in balanceData.Data
Your code should look like this:
using (var client = new BinanceClient())
{
var balanceData = await client.UsdFuturesApi.Account.GetBalancesAsync();
if(!balanceData.Success){
Console.WriteLine(balanceData.Error.Message);
}
else
{
foreach(var asset in balanceData.Data)
{
Console.WriteLine(string.Format("Asset: {0} | Balance: {1}", asset.Asset, asset.AvailableBalance));
// more info available in obj asset, just pick the ones you need
}
}
}

How to get Start Parameters for the windows service created by using Topshelf

Hi i have created a windows service using topshelf dll. But i am unable to get start parameters.
My code :-
class Program
{
public static string filePath = "C:\\";
public static string outputXml = "C:\\Pranay";
static void Main(string[] args)
{
try
{
if (args.Length != 0 && !args[0].Equals("install", StringComparison.CurrentCultureIgnoreCase) && !args[0].Equals("uninstall", StringComparison.CurrentCultureIgnoreCase))
{
//filePath = args[2];
//outputXml = args[3];
}
XmlConfigurator.ConfigureAndWatch(
new FileInfo(".\\log4net.config"));
var host = HostFactory.New(x =>
{
x.EnableDashboard();
x.Service<XmlConverterService>(s =>
{
s.SetServiceName("XmlConverterService");
s.ConstructUsing(name => new XmlConverterService());
s.WhenStarted(tc =>
{
XmlConfigurator.ConfigureAndWatch(
new FileInfo(".\\log4net.config"));
tc.Start(args);
});
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetDescription("I have created this to service");
x.SetDisplayName("PranayXMLService");
x.SetServiceName("PranayXMLService");
});
host.Run();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadKey();
}
}
I have installed it and when i am trying to pass start argument as:-
sc start PranayXmlConverter C:\\ C:\\Pranay
nothing is being passed. To check what i am getting in args i have passed it in start(args) method and when i printed what is in args i got to know the output was as follows:
-displayname
PranayXMLService
-servicename:PranayXMLService
My question is how can i get start parameter and where?

Executing PowerShell Script with Parameters

I'm adapting this solution to a Windows Forms solution. So far I've been able to execute the Get-WUList command with no problems. But it doesn't seem to go well with the Hide-WUUpdate. This is what I've tried so far:
public class PowerShellController : IPowerShell
{
//Created at a global scope so anyone can fetch it.
InitialSessionState initial;
RunspaceInvoke scriptInvoker;
Runspace runspace;
PowerShell ps;
//The View to Control
IView view;
//The Helper GridViewProcessor class
IGridViewProcessor gp;
//Initializing the Controller - Loads the Module.
public PowerShellController()
{
initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { #"C:\Users\Jose\Documents\WindowsPowerShell\Modules\PSWindowsUpdate\PSWindowsUpdate.psd1" });
scriptInvoker = new RunspaceInvoke();
scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted -Scope Process");
runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
using (ps = PowerShell.Create())
{
ps.Runspace = runspace;
}
//Console.WriteLine("Please Wait. This will take a while to load.");
}
public void SetView(IView view, IGridViewProcessor gp)
{
this.view = view;
this.gp = gp;
}
public void GetAvailableUpdates()
{
MessageBox.Show("Ok. The program will kind of hang. This is normal." +
"This Means that it will start looking for updates "
);
IEnumerable<PSObject> WUList; //Placeholder for the PS Executed Command
using (ps = PowerShell.Create())
{
//Adds the PowerShell Command
ps.Commands.AddCommand("Get-WUList");
//Executes the PowerShell command
WUList = ps.Invoke();
}
//Loads the Model - Can be later on rewritten for Ninject Support.
List<WindowsUpdate> model = new List<WindowsUpdate>();
int id = 1;
foreach (PSObject result in WUList)
{
WindowsUpdate item = new WindowsUpdate
{
Id = id,
Name = result.Members["Title"].Value.ToString(),
Size = result.Members["Size"].Value.ToString(),
Type = UpdateType.Undefined,
};
model.Add(item);
id++; //Icnrease ID count
//Console.WriteLine("Update Name {0} --- Size: {1}", result.Members["Title"].Value.ToString(), result.Members["Size"].Value.ToString());
}
//Adds it to the view:
view.AddUpdateToGrid(model);
}
public void HideSelectedUpdates(DataGridView grid)
{
//Gets SelectedUpdates to the WindowsUpdate model
var SelectedUpdates = gp.GetSelectedUpdates(grid);
using (ps = PowerShell.Create())
{
foreach (var update in SelectedUpdates)
{
ps.Commands.Clear();
ps.Commands.AddCommand("Hide-WUUpdate").AddParameter("Title",update.Name).AddParameter("Confirm", false);
//ps.Commands.AddCommand("Hide-WUUpdate -Title \""+update.Name+"\"");
var result = ps.Invoke();
}
}
MessageBox.Show("Updates Have been hidden");
}
}
The method I can't seem to work is the HideSelectedUpdates(DataGridView grid).
Script gets executed and no exceptions are thrown, but it doesn't seem to reflect any changes at all.
Any suggestions?

How to kill the application that is using a TCP port in C#?

I want to free a TCP port during startup of my application (asking confirmation to user), how to get the PID number and then, if the user confirm, kill it?
I know I can get this information by netstat, but how to do it in a script or better in a C# method.
You can run netstat then redirect the output to a text stream so you can parse and get the info you want.
Here is what i did.
Run netstat -a -n -o as a Process
redirect the standard out put and capture the output text
capture the result, parse and return all the processes in use
check if the port is being used
find the process using linq
Run Process.Kill()
you will have to do the exception handling.
namespace test
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
Console.WriteLine("Port number you want to clear");
var input = Console.ReadLine();
//var port = int.Parse(input);
var prc = new ProcManager();
prc.KillByPort(7972); //prc.KillbyPort(port);
}
}
public class PRC
{
public int PID { get; set; }
public int Port { get; set; }
public string Protocol { get; set; }
}
public class ProcManager
{
public void KillByPort(int port)
{
var processes = GetAllProcesses();
if (processes.Any(p => p.Port == port))
try{
Process.GetProcessById(processes.First(p => p.Port == port).PID).Kill();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
else
{
Console.WriteLine("No process to kill!");
}
}
public List<PRC> GetAllProcesses()
{
var pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = "netstat.exe";
pStartInfo.Arguments = "-a -n -o";
pStartInfo.WindowStyle = ProcessWindowStyle.Maximized;
pStartInfo.UseShellExecute = false;
pStartInfo.RedirectStandardInput = true;
pStartInfo.RedirectStandardOutput = true;
pStartInfo.RedirectStandardError = true;
var process = new Process()
{
StartInfo = pStartInfo
};
process.Start();
var soStream = process.StandardOutput;
var output = soStream.ReadToEnd();
if(process.ExitCode != 0)
throw new Exception("somethign broke");
var result = new List<PRC>();
var lines = Regex.Split(output, "\r\n");
foreach (var line in lines)
{
if(line.Trim().StartsWith("Proto"))
continue;
var parts = line.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
var len = parts.Length;
if(len > 2)
result.Add(new PRC
{
Protocol = parts[0],
Port = int.Parse(parts[1].Split(':').Last()),
PID = int.Parse(parts[len - 1])
});
}
return result;
}
}
}

How to start Windows Azure Storage Emulator V3.0 from code

Since I installed the new Windows Azure SDK 2.3 I got a warning from csrun:
"DevStore interaction through CSRun has been depricated. Use WAStorageEmulator.exe instead."
So there are two questions:
1) How to start the new storage emulator correctly from code?
2) How to determine from code if the storage emulator is already running?
I found the solution myself. Here is my C# code. The old code used for SDK 2.2 is commented out.
public static void StartStorageEmulator()
{
//var count = Process.GetProcessesByName("DSServiceLDB").Length;
//if (count == 0)
// ExecuteCSRun("/devstore:start");
var count = Process.GetProcessesByName("WAStorageEmulator").Length;
if (count == 0)
ExecuteWAStorageEmulator("start");
}
/*
private static void ExecuteCSRun(string argument)
{
var start = new ProcessStartInfo
{
Arguments = argument,
FileName = #"c:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe"
};
var exitCode = ExecuteProcess(start);
Assert.AreEqual(exitCode, 0, "Error {0} executing {1} {2}", exitCode, start.FileName, start.Arguments);
}
*/
private static void ExecuteWAStorageEmulator(string argument)
{
var start = new ProcessStartInfo
{
Arguments = argument,
FileName = #"c:\Program Files (x86)\Microsoft SDKs\Windows Azure\Storage Emulator\WAStorageEmulator.exe"
};
var exitCode = ExecuteProcess(start);
Assert.AreEqual(exitCode, 0, "Error {0} executing {1} {2}", exitCode, start.FileName, start.Arguments);
}
private static int ExecuteProcess(ProcessStartInfo start)
{
int exitCode;
using (var proc = new Process { StartInfo = start })
{
proc.Start();
proc.WaitForExit();
exitCode = proc.ExitCode;
}
return exitCode;
}
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Xunit;
namespace UnitTests.Persistence
{
public class AzureStorageEmulatorManagerV3
{
private const string ProcessName = "WAStorageEmulator";
public static void StartStorageEmulator()
{
var count = Process.GetProcessesByName(ProcessName).Length;
if (count == 0)
ExecuteWAStorageEmulator("start");
}
public static void StopStorageEmulator()
{
Process process = GetWAstorageEmulatorProcess();
if (process != null)
{
process.Kill();
}
}
private static void ExecuteWAStorageEmulator(string argument)
{
var start = new ProcessStartInfo
{
Arguments = argument,
FileName = #"c:\Program Files (x86)\Microsoft SDKs\Windows Azure\Storage Emulator\WAStorageEmulator.exe"
};
var exitCode = ExecuteProcess(start);
if (exitCode != 0)
{
string message = string.Format(
"Error {0} executing {1} {2}",
exitCode,
start.FileName,
start.Arguments);
throw new InvalidOperationException(message);
}
}
private static int ExecuteProcess(ProcessStartInfo start)
{
int exitCode;
using (var proc = new Process { StartInfo = start })
{
proc.Start();
proc.WaitForExit();
exitCode = proc.ExitCode;
}
return exitCode;
}
public static Process GetWAstorageEmulatorProcess()
{
return Process.GetProcessesByName(ProcessName).FirstOrDefault();
}
[Fact]
public void StartingAndThenStoppingWAStorageEmulatorGoesOk()
{
// Arrange Start
AzureStorageEmulatorManagerV3.StartStorageEmulator();
// Act
Thread.Sleep(2000);
Process WAStorageEmulatorProcess = GetWAstorageEmulatorProcess();
// Assert
Assert.NotNull(WAStorageEmulatorProcess);
Assert.True(WAStorageEmulatorProcess.Responding);
// Arrange Stop
AzureStorageEmulatorManagerV3.StopStorageEmulator();
Thread.Sleep(2000);
// Act
WAStorageEmulatorProcess = GetWAstorageEmulatorProcess();
// Assert
Assert.Null(WAStorageEmulatorProcess);
}
}
}
See my answer here. It actually uses the WAStorageEmulator status API instead of simply relying on testing whether or not the process exists as in #huha's own answer.
See my answer here. It uses a neat little NuGet package to assist with starting/stopping the Azure Storage Emulator programmatically: RimDev.Automation.StorageEmulator.

Categories

Resources