Threading issue while printing pdf through c#.net code? - c#

I am trying to print pdf from windows application in my project with iTextSharp dll..
But,The methods I have used till now doesn't seems to be reliable.(Sometimes it work and sometime it doesn't)
I am combining the whole process in a Process class and writing the followin code.
printProcess = new Process[noOfCopies];
// Print number of copies specified in configuration file
for (int counter = 0; counter < noOfCopies; counter++)
{
printProcess[counter] = new Process();
// Set the process information
printProcess[counter].StartInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
Verb = "Print",
FileName = pdfFilePath,
ErrorDialog = false,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
};
// Start the printing process and wait for exit for 7 seconds
printProcess[counter].Start();
// printProcess[counter].WaitForInputIdle(waitTimeForPrintOut);
printProcess[counter].WaitForExit(waitTimeForPrintOut); //<--**This is line for discussion**
if (!printProcess[counter].HasExited)
{
printProcess[counter].Kill();
}
}
// Delete the file before showing any message for security reason
File.Delete(pdfFilePath);
The problem is that if,no pdf is open then the process works fine...(It prints well).But if any pdf is open then WaitForExit(..) method just doesn't waits for the process to exit..and hence the process runs too fast and as I am deleting the file after print it gives error if counter(no of times..) for printing report is more than once..
I have also used Timer to slow the process but it just doesn't works.I don't know why.
Used Sleep command too..but it makes main thread to go to sleep and hence doesn't suits me either.
Please suggest me some really reliable way to do so..:)

I do not know what kind of application you are trying to print from but a real easy way to print documents or pdfs is to simply copy the file to the printer queue and it will handle everything for you. Very reliable. Just have to have adobe reader installed on the machine printing and the correct driver for the printer. Example code:
var printer = PrinterHelper.GetAllPrinters().FirstOrDefault(p => p.Default);
PrinterHelper.SendFileToPrinter("C:\\Users\\Public\\Documents\\Form - Career Advancement Request.pdf", printer.Name);
Printer Helper code:
public static class PrinterHelper
{
public class PrinterSettings
{
public string Name { get; set; }
public string ServerName { get; set; }
public string DeviceId { get; set; }
public string ShareName { get; set; }
public string Comment { get; set; }
public bool Default { get; set; }
}
/// <summary>
/// Sends the file to printer.
/// </summary>
/// <param name="filePathAndName">Name of the file path and Name of File.</param>
/// <param name="printerName">Name of the printer with Path. E.I. \\PRINT2.company.net\P14401</param>
public static void SendFileToPrinter(string filePathAndName, string printerName)
{
FileInfo file = new FileInfo(filePathAndName);
file.CopyTo(printerName);
}
/// <summary>
/// Gets all printers that have drivers installed on the calling machine.
/// </summary>
/// <returns></returns>
public static List<PrinterSettings> GetAllPrinters()
{
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Printer");
ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
List<PrinterSettings> printers = new List<PrinterSettings>();
foreach (ManagementObject mo in mos.Get())
{
PrinterSettings printer = new PrinterSettings();
foreach (PropertyData property in mo.Properties)
{
if (property.Name == "Name")
printer.Name = property.Value == null ? "" : property.Value.ToString();
if (property.Name == "ServerName")
printer.ServerName = property.Value == null ? "" : property.Value.ToString();
if (property.Name == "DeviceId")
printer.DeviceId = property.Value == null ? "" : property.Value.ToString();
if (property.Name == "ShareName")
printer.ShareName = property.Value == null ? "" : property.Value.ToString();
if (property.Name == "Comment")
printer.Comment = property.Value == null ? "" : property.Value.ToString();
if (property.Name == "Default")
printer.Default = (bool)property.Value;
}
printers.Add(printer);
}
return printers;
}
}

