How can i get application name which is currently focused [duplicate] - c#

This question already has answers here:
C#: Detecting which application has focus
(3 answers)
Closed 6 years ago.
I am using windows forms and was wondering whether a user can get the name of other application, that get focused, or not.
e.g if i run an application then i should get the name of that application that recently started and is currently on focus.
i searched on google but didn't find any appropriate solution.
Thanks!

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
public string GetActiveWindowTitle()
{
var handle = GetForegroundWindow();
string fileName = "";
string name = "";
uint pid = 0;
GetWindowThreadProcessId(handle, out pid);
Process p = Process.GetProcessById((int)pid);
var processname = p.ProcessName;
switch (processname)
{
case "explorer": //metro processes
case "WWAHost":
name = GetTitle(handle);
return name;
default:
break;
}
string wmiQuery = string.Format("SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId LIKE '{0}'", pid.ToString());
var pro = new ManagementObjectSearcher(wmiQuery).Get().Cast<ManagementObject>().FirstOrDefault();
fileName = (string)pro["ExecutablePath"];
// Get the file version
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(fileName);
// Get the file description
name = myFileVersionInfo.FileDescription;
if (name == "")
name = GetTitle(handle);
return name;
}
public string GetTitle(IntPtr handle)
{
string windowText = "";
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
if (GetWindowText(handle, Buff, nChars) > 0)
{
windowText = Buff.ToString();
}
return windowText;
}

Related

get data from printer local port

I have done a virtual printer by using some sample code. But I don't know how to get data from it when it starts printing.
When it starts printing It gives notification that ERROR IN PRITNING.
And Why there is "C:/MyLocalPort.txt".
Anyone Help me to get data this virtual printer sets to print.
Here is the Sample Code:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Management;
namespace virtualPrinter
{
public static class PrinterClass // class which carries SetDefaultPrinter function
{
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetDefaultPrinter(string Printer);
}
class myPrinterClass
{
public static void getPrinterNames()
{
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
MessageBox.Show(printer);
}
}
public static void installPrinter(string printerName) //works on win 7,8,8.1,10 on both x84 and x64
{
Winspool.AddLocalPort(#"C:\MyLocalPort.txt");
//https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/rundll32-printui
// /if Installs a printer by using an .inf file.
// /b[name] Specifies the base printer name.
// /#[file] Specifies a command-line argument file and directly inserts the text in that file into the command line.
// /f[file] Species the Universal Naming Convention (UNC) path and name of the .inf file name or the output file name, depending on the task that you are performing. Use /F[file] to specify a dependent .inf file.
// /r[port] Specifies the port name.
// /m[model] Specifies the driver model name. (This value can be specified in the .inf file.)
string arg;
arg = "printui.dll , PrintUIEntry /if /b " + "\"" + printerName + "\"" + #" /f C:\Windows\inf\ntprint.inf /r " + "\"" + #"C:\MyLocalPort.txt" + "\"" + " /m " + "\"" + "Generic / Text Only" + "\""; //initial arg
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = "rundll32.exe";
p.Arguments = arg;
p.WindowStyle = ProcessWindowStyle.Hidden;
try
{
Process.Start(p);
MessageBox.Show(printerName + " installed succesfully!");
}
catch (Exception ex)
{
MessageBox.Show("Something went wrong. Try again!" );
}
}
public static bool printerExists(string printerName)
{
bool res = false;
foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
if (printer == printerName)
{
res = true;
}
}
return res;
}
public static void uninstallPrinter(string printerName)
{
string arg;
ProcessStartInfo p = new ProcessStartInfo();
arg = "printui.dll, PrintUIEntry /dl /n " + "\"" + printerName + "\"";
if (printerExists(printerName))
{
p.FileName = "rundll32.exe";
p.Arguments = arg;
p.WindowStyle = ProcessWindowStyle.Hidden;
try
{
Process.Start(p);
MessageBox.Show(printerName + " unistalled successfully");
}
catch (Exception ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
p = null;
}
}
public static string GetLocalIPAddress() //erxomeno feature
{
var host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
throw new Exception("No network adapters with an IPv4 address in the system!");
}
public static class Winspool
{
[StructLayout(LayoutKind.Sequential)]
private class PRINTER_DEFAULTS
{
public string pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[DllImport("winspool.drv", EntryPoint = "XcvDataW", SetLastError = true)]
private static extern bool XcvData(
IntPtr hXcv,
[MarshalAs(UnmanagedType.LPWStr)] string pszDataName,
IntPtr pInputData,
uint cbInputData,
IntPtr pOutputData,
uint cbOutputData,
out uint pcbOutputNeeded,
out uint pwdStatus);
[DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true)]
private static extern int OpenPrinter(
string pPrinterName,
ref IntPtr phPrinter,
PRINTER_DEFAULTS pDefault);
[DllImport("winspool.drv", EntryPoint = "ClosePrinter")]
private static extern int ClosePrinter(IntPtr hPrinter);
public static int AddLocalPort(string portName)
{
PRINTER_DEFAULTS def = new PRINTER_DEFAULTS();
def.pDatatype = null;
def.pDevMode = IntPtr.Zero;
def.DesiredAccess = 1; //Server Access Administer
IntPtr hPrinter = IntPtr.Zero;
int n = OpenPrinter(",XcvMonitor Local Port", ref hPrinter, def);
if (n == 0)
return Marshal.GetLastWin32Error();
if (!portName.EndsWith("\0"))
portName += "\0"; // Must be a null terminated string
// Must get the size in bytes. Rememeber .NET strings are formed by 2-byte characters
uint size = (uint)(portName.Length * 2);
// Alloc memory in HGlobal to set the portName
IntPtr portPtr = Marshal.AllocHGlobal((int)size);
Marshal.Copy(portName.ToCharArray(), 0, portPtr, portName.Length);
uint needed; // Not that needed in fact...
uint xcvResult; // Will receive de result here
XcvData(hPrinter, "AddPort", portPtr, size, IntPtr.Zero, 0, out needed, out xcvResult);
ClosePrinter(hPrinter);
Marshal.FreeHGlobal(portPtr);
return (int)xcvResult;
}
}
}
}
Ok, I Can't do this that way.
First I have to create a port monitor I have used mfilemon.dll
Then I created a port with that port monitor
Then Pasted All Driver files in System Driver Dictionary.
Then finally Added Printer And Done.
You can refer this
https://github.com/Gohulan/Virtual-Printer/blob/main/PrinterSetup/SpoolerHelper.cs
This contains all the steps to create a virtual printer to make a print to pdf virtual printer

