I'm trying to hide Internet Explorer windows using PowerShell and have tried different approaches but no luck. I've found this code at https://superuser.com/questions/1079133/run-a-windows-application-without-displaying-its-gui, This only works for Notepad. I need help to make this code work for IE i.e an internet explorer window is opened with page Google. I want to hide this window using below code.
$definition = #"
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public static void Show(string wClass, string wName)
{
IntPtr hwnd = FindWindow(wClass, wName);
if ((int)hwnd > 0)
ShowWindow(hwnd, 1);
}
public static void Hide(string wClass, string wName)
{
IntPtr hwnd = FindWindow(wClass, wName);
if ((int)hwnd > 0)
ShowWindow(hwnd, 0);
}
"#
add-type -MemberDefinition $definition -Namespace my -Name WinApi
[my.WinApi]::Hide('Internet Explorer', 'Google - Internet Explorer')
This code doesn't work to hide internet explorer window.
I've figured out that it works when replace 'Internet Explorer' with 'IEFrame'.
it worked with below line
[my.WinApi]::Hide("IEFrame", 'Google - Internet Explorer')
Related
I have a project that I developed about seven years ago in Win95, and works in Win7. It is developed in Visual Studio 2005. This application looks for the "You have new email" tray icon that appears in the tray (in various forms) by most email applications. I use it to blink an LED on a serial port, so I can glance in the room to see if I have email, rather than going to the computer, moving the mouse to wake the screen, and looking at the tray or the email program itself. It's a time-saver and aggravation-reducer.
It works by getting the system tray handle, and then using this handle, iterates all the buttons in the tray, and comparing the button text for a specific string. Here is the part that is having a problem in Windows 10:
IntPtr hWndTray = GetSystemTrayHandle();
listBoxIcons.Items.Add(string.Format("Tray handle=0x{0:X}", (int)hWndTray));
UInt32 count = User32.SendMessage(hWndTray, TB.BUTTONCOUNT, 0, 0);
listBoxIcons.Items.Add(string.Format("Tray button count={0:D}", count));
The call to GetSystemTrayHandle() works fine, I get a non-null value. The call to SendMessage(hWndTray, TB.BUTTONCOUNT, ...) returns zero, even though in the test case I'm using, there are nine buttons in the tray.
Did the concept of "tray icons", or the API calls to get them, change in Windows 10?
Here are the API calls I am using:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
From User32.cs:
internal class TB
{
public const uint GETBUTTON = WM.USER + 23 ;
public const uint BUTTONCOUNT = WM.USER + 24 ;
public const uint CUSTOMIZE = WM.USER + 27 ;
public const uint GETBUTTONTEXTA = WM.USER + 45 ;
public const uint GETBUTTONTEXTW = WM.USER + 75 ;
}
Here is the GetSystemTrayHandle() method:
private IntPtr GetSystemTrayHandle()
{
IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
if (hWndTray != IntPtr.Zero)
{
hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "TrayNotifyWnd", null);
if (hWndTray != IntPtr.Zero)
{
hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "SysPager", null);
if (hWndTray != IntPtr.Zero)
{
hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "ToolbarWindow32", null);
return hWndTray;
}
}
}
return IntPtr.Zero;
}
The "SendMessage" call has existed since about the inception of Windows, so if it no longer works, TB.BUTTONCOUNT may have been redefined or superceded in Windows 10. I cannot find any information on this.
Edit: Developed on Win98, not Win95.
Remy's message spurred further research into notification icons. The answer was found using information at http://www.ghacks.net/2015/03/11/manage-and-display-system-tray-icons-in-windows-10/. Once notifications were enabled, for example "email" and "volume," this program, as written, can now see them.
is it possible to simulate Click on a process without actually clicking on it?
e.g. I wanna Click on a running Calculator with mouse stand still. is this possible?
If you are just trying to click a button within a fairly typical labels, fields, and buttons application, you can use a little bit of P/Invoke to use FindWindow and SendMessage to the control.
If you are not already familiar with Spy++, now is the time to start!
It is packaged with Visual Studio 2012 RC in: C:\Program Files\Microsoft Visual Studio 11.0\Common7\Tools. It should be similarly found for other versions.
Try this as Console C# application:
class Program
{
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
private const uint BM_CLICK = 0x00F5;
static void Main(string[] args)
{
// Get the handle of the window
var windowHandle = FindWindow((string)null, "Form1");
// Get button handle
var buttonHandle = FindWindowEx(windowHandle, IntPtr.Zero, (string)null, "A Huge Button");
// Send click to the button
SendMessage(buttonHandle, BM_CLICK, 0, 0);
}
}
This gets the handle to the window captioned "Form1". Using that handle, it gets a handle to the Button within the Window. Then sends a message of type "BM_CLICK" with no useful params to the button control.
I used a test WinForms app as my target. A single button and some code behind to increment a counter.
You should see the counter increment when you run the P/Invoke console application. However, you will not see the button animate.
You could also use the Spy++ Message Logger function. I recommend a filter to BM_CLICK and maybe WM_LBUTTONDOWN/WM_LBUTTONUP (what a manual click will give you).
Hope that helps!
i want to place a small form above the notification icons
in left-to-right interface the icons to the right of the screen
in right-to-left interface the icons to the left of the screen
i want the code for that to work on xp and win7 please
Is this what you're looking for?
private static bool IsRightToLeft()
{
return CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft;
}
The flag you're looking for is WS_EX_LAYOUTRTL (400000 hexadecimal). You get this flag by calling GetWindowLong(FindWindow(L"HHTaskBar", NULL), GWL_EXSTYLE).
Any System.Windows.Forms.Control support such check: Control.RightToLeft.
MSDN
Stuart Dunkeld
that dosnt help , CultureInfo has nothing to do with the interface
if i could locate the location of the start button (on the taskbar) that would help
If you insist you can find the position and size of the Windows start button.
To do that, first add this inside your class:
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hwnd, ref Rectangle rectangle);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, IntPtr className, string lpszWindow);
Then use such code.. in this example I show its width but you can read its Left/Right location as well:
IntPtr hwndTaskBarWin = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", null);
IntPtr hwndStartButton = FindWindowEx(hwndTaskBarWin, IntPtr.Zero, "Button", null);
if (hwndStartButton.Equals(IntPtr.Zero))
{
//Maybe Vista/Windows7?
hwndStartButton = FindWindowEx(IntPtr.Zero, IntPtr.Zero, (IntPtr)0xC017, null);
}
if (hwndStartButton.Equals(IntPtr.Zero))
{
MessageBox.Show("Sorry, can't find the Start button/orb");
}
else
{
Rectangle rect = Rectangle.Empty;
if (GetWindowRect(hwndStartButton, ref rect))
MessageBox.Show("Start button width: " + rect.Width);
}
Tested successfully under XP and Windows7, the Vista/7 trick credit goes to Waylon Flynn in his answer to this question.
Every time i switch branch in git, visual studio pisses me off with those popups asking me if I want to reload project or ignore changes.
How to automatically reload solution?
Try VSCommands 2010 Lite, it allows you to reload all projects:
I found this also very irritating, so i looked for a solution myself. And came up with a little console app I wrote, with the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
internal class Program
{
// For Windows Mobile, replace user32.dll with coredll.dll
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
// static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
internal static void Main(string[] args)
{
do
{
Console.Title = "Waiting...";
Console.WriteLine("Waiting...");
IntPtr hwnd = FindWindowByCaption(IntPtr.Zero, "File Modification Detected");
while ((int)hwnd == 0)
{
Thread.Sleep(500);
hwnd = FindWindowByCaption(IntPtr.Zero, "File Modification Detected");
}
Console.Title = "Found one, kill it...";
Console.WriteLine("Found one, kill it...");
// ShowNormal = 1
// Show = 5
ShowWindow(hwnd, 5);
SendKeys.SendWait("{ENTER}");
Thread.Sleep(500);
hwnd = IntPtr.Zero;
} while (true);
}
}
If you start this program, it waits for those popups, and clicks on Reload automatically.
I totally agree. I cannot believe they did not fix it in VS 2010.
But just an FYI:
This one is closed Microsoft Connect.
This one seems to be still active and has a workaround(which is not worth the time for me) : Microsoft Active
I guess this tells you how seriously Microsoft takes this:
Issue is still outstanding from 5 years ago: 283618
I can display and select a single file in windows explorer like this:
explorer.exe /select, "c:\path\to\file.txt"
However, I can't work out how to select more than one file. None of the permutations of select I've tried work.
Note: I looked at these pages for docs, neither helped.
https://support.microsoft.com/kb/314853
http://web.archive.org/web/20100716112458/http://www.infocellar.com:80/Win98/explorer-switches.htm
This should be possible with the shell function SHOpenFolderAndSelectItems
EDIT
Here is some sample code showing how to use the function in C/C++, without error checking:
//Directory to open
ITEMIDLIST *dir = ILCreateFromPath(_T("C:\\"));
//Items in directory to select
ITEMIDLIST *item1 = ILCreateFromPath(_T("C:\\Program Files\\"));
ITEMIDLIST *item2 = ILCreateFromPath(_T("C:\\Windows\\"));
const ITEMIDLIST* selection[] = {item1,item2};
UINT count = sizeof(selection) / sizeof(ITEMIDLIST);
//Perform selection
SHOpenFolderAndSelectItems(dir, count, selection, 0);
//Free resources
ILFree(dir);
ILFree(item1);
ILFree(item2);
The true way of selecting multiple files in Explorer is the next
Unmanaged code looks like this (compiled from China code posts with fixing its bugs)
static class NativeMethods
{
[DllImport("shell32.dll", ExactSpelling = true)]
public static extern int SHOpenFolderAndSelectItems(
IntPtr pidlFolder,
uint cidl,
[In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
uint dwFlags);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr ILCreateFromPath([MarshalAs(UnmanagedType.LPTStr)] string pszPath);
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214F9-0000-0000-C000-000000000046")]
public interface IShellLinkW
{
[PreserveSig]
int GetPath(StringBuilder pszFile, int cch, [In, Out] ref WIN32_FIND_DATAW pfd, uint fFlags);
[PreserveSig]
int GetIDList([Out] out IntPtr ppidl);
[PreserveSig]
int SetIDList([In] ref IntPtr pidl);
[PreserveSig]
int GetDescription(StringBuilder pszName, int cch);
[PreserveSig]
int SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
[PreserveSig]
int GetWorkingDirectory(StringBuilder pszDir, int cch);
[PreserveSig]
int SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
[PreserveSig]
int GetArguments(StringBuilder pszArgs, int cch);
[PreserveSig]
int SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
[PreserveSig]
int GetHotkey([Out] out ushort pwHotkey);
[PreserveSig]
int SetHotkey(ushort wHotkey);
[PreserveSig]
int GetShowCmd([Out] out int piShowCmd);
[PreserveSig]
int SetShowCmd(int iShowCmd);
[PreserveSig]
int GetIconLocation(StringBuilder pszIconPath, int cch, [Out] out int piIcon);
[PreserveSig]
int SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
[PreserveSig]
int SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
[PreserveSig]
int Resolve(IntPtr hwnd, uint fFlags);
[PreserveSig]
int SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
[Serializable, StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), BestFitMapping(false)]
public struct WIN32_FIND_DATAW
{
public uint dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
public static void OpenFolderAndSelectFiles(string folder, params string[] filesToSelect)
{
IntPtr dir = ILCreateFromPath(folder);
var filesToSelectIntPtrs = new IntPtr[filesToSelect.Length];
for (int i = 0; i < filesToSelect.Length; i++)
{
filesToSelectIntPtrs[i] = ILCreateFromPath(filesToSelect[i]);
}
SHOpenFolderAndSelectItems(dir, (uint) filesToSelect.Length, filesToSelectIntPtrs, 0);
ReleaseComObject(dir);
ReleaseComObject(filesToSelectIntPtrs);
}
private static void ReleaseComObject(params object[] comObjs)
{
foreach (object obj in comObjs)
{
if (obj != null && Marshal.IsComObject(obj))
Marshal.ReleaseComObject(obj);
}
}
}
it cannot be done through explorer.exe
Depending on what you actually want to accomplish you may be able to do it with AutoHotKey. It is an amazing free tool for automating things you normally can't do. It should come with Windows. This script will select your file and highlight the next two files below it when you hit F12.
F12::
run explorer.exe /select`, "c:\path\to\file.txt"
SendInput {Shift Down}{Down}{Down}{Shift Up}
return
It is also possible to just put those two middle lines in a text file and then pass it is a parm to autohotkey.exe. They have an option to compile the script also, which would make it a standalone exe that you could call. Works great with a great help file.
#Orion, It is possible to use autohotkey from C#. You can make an autohotkey script into a standalone executable (about 400k) that can be launched by your C# app (just the way you are launching explorer). You can also pass it command line parameters. It does not have any runtime requirements.
There are COM Automation LateBinding IDispatch interfaces, these are easy to use from PowerShell, Visual Basic.NET and C#, some sample code:
$shell = New-Object -ComObject Shell.Application
function SelectFiles($filesToSelect)
{
foreach ($fileToSelect in $filesToSelect)
{
foreach ($window in $shell.Windows())
{
foreach ($folderItem in $window.Document.Folder.Items())
{
if ($folderItem.Path -eq $fileToSelect)
{
$window.Document.SelectItem($folderItem, 1 + 8)
}
}
}
}
}
-
Option Strict Off
Imports Microsoft.VisualBasic
Public Class ExplorerHelp
Shared ShellApp As Object = CreateObject("Shell.Application")
Shared Sub SelectFile(filepath As String)
For Each i In ShellApp.Windows
For Each i2 In i.Document.Folder.Items()
If i2.Path = filepath Then
i.Document.SelectItem(i2, 1 + 8)
Exit Sub
End If
Next
Next
End Sub
End Class
https://learn.microsoft.com/en-us/windows/win32/shell/shellfolderview-selectitem
This is one of those questions where it may be good to consider what you're trying to achieve, and whether there's a better method.
To add some more context -
Our company develops a C# client application, which allows users to load files and do stuff with them, kind of like how iTunes manages your MP3 files without showing you the actual file on disk.
It's useful to select a file in the application, and do a 'Show me this file in Windows Explorer` command - this is what I'm trying to achieve, and have done so for single files.
We have a ListView which allows users to select multiple files within the application, and move/delete/etc them. It would be nice to have this 'show me this file in windows' command work for multiple selected files - at least if all the source files are in the same directory, but if it's not possible then it's not a major feature.
I suppose you can use FindWindowEx to get the SysListView32 of Windows Explorer, then use SendMessage with LVM_SETITEMSTATE to select the items. The difficulty being to know the position of the items... Perhaps LVM_FINDITEM can be used for this.
Grr i would like to do this as well. Media Player does it when you select 2+ files and right click and do "open file location" but not exactly sure how (nor do i really feel like spending the time w/ procmon to figure it out).