In my project with six laser particle counters, when I send the commands, always return extraneous characters. And sometimes the string received in the form this incomplete. Below is a snippet of code: Who know fix this?
/// <summary>
/// Class to keep track of string and color for lines in output window.
/// </summary>
private class Line
{
public string Str;
public Color ForeColor;
public Line(string str, Color color)
{
Str = str;
ForeColor = color;
}
}
ArrayList lines = new ArrayList();
Font origFont;
Font monoFont;
public Form1()
{
InitializeComponent();
outputList_Initialize();
Settings.Read();
TopMost = Settings.Option.StayOnTop;
CommPort com = CommPort.Instance;
com.StatusChanged += OnStatusChanged;
com.DataReceived += OnDataReceived;
com.Open();
}
#region Event handling - data received and status changed
/// <summary>
/// Prepare a string for output by converting non-printable characters.
/// </summary>
/// <param name="StringIn">input string to prepare.</param>
/// <returns>output string.</returns>
private String PrepareData(String StringIn)
{
// The names of the first 32 characters
string[] charNames = {
// "NUL", "SOH", "STX", "ETX", "EOT",
//"ENQ", "ACK", "BEL", "BS", "TAB", "LF", "VT", "FF", "CR", "SO", "SI",
//"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB",
//"ESC", "FS", "GS", "RS", "US", "Space"
};
string StringOut = "";
foreach (char c in StringIn)
{
if (Settings.Option.HexOutput)
{
StringOut = StringOut + String.Format("{0:X2} ", (int)c);
}
else if (c < 32 && c != 9)
{
StringOut = StringOut + "";// +"<"+charNames[c]+">";
//Uglier "Termite" style
//StringOut = StringOut + String.Format("[{0:X2}]", (int)c);
}
else
{
StringOut = StringOut + c;
}
}
return StringOut;
}
/// <summary>
/// Partial line for AddData().
/// </summary>
private Line partialLine = null;
/// <summary>
/// Add data to the output.
/// </summary>
/// <param name="StringIn"></param>
/// <returns></returns>
private Line AddData(String StringIn)
{
String StringOut = PrepareData(StringIn);
// if we have a partial line, add to it.
if (partialLine != null)
{
// tack it on
partialLine.Str = partialLine.Str + StringOut;
outputList_Update(partialLine);
return partialLine;
}
return outputList_Add(StringOut, receivedColor);
}
// delegate used for Invoke
internal delegate void StringDelegate(string data);
/// <summary>
/// Handle data received event from serial port.
/// </summary>
/// <param name="data">incoming data</param>
public void OnDataReceived(string dataIn)
{
//Handle multi-threading
if (InvokeRequired)
{
Invoke(new StringDelegate(OnDataReceived), new object[] { dataIn });
return;
}
// pause scrolling to speed up output of multiple lines
bool saveScrolling = scrolling;
scrolling = false;
// if we detect a line terminator, add line to output
int index;
while (dataIn.Length > 0 &&
((index = dataIn.IndexOf("\r")) != -1 ||
(index = dataIn.IndexOf("\n")) != -1))
{
String StringIn = dataIn.Substring(0, index);
dataIn = dataIn.Remove(0, index + 1);
logFile_writeLine(AddData(StringIn).Str);
logFile_writeLine1(AddData(StringIn).Str);
partialLine = null; // terminate partial line
}
// if we have data remaining, add a partial line
if (dataIn.Length > 0)
{
partialLine = AddData(dataIn);
}
// restore scrolling
scrolling = saveScrolling;
outputList_Scroll();
listBox1_Scroll();
}
/// <summary>
/// Update the connection status
/// </summary>
public void OnStatusChanged(string status)
{
//Handle multi-threading
if (InvokeRequired)
{
Invoke(new StringDelegate(OnStatusChanged), new object[] { status });
return;
}
textBox1.Text = status;
}
#endregion
Could it be bit (or byte) stuffing ?
Related
Creating an application to read excel (.xls) file.
I am able to read the file but it is showing only count of data.
But not able to get the data from file.
Microsoft.Office.Interop.Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"C:\Landingfolder\file.xls");
Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
//new line
if (j == 1)
Console.Write("\r\n");
//write the value to the console
if (xlRange.Cells[i, j] != null && xlRange.Cells[i, j].Value2 != null)
Console.Write(xlRange.Cells[i, j].Value2.ToString() + "\t");
Console.ReadLine();
}
}
Please let me know the right process.
Use this Code
using System.Data.OleDb;
using System.IO;
using System.Data;
public class Employee
{
public string Name { get; set; }
public string Designation { get; set; }
public int? Experience { get; set; }
}
/// <summary>
/// Open Connection
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private OleDbConnection OpenConnection(string path)
{
OleDbConnectio n oledbConn = null;
try
{
if (Path.GetExtension(path) == ".xls")
oledbConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + path +
"; Extended Properties= \"Excel 8.0;HDR=Yes;IMEX=2\"");
else if (Path.GetExtension(path) == ".xlsx")
oledbConn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" +
path + "; Extended Properties='Excel 12.0;HDR=YES;IMEX=1;';");
oledbConn.Open();
}
catch (Exception ex)
{
//Error
}
return oledbConn;
}
/// <summary>
/// Extract 'Service Information' sheet
/// </summary>
/// <param name="oledbConn"></param>
private IList<Employee> ExtractEmployeeExcel(OleDbConnection oledbConn)
{
OleDbCommand cmd = new OleDbCommand (); ;
OleDbDataAdapter oleda = new OleDbDataAdapter();
DataSet dsEmployeeInfo = new DataSet ();
cmd.Connection = oledbConn;
cmd.CommandT ype = CommandType.Text;
cmd.CommandT ext = "SELECT * FROM [Employee$]"; //Excel Sheet Name ( Employee )
oleda = new OleDbDataAdapter(cmd);
oleda.Fill (dsEmployeeInfo, "Employee");
var dsEm ployeeInfoList = dsEmployeeInfo.Tables[0].AsEnumerable().Select (s => new Employee
{
Name = Convert.ToString(s["Name"] ! = DBNull.Value ? s["Name"] : ""),
Designation = Convert.ToString(s["Designation"] ! = DBNull.Value ? s["Designation"] : ""),
Experience = Convert.ToInt32(s["Experience"])
}).ToList ();
return dsEmployeeInfoList;
}
/// <summary>
/// Read excel sheet with the user path
/// </summary>
/// <param name="path"></param>
public IList<Employee> ReadExcel(string path)
{
IList<Employ ee> objEmployeeInfo = new List<Employee>();
try
{
OleDbConnection oledbConn = OpenConnection(path);
if (oledbConn.State == ConnectionState.Open)
{
objEmployeeInfo = ExtractEmployeeExcel (oledbConn);
oledbConn.Close();
}
}
catch (Exception ex)
{
// Error
}
return objEmployeeInfo;
}
Use of Code:
Here calling the ReadExcel() method to get the excel content.
string path = #"D:\Employee.xls";
IList<Employee> objExcelCon = ReadExcel(path);
I am new to threading and I have currently used Tasks to perform multi threading. As you can see in the code, one set of tasks perform a series of extraction from an Excel and the Task.WaitAll() is working as expected.
But for the second set of tasks, the Task.WaitAll() is not working as expected. The control is going directly to the next method outside the task pool instead of waiting for the tasks to complete.
I am using the first set of tasks to extract from an Excel and the next set of tasks to store the values in objects.
Thanks in advance.
//MainClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication2
{
/// <summary>
/// class to call the methods to extract values and assign values using multithreading
/// </summary>
public class MainClass : ExtractValues
{
public static int size;
static void Main(string[] args)
{
ExtractValues objectOfExtractValues = new ExtractValues();
Values objectOfValues = new Values();
size = objectOfExtractValues.initialize();
List<int> Range = new List<int>();
Range = objectOfExtractValues.cellRangeFinder();
//creating a new task to call methods to extract details from the excel to run parallelly
Task[] task = new Task[6];
{
task[0] = Task.Factory.StartNew(() => objectOfExtractValues.thread1(Range[0]));
task[1] = Task.Factory.StartNew(() => objectOfExtractValues.thread2(Range[0], Range[1]));
task[2] = Task.Factory.StartNew(() => objectOfExtractValues.thread3(Range[2], Range[3]));
task[3] = Task.Factory.StartNew(() => objectOfExtractValues.thread4(Range[4], Range[5]));
task[4] = Task.Factory.StartNew(() => objectOfExtractValues.thread5(Range[6], Range[7]));
task[5] = Task.Factory.StartNew(() => objectOfExtractValues.thread6(Range[8], Range[9]));
}
Task.WaitAll(task);
objectOfValues.init();
Task tasknew1 = Task.Factory.StartNew(() => objectOfValues.assignValues1());
Task tasknew2 = Task.Factory.StartNew(() => objectOfValues.assignValues2());
Task tasknew3 = Task.Factory.StartNew(() => objectOfValues.assignValues3());
Task tasknew4 = Task.Factory.StartNew(() => objectOfValues.assignValues4());
Task tasknew5 = Task.Factory.StartNew(() => objectOfValues.assignValues5());
Task tasknew6 = Task.Factory.StartNew(() => objectOfValues.assignValues6());
Task tasknew7 = Task.Factory.StartNew(() => objectOfValues.assignValues7());
Task.WaitAll(tasknew1, tasknew2, tasknew3, tasknew4, tasknew5, tasknew6, tasknew7);
//Task.WhenAll();
//Task.WaitAll();
//calling method to initialize the object array
// creating another task to call methods to assign details stored in the list to objects parallelly
objectOfExtractValues.endProcess();
// wait
Console.ReadLine();
objectOfValues.show();
}
}
}
** ExtractValue.cs**
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Excel = Microsoft.Office.Interop.Excel;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Threading;
namespace ConsoleApplication2
{
/// <summary>
/// class containing methods to extract values from the excel
/// </summary>
public class ExtractValues
{
public int rowCount;
public int colCount;
//lists to store values from different sections of the excel
public static List<int> rangeList = new List<int>();
public static List<string> tempList = new List<string>();
public static List<string> tempList2 = new List<string>();
public static List<string> tempList3 = new List<string>();
public static List<string> tempList4 = new List<string>();
public static List<string> tempList5 = new List<string>();
public static List<string> tempList6 = new List<string>();
public static List<string> tempList7 = new List<string>();
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
Excel.Application xlApp;
Excel.Workbook xlWorkbook;
Excel._Worksheet xlWorksheet;
Excel.Range xlRange;
int start, end;
/// <summary>
/// method to initaialize the excel and get the column and row count
/// </summary>
public int initialize()
{
var dir = System.IO.Path.GetDirectoryName(path);
string location = dir + "\\some.xlsx";
xlApp = new Excel.Application();
xlWorkbook = xlApp.Workbooks.Open(location);
xlWorksheet = xlWorkbook.Sheets[1];
xlRange = xlWorksheet.UsedRange;
rowCount = xlWorksheet.UsedRange.Rows.Count;
colCount = xlWorksheet.Columns.CurrentRegion.EntireColumn.Count;
return colCount;
}
/// <summary>
/// method to read from the excel file and print it. method reads the rows until the count passed to it.
/// </summary>
/// <param name="count"></param>
public void thread1(int count)
{
for (int i = 2; i <colCount; i++)
{
for (int j = 1; j < count; j++)
{
if (xlRange.Cells[j, i].Value == null && xlRange.Cells[j + 1, i].Value != null)
{
tempList.Add(" ");
}
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null )
tempList.Add(xlRange.Cells[j, i].Value.ToString());
}
}
// for loop to read the cardpan row
for (int i = 2; i <= colCount; i++)
{
for (int j = 12; j <= 12; j++)
{
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null)
tempList7.Add(xlRange.Cells[j, i].Value.ToString());
}
}
}
/// <summary>
/// method to read from the excel file and print it. method reads the rows from and until the count passed to it.
/// </summary>
public void thread2(int count1, int count2)
{
for (int i = 2; i <= colCount; i++)
{
for (int j = count1; j <=count2; j++)
{
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null)
tempList2.Add(xlRange.Cells[j, i].Value.ToString());
}
}
}
/// <summary>
/// method to read from the excel file and print it. method reads the rows from and until the count passed to it.
/// </summary>
/// <param name="count1"></param>
/// <param name="count2"></param>
public void thread3(int count1, int count2)
{
for (int i = 2; i <= colCount; i++)
{
for (int j = count1; j <= count2; j++)
{
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null)
tempList3.Add(xlRange.Cells[j, i].Value.ToString());
}
}
}
/// <summary>
/// method to read from the excel file and print it. method reads the rows from and until the count passed to it.
/// </summary>
/// <param name="count1"></param>
/// <param name="count2"></param>
public void thread4(int count1, int count2)
{
for (int i = 2; i <= colCount; i++)
{
for (int j = count1; j <= count2; j++)
{
if (xlRange.Cells[j, i].Value == null && xlRange.Cells[j + 1, i].Value == null)
{
tempList4.Add(" ");
break;
}
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null)
tempList4.Add(xlRange.Cells[j, i].Value.ToString());
}
}
}
/// <summary>
/// method to read from the excel file and print it. Method reads the rows from and until the count passed to it.
/// </summary>
/// <param name="count1"></param>
/// <param name="count2"></param>
public void thread5(int count1, int count2)
{
for (int i = 2; i <= colCount; i++)
{
for (int j = count1; j <= count2; j++)
{
if (xlRange.Cells[j, i].Value == null && xlRange.Cells[j + 1, i].Value == null)
{
tempList5.Add(" ");
break;
}
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null)
tempList5.Add(xlRange.Cells[j, i].Value.ToString());
//add useful things here!
}
}
}
/// <summary>
/// method to read from the excel file and print it. method reads the rows from and till the count passed to it.
/// </summary>
/// <param name="count1"></param>
/// <param name="count2"></param>
public void thread6(int count1, int count2)
{
for (int i = 2; i <= colCount; i++)
{
for (int j = count1; j <= count2; j++)
{
if (xlRange.Cells[j, i].Value == null && xlRange.Cells[j + 1, i].Value == null)
{
tempList6.Add(" ");
break;
}
if (xlRange.Cells[j, i] != null && xlRange.Cells[j, i].Value != null)
tempList6.Add(xlRange.Cells[j, i].Value.ToString());
}
}
}
/// <summary>
/// method to end the excel file operations
/// </summary>
public void endProcess()
{
xlWorkbook.Close();
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlWorksheet);
//close and release
Marshal.ReleaseComObject(xlWorkbook);
//quit and release
xlApp.Quit();
Marshal.ReleaseComObject(xlApp);
}
/// <summary>
/// method to find the merged cells in the excel and store their starting and ending cell values in a list
/// </summary>
/// <returns></returns>
public List<int> cellRangeFinder()
{
for (int i = 1; i <= rowCount; i++)
{
for (int k = 1; k <=1 ; k++)
{
if (xlRange.Cells[i, k] != null && xlRange.Cells[i+1, k].Value == null)
{
start = i;
int tempCounter = i + 1;
while(xlRange.Cells[tempCounter, k].Value == null && (tempCounter<=rowCount+3))
{
tempCounter++;
}
end = tempCounter-1;
rangeList.Add(start);
rangeList.Add(end);
i = tempCounter-1;
}
}
}
return rangeList;
}
}
}
Values.cs
enter code here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
/// <summary>
/// Class to store the values in the objects
/// </summary>
public class Values : MainClass
{
// Variables to store the values of each object
public int ID { get; set; }
public string tType { get; set; }
public string cType { get; set; }
public string tName { get; set; }
public string SNumber { get; set; }
public string title { get; set; }
public string objective { get; set; }
public string reference { get; set; }
public string prerequisite { get; set; }
public string procedure { get; set; }
public string cPan { get; set; }
public string amount { get; set; }
public string pHost { get; set; }
public string pCard { get; set; }
public string cSlip { get; set; }
// Declaring the Values' class object array
Values[] list;
/// <summary>
/// method to set the size of the array object
/// </summary>
public void init()
{
list= new Values[size];
}
/// <summary>
/// Method to assign the values of the first temp list into the object array
/// </summary>
/// <param name="size"> size varaible is to check the creating of new objects</param>
public void assignValues1()
{
int m = 0;
list[m] = new Values();
for (int i = 0; i < tempList.Count();)
{
list[m].ID = Convert.ToInt32(tempList[i]);
list[m].tType = tempList[i + 1];
list[m].cType = tempList[i + 2];
list[m].tName = tempList[i + 3];
list[m].SNumber = tempList[i + 4];
list[m].title = tempList[i + 5];
list[m].objective = tempList[i + 6];
list[m].reference = tempList[i + 7];
list[m].prerequisite = tempList[i + 8];
i = i + 9;
m++;
if (m < size)
list[m] = new Values();
else
break;
}
}
/// <summary>
/// Method to assign the values of the sevent temp list into the object array which contains Card Pan
/// </summary>
public void assignValues2()
{
int m = 0;
list[m] = new Values();
for (int i = 0; i < tempList7.Count();)
{
list[m].cPan = tempList7[i];
i = i + 1;
m++;
if (m < size)
list[m] = new Values();
else
break;
}
}
/// <summary>
/// Method to assign the values of the second temp list into the object array which contains the procedure
/// </summary>
/// <param name="size"> size varaible is to check the creating of new objects</param>
public void assignValues3()
{
int m = 0;
list[m] = new Values();
for (int i = 0; i < tempList2.Count();)
{
list[m].procedure = tempList2[i] + tempList2[i+1];
i = i + 2;
m++;
if (m < size)
list[m] = new Values();
else
break;
}
}
/// <summary>
/// Method to assign the values of the amount temp list into the object array which contains amount values
/// </summary>
/// <param name="size"> size varaible is to check the creating of new objects</param>
public void assignValues4()
{
int m = 0;
list[m] = new Values();
for (int i = 0; i < tempList3.Count();)
{
list[m].amount = tempList3[i];
i = i + 1;
m++;
if (m < size)
list[m] = new Values();
else
break;
}
}
/// <summary>
/// Method to assign the values of the fourth list into the object array which contains phost values
/// </summary>
/// <param name="size"> size varaible is to check the creating of new objects</param>
public void assignValues5()
{
int m = 0;
int i = 0;
list[m] = new Values();
for (i = 0; i < tempList4.Count();i++)
{
while (tempList4[i] != " " )
{
list[m].pHost = tempList4[i];
i++;
}
if (tempList4[i] == " " && i + 1 < tempList5.Count() && tempList4[i + 1] == " ")
{
m++;
i++;
list[m] = new Values();
list[m].pHost = tempList4[i];
}
m++;
if (m < size)
list[m] = new Values();
else
break;
}
}
/// <summary>
/// Method to assign the values of the fifth temp list into the object array which contains pCard values
/// </summary>
/// <param name="size"> size varaible is to check the creating of new objects</param>
public void assignValues6()
{
int m = 0;
int m2 = 0;
list[m] = new Values();
for (int i = 0; i < tempList5.Count() ; i++)
{
while (tempList5[i] != " ")
{
list[m].pCard = tempList5[i];
i++;
}
if (tempList5[i] == " " && i + 1 < tempList5.Count() && tempList5[i + 1] == " ")
{
if (m == m2 && m + 1 < size)
{
m++;
m2 = m;
}
list[m] = new Values();
list[m].pCard = " ";
m++;
if (m < size)
continue;
else
break;
}
m++;
m2 = m;
if (m < size)
list[m] = new Values();
else
break;
}
}
/// <summary>
/// Method to assign the values of the sixth temp list into the object array which contains the cslip details
/// </summary>
/// <param name="size"> size varaible is to check the creating of new objects</param>
public void assignValues7()
{
int m = 0;
int m2 = 0;
list[m] = new Values();
for (int i = 0; i < tempList6.Count();)
{
while (tempList6[i] != " ")
{
list[m].cslip = tempList6[i];
i++;
}
if (tempList6[i] == " " && i + 1 < tempList6.Count() && tempList6[i + 1] == " ")
{
if (m == m2 && m + 1 < size)
{
m++;
m2 = m;
}
list[m].cSlip = " ";
m++;
if (m < size)
continue;
else
break;
}
m++;
m2 = m;
if (m < size)
list[m] = new Values();
else
break;
}
}
public void show()
{
for(int i=0; i<size; i++)
{
Console.WriteLine(list[i].ID + " " + list[i].tName);
}
Console.ReadKey();
}
}
}
Your code is written OK, it seems that there is an issue with the thread that waits for all your tasks to be done ( Task.WaitAll call on tasks/tasknew arrays).
For instance, if you'll run your code from ConsoleApplciation in Main function, your process will end way before your tasks. So, simple Console.ReadLine call will solve your issue in this specific case.
Something like this:
Task[] task = new Task[6];
{
///...
Task.WaitAll(task);
Task[] tasknew = new Task[7];
{
//...
}
Task.WaitAll(tasknew);
//This will prevant you process to be closed, since it will wait for keyboard input.
Console.ReadKey();
I am working in a cross platform project, where we need to connect to Azure Notification Hub from Unity 3d.
We are trying to use the REST API, but we are having a problem with the generation of the SAS token. When trying to write to the stream we get an exception "Error writing request: The authentication or decryption has failed."
I think the generation of the SaS token has something wrong since it had to be modified to be cross platform and work within Unity.
Here is the code so far
using UnityEngine;
using System.Collections;
using System;
using System.Net;
using System.IO;
using System.Text;
/// <summary>
/// check https://msdn.microsoft.com/en-us/library/azure/dn495627.aspx
/// check also http://piotrwalat.net/hmac-authentication-in-asp-net-web-api/
/// </summary>
public class AzureNotificationHub : MonoBehaviour
{
public string CloudServiceNotificationHubPath = "cloudservicechat";
public string CloudServiceNotificationHubConnectionString =
"{CONNSTRINGHERE}";
public string NotificationHubUrl = "{HUBURLHERE}";
private ConnectionStringUtility objConnectionStringUtility = null;
public string SasToken;
public TextAsset CreateRegistrationTemplate = null;
// Use this for initialization
void Start()
{
this.objConnectionStringUtility = new ConnectionStringUtility(CloudServiceNotificationHubConnectionString);
this.SasToken = this.objConnectionStringUtility.getSaSToken(this.NotificationHubUrl, 10);
}
// Update is called once per frame
void Update()
{
}
private string atomContentType = "application/atom+xml;type=entry;charset=utf-8";
public void CreateRegistration()
{
string methodUrl = string.Format("{0}/{1}", this.NotificationHubUrl, "registrations/?api-version=2015-01");
string result = HttpPost(methodUrl);
}
/// <summary>
/// check http://stackoverflow.com/questions/9153181/adding-a-body-to-a-httpwebrequest-that-is-being-used-with-the-azure-service-mgmt
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
string HttpGet(string url)
{
HttpWebRequest req = WebRequest.Create(url)
as HttpWebRequest;
req.Headers.Add("Content-Type", this.atomContentType);
req.Headers.Add("Authorization", this.SasToken);
req.Headers.Add("x-ms-version", "2015-01");
req.Method = WebRequestMethods.Http.Get;
string result = null;
//writeStream.Write
using (HttpWebResponse resp = req.GetResponse()
as HttpWebResponse)
{
StreamReader reader =
new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}
return result;
}
string HttpPost(string url)
{
string result = null;
string tokenForUrl = this.objConnectionStringUtility.getSaSToken(url, 10);
try
{
string body = this.CreateRegistrationTemplate.text;
body = body.Replace("{tags}", string.Empty);
body = body.Replace("{ChannelUri}", this.NotificationHubUrl);
byte[] bodyArray = System.Text.Encoding.UTF8.GetBytes(body);
HttpWebRequest req = WebRequest.Create(url)
as HttpWebRequest;
req.ContentType = this.atomContentType;
//req.Headers.Add(HttpRequestHeader.Authorization, this.SasToken);
req.Headers.Add(HttpRequestHeader.Authorization, tokenForUrl);
req.Headers.Add("x-ms-version", "2015-01");
req.Method = WebRequestMethods.Http.Post;
Stream writeStream = req.GetRequestStream();
writeStream.Write(bodyArray, 0, bodyArray.Length);
writeStream.Flush();
writeStream.Close();
using (HttpWebResponse resp = req.GetResponse()
as HttpWebResponse)
{
StreamReader reader =
new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
}
public partial class ConnectionStringUtility
{
public string Endpoint { get; private set; }
public string SasKeyName { get; private set; }
public string SasKeyValue { get; private set; }
private string sasTokenn { get; set; }
public ConnectionStringUtility(string connectionString)
{
//Parse Connectionstring
char[] separator = { ';' };
string[] parts = connectionString.Split(separator);
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].StartsWith("Endpoint"))
Endpoint = "https" + parts[i].Substring(11);
if (parts[i].StartsWith("SharedAccessKeyName"))
SasKeyName = parts[i].Substring(20);
if (parts[i].StartsWith("SharedAccessKey"))
SasKeyValue = parts[i].Substring(16);
}
}
/// <summary>
/// check http://buchananweb.co.uk/security01i.aspx
/// </summary>
/// <param name="uri"></param>
/// <param name="minUntilExpire"></param>
/// <returns></returns>
public string getSaSToken(string uri, int minUntilExpire)
{
string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();
// Add an expiration in seconds to it.
long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
expiresOnDate += minUntilExpire * 60 * 1000;
long expires_seconds = expiresOnDate / 1000;
String toSign = targetUri + "\n" + expires_seconds;
HmacSignatureCalculator hmacSigner = new HmacSignatureCalculator();
System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed();
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
var messageBuffer = ConvertStringToBinary(toSign, encoding);
var keyBuffer = ConvertStringToBinary(SasKeyValue, encoding);
var hmacKey = CreateKey(keyBuffer);
var signedMessage = Sign(hmacKey, messageBuffer);
string signature = Uri.EscapeDataString(signedMessage);
return "SharedAccessSignature sr=" + targetUri + "&sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName;
}
private byte[] CreateKey(byte[] keyBuffer)
{
System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed();
var computedHash = crypto.ComputeHash(keyBuffer);
return computedHash;
}
public string Sign(byte[] hmacKey, byte[] messageBuffer)
{
using (System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed())
{
var hash = crypto.ComputeHash(hmacKey);
var signature = Convert.ToBase64String(hash);
return signature;
}
}
public byte[] ConvertStringToBinary(string value, Encoding encoding)
{
//Requires.NotNull(value, "value");
//Requires.NotNull(encoding, "encoding");
return encoding.GetBytes(value);
}
}
Any ideas what I should do?
Thanks for the help.
I've building a windows app for browsing web pages using cefSharp.
I need to implement some short cut keys into that application, can any one tell me how can i achieve this functionality.
Ex.
ctrl + tab = move to next tab
I'm able to track if user presses any single key, but unable to track multi key pressing.
IKeyboardHandler
public class KeyboardHandler : IKeyboardHandler
{
public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
{
bool result = false;
Debug.WriteLine(String.Format("OnKeyEvent: KeyType: {0} 0x{1:X} Modifiers: {2}", type, windowsKeyCode, modifiers));
// TODO: Handle MessageNeeded cases here somehow.
return result;
}
public bool OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut)
{
const int WM_SYSKEYDOWN = 0x104;
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
const int WM_SYSKEYUP = 0x105;
const int WM_CHAR = 0x102;
const int WM_SYSCHAR = 0x106;
const int VK_TAB = 0x9;
bool result = false;
isKeyboardShortcut = false;
// Don't deal with TABs by default:
// TODO: Are there any additional ones we need to be careful of?
// i.e. Escape, Return, etc...?
if (windowsKeyCode == VK_TAB)
{
return result;
}
Control control = browserControl as Control;
int msgType = 0;
switch (type)
{
case KeyType.RawKeyDown:
if (isSystemKey)
{
msgType = WM_SYSKEYDOWN;
}
else
{
msgType = WM_KEYDOWN;
}
break;
case KeyType.KeyUp:
if (isSystemKey)
{
msgType = WM_SYSKEYUP;
}
else
{
msgType = WM_KEYUP;
}
break;
case KeyType.Char:
if (isSystemKey)
{
msgType = WM_SYSCHAR;
}
else
{
msgType = WM_CHAR;
}
break;
default:
Trace.Assert(false);
break;
}
// We have to adapt from CEF's UI thread message loop to our fronting WinForm control here.
// So, we have to make some calls that Application.Run usually ends up handling for us:
PreProcessControlState state = PreProcessControlState.MessageNotNeeded;
// We can't use BeginInvoke here, because we need the results for the return value
// and isKeyboardShortcut. In theory this shouldn't deadlock, because
// atm this is the only synchronous operation between the two threads.
control.Invoke(new Action(() =>
{
Message msg = new Message() { HWnd = control.Handle, Msg = msgType, WParam = new IntPtr(windowsKeyCode), LParam = new IntPtr(nativeKeyCode) };
// First comes Application.AddMessageFilter related processing:
// 99.9% of the time in WinForms this doesn't do anything interesting.
bool processed = Application.FilterMessage(ref msg);
if (processed)
{
state = PreProcessControlState.MessageProcessed;
}
else
{
// Next we see if our control (or one of its parents)
// wants first crack at the message via several possible Control methods.
// This includes things like Mnemonics/Accelerators/Menu Shortcuts/etc...
state = control.PreProcessControlMessage(ref msg);
}
}));
if (state == PreProcessControlState.MessageNeeded)
{
// TODO: Determine how to track MessageNeeded for OnKeyEvent.
isKeyboardShortcut = true;
}
else if (state == PreProcessControlState.MessageProcessed)
{
// Most of the interesting cases get processed by PreProcessControlMessage.
result = true;
}
Debug.WriteLine(String.Format("OnPreKeyEvent: KeyType: {0} 0x{1:X} Modifiers: {2}", type, windowsKeyCode, modifiers));
Debug.WriteLine(String.Format("OnPreKeyEvent PreProcessControlState: {0}", state));
return result;
}
Finally got an alternative to implement shortcut functionality without implementing IKeyboardHandler.
Here i used Global Keyboard Hook to implement this.
GlobalKeyboardHook
public class GlobalKeyboardHook
{
#region Variables and dll import
#region For key capturing
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int code, int wParam, ref keyBoardHookStruct lParam);
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, LLKeyboardHook callback, IntPtr hInstance, uint theardID);
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
public delegate int LLKeyboardHook(int Code, int wParam, ref keyBoardHookStruct lParam);
public struct keyBoardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x0100;
const int WM_KEYUP = 0x0101;
const int WM_SYSKEYDOWN = 0x0104;
const int WM_SYSKEYUP = 0x0105;
LLKeyboardHook llkh;
public List<Keys> HookedKeys = new List<Keys>();
IntPtr Hook = IntPtr.Zero;
public event KeyEventHandler KeyDown;
public event KeyEventHandler KeyUp;
#endregion
#region For modifier capturing
/// <summary>
/// Gets the state of modifier keys for a given keycode.
/// </summary>
/// <param name="keyCode">The keyCode</param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);
//Modifier key vkCode constants
private const int VK_SHIFT = 0x10;
private const int VK_CONTROL = 0x11;
private const int VK_MENU = 0x12;
private const int VK_CAPITAL = 0x14;
#endregion
#endregion
#region Constructor
// This is the Constructor. This is the code that runs every time you create a new GlobalKeyboardHook object
public GlobalKeyboardHook()
{
llkh = new LLKeyboardHook(HookProc);
// This starts the hook. You can leave this as comment and you have to start it manually
// Or delete the comment mark and your hook will start automatically when your program starts (because a new GlobalKeyboardHook object is created)
// That's why there are duplicates, because you start it twice! I'm sorry, I haven't noticed this...
// hook(); <-- Choose!
}
~GlobalKeyboardHook()
{ unhook(); }
#endregion
#region Functions and implementation
/// <summary>
/// Hook (Start listening keybord events)
/// </summary>
public void hook()
{
IntPtr hInstance = LoadLibrary("User32");
Hook = SetWindowsHookEx(WH_KEYBOARD_LL, llkh, hInstance, 0);
}
/// <summary>
/// Unhook (Stop listening keybord events)
/// </summary>
public void unhook()
{
UnhookWindowsHookEx(Hook);
}
/// <summary>
/// Pass key into event
/// </summary>
/// <param name="Code">Key code</param>
/// <param name="wParam">int event type (keydown/keyup)</param>
/// <param name="lParam">keyBoardHookStruct enum for detecting key</param>
/// <returns>next hook call</returns>
public int HookProc(int Code, int wParam, ref keyBoardHookStruct lParam)
{
if (Code >= 0)
{
Keys key = (Keys)lParam.vkCode;
if (HookedKeys.Contains(key))
{
//Get modifiers
key = AddModifiers(key);
KeyEventArgs kArg = new KeyEventArgs(key);
if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
{
KeyDown(this, kArg);
}
else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
{
KeyUp(this, kArg);
}
if (kArg.Handled)
return 1;
}
}
return CallNextHookEx(Hook, Code, wParam, ref lParam);
}
/// <summary>
/// Checks whether Alt, Shift, Control or CapsLock
/// is pressed at the same time as the hooked key.
/// Modifies the keyCode to include the pressed keys.
/// </summary>
private Keys AddModifiers(Keys key)
{
//CapsLock
if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0) key = key | Keys.CapsLock;
//Shift
if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) key = key | Keys.Shift;
//Ctrl
if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) key = key | Keys.Control;
//Alt
if ((GetKeyState(VK_MENU) & 0x8000) != 0) key = key | Keys.Alt;
return key;
}
#endregion
}
Start hook
To start hook add below code to form load or application start
//Start listening keybord events
gHook = new GlobalKeyboardHook();
gHook.KeyDown += new KeyEventHandler(gHook_KeyDown);
foreach (Keys key in Enum.GetValues(typeof(Keys)))
{
gHook.HookedKeys.Add(key);
}
gHook.hook();
Stop hook
Add this code on application exit(form closing event)
//Stop listening keybord events
gHook.unhook();
Handel key down event for shortcut implementation
public void gHook_KeyDown(object sender, KeyEventArgs e)
{
if (this.ContainsFocus)
{
if (e.KeyData.ToString().ToUpper().IndexOf("ALT".ToUpper()) >= 0
&& e.KeyValue == 66)//B = 66
{
//ALT + B
new Thread(() =>
{
// execute this on the gui thread. (winforms)
this.Invoke(new Action(delegate
{
tosBrowserBtnBack_Click(this, new EventArgs());
}));
}).Start();
}
else if (e.KeyData.ToString().ToUpper().IndexOf("ALT".ToUpper()) >= 0
&& e.KeyValue == 70)//F = 70
{
//ALT + F
new Thread(() =>
{
// execute this on the gui thread. (winforms)
this.Invoke(new Action(delegate
{
tosBrowserBtnFor_Click(this, new EventArgs());
}));
}).Start();
}
}
Global hook works for every keystroke whether your application has focus or not, so here I've used this.ContainsFocus to check current form has focus or not, if has then handle shortcut events. If you need to implementation shortcut on hole application then you need to check if application has focus or not.
For that you need to create a new class
ApplicationFocus
public class ApplicationFocus
{
/// <summary>Returns true if the current application has focus, false otherwise</summary>
public static bool ApplicationIsActivated()
{
var activatedHandle = GetForegroundWindow();
if (activatedHandle == IntPtr.Zero)
{
return false; // No window is currently activated
}
var procId = Process.GetCurrentProcess().Id;
int activeProcId;
GetWindowThreadProcessId(activatedHandle, out activeProcId);
return activeProcId == procId;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
}
Then replace if (this.ContainsFocus) with ApplicationFocus.ApplicationIsActivated() in gHook_KeyDown event.
This is worked for me.
Below is my attempt to turn a System.Diagnostics.Process into an IConnectableObservable.
This solution has a problem: I'd like to listen to the standard output and error continiously and use the event Process.Exited as trigger for OnCompleted. Unfortunately I found out that Process.Exited is raised before output buffers are empty. This means that without my ugly workaround with a thread sleep I can reproduce situations where the output is not served via OnNext statements.
Q1: Do you see any workaround for this issue?
Q2: With regard to System.Reactive: What could I have done better in my solution?
regards,
Markus
public static class RxProcessUtilities
{
/// <summary>
/// Creates a connectable observable for a process.
/// </summary>
/// <remarks>Must be a connectable observable in order to hinder multiple
/// subscriptions to call the process multiple times.</remarks>
/// <param name="process">The process.</param>
/// <returns></returns>
public static IConnectableObservable<string> CreateConnectableObservableProcess
(string filename, string arguments, IObservable<string> input = null)
{
var observable = Observable.Using(() =>
{
Process process = new Process();
// process configuration
process.StartInfo.FileName = filename;
process.StartInfo.Arguments = arguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.EnableRaisingEvents = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
if (null != input)
{
process.StartInfo.RedirectStandardInput = true;
input.Subscribe(s =>
{
if (!process.HasExited)
{
process.StandardInput.Write(s);
}
});
}
return process;
},
process =>
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
// listen to stdout and stderr
var stdOut = RxProcessUtilities.CreateStandardOutputObservable(process);
var stdErr = RxProcessUtilities.CreateStandardErrorObservable(process);
var stdOutSubscription = stdOut.Subscribe(observer);
var stdErrSubscription = stdErr.Subscribe(observer);
var processExited = Observable.FromEventPattern
(h => process.Exited += h, h => process.Exited -= h);
var processError = processExited.Subscribe(args =>
{
// Here is my problem: process sends exited event *before* all
// *DataReceived events have been raised
// My ugly workaround for process exit before stdout and stderr buffers are empty.
Thread.Sleep(2000);
// Also: AFAICS we cannot read synchronously what is left in the buffer,
// since we started asynchronously. This will throw:
// string restOfStdOut = process.StandardOutput.ReadToEnd();
// string restOfStdErr = process.StandardError.ReadToEnd();
if (process.ExitCode != 0)
{
observer.OnError(new Exception
(String.Format("Process '{0}' terminated with error code {1}",
process.StartInfo.FileName, process.ExitCode)));
}
else
{
observer.OnCompleted();
}
});
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
return new CompositeDisposable
(stdOutSubscription,
stdErrSubscription,
processError);
});
});
return observable.Publish();
}
/// <summary>
/// Creates an IObservable<string> for the standard error of a process.
/// </summary>
/// <param name="process">The process.</param>
/// <returns></returns>
public static IObservable<string> CreateStandardErrorObservable(Process process)
{
// var processExited = Observable.FromEventPattern
// (h => process.Exited += h, h => process.Exited -= h);
var receivedStdErr =
Observable.FromEventPattern<DataReceivedEventHandler, DataReceivedEventArgs>
(h => process.ErrorDataReceived += h,
h => process.ErrorDataReceived -= h)
//.TakeUntil(processExited)
// cannot be used here, since process exited event might be raised
// before all stderr and stdout events occurred.
.Select(e => e.EventArgs.Data);
return Observable.Create<string>(observer =>
{
var cancel = Disposable.Create(process.CancelErrorRead);
return new CompositeDisposable(cancel, receivedStdErr.Subscribe(observer));
});
}
/// <summary>
/// Creates an IObservable<string> for the standard output of a process.
/// </summary>
/// <param name="process">The process.</param>
/// <returns></returns>
public static IObservable<string> CreateStandardOutputObservable(Process process)
{
var receivedStdOut =
Observable.FromEventPattern<DataReceivedEventHandler, DataReceivedEventArgs>
(h => process.OutputDataReceived += h,
h => process.OutputDataReceived -= h)
.Select(e => e.EventArgs.Data);
return Observable.Create<string>(observer =>
{
var cancel = Disposable.Create(process.CancelOutputRead);
return new CompositeDisposable(cancel, receivedStdOut.Subscribe(observer));
});
}
}
The trick is
process.WaitForExit();
See http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx: "This overload [WaitForExit()] ensures that all processing has been completed, including the handling of asynchronous events for redirected standard output. You should use this overload after a call to the WaitForExit(Int32) overload when standard output has been redirected to asynchronous event handlers."
Here is the complete solution:
/// <summary>
/// Creates a connectable observable for a process.
/// </summary>
/// <remarks>Must be a connectable observable in order to hinder multiple subscriptions to call the process multiple times.</remarks>
/// <param name="process">The process.</param>
/// <returns></returns>
public static IConnectableObservable<string> CreateConnectableObservableProcess(string filename, string arguments, IObservable<string> input = null)
{
var observable = Observable.Using(() =>
{
Process process = new Process();
// process configuration
process.StartInfo.FileName = filename;
process.StartInfo.Arguments = arguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.EnableRaisingEvents = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
if (null != input)
{
process.StartInfo.RedirectStandardInput = true;
input.Subscribe(s =>
{
if (!process.HasExited)
{
process.StandardInput.Write(s);
}
});
}
return process;
},
process =>
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
// listen to stdout and stderr
var stdOut = RxProcessUtilities.CreateStandardOutputObservable(process);
var stdErr = RxProcessUtilities.CreateStandardErrorObservable(process);
var stdOutSubscription = stdOut.Subscribe(observer);
var stdErrSubscription = stdErr.Subscribe(observer);
var processExited = Observable.FromEventPattern(h => process.Exited += h, h => process.Exited -= h);
var processError = processExited.Subscribe(args =>
{
process.WaitForExit();
try
{
if (process.ExitCode != 0)
{
observer.OnError(new Exception(String.Format("Process '{0}' terminated with error code {1}",
process.StartInfo.FileName, process.ExitCode)));
}
else
{
observer.OnCompleted();
}
}
finally
{
process.Close();
}
});
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
return new CompositeDisposable(stdOutSubscription,
stdErrSubscription,
processError);
});
});
return observable.Publish();
}