MacOs active window title using C# - c#

So I have a C# application using Mono and Gtk+2 running on Mac
Is there some way to get active application window title?
https://stackoverflow.com/a/37368813/3794943 says that I need CGWindowListCopyWindowInfo (I already have the rest of their recipe, like process identifier, front most application, etc.).
Where can I get CGWindowListCopyWindowInfo or something similar from? Or is there some other way to get active window title when using mono on mac os?

Ok, finally found it here: https://forums.xamarin.com/discussion/comment/95429/#Comment_95429
At first you import that function like this:
[DllImport(#"/System/Library/Frameworks/QuartzCore.framework/QuartzCore")]
static extern IntPtr CGWindowListCopyWindowInfo(CGWindowListOption option, uint relativeToWindow);
Then you call it like this:
string result = null;
IntPtr windowInfo = CGWindowListCopyWindowInfo(CGWindowListOption.OnScreenOnly, 0);
NSArray values = (MonoMac.Foundation.NSArray)Runtime.GetNSObject(windowInfo);
for (ulong i = 0, len = values.Count; i < len; i++)
{
NSObject window = Runtime.GetNSObject(values.ValueAt(i));
NSString key = new NSString("kCGWindowOwnerPID");
NSNumber value = (MonoMac.Foundation.NSNumber)window.ValueForKey(key);
// and so on
}
P.S. MonoMac package must be added using NuGet

Related

How to pin application into taskbar programmatically

I have tried this code it works fine for unpinning application from taskbar in Windows 10 but it is not working for pinning application into taskbar.
public static void PinUnpinTaskbar(bool pin)
{
string l_strFilePath = System.Reflection.Assembly.GetEntryAssembly().Location;
if (!File.Exists(l_strFilePath)) throw new FileNotFoundException(l_strFilePath);
int MAX_PATH = 255;
var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
//uncomment the following line to pin to start instead
//actionIndex = pin ? 51201 : 51394;
StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
IntPtr hShell32 = LoadLibrary("Shell32.dll");
LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
string localizedVerb = szPinToStartLocalized.ToString();
string path = Path.GetDirectoryName(l_strFilePath);
string fileName = Path.GetFileName(l_strFilePath);
// create the shell application object
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
for (int i = 0; i < verbs.Count(); i++)
{
dynamic verb = verbs.Item(i);
if (verb.Name.Equals(localizedVerb))
{
verb.DoIt();
return;
}
}
return;
}
Cannot see anything wrong in your solution, also tried it several times but the verb does no longer exist. After some research I found this:
Update KB3093266 removes shell.Application object 'taskbarpin' verb
Update KB3093266 removes shell.Application object 'taskbarpin' verb
for adding taskbar pin item pins
It is most likely broken by one of the updates that KB3093266
supersedes
And this (Powershell but same library): Pin to Taskbar fails in Windows 10

Can I get the MainWindowHandle of an Electron window?

I have an Electron app that spawns a C# app. The C# app wants to fetch the Electron BrowserWindow's MainWindowHandle, but it always returns IntPtr.Zero, and I don't know why.
The docs say:
You must use the Refresh method to refresh the Process object to get the current main window handle if it has changed.
If the associated process does not have a main window, the MainWindowHandle value is zero. The value is also zero for processes that have been hidden, that is, processes that are not visible in the taskbar.
My C# app runs Refresh just in case, and my Electron window is definitely visible, and I see the icon in the taskbar:
My Electron code launches my C# app and sends it the renderer process' pid (you can download the electron-quick-start app and make the following changes to reproduce):
const mainWindow = new BrowserWindow({width: 800, height: 600, show: false});
mainWindow.once("ready-to-show", () => {
mainWindow.show();
});
mainWindow.once("show", () => {
// by now, our window should have launched, and we should have a pid for it
const windowPid = mainWindow.webContents.getOSProcessId();
const proc = cp.spawn("my/exeFile.exe");
// send the pid to the C# process
const buff = Buffer.allocUnsafe(4);
buff.writeIntLE(windowPid, 0, 4);
proc.stdin.write(buff);
});
And the C# process starts and joins a thread with an infinite loop that reads that pid and tries to get its main window handle:
byte[] buffer = new byte[4];
inStream.Read(buffer, 0, 4);
int pid = BitConverter.ToInt32(buffer, 0); // I've verified that the pid I'm sending is the pid I'm getting
Process proc = Process.GetProcessById(pid);
proc.Refresh(); // just in case
IntPtr windowHandler = proc.MainWindowHandle; // 0x00000000
IntPtr handle = proc.Handle; // 0x000004b8
Am I sending the right electron pid over? I don't see which other pid I can use. The main process pid doesn't seem right, so all I'm left with is the renderer pid, which is what I'm using.
Should I expect MainWindowHandle to be set when the window is an Electron/Chromium window, or does this only work for C# windows?
There's a BrowserWindow API for this:
win.getNativeWindowHandle()
which return the HWND you can use in any native windows code
In your case I guess you can use it like this:
byte[] bytes = new byte[8];
for (int i = 0; i < data.Length; i++) {
object item = data[i];
bytes[i] = (byte)(int)item;
}
return BitConverter.ToUInt64(bytes, 0);

The right way for multithreading in c++ with using of boost library

I've got a C++ dll and I've used boost library to implement multithreading and then I’d like to use this dll in a C# program.
I did it and my program is running as I expected and there isn’t any problems in my system.
When I create an installer with using of Advanced Installer and install it as a new program in my system, (which I've developed application on it) everything is ok too and there isn't any problems. But when I installed this program in other systems and run it, at first, program will run normally but when it wants to create threads and run them, program will be stopped.
A part of my codes in C++ dll are as follow:
struct ThreadParams
{
int thetaStart,
thetaEnd,
rStart;
vector<string> files;
}thParams;
const int NUM_OF_THREADS = 5;
extern "C"
{
__declspec(dllexport) int __stdcall Start(const char *path)
{
thParams.files = listFilesInDirectory(path);
int step = thParams.files.size()/NUM_OF_THREADS;
thParams.rStart = 1;
thParams.thetaStart = 0;
thParams.thetaEnd = 360;
boost::thread_group tgroup;
FILE *output_text;
char *buffer = new char[128];
for (int i = 0; i < NUM_OF_THREADS; i++)
{
sprintf(buffer,"out%d.txt",i+1);
output_text = fopen(buffer,"wt");
int start = i*step;
int end = (thParams.files.size() - (start+step)) >= step ? (start+step) : thParams.files.size();
tgroup.create_thread(boost::bind(ThreadProcess,start,end,output_text,i+1));
}
tgroup.join_all();
_fcloseall();
delete buffer;
buffer = NULL;
}
}
void ThreadProcess(int start, int end, FILE *out, int threadID)
{
for(int i = start; i < end; ++i)
{
fprintf(out,"%s\n",thParams.files[i].c_str());
}
}
Could anybody help me to resolve this problem, please?
Thanks in advance.
Boost.thread is one of the few boost libraries which are not header-only and they need a compiled library to be present. Most likely, you linked your code with dynamic version of boost.thread.
Your solutions:
Link with static version of boost.thread
Include dynamic library with your distribution.

Disconnect and Reconnect Displays Programmatically

Question: What is the best way to programmatically disconnect and reconnect displays programmatically?
The Goal: Kill the video output (black screen with no backlight) on a display and later turn it back on. Imagine unplugging the video cord from the monitor, then plugging it back in.
My Attempt:
// Get the monitor to disable
uint iDevNum = 0;
DISPLAY_DEVICE displayDevice = new DISPLAY_DEVICE();
displayDevice.cb = Marshal.SizeOf(displayDevice);
EnumDisplayDevices(null, iDevNum, ref displayDevice, 0))
DEVMODE devMode = new DEVMODE();
EnumDisplaySettings(displayDevice.DeviceName, 0, ref devMode);
//
// Do something here to disable this display device!
//
// Save the display settings
ChangeDisplaySettingsEx(displayDevice.DeviceName, ref devMode,
IntPtr.Zero, ChangeDisplaySettingsFlags.CDS_NONE, IntPtr.Zero);
I can interact with each display, but I can't figure out how to disconnect one.
It is similar to "Disconnect this display" in the Screen Resolution properties in Windows 7:
Notes:
Turning off video output on all displays won't work because I need the other monitors to stay on.
The desktop area on the "dead" display does NOT need to be usable when it is off. Also, it is fine if windows move around.
References:
SO: Enabling a Second Monitor
How to Turn Off a Monitor
1) Get MultiMonitorHelper from here:
https://github.com/ChrisEelmaa/MultiMonitorHelper/tree/master
2) Extend Win7Display to disconnect the display:
using MultiMonitorHelper.DisplayModels.Win7.Enum;
using MultiMonitorHelper.DisplayModels.Win7.Struct;
/// <summary>
/// Disconnect a display.
/// </summary>
public void DisconnectDisplay(int displayNumber)
{
// Get the necessary display information
int numPathArrayElements = -1;
int numModeInfoArrayElements = -1;
StatusCode error = CCDWrapper.GetDisplayConfigBufferSizes(
QueryDisplayFlags.OnlyActivePaths,
out numPathArrayElements,
out numModeInfoArrayElements);
DisplayConfigPathInfo[] pathInfoArray = new DisplayConfigPathInfo[numPathArrayElements];
DisplayConfigModeInfo[] modeInfoArray = new DisplayConfigModeInfo[numModeInfoArrayElements];
error = CCDWrapper.QueryDisplayConfig(
QueryDisplayFlags.OnlyActivePaths,
ref numPathArrayElements,
pathInfoArray,
ref numModeInfoArrayElements,
modeInfoArray,
IntPtr.Zero);
if (error != StatusCode.Success)
{
// QueryDisplayConfig failed
}
// Check the index
if (pathInfoArray[displayNumber].sourceInfo.modeInfoIdx < modeInfoArray.Length)
{
// Disable and reset the display configuration
pathInfoArray[displayNumber].flags = DisplayConfigFlags.Zero;
error = CCDWrapper.SetDisplayConfig(
pathInfoArray.Length,
pathInfoArray,
modeInfoArray.Length,
modeInfoArray,
(SdcFlags.Apply | SdcFlags.AllowChanges | SdcFlags.UseSuppliedDisplayConfig));
if (error != StatusCode.Success)
{
// SetDisplayConfig failed
}
}
}
3) Extend Win7Display to reconnect the display using an answer from this post:
using System.Diagnostics;
/// <summary>
/// Reconnect all displays.
/// </summary>
public void ReconnectDisplays()
{
DisplayChanger.Start();
}
private static Process DisplayChanger = new Process
{
StartInfo =
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "DisplaySwitch.exe",
Arguments = "/extend"
}
};
4) Update the methods in IDisplay.
5) Implement the methods:
IDisplayModel displayModel = DisplayFactory.GetDisplayModel();
List<IDisplay> displayList = displayModel.GetActiveDisplays().ToList();
displayList[0].DisconnectDisplay(0);
displayList[0].ReconnectDisplays();
There's a github project that I STILL haven't got around, but it's a starting point. You need to use Win7 specific API in order to change settings. ChangeDisplaySettings won't work.
Have a look: https://github.com/ChrisEelmaa/MultiMonitorHelper
This is what you need to do:
update the IDisplay interface to support TurnOff() method,
and then call it:
var displayModel = DisplayFactory.GetDisplayModel();
var displayList = displayModel.GetActiveDisplays().ToList();
var firstDisplay = displayList[0].TurnOff();
How to implement TurnOff()? I WOULD imagine this is how(I might be wrong here now):
You need to break the connection between GPU & monitor through breaking the "paths". You can break path between source and target like this:
Call SetDisplayConfig() and pass inside specific paths and make sure you map out the DISPLAYCONFIG_PATH_ACTIVE from the DISPLAY_PATH_INFO structure flags integer.
http://msdn.microsoft.com/en-us/library/windows/hardware/ff553945(v=vs.85).aspx
Sorry for not being more helpful, but this is pretty hardcore stuff, it took me quite a while to even understand the basics of that API. It's a starting point :-),
take a look at the example how to rotate specific monitor in Win7: How do I set the monitor orientation in Windows 7?
In all honesty, just wrap the DisplaySwitch.exe for Win7, and pass /internal or /external(depending if you want to disable/enable first/second monitor), this might or might not work for >2 monitors.

How to get the name of current application in C#

I want to get the name of current application that it's running on windows.
For example, if i work with i.e, this function give "Internet explorer" or if i work with Google chrome, give Chrome...
System.AppDomain.CurrentDomain.FriendlyName
or maybe
System.Reflection.Assembly.GetExecutingAssembly()
or if you mean that you want the name of the active window then you should look at;
How do I get the title of the current active window using c#?
You can use Assembly.FullName
System.Reflection.Assembly.GetEntryAssembly().FullName;
Please also take a look at this question:
How do I get the name of the current executable in C#?
Try this, If you have used GetWindowThreadProcessId.
public String GetActiveFileNameTitle()
{
IntPtr hWnd = GetForegroundWindow();
uint procId = 0;
GetWindowThreadProcessId(hWnd, out procId);
var proc = Process.GetProcessById((int)procId);
if (proc != null)
{
return proc.MainModule.FileVersionInfo.ProductName;
}
}

Categories

Resources