Get icon from Process List instead of File

How would I be able to extract the icon from processlist instead of filenames as of currently? As of now the this works by opening Form Dialog, they click on a file, then it adds it into listView with icon. How to do I just get the processes icon's and display them int he listView?
[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public IntPtr iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
class Win32
{
public const uint SHGFI_ICON = 0x100;
public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
public const uint SHGFI_SMALLICON = 0x1; // 'Small icon
[DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath,
uint dwFileAttributes,
ref SHFILEINFO psfi,
uint cbSizeFileInfo,
uint uFlags);
}
private int nIndex = 0;
private void materialFlatButton13_Click_1(object sender, EventArgs e)
{
IntPtr hImgSmall; //the handle to the system image list
IntPtr hImgLarge; //the handle to the system image list
string fName; // 'the file name to get icon from
SHFILEINFO shinfo = new SHFILEINFO();
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\temp\\";
openFileDialog1.Filter = "All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
listView1.SmallImageList = imageList1;
listView1.LargeImageList = imageList1;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
fName = openFileDialog1.FileName;
//Use this to get the small Icon
hImgSmall = Win32.SHGetFileInfo(fName, 0, ref shinfo,
(uint)Marshal.SizeOf(shinfo),
Win32.SHGFI_ICON |
Win32.SHGFI_SMALLICON);
System.Drawing.Icon myIcon =
System.Drawing.Icon.FromHandle(shinfo.hIcon);
imageList1.Images.Add(myIcon);
//Add file name and icon to listview
listView1.Items.Add(fName, nIndex++);
}
You can find processes information using a WMI query on Win32_Process and use ExecutablePath to find executable path of the process. Then you can use Icon.ExtractAssociatedIcon to extract the associated icon of the process:
Example
Drop an ImageList on the form and set its ColorDepth to Depth32Bit and its ImageSize to 32,32. The drop a ListView on the form and set its LargImageList to imageList1 which you created in the first step.
Add reference to System.Management.dll and add using System.Management; and use below code to fill listView1 with icons:
var query = "SELECT ProcessId, Name, ExecutablePath FROM Win32_Process";
using (var searcher = new ManagementObjectSearcher(query))
using (var results = searcher.Get())
{
var processes = results.Cast<ManagementObject>().Select(x => new
{
ProcessId = (UInt32)x["ProcessId"],
Name = (string)x["Name"],
ExecutablePath = (string)x["ExecutablePath"]
});
foreach (var p in processes)
{
if (System.IO.File.Exists(p.ExecutablePath))
{
var icon = Icon.ExtractAssociatedIcon(p.ExecutablePath);
var key = p.ProcessId.ToString();
this.imageList1.Images.Add(key, icon.ToBitmap());
this.listView1.Items.Add(p.Name, key);
}
}
}
Then you will have such result:
Solution for 32-bit AND 64-bit processes
(with only System.Diagnostics)
This will get the icon of the main module (The exe file). It will also work if the architecture of the accessing and the targeted process differs:
var icon = Process.GetProcessById(1234).GetIcon()
With the extension methods:
public static class ProcessExtensions {
[DllImport("Kernel32.dll")]
private static extern uint QueryFullProcessImageName([In] IntPtr hProcess, [In] uint dwFlags, [Out] StringBuilder lpExeName, [In, Out] ref uint lpdwSize);
public static string GetMainModuleFileName(this Process process, int buffer = 1024) {
var fileNameBuilder = new StringBuilder(buffer);
uint bufferLength = (uint)fileNameBuilder.Capacity + 1;
return QueryFullProcessImageName(process.Handle, 0, fileNameBuilder, ref bufferLength) != 0 ?
fileNameBuilder.ToString() :
null;
}
public static Icon GetIcon(this Process process) {
try {
string mainModuleFileName = process.GetMainModuleFileName();
return Icon.ExtractAssociatedIcon(mainModuleFileName);
}
catch {
// Probably no access
return null;
}
}
}
See here: C#: How to get the full path of running process?
foreach(var process in Process.GetProcesses()){
string fullPath = process.MainModule.FileName;
// do your stuff here
}
You can substitute this into your existing code. Or, tailor it to what you're doing now.
Edit: added the code to get processes

How to find the installed Software name and version for the running processes

I have derived the list of current running process based on this code
static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
foreach (Process p in Process.GetProcesses())
{
if (p.Id == pid)
new TrayLog().Log(
System.Security.Principal.WindowsIdentity.GetCurrent().Name + "^" + p.Id + "^" + p.ProcessName + "^" + System.DateTime.Now.ToString("yyyyMMddHHmmss")
);
}
}
And the list of current installed software are derived based on the below code
RegistryKey key;
// search in: CurrentUser
key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
try
{
if (!subkey.GetValue("DisplayName").Equals(null))
{
DataRow rows = dts.NewRow();
rows["Machine_UUID"] = Machine_UUID;
rows["Display_Name"] = subkey.GetValue("DisplayName").ToString();
rows["Display_Version"] = subkey.GetValue("DisplayVersion").ToString();
rows["Internal_Version"] = subkey.GetValue("Version").ToString();
rows["Installation_Date"] = DateTime.ParseExact(subkey.GetValue("InstallDate").ToString(), "yyyyMMdd", null);
rows["strInstallation_Date"] = ((DateTime)rows["Installation_Date"]).ToString("yyyyMMdd");
rows["Installation_Location"] = subkey.GetValue("InstallLocation").ToString();
rows["Installation_Source"] = subkey.GetValue("InstallSource").ToString();
rows["Uninstall_String"] = subkey.GetValue("UninstallString").ToString();
rows["Estimated_Size"] = subkey.GetValue("EstimatedSize").ToString();
dts.Rows.Add(rows);
}
}
catch (Exception e) { }
}
I need to match these two list, such that I need to get the Software name and other details of the running process...
You could get the Process.MainModule.FileName and then use FileVersionInfo.FileDescription to get the display name.
Then use this key, which is a List of all the current installed programs, and their uninstall information.
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
Now get the display name from the keys and compare them with the process display names.