Try this, you need .net 4 or above. And System.Threading.Tasks
printProcess = new Process[noOfCopies];
// Print number of copies specified in configuration file
Parallel.For(0, noOfCopies, i =>
{
printProcess[i] = new Process();
// Set the process information
printProcess[i].StartInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
Verb = "Print",
FileName = pdfFilePath,
ErrorDialog = false,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
};
// Start the printing process and wait for exit for 7 seconds
printProcess[i].Start();
// printProcess[counter].WaitForInputIdle(waitTimeForPrintOut);
printProcess[counter].WaitForExit(waitTimeForPrintOut); //<--**This is line for discussion**
if(!printProcess[i].HasExited)
{
printProcess[i].Kill();
}
});
// Delete the file before showing any message for security reason
File.Delete(pdfFilePath);

Related

No console output during call WSL/WSL2 command in Powershell from C#

I have Pengwin (Linux distro optimalized for working with WSL - surely everybody know) with installed github-linguist, set up by tutorial in https://github.com/github/linguist/blob/master/README.md . Even I have use my Insider Windows instance, change version WSL for upcoming 2, but everything keep like before.
In Pengwin and Powershell cmd is everything OK:
wsl bash -c "github-linguist '/mnt/d/Documents/Visual Studio 2017/Projects/LearnCss/LearnCss/Program.cs'"
But by calling in C# is output empty (any other commmand like dir works):
static PowershellBuilder builder = new PowershellBuilder();
/// <summary>
/// Tested, working
/// For every command return at least one entry in result
/// </summary>
/// <param name="commands"></param>
/// <returns></returns>
public async static Task<List< List<string>>> InvokeAsync(IEnumerable<string> commands)
{
List<List<string>> returnList = new List<List<string>>();
PowerShell ps = null;
// After leaving using is closed pipeline, must watch for complete or
using (ps = PowerShell.Create())
{
foreach (var item in commands)
{
ps.AddScript(item);
var async = ps.BeginInvoke();
// Return for SleepWithRandomOutputConsole zero outputs
var psObjects = ps.EndInvoke(async);
returnList.Add(ProcessPSObjects(psObjects));
}
}
return returnList;
}
/// <summary>
/// Tested, working
/// For every command return at least one entry in result
/// </summary>
/// <param name="commands"></param>
/// <returns></returns>
public static List<List<string>> Invoke(IEnumerable<string> commands)
{
var result = InvokeAsync(commands);
result.Wait();
return result.Result;
}
private static List<string> ProcessPSObjects(ICollection<PSObject> pso)
{
List<string> output = new List<string>();
foreach (var item in pso)
{
if (item != null)
{
output.Add(item.ToString());
}
}
return output;
}
public static List<string> InvokeSingle(string command)
{
return Invoke(CA.ToListString(command))[0];
}
But with calling with Process.Start all works like a charm:
/// <summary>
/// If in A1 will be full path specified = 'The system cannot find the file specified'
/// A1 if dont contains extension, append exe
/// </summary>
/// <param name="exeFileNameWithoutPath"></param>
/// <param name="arguments"></param>
/// <returns></returns>
public static List<string> InvokeProcess(string exeFileNameWithoutPath, string arguments)
{
FS.AddExtensionIfDontHave(exeFileNameWithoutPath, AllExtensions.exe);
//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
// Must contains only filename, not full path
pProcess.StartInfo.FileName = exeFileNameWithoutPath;
//strCommandParameters are parameters to pass to program
pProcess.StartInfo.Arguments = arguments;
pProcess.StartInfo.UseShellExecute = false;
//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = true;
//Optional, recommended do not enter, then old value is not deleted and both paths is combined
//pProcess.StartInfo.WorkingDirectory = ;
//Start the process
pProcess.Start();
W32.EnableWow64FSRedirection(true);
//Get program output
string strOutput = pProcess.StandardOutput.ReadToEnd();
//Wait for process to finish
pProcess.WaitForExit();
var result = SH.GetLines(strOutput);
return result;
}
Calling code:
const string lang = "language:";
public static string DetectLanguageForFileGithubLinguist(string windowsPath)
{
string command = null;
string arguments = null;
// With WSL or WSL 2 not working. In both cases Powershell returns right values but in c# everything empty. Asked on StackOverflow
StringBuilder linuxPath = new StringBuilder();
linuxPath.Append("/mnt/");
linuxPath.Append(windowsPath[0].ToString().ToLower());
var parts = SH.Split(windowsPath, AllStrings.bs);
for (int i = 1; i < parts.Count; i++)
{
linuxPath.Append("/" + parts[i]);
}
command = "wsl";
arguments = " bash -c \"github-linguist '" + linuxPath + "'\"";
W32.EnableWow64FSRedirection(false);
// empty
var pc = PowershellRunner.InvokeSingle("cmd /c bash -c 'ruby -v'");
// empty
var pc2 = PowershellRunner.InvokeSingle("wsl bash -c whoami");
// with content
var pc3 = PowershellRunner.InvokeSingle("dir");
//command = #"c:\Windows\System32\wsl.exe";
//arguments = " -- github-linguist \"/mnt/d/Documents/Visual Studio 2017/Projects/LearnCss/LearnCss/Program.cs\"";
// empty
var pc4 = PowershellRunner.InvokeSingle(command + arguments);
PowershellRunner.InvokeProcess(command + ".exe", arguments);
var lines = PowershellRunner.InvokeSingle(command);
var line = CA.ReturnWhichContains(lines, lang).FirstOrNull();
if (line == null)
{
return null;
}
var result = line.ToString().Replace(lang, string.Empty).Trim();
return result;
}
Why calling with PowerShell class is not working?

