121 lines
3.0 KiB
C#

using BarRaider.SdTools;
using FocusVolumeControl.AudioSessions;
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace FocusVolumeControl.AudioHelpers;
public class NameAndIconHelper
{
public (string name, string icon) GetProcessInfo(Process process)
{
//i know this is dumb, but its only used by the sound browser, not real prod code
var blah = new ActiveAudioSessionWrapper();
SetProcessInfo(process, blah);
return (blah.DisplayName, blah.IconPath ?? blah.ExecutablePath);
}
public void SetProcessInfo(Process process, ActiveAudioSessionWrapper results)
{
try
{
//appx packages are installed from the windows store. eg, itunes
var appx = AppxPackage.FromProcess(process);
if (appx == null)
{
//using process.MainModule.FileVersionInfo sometimes throws permission exceptions
//we get the file version info with a limited query flag to avoid that
var fileVersionInfo = GetFileVersionInfo(process);
//if the display name is already set, then it came from the display name of the audio session
if (string.IsNullOrEmpty(results.DisplayName))
{
results.DisplayName = process.MainWindowTitle;
if (string.IsNullOrEmpty(results.DisplayName))
{
results.DisplayName = fileVersionInfo?.FileDescription;
if (string.IsNullOrEmpty(results.DisplayName))
{
results.DisplayName = process.ProcessName;
}
}
}
results.ExecutablePath = fileVersionInfo?.FileName;
}
else
{
results.DisplayName = appx.DisplayName;
results.IconPath = Path.Combine(appx.Path, appx.Logo);
}
}
catch { }
finally
{
//if anything threw an exception, set the display name to the process name, and just let the
// icon/executable path be blank and the stream deck will just show the default icon
if (string.IsNullOrEmpty(results.DisplayName))
{
results.DisplayName = process.ProcessName;
}
}
}
FileVersionInfo GetFileVersionInfo(Process process)
{
var path = GetExecutablePathWithPInvoke(process);
if (!string.IsNullOrEmpty(path))
{
return FileVersionInfo.GetVersionInfo(path);
}
return null;
}
string GetExecutablePathWithPInvoke(Process process)
{
IntPtr processHandle = IntPtr.Zero;
try
{
string pathToExe = string.Empty;
if (process != null)
{
//use query limited information handle instead of process.handle to prevent permission errors
processHandle = Native.OpenProcess(0x00001000, false, process.Id);
var buffer = new StringBuilder(1024);
var bufferSize = (uint)buffer.Capacity + 1;
var success = Native.QueryFullProcessImageName(processHandle, 0, buffer, ref bufferSize);
if (success)
{
return buffer.ToString();
}
else
{
var error = Marshal.GetLastWin32Error();
Logger.Instance.LogMessage(TracingLevel.ERROR, $"Error = {error} getting process name");
return "";
}
}
}
catch
{
}
finally
{
if(processHandle != IntPtr.Zero)
{
Native.CloseHandle(processHandle);
}
}
return "";
}
}