How to get a active file/Application Complete path with file Extension

i am trying to track active Application/File on my system using Windows application(c#).
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString() + " " + handle;
}
return null;
}
private string GetActiveWindowPath()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
int handleint = int.Parse(handle + "");
SHDocVw.ShellWindows explorer = new SHDocVw.ShellWindows();
//var xy = new SHDocVw.InternetExplorerMedium();
var xpl = explorer.Cast<SHDocVw.InternetExplorerMedium>().Where(hwnd => hwnd.HWND == handleint).FirstOrDefault();
if (xpl != null)
{
string path = new Uri(xpl.LocationURL).LocalPath;
return ("location:" + xpl.LocationName + " path:" + path);
}
return "HWND" + handleint;
}
But by using the above code i only getting file title not the complete file name with extension and by using other method i am just getting folder info.
But i am trying to get the file extension with path
Eg: D:\New Folder\sampleFile.txt
public static string GetMainModuleFilepath(int processId)
{
string wmiQueryString = "SELECT * FROM Win32_Process WHERE ProcessId = " + processId;
using (var searcher = new ManagementObjectSearcher(wmiQueryString))
{
using (var results = searcher.Get())
{
ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
if (mo != null)
{
return (string)mo["CommandLine"];
}
}
}
Process testProcess = Process.GetProcessById(processId);
return null;
}
by using this function you will get a string like
"c:..\notepade.exe" D:\New Folder\sampleFile.txt"
after that split as you like to get the path.
I have written this code for office 2007 you guys can debug and find the proper path for the higher versions.

