I am new in C#, i've got some problem to capture any windows dialog show in my server. I need to know the message (caption and title) from windows dialog so i can write to my application log.
I know that i must find #32770 class windows, but i do not know how to enumwindows. In delphi 7, the code should use some functions like:
Enumwindows
EnumProcess
Enumchildwindows
Enumchildwindowsproc
Getwindowthreadprocessid
GetClassName
Getwindowtext
Is there any solution for this ?
You can use windows API in C# as well. You can find a lot information and examples of using here. And here is information about DllImport attribute.
You can try something like:
class Program
{
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
static void Main(string[] args)
{
var handle = IntPtr.Zero;
do
{
handle = FindWindowEx(IntPtr.Zero, handle, "#32770", null);
if (handle != IntPtr.Zero )
Console.WriteLine("Found handle: {0:X}", handle.ToInt64());
} while (handle != IntPtr.Zero);
Console.ReadLine();
}
}
Related
I have developed a C# code which access to user32.dll and it is using GetWindowText function. The code is working properly when Teamviewer is uninstalled on Windows 7.
However if you install Teamviewer, the code can not retrieve the text of control in window with GetWindowText function. The code is given below. How can I solve this problem ?
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr FindWindowExW(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass,
string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr GetWindowText(IntPtr hwndParent, StringBuilder Wintxt, int txtsize);
public void CloseWin(string param)
{
try
{
IntPtr hwnD = FindWindowExW(IntPtr.Zero, IntPtr.Zero, "CabinetWClass", null);
IntPtr hwnD2 = FindWindowExW(hwDvar, IntPtr.Zero, "WorkerW", null);
IntPtr hwnD3 = FindWindowExW(hwnD2, IntPtr.Zero, "ReBarWindow32", null);
IntPtr hwnD4 = FindWindowExW(hwnD3, IntPtr.Zero, "Address Band Root", null);
IntPtr hwnD5 = FindWindowExW(hwnD4, IntPtr.Zero, "msctls_progress32", null);
IntPtr hwnD6 = FindWindowExW(hwnD5, IntPtr.Zero, "Breadcrumb Parent", null);
IntPtr hwnD7 = FindWindowExW(hwnD6, IntPtr.Zero, "ToolbarWindow32", null);
StringBuilder sb = new StringBuilder(255);
GetWindowText(hwnD7, sb, 255);
Well I have resolved the issue. I was calling also dialog file class with the function FindWindowEx by the class name #32770.
This class type is used also by Teamviewer(TV) quick support user interface. When I run my code, there is a intervention to the interface of TV and blocks of working user32 functions.
To solve the problem I have called the FindWindow function with class name and control name so that there is no intervention to the TV and problem solved.
I am facing a problem. I have written and win32 DLL in delphi 2009. Now I want to dynamically load that DLL from C# desktop application but LoadLibray function returns 0. Here is CSharp code, please can any body helps me why DLL is not loading?
public partial class Form1 : Form
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad, IntPtr hFile, uint dwFlag);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("Kernel32.dll")]
private extern static Boolean CloseHandle(IntPtr handle);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
IntPtr ptr = IntPtr.Zero;
ptr = LoadLibrary("MyDLL.dll", IntPtr.Zero, 0);
if (ptr == IntPtr.Zero)
{
MessageBox.Show("DLL not laded");
}
}
}
}
You have the wrong signature for LoadLibrary. It should be:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllname);
You had two spurious parameters and weren't capturing the error code.
Always check for errors when calling Win32 functions. In this case
IntPtr lib = LoadLibrary(dllname);
if (lib == IntPtr.Zero)
throw new Win32Exception();
Common failure modes include:
Mis-matched bitness.
DLL not found on DLL search path.
DLL's dependencies not resolved.
I can't tell you why that DLL is not loading as there is not enough information in the question.
Hint: Have you checked that your application is running in 32-bit or 64-bit appropriately for the DLL?
However, I can tell you how to get more information about the problem.
First, add the following to the attributes:
[DllImport("Kernel32.dll", SetLastError=true)]
^-----------------^
Then add this to your if-statement that handles the problem:
if (ptr == IntPtr.Zero)
throw new Win32Exception();
This should give you a more specific exception message indicating what the problem might be.
i've developed a simple application (.dll) in LABVIEW and i implorted that dll to a C# windows application(Winforms) . Like
[DllImport(#".\sample.dll")]
public static extern void MyFunc(char[] a, StringBuilder b ,Int32 c);
so when i call the function MyFunc a window will be popped up( the Lab View window( Front panel of my labview application
i need to get the window name (ExpectedFuncName) in my C# application. i.e i need to get the name of the external window which is opend by my C# application. Can we use FileVersionInfo or assembly loader to get the name?
Is there any idea to do this?
Thanks in advance.
If you have the window handle, this is relatively easy:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
...
int len;
// Window caption
if ((len = GetWindowTextLength(WindowHandle)) > 0) {
sb = new StringBuilder(len + 1);
if (GetWindowText(WindowHandle, sb, sb.Capacity) == 0)
throw new Exception(String.Format("unable to obtain window caption, error code {0}", Marshal.GetLastWin32Error()));
Caption = sb.ToString();
}
Here, 'WindowHandle' is the handle of the created window.
In the case you do not have a window handle (I see you don't), you have to enumerate every desktop top-level window, filter them by the creating process (I see the window is created by you application by calling MyFunc, so you know the process ID [*]), and then use some heuristic to determine the required information.
Here is the C# import of the functions you shall use in the case you do not have the handle:
[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
Basically EnumWindows calls EnumWindowsProc for each window found in the current desktop. So you can get the window caption.
List<string> WindowLabels = new List<string>();
string GetWindowCaption(IntPtr hWnd) { ... }
bool MyEnumWindowsProc(IntPtr hWnd, IntPtr lParam) {
int pid;
GetWindowThreadProcessId(hWnd, out pid);
if (pid == Process.GetCurrentProcess().Id) {
// Window created by this process -- Starts heuristic
string caption = GetWindowCaption(hWnd);
if (caption != "MyKnownMainWindowCaption") {
WindowLabels.Add(caption);
}
}
return (true);
}
void DetectWindowCaptions() {
EnumWindows(MyEnumWindowsProc, IntPtr.Zero);
foreach (string s in WindowLabels) {
Console.WriteLine(s);
}
}
[*] In the case the window is not created by your application (i.e but from another background process), you shall filter the values returned by GetWindowThreadProcessId using another process ID, but this requires another question...
If you activate LabVIEW scripting (LabVIEW 2010), or install it (LV 8.6, 2009) there is a front-panel property called 'FP.nativewindow'. This returns a handle to the front panel window.
Use the following snippet to get the property:
I've been wondering how to do this for ages. I'm creating a little app, and I need to figure out how many apps or windows are displayed in the TaskBar.
I've yet to find any info on this at all, I'd appreciate any help at all.
Thank you :)
Here is an article that shows how to get the windows, that are shown when you are using the ALT+TAB key combination.
Basically, you will get the same windows that are shown in the taskbar (unless it is a tool window that is not displayed), but then again, you can always check against WS_EX_TOOLWINDOW (not shown) and WS_EX_APPWINDOW (shown).
You may have a look at my previous answer here; the main difference here is that you just have to count the windows that match the given requirements.
As other's have said you need to enumerate through the windows using the Win32 EnumWindows function, and get your count that way.
You can also enumerate through processes using Process.GetProcesses(); However windows like explorer windows which are not a separate process will not show up in that list.
int appCount = 0;
public bool EnumerateWindows(IntPtr hwnd, IntPtr lParam)
{
if (IsWindowVisible(hwnd))
{
StringBuilder sb = new StringBuilder();
string text = "";
GetWindowText(hwnd, sb, 1024);
text = sb.ToString();
if (text != string.Empty && text != "Program Manager")
{
appCount++;
}
}
return true;
}
private int GetAppCount()
{
appCount = 0;
EnumWindows(EnumerateWindows, new IntPtr(0));
return appCount;
}
internal delegate bool EnumThreadWindowsCallback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool EnumWindows(EnumThreadWindowsCallback callback, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern bool IsWindowVisible(IntPtr hwnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
As far as I know there is no managed way of accessing the taskbar. Here is a link that describes how to access the taskbar by the Windows API. However, I a quick scan did not show any "number of items" or something similar. Still it might point you in the right direction.
Can anyone provide me an example of how to use WM_CLOSE to close a small application like Notepad?
Provided you already have a handle to send to.
...Some Class...
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
//I'd double check this constant, just in case
static uint WM_CLOSE = 0x10;
public void CloseWindow(IntPtr hWindow)
{
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
...Continue Class...
Getting a handle can be tricky. Control descendant classes (WinForms, basically) have Handle's, and you can enumerate all top-level windows with EnumWindows (which requires more advanced p/invoke, though only slightly).
Suppose you want to close notepad. the following code will do it:
private void CloseNotepad(){
string proc = "NOTEPAD";
Process[] processes = Process.GetProcesses();
var pc = from p in processes
where p.ProcessName.ToUpper().Contains(proc)
select p;
foreach (var item in pc)
{
item.CloseMainWindow();
}
}
Considerations:
If the notepad has some unsaved text it will popup "Do you want to save....?" dialog or if the process has no UI it throws following exception
'item.CloseMainWindow()' threw an exception of type
'System.InvalidOperationException' base {System.SystemException}:
{"No process is associated with this object."}
If you want to force close process immediately please replace
item.CloseMainWindow()
with
item.Kill();
If you want to go PInvoke way you can use handle from selected item.
item.Handle; //this will return IntPtr object containing handle of process.