Printers visible to exe not visible to web app?

Solved - thanks to Steve. The problem was that the App Pool I used was using the default App Pool Identity, which doesn't have sufficient privileges. Changing to an App Pool that used an account with sufficient privileges fixed the problem.
I have a simple C# class to get a list of available printers. When called from within a simple Console app, it returns the complete list of locally defined printers (9 printers). When called from the code behind in an aspx web app, it only returns the default printer. The web app is installed and runs as a user that is a local administrator on the server, and all printers are defined within that user's profile.
Note - I remote desktop to the server and run the console exe app there and it shows all the printers. I am trying to get a list of all the printers defined on the server.
Is there some security issue that I am missing?
Class code:
using System.Management;
/// <summary>
/// Returns a list of printers available on the current system.
/// </summary>
public static class PrinterList
{
public class Printer
{
public string name { get; set; }
public string server { get; set; }
public string location { get; set; }
public string portname { get; set; }
public string sharename { get; set; }
}
public static Printer[] GetInstalledPrinterList()
{
Printer[] printers = new Printer[0];
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * from Win32_Printer");
ManagementObjectCollection coll = searcher.Get();
foreach (ManagementObject printer in coll)
{
string name = printer.GetPropertyValue("Name").ToString();
if ((!name.ToLower().Contains("send to onenote")) &&
(!name.ToLower().Contains("xps document writer")) &&
(!name.ToLower().Contains("print to pdf")) &&
(!name.ToLower().Contains(" fax")) &&
(!name.ToLower().Equals("fax")))
{
string server = "";
if (printer.GetPropertyValue("ServerName") != null)
server = printer.GetPropertyValue("ServerName").ToString();
string location = "";
if (printer.GetPropertyValue("Location") != null)
location = printer.GetPropertyValue("Location").ToString();
string portname = "";
if (printer.GetPropertyValue("PortName") != null)
portname = printer.GetPropertyValue("PortName").ToString();
string sharename = "";
if (printer.GetPropertyValue("ShareName") != null)
sharename = printer.GetPropertyValue("ShareName").ToString();
Printer newPrinter = new Printer();
newPrinter.name = name;
newPrinter.server = server;
newPrinter.location = location;
newPrinter.portname = portname;
newPrinter.sharename = sharename;
Printer[] newlist = new Printer[printers.Length + 1];
for (int i = 0;i < printers.Length; i++)
{
newlist[i] = printers[i];
}
newlist[printers.Length] = newPrinter;
printers = newlist;
}
}
return printers;
}
}
Your asp.net c# code runs on your server not on client's computer. This is really important fact to remember.
By calling get printers on asp.net you are basically getting the available printers connected to your server not the ones from client.
Edit: Turns out that you were using the default account for the app pool. By using an account with admin right for the app pool solves the problem.

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;
}
}
}

