mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-17 13:53:52 +02:00
URI Scheme
This commit is contained in:
@@ -337,6 +337,13 @@ namespace VRCX
|
||||
VRCXVR._browser2.ExecuteScriptAsync($"$app.{function}", json);
|
||||
}
|
||||
|
||||
public string GetLaunchCommand()
|
||||
{
|
||||
string command = StartupArgs.LaunchCommand;
|
||||
StartupArgs.LaunchCommand = string.Empty;
|
||||
return command;
|
||||
}
|
||||
|
||||
public void SetStartup(bool enabled)
|
||||
{
|
||||
try
|
||||
|
||||
73
IPCClient.cs
Normal file
73
IPCClient.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright(c) 2019-2021 pypy. All rights reserved.
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
using CefSharp;
|
||||
using System;
|
||||
using System.IO.Pipes;
|
||||
using System.Text;
|
||||
|
||||
namespace VRCX
|
||||
{
|
||||
class IPCClient
|
||||
{
|
||||
private NamedPipeServerStream _ipcServer;
|
||||
private byte[] _recvBuffer = new byte[1024 * 8];
|
||||
|
||||
private string _currentPacket;
|
||||
|
||||
public IPCClient(NamedPipeServerStream ipcServer)
|
||||
{
|
||||
_ipcServer = ipcServer;
|
||||
}
|
||||
|
||||
public void BeginRead()
|
||||
{
|
||||
_ipcServer.BeginRead(_recvBuffer, 0, _recvBuffer.Length, OnRead, _ipcServer);
|
||||
}
|
||||
|
||||
private void OnRead(IAsyncResult asyncResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bytesRead = _ipcServer.EndRead(asyncResult);
|
||||
|
||||
if (bytesRead <= 0)
|
||||
{
|
||||
_ipcServer.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
_currentPacket += Encoding.UTF8.GetString(_recvBuffer, 0, bytesRead);
|
||||
|
||||
if (_currentPacket[_currentPacket.Length - 1] == (char)0x00)
|
||||
{
|
||||
var packets = _currentPacket.Split((char)0x00);
|
||||
|
||||
foreach (var packet in packets)
|
||||
{
|
||||
if (string.IsNullOrEmpty(packet))
|
||||
continue;
|
||||
|
||||
MainForm.Instance.Browser.ExecuteScriptAsync("$app.ipcEvent", packet);
|
||||
}
|
||||
|
||||
_currentPacket = string.Empty;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
BeginRead();
|
||||
}
|
||||
|
||||
public static void OnSend(IAsyncResult asyncResult)
|
||||
{
|
||||
var ipcClient = (NamedPipeClientStream)asyncResult.AsyncState;
|
||||
ipcClient.EndWrite(asyncResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
IPCServer.cs
Normal file
48
IPCServer.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright(c) 2019-2021 pypy. All rights reserved.
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
using System;
|
||||
using System.IO.Pipes;
|
||||
|
||||
namespace VRCX
|
||||
{
|
||||
class IPCServer
|
||||
{
|
||||
public static readonly IPCServer Instance;
|
||||
|
||||
static IPCServer()
|
||||
{
|
||||
Instance = new IPCServer();
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
new IPCServer().CreateIPCServer();
|
||||
}
|
||||
|
||||
public void CreateIPCServer()
|
||||
{
|
||||
var ipcServer = new NamedPipeServerStream("vrcx-ipc", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
|
||||
ipcServer.BeginWaitForConnection(asyncResult => DoAccept(asyncResult), ipcServer);
|
||||
}
|
||||
|
||||
private void DoAccept(IAsyncResult asyncResult)
|
||||
{
|
||||
var ipcServer = (NamedPipeServerStream)asyncResult.AsyncState;
|
||||
|
||||
try
|
||||
{
|
||||
ipcServer.EndWaitForConnection(asyncResult);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
new IPCClient(ipcServer).BeginRead();
|
||||
CreateIPCServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,14 @@ Section "Install" SecInstall
|
||||
CreateShortCut "$SMPROGRAMS\VRCX.lnk" "$INSTDIR\VRCX.exe"
|
||||
ApplicationID::Set "$SMPROGRAMS\VRCX.lnk" "VRCX"
|
||||
|
||||
WriteRegStr HKCU "Software\Classes\vrcx" "" "URL:vrcx"
|
||||
WriteRegStr HKCU "Software\Classes\vrcx" "FriendlyTypeName" "VRCX"
|
||||
WriteRegStr HKCU "Software\Classes\vrcx" "URL Protocol" ""
|
||||
WriteRegExpandStr HKCU "Software\Classes\vrcx\DefaultIcon" "" "$INSTDIR\VRCX.ico"
|
||||
WriteRegStr HKCU "Software\Classes\vrcx\shell" "" "open"
|
||||
WriteRegStr HKCU "Software\Classes\vrcx\shell\open" "FriendlyAppName" "VRCX"
|
||||
WriteRegStr HKCU "Software\Classes\vrcx\shell\open\command" "" '"D:\WindowsFiles\Documents\git\VRCX\bin\x64\Release\VRCX.exe" /uri="%1" /params="%2 %3 %4"'
|
||||
|
||||
${If} ${Silent}
|
||||
SetOutPath $INSTDIR
|
||||
ShellExecAsUser::ShellExecAsUser "" "$INSTDIR\VRCX.exe" ""
|
||||
@@ -169,6 +177,7 @@ Section "Uninstall"
|
||||
|
||||
DeleteRegKey HKLM "Software\VRCX"
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\VRCX"
|
||||
DeleteRegKey HKCU "Software\Classes\vrcx"
|
||||
|
||||
Delete "$SMPROGRAMS\VRCX.lnk"
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace VRCX
|
||||
|
||||
private static void Run()
|
||||
{
|
||||
StartupArgs.ArgsCheck();
|
||||
Update.Check();
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
@@ -66,6 +67,7 @@ namespace VRCX
|
||||
LogWatcher.Instance.Init();
|
||||
|
||||
CefService.Instance.Init();
|
||||
IPCServer.Instance.Init();
|
||||
VRCXVR.Instance.Init();
|
||||
Application.Run(new MainForm());
|
||||
WebApi.Instance.SaveCookies();
|
||||
|
||||
72
StartupArgs.cs
Normal file
72
StartupArgs.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright(c) 2019-2021 pypy. All rights reserved.
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace VRCX
|
||||
{
|
||||
class StartupArgs
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool ShowWindow(IntPtr hWnd, int flags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern int SetForegroundWindow(IntPtr hwnd);
|
||||
|
||||
public static string LaunchCommand;
|
||||
|
||||
public static void ArgsCheck()
|
||||
{
|
||||
string[] args = Environment.GetCommandLineArgs();
|
||||
if (args.Length == 0)
|
||||
return;
|
||||
|
||||
foreach (string arg in args)
|
||||
{
|
||||
if (arg.Length > 12 && arg.Substring(0, 12) == "/uri=vrcx://")
|
||||
{
|
||||
LaunchCommand = arg.Substring(12);
|
||||
ProcessCheck(LaunchCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessCheck(string command)
|
||||
{
|
||||
Process currentProcess = Process.GetCurrentProcess();
|
||||
Process[] processList = Process.GetProcessesByName("VRCX");
|
||||
|
||||
if (processList.Length > 1)
|
||||
{
|
||||
new IPCServer().CreateIPCServer();
|
||||
var ipcClient = new NamedPipeClientStream(".", "vrcx-ipc", PipeDirection.InOut);
|
||||
ipcClient.Connect();
|
||||
|
||||
if (ipcClient.IsConnected)
|
||||
{
|
||||
var buffer = Encoding.UTF8.GetBytes($"{{\"type\":\"LaunchCommand\",\"command\":\"{command}\"}}" + (char)0x00);
|
||||
ipcClient.BeginWrite(buffer, 0, buffer.Length, IPCClient.OnSend, ipcClient);
|
||||
}
|
||||
|
||||
foreach (Process process in processList)
|
||||
{
|
||||
if (process.Id != currentProcess.Id)
|
||||
{
|
||||
IntPtr handle = process.MainWindowHandle;
|
||||
ShowWindow(handle, 9);
|
||||
SetForegroundWindow(handle);
|
||||
}
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssetBundleCacher.cs" />
|
||||
<Compile Include="IPCClient.cs" />
|
||||
<Compile Include="IPCServer.cs" />
|
||||
<Compile Include="StartupArgs.cs" />
|
||||
<Compile Include="Update.cs" />
|
||||
<Compile Include="CefService.cs" />
|
||||
<Compile Include="Discord.cs" />
|
||||
|
||||
@@ -15582,6 +15582,53 @@ speechSynthesis.getVoices();
|
||||
return user.currentAvatarImageUrl;
|
||||
};
|
||||
|
||||
$app.methods.ipcEvent = function (json) {
|
||||
try {
|
||||
var data = JSON.parse(json);
|
||||
} catch {
|
||||
console.error(`IPC invalid JSON, ${json}`);
|
||||
}
|
||||
switch (data.type) {
|
||||
case 'Ping':
|
||||
this.eventPing(data);
|
||||
break;
|
||||
case 'LaunchCommand':
|
||||
this.eventLaunchCommand(data.command);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
API.$on('LOGIN', async function () {
|
||||
var command = await AppApi.GetLaunchCommand();
|
||||
if (command) {
|
||||
$app.eventLaunchCommand(command);
|
||||
}
|
||||
});
|
||||
|
||||
$app.methods.eventLaunchCommand = function (command) {
|
||||
if (!API.isLoggedIn) {
|
||||
return;
|
||||
}
|
||||
var args = command.split('/');
|
||||
var command = args[0];
|
||||
var commandArg = args[1];
|
||||
switch (command) {
|
||||
case 'world':
|
||||
this.showWorldDialog(commandArg);
|
||||
break;
|
||||
case 'avatar':
|
||||
this.showAvatarDialog(commandArg);
|
||||
break;
|
||||
case 'user':
|
||||
this.showUserDialog(commandArg);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
$app.methods.eventPing = function (data) {
|
||||
console.log('IPC Ping', data.version);
|
||||
};
|
||||
|
||||
$app = new Vue($app);
|
||||
window.$app = $app;
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user