|
Hi Alan,
This is quite humbling. I honestly cannot figure out how to modify your class, ashamedly.
What I am trying to do is to get the class to return a list of hwnds and pids and then I was going to use GetWindowText to narrow down the proper hwnd while parsing through that list, as I am getting 4 or 5 handles found. This may be the wrong way to go about this, and this might be why I am having such trouble with it.
Using a Messagebox.Show in place of the // Do something I was able identify the proper pid and handle associated with it, but embarrassingly, I cannot figure out how to create an array of some sort, add each handle found and then return it to my calling function so that I can then parse through the returned data. I cannot figure out how this part of the code works
EnumWindows(SelectWindowsByPID, (IntPtr)selectedProcess.Id);
when SelectWindowsByPID requires two parameters by delclaration
IntPtr hwnd, IntPtr state and I see that it somehow interacts with a static extern, which I have never used before. I apologize for my ignorance, but I'm self taught and apparently have discovered a large hole in my learning.
|
|
|
|
|
I see you've got Dave's FindWindow suggestion working and it's certainly a lot simpler than my method.
As you asked about EnumWindows here goes, although you may have to do some reading yourself, as getting callback functions to work reliably requires some advanced techniques.
First part of the answer on how EnumWindows works
EnumWindows(SelectWindowsByPID, (IntPtr)selectedProcess.Id);
The .NET program calls EnumWindows and supplies a method that will be called by Windows for every handle that is found. This is the callback method, the c# signature of which is fixed as
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr state);
Windows sets the first parameter to the window handle it has found. The second parameter is a copy of the second argument supplied to EnumWindows, which provides a way for the programmer to pass information into the callback. I've used it to pass in the process Id.
Fully operational examples have additional complexity as it is essential to stop the .NET garbage collector moving any object that is referenced by the callback function. Rather than modify the original code I'll show you a complete class that gives a list of window handles.
using System;
using System.Runtime.InteropServices;
public class ProcessWindowList2 : System.Collections.Generic.List<IntPtr> {
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc callbackMethod, IntPtr state);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr state);
[DllImport("user32.dll")]
private static extern UInt32 GetWindowThreadProcessId(
[In] IntPtr hwnd,
out UInt32 processId);
private readonly Int32 pid;
private static Int32 GetWindowPID(IntPtr hwnd) {
UInt32 PID;
GetWindowThreadProcessId(hwnd, out PID);
return unchecked((Int32)PID);
}
private static Boolean SelectWindows(IntPtr hwnd, IntPtr state) {
GCHandle gch = GCHandle.FromIntPtr(state);
ProcessWindowList2 list = (ProcessWindowList2)gch.Target;
Int32 windowPid = GetWindowPID(hwnd);
if (list.pid == windowPid) {
list.Add(hwnd);
}
return true;
}
public ProcessWindowList2(Int32 processId) {
this.pid = processId;
EnumWindowsProc callback = new EnumWindowsProc(SelectWindows);
GCHandle gch = GCHandle.Alloc(this);
try {
EnumWindows(callback, GCHandle.ToIntPtr(gch));
} finally {
gch.Free();
}
}
}
This is a modified version of published code http://msdn.microsoft.com/en-us/magazine/bb985713.aspx[^]. It's derived from List<IntPtr> but has a special constructor that populates the list with handles. The code makes use of GCHandle.Alloc(this) to inform the garbage collector that objects of this class must not be moved until GCHandle.Free is called. This is essential for the safe operation of the callback.
Using the class is very simple
Process p = Process.Start(@"c:\Windows\System32\rundll32.exe", "shell32.dll,#61");
ProcessWindowList2 hwndList = new ProcessWindowList2(p.Id);
foreach (IntPtr hwnd in hwndList) {
}
Have fun!
Alan.
|
|
|
|
|
Thank you very much for taking the time to explain this Alan. This is completely new to me and I have a lot to read and learn about, but each time I read your post it becomes a little more clear. Hopefully I'll be able to come back and read this in a few weeks and understand it fully as I fill in this hole in my c sharp knowledge.
-Brad
|
|
|
|
|
|
You could, but EF already wraps every batch of updates (when you call DbContext.SaveChanges ) in a transaction by itself.
You get more control over this process if you're using EF6.0 or above. Read this[^] for more information.
Before you get into doing your own transactions you might want to read this[^].
|
|
|
|
|
i know this but problem with this is mostly these calls are in DAL.
IN General you call ur business function from controller and there are multiple calls made which should be in transaction e.g.
using(Transaction.....)
{
BLL.SomeFunction1()
BLL.SomeFunction2()
}
|
|
|
|
|
OK, that's still a bit backwards. The controller should be concerned with translating between the View (ViewModel) and the Business Logic, not controlling a transaction which is something that belongs in the Data Layer and possibly controlled by the Business Logic.
So long as the last call you make in the Business Logic is the DbContext.SaveChanges, all the changes the Business Logic makes will be wrapped in a Transaction AUTOMATICALLY. You don't have to create a transaction yourself!
public class BusinessLogic
{
private MyDbContext context = new MyDbContext();
public void BusinessFunction1()
{
}
public void BusinessFunction2()
{
}
public void SaveChanges()
{
context.SaveChanges();
}
public void Dispose()
{
context.Dispose();
}
}
Besides, you already linked to the article that shows you how to do it! I already linked to a couple of articles that shows you the pitfalls of what you want to do.
The problem with what you want to do is that you have to be VERY careful that the transaction mode you use doesn't LOCK THE ENTIRE TABLE while you do your transaction processing. If you're not careful, the lock will prevent other instances from even reading the data in locked tables, preventing other users of your web site from seeing pages that are backed by data!
|
|
|
|
|
In multi thread, i use async socket , alway An error occurred:
ReceiveCallback Error: System.ObjectDisposedException: 无法访问已释放的对象。
对象名:“System.Net.Sockets.Socket”。
在 System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
在 System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult) ....
This is my code:
private void ReceiveCallback(IAsyncResult ar)
{
try
{
if (null == ar)
return;
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
if (null == state)
return;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
ms.Write(state.buffer, 0, bytesRead);
state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead));
if (!state.sb.ToString().EndsWith("\r\n\r\n"))
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
int index = state.sb.ToString().IndexOf("\r\n\r\n", System.StringComparison.Ordinal);
int lastclr = state.sb.ToString().LastIndexOf("\r\n", index);
string strhex = state.sb.ToString().Substring(lastclr + 2, index - lastclr -2);
Int32 hex;
if (Int32.TryParse(strhex, System.Globalization.NumberStyles.AllowHexSpecifier, null,
out hex))
{
if (state.sb.Length > 1)
{
Response = state.sb.ToString();
}
receiveDone.Set();
}
else
{
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
ReceiveCallback, state);
}
}
}
else
{
if (state.sb.Length > 1)
{
Response = state.sb.ToString();
}
receiveDone.Set();
}
}
catch (Exception e)
{
throw new Exception("ReceiveCallback Error: " + e);
}
}
for (int nIndex = 0; nIndex < value; nIndex++)
{
if (threadsRun[nIndex] == null && ThreadsRunning)
{
threadsRun[nIndex] = new Thread(new ThreadStart(delegate() { ThreadScraper(); }));
threadsRun[nIndex].Name = nIndex.ToString();
threadsRun[nIndex].Start();
}
else
{
Console.Write("");
}
}
|
|
|
|
|
I'm looking for a decent book on C# that handles the new features from 4.0 til the latest version of C# in great detail.
Mostly interested in lambda expressions, linq to sql.
So many books out there, but which ones are decent and detailed? Would like a few recommendations.
Many thanks.
|
|
|
|
|
Go with Jon Skeet's book. It's very good.
|
|
|
|
|
In addition to highly recommending the book by Jon Skeet that Pete O'Hanlon is referring to: "C# In Depth," Third Edition, Manning Press, 2013 [^], I'd highly recommend the "C# Language Fourth Edition," Annotated Edition, Anders Hejlsberg, Mads Torgersen, Scott Wiltamuth, Peter Golde, Addison-Wesley, 2011 [^].
The annotated edition of the C# language reference by Anders, et. al., includes comments (sidebars) by the gurus' gurus of .NET including Jon Skeet, Eric Lippert, Brad Abrams, Jesse Liberty, Joseph Albihari, and Chris Sells, as well as others: imho their comments/discussion are "worth their weight in gold."
I found "CLR via C#," 3rd. Edition, Eric Richter, Microsoft Press, 2010, very informative and well-written, and there is now a 4th. edition of that book out (2012) that I plan to acquire: [^].
“I speak in a poem of the ancient food of heroes: humiliation, unhappiness, discord. Those things are given to us to transform, so that we may make from the miserable circumstances of our lives things that are eternal, or aspire to be so.” Jorge Luis Borges
|
|
|
|
|
I just buy the latest O'Reilly "C# X.X in a nutshell" book. Where X.X would seem to be 5.0 on my shelf right now.
|
|
|
|
|
/ravi
|
|
|
|
|
|
Go for LINQ in Action
Fabrice Marguerie, Steve Eichert and Jim Wooley
|
|
|
|
|
Good book LINQ in Action
Fabrice Marguerie, Steve Eichert and Jim Wooley
|
|
|
|
|
|
|
Hi folks,
I have a simple app to look up products, search box, search button, DataGridView to display results and a loading GIF image to show progress.
Initially, I run the query to display results in the grid successfully, but the GIF image will freeze without refreshing.
I was suggested to use threading to run the query on a different thread, I was able to run the query and the GIF image will refresh
However, when using threading, the scrollbars on the grid will not work, I cannot move them at all
If I remove the threading, scrollbars work, but GIF image will not refresh.
Any pointers on what I am doing wrong here?
See the code below for your reference.
Thanks,
...Alex
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RmsBottleByLocation
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
private void btnCancel_Click(object sender, EventArgs e)
{
this.Close();
System.Environment.Exit(0);
}
private void btnSearch_Click(object sender, EventArgs e)
{
lblResults.Text = String.Empty;
grdResults.DataSource = null;
grdResults.Rows.Clear();
grdResults.Refresh();
string keyword = txtKeyword.Text.Trim();
int minimumKeywordLength = Int32.Parse(ConfigurationManager.AppSettings["MinimumKeywordLength"]);
if (keyword.Length < minimumKeywordLength)
{
MessageBox.Show("Please enter item code or item description with at least " + minimumKeywordLength.ToString() + " characters!",
this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
txtKeyword.SelectAll();
txtKeyword.Focus();
return;
}
loadingImage.Visible = true;
this.Refresh();
runQuery();
}
private void runQuery()
{
string keyword = txtKeyword.Text.Trim();
btnSearch.Enabled = false;
this.Cursor = Cursors.WaitCursor;
string hostName = System.Net.Dns.GetHostName();
string getBottleByLocationStoredProcedure = ConfigurationManager.AppSettings["GetBottleByLocationStoredProcedure"];
string connectionString = ConfigurationManager.AppSettings["ConnectionString"];
string connectionTimeout = ConfigurationManager.AppSettings["ConnectionTimeout"];
connectionString = string.Format(connectionString, hostName);
SqlCommand command = new SqlCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = getBottleByLocationStoredProcedure;
command.CommandTimeout = Int32.Parse(connectionTimeout);
command.Parameters.Add(new SqlParameter("@Keyword", keyword));
try
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
command.Connection = connection;
SqlDataReader dr = command.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
grdResults.DataSource = dt;
grdResults.Columns[0].Width = 500;
grdResults.Columns[0].Frozen = true;
grdResults.Columns[0].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
lblResults.Text = grdResults.Rows.Count.ToString() + " items found!";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
loadingImage.Visible = false;
this.Refresh();
btnSearch.Enabled = true;
this.Cursor = Cursors.Arrow;
}
}
private void grdResults_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
if (e.RowIndex >= 0 && e.ColumnIndex >= 0 && dgv[e.ColumnIndex, e.RowIndex].Value is int)
{
if ((int)dgv[e.ColumnIndex, e.RowIndex].Value == 0)
{
e.Value = "-";
}
}
}
}
}
|
|
|
|
|
You can't just move runQuery into a separate thread - it doesn't work like that.
You can't update display controls from any thread except the one they were created on: the UI thread.
What I would do is use a BackgroundWorker, and use the RunWorkerCompleted event to set the DataSource to the (now complete) DataTable. If that is causing the bottleneck then I'd load each record individually from the DataReader and pass it to the UI thread via the ProgressChanged event (which has a UserState property to the ProgressChangedEventArgs) and add it manually to the display grid.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
|
You're welcome!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
Cannot use a leading .. to exit above the top directory.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: Cannot use a leading .. to exit above the top directory.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[HttpException (0x80004005): Cannot use a leading .. to exit above the top directory.]
System.Web.Util.UrlPath.ReduceVirtualPath(String path) +12705512
System.Web.Util.UrlPath.Reduce(String path) +169
System.Web.UI.Control.ResolveClientUrl(String relativeUrl) +314
System.Web.UI.HtmlControls.HtmlLink.RenderAttributes(HtmlTextWriter writer) +172
System.Web.UI.HtmlControls.HtmlLink.Render(HtmlTextWriter writer) +67
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +249
System.Web.UI.HtmlControls.HtmlHead.RenderChildren(HtmlTextWriter writer) +28
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +49
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +249
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
System.Web.UI.Control.RenderChildrenInternal(HtmlTex tWriter writer, ICollection children) +249
System.Web.UI.Page.Render(HtmlTextWriter writer) +40
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5363
|
|
|
|
|
Without your code? We are guessing...
But teh error is pretty explicit: you are trying to refer to a file directly using a relative path:
..\folder\file.jpg But the current folder is already at the root of the drive (or root of the website for a web app)
Try using an absolute path, or check your current folder is where you think it is!
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
I have a standard ComboBox. Under certain conditions, I would like the background color of the actual ComboBox rectangle (not the drop down list portion) to change. I have found a lot of example on the Internet explaining how to change the color of the items in the drop down list, but this is not what I want. Any ideas?
|
|
|
|
|