mirror of
https://github.com/cemu-project/DS4Windows.git
synced 2024-12-23 23:21:49 +01:00
Added cmdline options to send start/stop/shutdown/LoadProfile/LoadTempProfile commands to a background DS4Win app via IPC messaging interface.
This commit is contained in:
parent
a6ed8240df
commit
1c67d6145e
@ -85,6 +85,9 @@ namespace DS4Windows.Forms
|
||||
[DllImport("psapi.dll")]
|
||||
private static extern uint GetModuleFileNameEx(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
||||
|
||||
public DS4Form(string[] args)
|
||||
{
|
||||
Global.FindConfigLocation();
|
||||
@ -386,6 +389,17 @@ namespace DS4Windows.Forms
|
||||
if (!(StartMinimized || mini))
|
||||
Form_Resize(null, null);
|
||||
|
||||
// Write current window class name as InterProcessCommunication identifier. The IPC classname is used in WM_DATACOPY messaging interface. .NET WinForms creates a semi-random clas names per application.
|
||||
StringBuilder wndClassNameStr = new StringBuilder(256);
|
||||
if (GetClassName(this.Handle, wndClassNameStr, wndClassNameStr.Capacity) != 0 && wndClassNameStr.Length > 0)
|
||||
{
|
||||
if (System.IO.File.Exists(appdatapath + "\\IPCClassName.dat") && System.IO.File.ReadAllText(appdatapath + "\\IPCClassName.dat") == wndClassNameStr.ToString())
|
||||
wndClassNameStr.Clear(); // The wnd classname is still the same, so no need to re-write it
|
||||
|
||||
if(wndClassNameStr.Length > 0)
|
||||
System.IO.File.WriteAllText(appdatapath + "\\IPCClassName.dat", wndClassNameStr.ToString());
|
||||
}
|
||||
|
||||
Program.rootHub.Debug += On_Debug;
|
||||
|
||||
AppLogger.GuiLog += On_Debug;
|
||||
@ -1137,6 +1151,51 @@ Properties.Resources.DS4Update, MessageBoxButtons.YesNo, MessageBoxIcon.Question
|
||||
systemShutdown = true;
|
||||
break;
|
||||
}
|
||||
case Program.WM_COPYDATA:
|
||||
{
|
||||
// Received InterProcessCommunication (IPC) message. Handle the requested command
|
||||
Program.COPYDATASTRUCT cds = (Program.COPYDATASTRUCT)m.GetLParam(typeof(Program.COPYDATASTRUCT));
|
||||
if (cds.cbData >= 4)
|
||||
{
|
||||
int tdevice = -1;
|
||||
|
||||
byte[] buffer = new byte[cds.cbData];
|
||||
Marshal.Copy(cds.lpData, buffer, 0, cds.cbData);
|
||||
string[] strData = Encoding.ASCII.GetString(buffer).Split('.');
|
||||
|
||||
if (strData.Length >= 1)
|
||||
{
|
||||
strData[0] = strData[0].ToLower();
|
||||
|
||||
if (strData[0] == "start")
|
||||
ServiceStartup(true);
|
||||
else if (strData[0] == "stop")
|
||||
ServiceShutdown(true);
|
||||
else if (strData[0] == "shutdown")
|
||||
ScpForm_Closing(this, new FormClosingEventArgs(CloseReason.ApplicationExitCall, false));
|
||||
else if (strData[0] == "loadprofile" && strData.Length >= 3)
|
||||
{
|
||||
// Command syntax: LoadProfile.device#.profileName (fex LoadProfile.1.GameSnake)
|
||||
if(int.TryParse(strData[1], out tdevice)) tdevice--;
|
||||
|
||||
if (tdevice >= 0 && tdevice < 4)
|
||||
{
|
||||
ProfilePath[tdevice] = strData[2];
|
||||
LoadProfile(tdevice, true, Program.rootHub);
|
||||
}
|
||||
}
|
||||
else if (strData[0] == "loadtempprofile" && strData.Length >= 3)
|
||||
{
|
||||
// Command syntax: LoadTempProfile.device#.profileName (fex LoadTempProfile.1.GameSnake)
|
||||
if (int.TryParse(strData[1], out tdevice)) tdevice--;
|
||||
|
||||
if (tdevice >= 0 && tdevice < 4)
|
||||
LoadTempProfile(tdevice, strData[2], true, Program.rootHub);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,22 @@ namespace DS4Windows
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
[DllImport("user32.dll", EntryPoint = "FindWindow")]
|
||||
private static extern IntPtr FindWindow(string sClass, string sWindow);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
|
||||
|
||||
public const int WM_COPYDATA = 0x004A;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct COPYDATASTRUCT
|
||||
{
|
||||
public IntPtr dwData;
|
||||
public int cbData;
|
||||
public IntPtr lpData;
|
||||
}
|
||||
|
||||
// Add "global\" in front of the EventName, then only one instance is allowed on the
|
||||
// whole system, including other users. But the application can not be brought
|
||||
// into view, of course.
|
||||
@ -66,6 +82,46 @@ namespace DS4Windows
|
||||
Environment.ExitCode = 0;
|
||||
return;
|
||||
}
|
||||
else if (s == "command" || s == "-command")
|
||||
{
|
||||
i++;
|
||||
|
||||
IntPtr hWndDS4WindowsForm = IntPtr.Zero;
|
||||
|
||||
Global.FindConfigLocation();
|
||||
if (args[i].Length > 0 && !string.IsNullOrEmpty(Global.appdatapath) && System.IO.File.Exists(Global.appdatapath + "\\IPCClassName.dat"))
|
||||
{
|
||||
hWndDS4WindowsForm = FindWindow(System.IO.File.ReadAllText(Global.appdatapath + "\\IPCClassName.dat"), "DS4Windows");
|
||||
if (hWndDS4WindowsForm != IntPtr.Zero)
|
||||
{
|
||||
COPYDATASTRUCT cds;
|
||||
cds.lpData = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
cds.dwData = IntPtr.Zero;
|
||||
cds.cbData = args[i].Length;
|
||||
cds.lpData = Marshal.StringToHGlobalAnsi(args[i]);
|
||||
SendMessage(hWndDS4WindowsForm, WM_COPYDATA, IntPtr.Zero, ref cds);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(cds.lpData != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal(cds.lpData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Environment.ExitCode = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Environment.ExitCode = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
|
Loading…
Reference in New Issue
Block a user