Google Drive. Refresh authorization token while a file is uploading

What is the way to refresh authorization token while a large file is uploading to Google Drive?
For example: expiration time of the current authorization token is "06:00 AM". The file uploading started at "05:15 AM". So at "06:00 AM" the application get exception due authorization token is invalid.
I've tried to around the issue with the below source code, but it does not work.
/// <summary>
/// Uploads a file with a specified path.
/// </summary>
/// <param name="startFolder">The start folder.</param>
/// <param name="path">The path of destination file.</param>
/// <param name="localFile">The local file to upload.</param>
/// <returns>The uploaded file.</returns>
private File GdUploadFile(File startFolder, string path, FileInfo localFile)
{
if (startFolder == null)
{
throw new ArgumentNullException("startFolder");
}
if (localFile == null)
{
throw new ArgumentNullException("localFile");
}
if (!localFile.Exists)
{
throw new FileNotFoundException("File not found", localFile.FullName);
}
var config = GetConfiguration();
if (config.TraceLog)
{
Destination.Logger.LogDebug(string.Format("{0} \tUpload file \"{1}\" to \"{2}\"", Destination.Name, localFile.FullName, path));
}
string pathToFile = string.IsNullOrEmpty(path) ? localFile.Name : path;
string remotePath = ExtractFilePath(pathToFile);
var fileFolder = GdCreateFolderByPath(startFolder, remotePath);
var fileName = ExtractFileName(pathToFile);
DriveService service = GetDriveService();
var body = new File
{
Title = fileName,
Description = "My File",
MimeType = BackupFileMimeType,
Kind = DriveFileKindType,
OriginalFilename = fileName,
FileExtension = localFile.Extension,
Parents = new List<ParentReference>
{
new ParentReference
{
ETag = fileFolder.ETag,
Id = fileFolder.Id,
Kind = fileFolder.Kind
}
}
};
FilesResource.InsertMediaUpload request;
var source = new MediaFileSource(localFile.FullName, BackupFileMimeType);
using (var fileStream = source.GetDataStream())
{
if (config.TraceLog)
{
Destination.Logger.LogDebug(string.Format("{0} \tUploading \"{1}\"...", Destination.Name, localFile.FullName));
}
request = service.Files.Insert(body, fileStream, body.MimeType);
if (config.TraceLog)
{
int postedPercent = 0;
request.ProgressChanged += p =>
{
var currentPercent = (int) (p.BytesSent/(double) source.ContentLength*100);
if (currentPercent != postedPercent)
{
string msg = string.Format("{0} \tPosted {1}% ({2} bytes)", Destination.Name,
currentPercent, p.BytesSent);
Destination.Logger.LogDebug(msg);
postedPercent = currentPercent;
}
};
}
var connection = Destination.Connection as GoogleDriveDestinationConnection;
Debug.Assert(connection != null, "connection != null");
request.ProgressChanged += p =>
{
bool refreshAuth = connection.ForceRefreshAuthorization();
var auth =
request.Authenticator as
Google.Apis.Authentication.OAuth2.OAuth2Authenticator<NativeApplicationClient>;
if (auth != null && auth.State != null && refreshAuth)
{
var state = connection.AuthorizationState;
auth.State.AccessToken = state.AccessToken;
auth.State.AccessTokenExpirationUtc = state.AccessTokenExpirationUtc;
auth.State.AccessTokenIssueDateUtc = state.AccessTokenIssueDateUtc;
auth.State.Callback = state.Callback;
auth.State.RefreshToken = state.RefreshToken;
auth.State.SaveChanges();
if (config.TraceLog)
{
Destination.Logger.LogDebug("Authorization state for the upload request is updated");
}
}
};
request.ChunkSize = ChunkSize;
request.Upload();
if (config.TraceLog)
{
Destination.Logger.LogDebug(string.Format("{0} \t\"{1}\" uploaded", Destination.Name, localFile.FullName));
}
}
return request.ResponseBody;
}
Consider doing Resumable upload (https://developers.google.com/drive/manage-uploads#resumable). Refresh the token when needed and continue the upload where you left off.
I was not able to find a satisfactory solution to the problem of invalid authorization token.
So I have created my own open source lightweight library for working with files on Google Drive. The library invokes all REST functions directly and have full control over uploading or downloading processes. It resolves the problem by refreshing the authorization token every hour. The library is currently in use in thousands of installations of my company’s Sql Server backup product, it is very stable and has successfully resolved this problem. You can take the source code and examples from here: https://github.com/AlexeyVlg/Pranas.Net.Clouds

How to return JSON to browser from model class using SignalR and URL call to Web API?

Here's what's going on. I have an ASP.NET MVC 4 Web API web application. I can call API resources via URL. One of these functions get performance monitoring data for a specified amount of time and returns it in JSON once it has completed. However, what I want to do is return
It is IMPORTANT to note that I am working with a the browser and API resources in the model, not with a View. Please don't casually tell me to use Javascript in a View, because there is no view, or tell me to look at the SignalR wiki because the information for ".NET" sections is meant for desktop applications, not web apps. For example, you can't "Console.WriteLine()" to a browser.
To reiterate, I am using ASP.NET MVC 4 Web API to develop an API, and am calling the API via URL in the browser and it is returning JSON. I am attempting to use SignalR to have the app send JSON to the browser, but it is not doing anything at all. Rather, the application simply returns the completed JSON from the controller action with all of the performance data values once the process has completed. In other words, SignalR is not working.
So what I'm trying to do is while the API resource is gathering all the information, SignalR sends JSON to the browser every second so that the client can see what's going on in real time.
What I need to find out is why SignalR isn't sending it, and how I can send information to be displayed in the browser without Javascript, since I'm working from a model class, not from a view.
As you can see, I subscribe to the event using On, and then use Invoke to call the server-side hub method SendToClient.
Please let me know if I'm trying to do is impossible. I have never heard of a "real-time", dynamic API call via URL.
Here is my hub class. It is located in ~/signalr/hubs and is in a file called LiveHub.cs. The method Send is what I am trying to invoke in the method seen in the next code block.
namespace PerfMon2.signalr.hubs
{
public class LiveHub : Hub
{
public void SendToClient(List<DataValueInfo> json)
{
Clients.showValue(json);
}
}
}
Here is the method from LogDBRepository.cs that includes the SignalR calls.
public List<LogInfo> LogTimedPerfData(string macName, string categoryName, string counterName,
string instanceName, string logName, string live, long? seconds)
{
iModsDBRepository modsDB = new iModsDBRepository();
List<MachineInfo> theMac = modsDB.GetMachineByName(macName);
if (theMac.Count == 0)
return new List<LogInfo>();
else if (instanceName == null)
{
if (!PerformanceCounterCategory.Exists(categoryName, macName) ||
!PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) )
{
return new List<LogInfo>();
}
}
else if (instanceName != null)
{
if (!PerformanceCounterCategory.Exists(categoryName, macName) ||
!PerformanceCounterCategory.CounterExists(counterName, categoryName, macName) ||
!PerformanceCounterCategory.InstanceExists(instanceName, categoryName, macName))
{
return new List<LogInfo>();
}
}
else if (logName == null)
{
return new List<LogInfo>();
}
// Check if entered log name is a duplicate for the authenticated user
List<LogInfo> checkDuplicateLog = this.GetSingleLog(logName);
if (checkDuplicateLog.Count > 0)
{
return new List<LogInfo>();
}
PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName, theMac[0].MachineName);
if (category.CategoryName == null || category.MachineName == null)
{
return new List<LogInfo>();
}
List<LogInfo> logIt = new List<LogInfo>();
if (category.CategoryType != PerformanceCounterCategoryType.SingleInstance)
{
List<InstanceInfo> instances = modsDB.GetInstancesFromCatMacName(theMac[0].MachineName, category.CategoryName);
foreach (InstanceInfo inst in instances)
{
if (!category.InstanceExists(inst.InstanceName))
{
continue;
}
else if (inst.InstanceName.Equals(instanceName, StringComparison.OrdinalIgnoreCase))
{
PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName,
inst.InstanceName, theMac[0].MachineName);
//CounterSample data = perfCounter.NextSample();
//double value = CounterSample.Calculate(data, perfCounter.NextSample());
string data = "";
List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name);
string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
//string[] dataValues = new string[(int)seconds];
List<string> dataValues = new List<string>();
var hubConnection = new HubConnection("http://localhost/PerfMon2/");
hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
var perfMon = hubConnection.CreateProxy("LiveHub");
// perfMon.On("sendValue", message => Console.WriteLine(message));
perfMon.On("showValue", json => Console.WriteLine(json));
hubConnection.Start().Wait();
List<DataValueInfo> lol = new List<DataValueInfo>();
for (int i = 0; i < seconds; i++)
{
data = "Value " + i + ": " + perfCounter.NextValue().ToString();
//dataValues[i] = data;
dataValues.Add(data);
lol.Add(new DataValueInfo
{
Value = perfCounter.NextValue().ToString()
});
// perfMon.Invoke<List<DataValueInfo>>("Send", lol);
perfMon.Invoke("SendToClient", lol);
Thread.Sleep(1000);
}
string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
Log log = new Log
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = string.Join(",", dataValues),
UserID = currUser[0].UserID
};
this.CreateLog(log);
logIt.Add(new LogInfo
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = dataValues.ToList<string>()
});
break;
}
}
}
else
{
PerformanceCounter perfCounter = new PerformanceCounter(categoryName, counterName,
"", theMac[0].MachineName);
string data = "";
List<UserInfo> currUser = this.GetUserByName(WindowsIdentity.GetCurrent().Name);
string timeStarted = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
//string[] dataValues = new string[(int)seconds];
List<string> dataValues = new List<string>();
var hubConnection = new HubConnection("http://localhost/PerfMon2/");
hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
var perfMon = hubConnection.CreateProxy("LiveHub");
// perfMon.On("sendValue", message => Console.WriteLine(message));
perfMon.On("showValue", json => Console.WriteLine(json));
hubConnection.Start().Wait();
List<DataValueInfo> lol = new List<DataValueInfo>();
for (int i = 0; i < seconds; i++)
{
data = "Value " + i + ": " + perfCounter.NextValue().ToString();
//dataValues[i] = data;
dataValues.Add(data);
lol.Add(new DataValueInfo
{
Value = perfCounter.NextValue().ToString()
});
// perfMon.Invoke<List<DataValueInfo>>("Send", lol);
perfMon.Invoke("SendToClient", lol);
Thread.Sleep(1000);
}
string timeFinished = DateTime.Now.ToString("MM/dd/yyyy - h:mm:ss tt");
Log log = new Log
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = string.Join(",", dataValues),
UserID = currUser[0].UserID
};
this.CreateLog(log);
logIt.Add(new LogInfo
{
LogName = logName,
CounterName = perfCounter.CounterName,
InstanceName = perfCounter.InstanceName,
CategoryName = perfCounter.CategoryName,
MachineName = perfCounter.MachineName,
TimeStarted = timeStarted,
TimeFinished = timeFinished,
PerformanceData = dataValues.ToList<string>()
});
}
return logIt;
}
Here is the controller for the method in LogController.cs :
[AcceptVerbs("GET", "POST")]
public List<LogInfo> Log_Perf_Data(string machine_name, string category_name, string counter_name, string instance_name,
string log_name, long? seconds, string live, string enforceQuery)
{
LogController.CheckUser();
// POST api/log/post_data?machine_name=&category_name=&counter_name=&instance_name=&log_name=&seconds=
if (machine_name != null && category_name != null && counter_name != null && log_name != null && seconds.HasValue && enforceQuery == null)
{
List<LogInfo> dataVal = logDB.LogTimedPerfData(machine_name, category_name, counter_name, instance_name,
log_name, live, seconds);
logDB.SaveChanges();
return dataVal;
}
return new List<LogInfo>();
}
Maybe you can implement it in push technique. Here is how I do it:
Class with message
public class Message
{
/// <summary>
/// The name who will receive this message.
/// </summary>
public string RecipientName { get; set; }
/// <summary>
/// The message content.
/// </summary>
public string MessageContent { get; set; }
}
Class that will represent client:
public class Client
{
private ManualResetEvent messageEvent = new ManualResetEvent(false);
private Queue<Message> messageQueue = new Queue<Message>();
/// <summary>
/// This method is called by a sender to send a message to this client.
/// </summary>
/// <param name="message">the new message</param>
public void EnqueueMessage(Message message)
{
lock (messageQueue)
{
messageQueue.Enqueue(message);
// Set a new message event.
messageEvent.Set();
}
}
/// <summary>
/// This method is called by the client to receive messages from the message queue.
/// If no message, it will wait until a new message is inserted.
/// </summary>
/// <returns>the unread message</returns>
public Message DequeueMessage()
{
// Wait until a new message.
messageEvent.WaitOne();
lock (messageQueue)
{
if (messageQueue.Count == 1)
{
messageEvent.Reset();
}
return messageQueue.Dequeue();
}
}
}
Class to send messages to clients:
public class ClientAdapter
{
/// <summary>
/// The recipient list.
/// </summary>
private Dictionary<string, Client> recipients = new Dictionary<string,Client>();
/// <summary>
/// Send a message to a particular recipient.
/// </summary>
public void SendMessage(Message message)
{
if (recipients.ContainsKey(message.RecipientName))
{
Client client = recipients[message.RecipientName];
client.EnqueueMessage(message);
}
}
/// <summary>
/// Called by a individual recipient to wait and receive a message.
/// </summary>
/// <returns>The message content</returns>
public string GetMessage(string userName)
{
string messageContent = string.Empty;
if (recipients.ContainsKey(userName))
{
Client client = recipients[userName];
messageContent = client.DequeueMessage().MessageContent;
}
return messageContent;
}
/// <summary>
/// Join a user to the recipient list.
/// </summary>
public void Join(string userName)
{
recipients[userName] = new Client();
}
/// <summary>
/// Singleton pattern.
/// This pattern will ensure there is only one instance of this class in the system.
/// </summary>
public static ClientAdapter Instance = new ClientAdapter();
private ClientAdapter() { }
}
Sending messages:
Message message = new Message
{
RecipientName = tbRecipientName.Text.Trim(),
MessageContent = tbMessageContent.Text.Trim()
};
if (!string.IsNullOrWhiteSpace(message.RecipientName) && !string.IsNullOrEmpty(message.MessageContent))
{
// Call the client adapter to send the message to the particular recipient instantly.
ClientAdapter.Instance.SendMessage(message);
}
Receive messages (this is JavaScript functions written in test page. They render content of the message on ASPX page. Here you should implement your logic):
// This method will persist a http request and wait for messages.
function waitEvent() {
CSASPNETReverseAJAX.Dispatcher.WaitMessage("<%= Session["userName"] %>",
function (result) {
displayMessage(result);
// Keep looping.
setTimeout(waitEvent, 0);
}, function () {
// Keep looping.
setTimeout(waitEvent, 0);
});
}
// Append a message content to the result panel.
function displayMessage(message) {
var panel = document.getElementById("<%= lbMessages.ClientID %>");
panel.innerHTML += currentTime() + ": " + message + "<br />";
}
// Return a current time string.
function currentTime() {
var currentDate = new Date();
return currentDate.getHours() + ":" + currentDate.getMinutes() + ":" + currentDate.getSeconds();
}

Categories

Resources