Run command line program silently with c# on wince

I once again need some help.
I'm using the .net Compact Framework and the programming language C# to develop for mobile devices that are running WinCE 5.0.
What I want to accomplish is to programmatically mount a network drive. To do so, the app runs the following code in a background thread:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "net";
startInfo.UseShellExecute = false;
startInfo.Arguments = #"use logs \\server\logs /user:dom\uname /password:pw";
Process p = Process.Start(startInfo);
p.WaitForExit(5000);
Now my problem is, that this code will display a console in the foreground and writes the command to it and the answer from the command as well. Also, the console won't disappear anymore.
The parameter 'UseShellExecute' doesn't seem to show any effect.
I've read about the parameter 'CreateNoWindow', but it doesn't exist in the compact framework.
So folks, is there a possibility to run net-commands in the background, the user shouldn't notice and certainly not see the command including the password in plain text.
I hope you get the idea.
Many thanks in advance
Toby
Thank you very much Shaihi,
you set me on the right track.
The code and links you provided got me finally to the following solution that works fine for me:
[DllImport("coredll.dll")]
private static extern int WNetAddConnection3(IntPtr hWndOwner,
ref NetResource lpNetResource, string lpPassword, string lpUserName, int dwFlags);
[DllImport("coredll.dll")]
static extern int WNetCancelConnection2(string lpName, Int32 dwFlags, bool bForce);
...
try
{
NetResource logsResource = new NetResource();
logsResource.lpLocalName = "logs";
logsResource.lpRemoteName = #"\\server\logs";
logsResource.dwType = 0x1; //const int RESOURCETYPE_DISK = 0x1
logsResource.dwScope = 0;
logsResource.dwUsage = 0;
logsResource.dwDisplayType = 0;
//try to connect the network resource
WNetAddConnection3(new IntPtr(0), ref logsResource, #"pass", #"dom\user", 0);
//copy files to the server
string[] logfiles = Directory.GetFiles(#"\System\Logs\");
foreach (string logfile in logfiles)
{
File.Copy(logfile, #"\network\logs\" +
logfile.Substring(logfile.LastIndexOf(#"\") + 1), true);
}
}
catch
{
}
finally
{
//try to disconnect network resource
WNetCancelConnection2("logs", 0, false);
}
The two WNET function calls return an integer value. If this value equals to 0 the operation finished successfully. Common codes I experienced are 53 and 85. Refer to this list to get a clue what the numbers mean!
You can use WNetAddConnetion3 by P/Invoking it (here is the declaration).Here is the declaration for the NetResource struct:
[StructLayout(LayoutKind.Sequential)]
internal struct NetResource
{
public uint dwScope;
public uint dwType;
public uint dwDisplayType;
public uint dwUsage;
[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
public string lpLocalName;
[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
public string lpRemoteName;
[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
public string lpComment;
[MarshalAs(UnmanagedType.LPWStr, SizeConst = 64)]
public string lpProvider;
}
Create a Windows Form Application instead of Console Application and replace all the code in Main method of program.cs with
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "net";
startInfo.UseShellExecute = false;
startInfo.Arguments = #"use logs \\server\logs /user:dom\uname /password:pw";
Process p = Process.Start(startInfo);
p.WaitForExit(5000);
Delete Form1.cs

Categories