NET 8 Upgrade (#687)

* Initial .NET8 Upgrade

* Initial GitHub Actions Cleanup

* Fix Desktop Notifications

* Fix throw warning

* Upgrade vunerable transative nuget packages

* Fix warnings with registry overflow

* Adjust async/await usage for configRepository

* Fix TTS voice name and app auto start

* Install .NET 8 with setup

I regret NSIS

* Remove no longer needed System/MS references (included in dotnet sdk)

* Surpress stackalloc in loop warning, that code scares me.

* Removed unused SharpDX packages

* Ignore WebClient warning, hopefully this project doesn't move past NET 8

* Fixed terrifying code

* GenerateAssemblyInfo

* Trimmed editor config to only silence warning.

* Fix open webpage

* Fix updater

---------

Co-authored-by: DubyaDude <ushafiq141@gmail.com>
Co-authored-by: Natsumi <cmcooper123@hotmail.com>
This commit is contained in:
Ethan Cordray
2023-11-21 07:41:57 -05:00
committed by GitHub
parent 7bb5c8ea45
commit 2e9db3153d
26 changed files with 796 additions and 736 deletions

4
.editorconfig Normal file
View File

@@ -0,0 +1,4 @@
[*.cs]
# SYSLIB0014: Type or member is obsolete
dotnet_diagnostic.SYSLIB0014.severity = suggestion

View File

@@ -1,51 +1,61 @@
name: VRCX
on:
- workflow_dispatch
- push
- pull_request
jobs:
build_dotnet:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Setup Nuget.exe
uses: nuget/setup-nuget@v1
- name: Restore packages
run: nuget restore VRCX.sln
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.1
- name: Build with MSBuild
run: msbuild VRCX.sln -p:Configuration=Release -p:Platform=x64
- uses: actions/upload-artifact@v3
with:
name: vrcx
path: bin/x64/Release
build_node:
build_vrcx_win:
runs-on: ubuntu-latest
defaults:
run:
working-directory: html
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
- name: Setup .NET 8
uses: actions/setup-dotnet@v3
with:
node-version: ${{ matrix.node-version }}
- name: Restore dependencies
run: npm ci
- name: Lint
run: npm run lint
- name: Build
run: npm run production
- name: Fix folder structure
id: fix-folders
run: |
mkdir upload
mv dist upload/html
- uses: actions/upload-artifact@v3
dotnet-version: '8.0.x'
- name: Setup NodeJS 18
uses: actions/setup-node@v4
with:
name: vrcx
path: html/upload
node-version: 18
- name: Setup NSIS
run: sudo apt update && sudo apt install -y nsis nsis-pluginapi
- name: Restore Node Dependencies
run: cd ${{ github.workspace }}/html && npm ci && cd ${{ github.workspace }}
#- name: JS Lint
# run: cd html && npm run lint && cd ..
- name: Build Web UI
run: cd ${{ github.workspace }}/html && npm run production && cd ${{ github.workspace }}
- name: Build .NET Application
run: dotnet build -p:Configuration=Release -p:Platform=x64 -p:EnableWindowsTargeting=true
- name: Copy Web UI
run: cp -r ${{ github.workspace }}/html/dist ${{ github.workspace }}/bin/x64/Release/html
- name: Fix NSIS Permissions
run: sudo chown -R $(whoami) /usr/share/nsis/Plugins/
- name: Build Installer
uses: joncloud/makensis-action@v4
with:
script-file: ${{ github.workspace }}/Installer/installer.nsi
additional-plugin-paths: ${{ github.workspace }}/Installer/Plugins
- name: Upload Zip
uses: actions/upload-artifact@v3
with:
name: "VRCX"
path: ${{ github.workspace }}/bin/x64/Release/*
- name: Upload Installer
uses: actions/upload-artifact@v3
with:
name: "VRCX_Setup"
path: ${{ github.workspace }}/Installer/VRCX_Setup.exe

View File

@@ -14,9 +14,9 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Windows.UI.Notifications;
using CefSharp;
using librsync.net;
using Microsoft.Toolkit.Uwp.Notifications;
using Microsoft.Win32;
using NLog;
@@ -106,7 +106,10 @@ namespace VRCX
if (url.StartsWith("http://") ||
url.StartsWith("https://"))
{
Process.Start(url).Close();
Process.Start(new ProcessStartInfo(url)
{
UseShellExecute = true
});
}
}
@@ -182,20 +185,18 @@ namespace VRCX
/// <param name="Image">The optional image to display in the notification.</param>
public void DesktopNotification(string BoldText, string Text = "", string Image = "")
{
var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText02);
var stringElements = toastXml.GetElementsByTagName("text");
var imagePath = Path.Combine(Program.BaseDirectory, "VRCX.ico");
if (!string.IsNullOrEmpty(Image))
{
imagePath = Image;
}
ToastContentBuilder builder = new ToastContentBuilder();
if (Uri.TryCreate(Image, UriKind.Absolute, out Uri uri))
builder.AddAppLogoOverride(uri);
stringElements[0].AppendChild(toastXml.CreateTextNode(BoldText));
stringElements[1].AppendChild(toastXml.CreateTextNode(Text));
var imageElements = toastXml.GetElementsByTagName("image");
imageElements[0].Attributes.GetNamedItem("src").NodeValue = imagePath;
var toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier("VRCX").Show(toast);
if (!string.IsNullOrEmpty(BoldText))
builder.AddText(BoldText);
if (!string.IsNullOrEmpty(Text))
builder.AddText(Text);
builder.Show();
}
/// <summary>
@@ -229,7 +230,8 @@ namespace VRCX
{
IPCServer.Send(new IPCPacket
{
Type = "VRCXLaunch"
Type = "VRCXLaunch",
MsgType = "VRCXLaunch"
});
}

View File

@@ -14,27 +14,25 @@ namespace VRCX
public partial class AppApi
{
[DllImport("advapi32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int RegSetValueExA(
IntPtr hKey,
string lpValueName,
int reserved,
public static extern uint RegSetValueEx(
UIntPtr hKey,
[MarshalAs(UnmanagedType.LPStr)] string lpValueName,
int Reserved,
RegistryValueKind dwType,
byte[] lpData,
int cbData
);
int cbData);
[DllImport("advapi32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int RegOpenKeyExA(
IntPtr hKey,
string lpSubKey,
public static extern int RegOpenKeyEx(
UIntPtr hKey,
string subKey,
int ulOptions,
int samDesired,
out IntPtr phkResult
);
out UIntPtr hkResult);
[DllImport("advapi32.dll")]
public static extern int RegCloseKey(IntPtr hKey);
public static extern int RegCloseKey(UIntPtr hKey);
public string AddHashToKeyName(string key)
{
// https://discussions.unity.com/t/playerprefs-changing-the-name-of-keys/30332/4
@@ -44,7 +42,7 @@ namespace VRCX
hash = (hash * 33) ^ c;
return key + "_h" + hash;
}
/// <summary>
/// Retrieves the value of the specified key from the VRChat group in the windows registry.
/// </summary>
@@ -94,7 +92,7 @@ namespace VRCX
{
if (regKey == null)
return false;
object setValue = null;
switch (type)
{
@@ -109,13 +107,13 @@ namespace VRCX
if (setValue == null)
return false;
regKey.SetValue(keyName, setValue, type);
}
return true;
}
/// <summary>
/// Sets the value of the specified key in the VRChat group in the windows registry.
/// </summary>
@@ -124,20 +122,20 @@ namespace VRCX
public void SetVRChatRegistryKey(string key, byte[] value)
{
var keyName = AddHashToKeyName(key);
var hKey = (IntPtr)0x80000001; // HKEY_LOCAL_MACHINE
var hKey = (UIntPtr)0x80000001; // HKEY_LOCAL_MACHINE
const int keyWrite = 0x20006;
const string keyFolder = @"SOFTWARE\VRChat\VRChat";
var openKeyResult = RegOpenKeyExA(hKey, keyFolder, 0, keyWrite, out var folderPointer);
var openKeyResult = RegOpenKeyEx(hKey, keyFolder, 0, keyWrite, out var folderPointer);
if (openKeyResult != 0)
throw new Exception("Error opening registry key. Error code: " + openKeyResult);
var setKeyResult = RegSetValueExA(folderPointer, keyName, 0, RegistryValueKind.DWord, value, value.Length);
var setKeyResult = RegSetValueEx(folderPointer, keyName, 0, RegistryValueKind.DWord, value, value.Length);
if (setKeyResult != 0)
throw new Exception("Error setting registry value. Error code: " + setKeyResult);
RegCloseKey(hKey);
}
public Dictionary<string, Dictionary<string, object>> GetVRChatRegistry()
{
var output = new Dictionary<string, Dictionary<string, object>>();
@@ -147,13 +145,17 @@ namespace VRCX
throw new Exception("Nothing to backup.");
var keys = regKey.GetValueNames();
Span<long> spanLong = stackalloc long[1];
Span<double> doubleSpan = MemoryMarshal.Cast<long, double>(spanLong);
foreach (var key in keys)
{
var data = regKey.GetValue(key);
var index = key.LastIndexOf("_h", StringComparison.Ordinal);
if (index <= 0)
continue;
var keyName = key.Substring(0, index);
if (data == null)
continue;
@@ -181,9 +183,9 @@ namespace VRCX
output.Add(keyName, dwordDict);
break;
}
Span<long> spanLong = stackalloc long[] { (long)data };
var doubleValue = MemoryMarshal.Cast<long, double>(spanLong)[0];
spanLong[0] = (long)data;
var doubleValue = doubleSpan[0];
var floatDict = new Dictionary<string, object>
{
{ "data", doubleValue },
@@ -191,7 +193,7 @@ namespace VRCX
};
output.Add(keyName, floatDict);
break;
default:
Debug.WriteLine($"Unknown registry value kind: {type}");
break;
@@ -225,20 +227,20 @@ namespace VRCX
SetVRChatRegistryKey(item.Key, dataBytes);
continue;
}
if (int.TryParse(data.ToString(), out var intValue))
{
SetVRChatRegistryKey(item.Key, intValue, type);
continue;
}
throw new Exception("Unknown number type: " + item.Key);
}
SetVRChatRegistryKey(item.Key, data, type);
}
}
public bool HasVRChatRegistryFolder()
{
using (var regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\VRChat\VRChat"))
@@ -258,7 +260,7 @@ namespace VRCX
throw new Exception("Error creating registry key.");
}
}
public void DeleteVRChatRegistryFolder()
{
using (var regKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\VRChat\VRChat"))
@@ -269,7 +271,7 @@ namespace VRCX
Registry.CurrentUser.DeleteSubKeyTree(@"SOFTWARE\VRChat\VRChat");
}
}
/// <summary>
/// Opens a file dialog to select a VRChat registry backup JSON file.
/// </summary>
@@ -298,7 +300,7 @@ namespace VRCX
var path = openFileDialog.FileName;
if (string.IsNullOrEmpty(path))
return;
// return file contents
var json = File.ReadAllText(path);
ExecuteAppFunction("restoreVrcRegistryFromFile", json);

View File

@@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Timers;
using NLog;
namespace VRCX
{
@@ -14,6 +15,7 @@ namespace VRCX
public class AutoAppLaunchManager
{
public static AutoAppLaunchManager Instance { get; private set; }
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public static readonly string VRChatProcessName = "VRChat";
public bool Enabled = false;
@@ -215,14 +217,23 @@ namespace VRCX
/// Starts a new child process.
/// </summary>
/// <param name="path">The path.</param>
internal void StartChildProcess(string path)
private void StartChildProcess(string path)
{
try
{
using (var process = Process.Start(path))
if (process != null)
startedProcesses.Add(path, new HashSet<int>() { process.Id });
} catch { }
var process = new Process();
process.StartInfo = new ProcessStartInfo(path)
{
UseShellExecute = true
};
process.Start();
if (process.Id != 0)
startedProcesses.Add(path, new HashSet<int>() { process.Id });
}
catch (Exception ex)
{
logger.Error(ex);
}
}
/// <summary>

View File

@@ -56,7 +56,7 @@ namespace VRCX
cefSettings.CefCommandLineArgs["remote-allow-origins"] = "*";
}
CefSharpSettings.WcfEnabled = true; // TOOD: REMOVE THIS LINE YO (needed for synchronous configRepository)
//CefSharpSettings.WcfEnabled = true; // TOOD: REMOVE THIS LINE YO (needed for synchronous configRepository)
CefSharpSettings.ShutdownOnExit = false;
if (Cef.Initialize(cefSettings) == false)

View File

@@ -110,7 +110,7 @@ namespace VRCX
if ("true".Equals(VRCXStorage.Instance.Get("VRCX_StartAsMinimizedState")) &&
"true".Equals(VRCXStorage.Instance.Get("VRCX_CloseToTray")))
{
BeginInvoke(new MethodInvoker(Hide));
BeginInvoke(Hide);
}
else
{

View File

@@ -12,6 +12,7 @@ using SharpDX.Direct3D11;
using System;
using System.Runtime.InteropServices;
using System.Threading;
using Range = CefSharp.Structs.Range;
namespace VRCX
{
@@ -87,7 +88,7 @@ namespace VRCX
var rowPitch = dataBox.RowPitch;
if (pitch == rowPitch)
{
WinApi.CopyMemory(
WinApi.RtlCopyMemory(
destinationPtr,
sourcePtr,
(uint)(_width * _height * 4)
@@ -97,7 +98,7 @@ namespace VRCX
{
for (var y = _height; y > 0; --y)
{
WinApi.CopyMemory(
WinApi.RtlCopyMemory(
destinationPtr,
sourcePtr,
(uint)pitch
@@ -168,7 +169,7 @@ namespace VRCX
);
}
WinApi.CopyMemory(
WinApi.RtlCopyMemory(
_paintBuffer.AddrOfPinnedObject(),
buffer,
(uint)(width * height * 4)

View File

@@ -263,11 +263,11 @@ namespace VRCX
}
}
_browser2.Dispose();
_browser1.Dispose();
_texture2.Dispose();
_texture1.Dispose();
_device.Dispose();
_browser2?.Dispose();
_browser1?.Dispose();
_texture2?.Dispose();
_texture1?.Dispose();
_device?.Dispose();
}
public void SetActive(bool active, bool hmdOverlay, bool wristOverlay, bool menuButton, int overlayHand)

View File

@@ -2003,7 +2003,7 @@ namespace SQLite
throw NotNullConstraintViolationException.New (ex, map, obj);
}
throw ex;
throw;
}
if (rowsAffected > 0)

View File

@@ -32,7 +32,7 @@ namespace VRCX
Install();
}
public static void Install()
private static void Install()
{
try
{
@@ -42,7 +42,9 @@ namespace VRCX
StartInfo = new ProcessStartInfo
{
FileName = VRCX_Setup_Executable,
Arguments = "/S"
Arguments = "/S",
UseShellExecute = true,
WorkingDirectory = Program.AppDataDirectory
}
};
VRCXProcess.Start();

View File

@@ -8,14 +8,14 @@ namespace VRCX
public static void ApplyJavascriptBindings(IJavascriptObjectRepository repository)
{
repository.NameConverter = null;
repository.Register("AppApi", AppApi.Instance, true);
repository.Register("SharedVariable", SharedVariable.Instance, false);
repository.Register("WebApi", WebApi.Instance, true);
repository.Register("VRCXStorage", VRCXStorage.Instance, true);
repository.Register("SQLite", SQLiteLegacy.Instance, true);
repository.Register("LogWatcher", LogWatcher.Instance, true);
repository.Register("Discord", Discord.Instance, true);
repository.Register("AssetBundleCacher", AssetBundleCacher.Instance, true);
repository.Register("AppApi", AppApi.Instance);
repository.Register("SharedVariable", SharedVariable.Instance);
repository.Register("WebApi", WebApi.Instance);
repository.Register("VRCXStorage", VRCXStorage.Instance);
repository.Register("SQLite", SQLiteLegacy.Instance);
repository.Register("LogWatcher", LogWatcher.Instance);
repository.Register("Discord", Discord.Instance);
repository.Register("AssetBundleCacher", AssetBundleCacher.Instance);
}
}
}

View File

@@ -70,7 +70,9 @@ namespace VRCX
{
using (var stream = new MemoryStream(Convert.FromBase64String((string)values[0])))
{
_cookieContainer = (CookieContainer)new BinaryFormatter().Deserialize(stream);
_cookieContainer = new CookieContainer();
_cookieContainer.Add(System.Text.Json.JsonSerializer.Deserialize<CookieCollection>(stream));
//_cookieContainer = (CookieContainer)new BinaryFormatter().Deserialize(stream);
}
}
catch
@@ -94,7 +96,8 @@ namespace VRCX
{
using (var memoryStream = new MemoryStream())
{
new BinaryFormatter().Serialize(memoryStream, _cookieContainer);
System.Text.Json.JsonSerializer.Serialize(memoryStream, _cookieContainer.GetAllCookies());
//new BinaryFormatter().Serialize(memoryStream, _cookieContainer);
SQLiteLegacy.Instance.ExecuteNonQuery(
"INSERT OR REPLACE INTO `cookies` (`key`, `value`) VALUES (@key, @value)",
new Dictionary<string, object>() {
@@ -116,7 +119,8 @@ namespace VRCX
using (var memoryStream = new MemoryStream())
{
new BinaryFormatter().Serialize(memoryStream, _cookieContainer);
System.Text.Json.JsonSerializer.Serialize(memoryStream, _cookieContainer.GetAllCookies());
//new BinaryFormatter().Serialize(memoryStream, _cookieContainer);
return Convert.ToBase64String(memoryStream.ToArray());
}
}
@@ -125,7 +129,9 @@ namespace VRCX
{
using (var stream = new MemoryStream(Convert.FromBase64String(cookies)))
{
_cookieContainer = (CookieContainer)new BinaryFormatter().Deserialize(stream);
//_cookieContainer = (CookieContainer)new BinaryFormatter().Deserialize(stream);
_cookieContainer = new CookieContainer();
_cookieContainer.Add(System.Text.Json.JsonSerializer.Deserialize<CookieCollection>(stream));
}
_cookieDirty = true; // force cookies to be saved for lastUserLoggedIn

View File

@@ -12,7 +12,7 @@ namespace VRCX
public static class WinApi
{
[DllImport("kernel32.dll", SetLastError = false)]
public static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
public static extern void RtlCopyMemory(IntPtr destination, IntPtr source, uint length);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

View File

@@ -46,6 +46,12 @@
!define MUI_ABORTWARNING
;--------------------------------
;Icons
!define MUI_ICON "../VRCX.ico"
!define MUI_UNICON "../VRCX.ico"
;--------------------------------
;Pages
@@ -112,6 +118,20 @@ Function .onInit
done:
FunctionEnd
Function CheckAndInstallDotNet
nsExec::ExecToStack /OEM 'cmd /c dir "%windir%\system32" | dotnet --list-runtimes | find /c /i "Microsoft.NETCore.App 8"'
Pop $0
Pop $1
StrCpy $2 $1 1
StrCmp $2 "1" 0 version_not_found
goto version_found
version_not_found:
inetc::get "https://aka.ms/dotnet/8.0/windowsdesktop-runtime-win-x64.exe" $TEMP\dotnet-runtime-win-x64.exe
ExecWait "$TEMP\dotnet-runtime-win-x64.exe /install /quiet /norestart"
Delete "$TEMP\dotnet-runtime-win-x64.exe"
version_found:
FunctionEnd
Function createDesktopShortcut
CreateShortcut "$DESKTOP\VRCX.lnk" "$INSTDIR\VRCX.exe"
FunctionEnd
@@ -142,9 +162,10 @@ Section "Install" SecInstall
inetc::get "https://aka.ms/vs/17/release/vc_redist.x64.exe" $TEMP\vcredist_x64.exe
ExecWait "$TEMP\vcredist_x64.exe /install /quiet /norestart"
Delete "$TEMP\vcredist_x64.exe"
VSRedistInstalled:
Call CheckAndInstallDotNet
SetOutPath "$INSTDIR"
File /r /x *.log /x *.pdb "..\bin\x64\Release\*.*"

View File

@@ -1,18 +1,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("VRCX")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VRCX")]
[assembly: AssemblyCopyright("vrcx-team, pypy, natsumi")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
using System.Runtime.Versioning;
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
@@ -21,16 +10,4 @@ using System.Runtime.InteropServices;
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("d9f66f2e-3ed9-4d53-a6ac-adcc1513562a")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SupportedOSPlatform("windows")]

View File

@@ -1,161 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>VRCX</RootNamespace>
<AssemblyName>VRCX</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<IsWebBootstrapper>false</IsWebBootstrapper>
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<TargetFrameworks>net8-windows10.0.19041.0</TargetFrameworks>
<Platforms>x64</Platforms>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<AssemblyTitle>VRCX</AssemblyTitle>
<Product>VRCX</Product>
<Copyright>vrcx-team, pypy, natsumi</Copyright>
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<Title>VRCX</Title>
<Description>VRCX</Description>
<PackageIcon>VRCX.png</PackageIcon>
<RepositoryUrl>https://github.com/vrcx-team/VRCX</RepositoryUrl>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>VRCX.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
<CefSharpExcludeSubProcessExe>true</CefSharpExcludeSubProcessExe>
</PropertyGroup>
<PropertyGroup Condition="'$(PlatformTarget)' == 'x64'">
<RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">win-x64</RuntimeIdentifier>
<SelfContained Condition="'$(SelfContained)' == ''">false</SelfContained>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<ContentSQLiteInteropFiles>true</ContentSQLiteInteropFiles>
<CopySQLiteInteropFiles>false</CopySQLiteInteropFiles>
<CleanSQLiteInteropFiles>false</CleanSQLiteInteropFiles>
<CollectSQLiteInteropFiles>false</CollectSQLiteInteropFiles>
</PropertyGroup>
<ItemGroup>
<Reference Include="Blake2Sharp">
<HintPath>librsync.net\Blake2Sharp.dll</HintPath>
</Reference>
<Reference Include="librsync.net">
<HintPath>librsync.net\librsync.net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Blake2Sharp">
<HintPath>librsync.net\Blake2Sharp.dll</HintPath>
</Reference>
<Reference Include="librsync.net">
<HintPath>librsync.net\librsync.net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Dotnet\AppApi\AppApi.cs" />
<Compile Include="Dotnet\AppApi\Folders.cs" />
<Compile Include="Dotnet\AppApi\GameHandler.cs" />
<Compile Include="Dotnet\AppApi\LocalPlayerModerations.cs" />
<Compile Include="Dotnet\AppApi\RegistryPlayerPrefs.cs" />
<Compile Include="Dotnet\AppApi\Screenshot.cs" />
<Compile Include="Dotnet\AppApi\VrcConfigFile.cs" />
<Compile Include="Dotnet\AppApi\XSOverlay.cs" />
<Compile Include="Dotnet\AssetBundleCacher.cs" />
<Compile Include="Dotnet\AutoAppLaunchManager.cs" />
<Compile Include="Dotnet\Cef\CefCustomDownloadHandler.cs" />
<Compile Include="Dotnet\Cef\CefCustomDragHandler.cs" />
<Compile Include="Dotnet\Cef\CefCustomMenuHandler.cs" />
<Compile Include="Dotnet\Cef\CefService.cs" />
<Compile Include="Dotnet\Cef\CefNoopDragHandler.cs" />
<Compile Include="Dotnet\CpuMonitor.cs" />
<Compile Include="Dotnet\Discord.cs" />
<Compile Include="Dotnet\ImageCache.cs" />
<Compile Include="Dotnet\IPC\IPCClient.cs" />
<Compile Include="Dotnet\IPC\IPCPacket.cs" />
<Compile Include="Dotnet\IPC\IPCServer.cs" />
<Compile Include="Dotnet\JsonSerializer.cs" />
<Compile Include="Dotnet\LogWatcher.cs" />
<Compile Include="Dotnet\MainForm.cs">
<Compile Update="Dotnet\MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dotnet\MainForm.Designer.cs">
<Compile Update="Dotnet\MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Dotnet\OpenVR\openvr_api.cs" />
<Compile Include="Dotnet\Overlay\OffScreenBrowser.cs" />
<Compile Include="Dotnet\Overlay\VRCXVR.cs" />
<Compile Include="Dotnet\Overlay\VRForm.cs">
<Compile Update="Dotnet\Overlay\VRForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dotnet\Overlay\VRForm.Designer.cs">
<Compile Update="Dotnet\Overlay\VRForm.Designer.cs">
<DependentUpon>VRForm.cs</DependentUpon>
</Compile>
<Compile Include="Dotnet\ProcessMonitor.cs" />
<Compile Include="Dotnet\Program.cs" />
<Compile Include="Dotnet\PWI\WorldDatabase.cs" />
<Compile Include="Dotnet\PWI\WorldDataRequestResponse.cs" />
<Compile Include="Dotnet\PWI\WorldDBManager.cs" />
<Compile Include="Dotnet\ScreenshotMetadata\ScreenshotHelper.cs" />
<Compile Include="Dotnet\ScreenshotMetadata\ScreenshotMetadata.cs" />
<Compile Include="Dotnet\ScreenshotMetadata\ScreenshotMetadataDatabase.cs" />
<Compile Include="Dotnet\SharedVariable.cs" />
<Compile Include="Dotnet\SQLite.cs" />
<Compile Include="Dotnet\SQLiteLegacy.cs" />
<Compile Include="Dotnet\StartupArgs.cs" />
<Compile Include="Dotnet\Update.cs" />
<Compile Include="Dotnet\Util.cs" />
<Compile Include="Dotnet\VRCXStorage.cs" />
<Compile Include="Dotnet\WebApi.cs" />
<Compile Include="Dotnet\WinApi.cs" />
<Compile Include="Dotnet\WinformBase.cs">
<Compile Update="Dotnet\WinformBase.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Dotnet\WinformThemer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Dotnet\MainForm.resx">
<EmbeddedResource Update="Dotnet\MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Dotnet\Overlay\VRForm.resx">
<EmbeddedResource Update="Dotnet\Overlay\VRForm.resx">
<DependentUpon>VRForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
@@ -165,7 +93,7 @@
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<Compile Update="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
@@ -174,9 +102,6 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Content Include="openvr_api.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -192,66 +117,22 @@
</Content>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<PackageReference Include="CefSharp.OffScreen.NETCore" Version="119.1.20" />
<PackageReference Include="CefSharp.WinForms.NETCore" Version="119.1.20" />
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.5" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.2.0" />
<PackageReference Include="SharpDX.Mathematics" Version="4.2.0" />
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
<PackageReference Include="System.Drawing.Common" Version="4.7.2" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.Json" Version="8.0.0" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CefSharp.Common">
<Version>119.1.20</Version>
</PackageReference>
<PackageReference Include="CefSharp.OffScreen">
<Version>119.1.20</Version>
</PackageReference>
<PackageReference Include="CefSharp.WinForms">
<Version>119.1.20</Version>
</PackageReference>
<PackageReference Include="DiscordRichPresence">
<Version>1.2.1.24</Version>
</PackageReference>
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications">
<Version>7.1.3</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.3</Version>
</PackageReference>
<PackageReference Include="NLog">
<Version>5.2.5</Version>
</PackageReference>
<PackageReference Include="SharpDX.D3DCompiler">
<Version>4.2.0</Version>
</PackageReference>
<PackageReference Include="SharpDX.Desktop">
<Version>4.2.0</Version>
</PackageReference>
<PackageReference Include="SharpDX.Direct2D1">
<Version>4.2.0</Version>
</PackageReference>
<PackageReference Include="SharpDX.Direct3D11">
<Version>4.2.0</Version>
</PackageReference>
<PackageReference Include="SharpDX.Mathematics">
<Version>4.2.0</Version>
</PackageReference>
<PackageReference Include="System.Data.SQLite.Core">
<Version>1.0.118</Version>
</PackageReference>
<PackageReference Include="System.Text.Json">
<Version>7.0.3</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<ContentSQLiteInteropFiles>true</ContentSQLiteInteropFiles>
<CopySQLiteInteropFiles>false</CopySQLiteInteropFiles>
<CleanSQLiteInteropFiles>false</CleanSQLiteInteropFiles>
<CollectSQLiteInteropFiles>false</CollectSQLiteInteropFiles>
</PropertyGroup>
<Target Name="CefSharpAfterBuildDebug" AfterTargets="AfterBuild">
<CallTarget Targets="CefSharpAfterBuildDiagnostic" />
</Target>
</Project>

View File

@@ -1,9 +1,14 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31605.320
# Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VRCX", "VRCX.csproj", "{D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VRCX", "VRCX.csproj", "{D9F66F2E-3ED9-4D53-A6AC-ADCC1513562A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8612F19B-3C1F-4B17-8679-A2747A53EC6B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@@ -1,4 +1,4 @@
@echo off
msbuild VRCX.sln -p:Configuration=Release -p:Platform=x64 -p:RestorePackagesConfig=true -t:"Restore;Clean;Build" -m
dotnet build VRCX.sln -p:Configuration=Release -p:Platform=x64 -p:RestorePackagesConfig=true -t:"Restore;Clean;Build" -m
mklink /J "%~dp0\bin\x64\Release\html" "%~dp0\html\dist"
pause

View File

@@ -87,6 +87,7 @@
"sort-vars": 0,
"strict": 0,
"vars-on-top": 0,
"object-curly-spacing": ["error", "always"]
"object-curly-spacing": ["error", "always"],
"require-atomic-updates": 0
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1677,7 +1677,7 @@ html
el-tooltip(placement="right" :content="$t('dialog.launch.copy_tooltip')" :disabled="hideTooltips")
el-button(@click="copyInstanceMessage(launchDialog.location)" size="mini" icon="el-icon-s-order" style="margin-right:5px" circle)
template(#footer)
el-checkbox(v-model="launchDialog.desktop" style="float:left;margin-top:5px") {{ $t('dialog.launch.start_as_desktop') }}
el-checkbox(v-model="launchDialog.desktop" @change="saveLaunchDialog" style="float:left;margin-top:5px") {{ $t('dialog.launch.start_as_desktop') }}
el-button(size="small" @click="showPreviousInstanceInfoDialog(launchDialog.location)") {{ $t('dialog.launch.info') }}
el-button(size="small" @click="showInviteDialog(launchDialog.location)" :disabled="!checkCanInvite(launchDialog.location)") {{ $t('dialog.launch.invite') }}
el-button(type="primary" size="small" @click="launchGame(launchDialog.location, launchDialog.shortName, launchDialog.desktop)" :disabled="!launchDialog.secureOrShortName") {{ $t('dialog.launch.launch') }}

View File

@@ -823,7 +823,7 @@
"role_updated_at": "更新日:",
"role_created_at": "作成日:",
"role_permissions": "権限:"
},
},
"posts": {
"header": "アナウンス",
"visibility": "表示範囲:",

View File

@@ -801,7 +801,7 @@
"invite_to_group": "邀请好友加入群组",
"visibility_everyone": "可见性:所有人",
"visibility_friends": "可见性:好友",
"visibility_hidden": "可见性:隐藏",
"visibility_hidden": "可见性:隐藏",
"moderation_tools": "成员管理",
"leave": "离开群组"
},

View File

@@ -13,7 +13,7 @@ async function syncLoop() {
await sqliteService.executeNonQuery('BEGIN');
try {
for (var key of dirtyKeySet) {
var value = sharedRepository.getString(key);
var value = await sharedRepository.getString(key);
if (value === null) {
await sqliteService.executeNonQuery(
'DELETE FROM configs WHERE `key` = @key',
@@ -54,9 +54,9 @@ class ConfigRepository extends SharedRepository {
syncLoop();
}
remove(key) {
async remove(key) {
var _key = transformKey(key);
sharedRepository.remove(_key);
await sharedRepository.remove(_key);
dirtyKeySet.add(_key);
}
@@ -65,10 +65,10 @@ class ConfigRepository extends SharedRepository {
return sharedRepository.getString(_key, defaultValue);
}
setString(key, value) {
async setString(key, value) {
var _key = transformKey(key);
var _value = String(value);
sharedRepository.setString(_key, _value);
await sharedRepository.setString(_key, _value);
dirtyKeySet.add(_key);
}
}

View File

@@ -10,35 +10,35 @@ class SharedRepository {
return SharedVariable.Remove(_key);
}
getString(key, defaultValue = null) {
async getString(key, defaultValue = null) {
var _key = transformKey(key);
var value = SharedVariable.Get(_key);
var value = await SharedVariable.Get(_key);
if (value === null) {
return defaultValue;
}
return value;
}
setString(key, value) {
async setString(key, value) {
var _key = transformKey(key);
var _value = String(value);
SharedVariable.Set(_key, _value);
await SharedVariable.Set(_key, _value);
}
getBool(key, defaultValue = null) {
var value = this.getString(key, null);
async getBool(key, defaultValue = null) {
var value = await this.getString(key, null);
if (value === null) {
return defaultValue;
}
return value === 'true';
}
setBool(key, value) {
this.setString(key, value ? 'true' : 'false');
async setBool(key, value) {
await this.setString(key, value ? 'true' : 'false');
}
getInt(key, defaultValue = null) {
var value = this.getString(key, null);
async getInt(key, defaultValue = null) {
var value = await this.getString(key, null);
if (value === null) {
return defaultValue;
}
@@ -49,12 +49,12 @@ class SharedRepository {
return value;
}
setInt(key, value) {
this.setString(key, value);
async setInt(key, value) {
await this.setString(key, value);
}
getFloat(key, defaultValue = null) {
var value = this.getString(key, null);
async getFloat(key, defaultValue = null) {
var value = await this.getString(key, null);
if (value === null) {
return defaultValue;
}
@@ -65,12 +65,12 @@ class SharedRepository {
return value;
}
setFloat(key, value) {
this.setString(key, value);
async setFloat(key, value) {
await this.setString(key, value);
}
getObject(key, defaultValue = null) {
var value = this.getString(key, null);
async getObject(key, defaultValue = null) {
var value = await this.getString(key, null);
if (value === null) {
return defaultValue;
}
@@ -83,20 +83,20 @@ class SharedRepository {
return value;
}
setObject(key, value) {
this.setString(key, JSON.stringify(value));
async setObject(key, value) {
await this.setString(key, JSON.stringify(value));
}
getArray(key, defaultValue = null) {
var value = this.getObject(key, null);
async getArray(key, defaultValue = null) {
var value = await this.getObject(key, null);
if (Array.isArray(value) === false) {
return defaultValue;
}
return value;
}
setArray(key, value) {
this.setObject(key, value);
async setArray(key, value) {
await this.setObject(key, value);
}
}