mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-26 12:09:32 +08:00
Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a5f8db69f | ||
|
|
3d3d126c64 | ||
|
|
8e32b428bd | ||
|
|
8193c6267a | ||
|
|
c845601863 | ||
|
|
1309d63389 | ||
|
|
fff5c293c8 | ||
|
|
e9136e7245 | ||
|
|
66b47e9042 | ||
|
|
5144b1d1b0 | ||
|
|
8213f8a776 | ||
|
|
799185d870 | ||
|
|
4796bc0b71 | ||
|
|
a5c49c470b | ||
|
|
c3affdde7e | ||
|
|
066cfa66c5 | ||
|
|
b89430e4cf | ||
|
|
729c7373fd | ||
|
|
6f843c3939 | ||
|
|
64099cf274 | ||
|
|
a33acc16b6 | ||
|
|
90d0291640 | ||
|
|
fa45e92d2f | ||
|
|
7aedb5dcef | ||
|
|
5509004c64 |
@@ -131,6 +131,7 @@
|
||||
<PackageVersion Include="ReactiveUI.XamForms" Version="18.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.AndroidX" Version="18.4.1" />
|
||||
<PackageVersion Include="ReactiveUI.Maui" Version="18.4.1" />
|
||||
|
||||
<!-- SkiaSharp & HarfBuzzSharp -->
|
||||
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/HarfBuzzSharp.props -->
|
||||
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.3" />
|
||||
@@ -204,7 +205,7 @@
|
||||
|
||||
<!-- .NET Compat -->
|
||||
<PackageVersion Include="OperatingSystem2" Version="2.0.0" />
|
||||
<PackageVersion Include="JustArchiNET.Madness" Version="3.8.0" />
|
||||
<PackageVersion Include="JustArchiNET.Madness" Version="3.9.0" />
|
||||
|
||||
<!-- Serialize -->
|
||||
<PackageVersion Include="MessagePack" Version="2.4.59" />
|
||||
|
||||
Submodule references/SteamAchievementManager updated: b84d4babe5...99ce54cac5
@@ -25,6 +25,9 @@
|
||||
12. ASF 升级至 V5.3.2.4
|
||||
12. .NET 运行时升级至 6.0.12,使用 fde 版本需要升级运行时
|
||||
13. 新增 Steam 设置可设置 模拟蒸汽平台启动参数
|
||||
14. 修复 Steam Beta 版库存游戏加载不出游戏详情和名称
|
||||
15. 修复 成就管理、云存档管理 无法打开
|
||||
16. 修复 库存游戏 首次加载后,游戏加载失败提示文本依然存在
|
||||
<!--
|
||||
|
||||
### 已知问题
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
namespace System.Properties
|
||||
{
|
||||
static partial class ThisAssembly
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// <para>在以下平台中还需要将版本号写入相关的清单文件:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item> iOS:\src\ST.Client.Mobile.iOS.App\Info.plist <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// <item> Android:\src\ST.Client.Mobile.Droid.App\Properties\AndroidManifest.xml <manifest ... android:versionCode(long递增) android:versionName </item>
|
||||
/// <item> UWP(DesktopBridge):\src\ST.Client.Desktop.Avalonia.App.Bridge.Package\Package.appxmanifest <Identity ... Version </item>
|
||||
/// <item> macOS:\packaging\build-osx-app.sh <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public const string Version = "2.8.5";
|
||||
namespace System.Properties;
|
||||
|
||||
//public const string InfoVersion = Version + "-beta";
|
||||
}
|
||||
static partial class ThisAssembly
|
||||
{
|
||||
/// <summary>
|
||||
/// 版本号
|
||||
/// <para>在以下平台中还需要将版本号写入相关的清单文件:</para>
|
||||
/// <list type="bullet">
|
||||
/// <item> iOS:\src\ST.Client.Mobile.iOS.App\Info.plist <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// <item> Android:\src\ST.Client.Mobile.Droid.App\Properties\AndroidManifest.xml <manifest ... android:versionCode(long递增) android:versionName </item>
|
||||
/// <item> UWP(DesktopBridge):\src\ST.Client.Desktop.Avalonia.App.Bridge.Package\Package.appxmanifest <Identity ... Version </item>
|
||||
/// <item> macOS:\packaging\build-osx-app.sh <CFBundleVersion> <CFBundleShortVersionString> </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
public const string Version = "2.8.6";
|
||||
|
||||
//public const string InfoVersion = Version + "-beta";
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
<Identity
|
||||
Name="4651ED44255E.47979655102CE"
|
||||
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
|
||||
Version="2.8.5.0" />
|
||||
Version="2.8.6.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Watt Toolkit</DisplayName>
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ namespace System.Application.UI.Views.Pages
|
||||
EnableNullSplitting = false,
|
||||
DataLabelsSize = 12,
|
||||
Stroke = LiveChartsSkiaSharp.DefaultPaint,
|
||||
TooltipLabelFormatter = (e) => $"{AppResources.Upload} {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
TooltipLabelFormatter = (e) => $"Upload {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
Mapping = (rate, point) =>
|
||||
{
|
||||
point.PrimaryValue = rate.Rate;
|
||||
@@ -51,7 +51,7 @@ namespace System.Application.UI.Views.Pages
|
||||
EnableNullSplitting = false,
|
||||
DataLabelsSize = 12,
|
||||
Stroke = LiveChartsSkiaSharp.DefaultPaint,
|
||||
TooltipLabelFormatter = (e) => $"{AppResources.Download} {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
TooltipLabelFormatter = (e) => $"Download {IOPath.GetDisplayFileSizeString(e.PrimaryValue)}/s",
|
||||
Mapping = (rate, point) =>
|
||||
{
|
||||
point.PrimaryValue = rate.Rate;
|
||||
|
||||
@@ -94,13 +94,13 @@
|
||||
<Border.ContextFlyout>
|
||||
<MenuFlyout>
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{ReflectionBinding Path=Res.UserChange_BtnText,
|
||||
Mode=OneWay,
|
||||
Source={x:Static resx:R.Current}}" />
|
||||
<MenuItem
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Header="{ReflectionBinding Path=Res.UserChange_OfflineBtn,
|
||||
Mode=OneWay,
|
||||
@@ -231,7 +231,7 @@
|
||||
Source={x:Static resx:R.Current}}">
|
||||
<i:Interaction.Behaviors>
|
||||
<ia:EventTriggerBehavior EventName="Tapped" SourceObject="{ReflectionBinding #nickname}">
|
||||
<ia:InvokeCommandAction Command="{ReflectionBinding #u.DataContext.SteamId_Click}" CommandParameter="{Binding}" />
|
||||
<ia:InvokeCommandAction Command="{ReflectionBinding #u.DataContext.SteamId_ClickCommand}" CommandParameter="{Binding}" />
|
||||
</ia:EventTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
</controls:ScrollingTextBlock>
|
||||
@@ -343,7 +343,7 @@
|
||||
Mode=OneWay,
|
||||
Source={x:Static resx:R.Current}}"
|
||||
Classes="flatbutton"
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Cursor="Hand">
|
||||
<controls:ScrollingTextBlock Text="{ReflectionBinding Path=Res.UserChange_OfflineBtn, Mode=OneWay, Source={x:Static resx:R.Current}}" />
|
||||
@@ -359,7 +359,7 @@
|
||||
MaxWidth="250"
|
||||
HorizontalAlignment="Stretch"
|
||||
Classes="flatbutton"
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_Click}"
|
||||
Command="{ReflectionBinding #u.DataContext.SteamId_ClickCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
Cursor="Hand">
|
||||
<controls:ScrollingTextBlock Text="{ReflectionBinding Path=Res.UserChange_BtnText, Mode=OneWay, Source={x:Static resx:R.Current}}" />
|
||||
|
||||
+26
-8
@@ -1,19 +1,37 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using System.Application.Services;
|
||||
|
||||
namespace System.Application.UI.Views.Pages
|
||||
namespace System.Application.UI.Views.Pages;
|
||||
|
||||
public partial class UserItem : UserControl
|
||||
{
|
||||
public partial class UserItem : UserControl
|
||||
public UserItem()
|
||||
{
|
||||
public UserItem()
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (UserService.Current.User != null)
|
||||
{
|
||||
InitializeComponent();
|
||||
var lastSignInTime = UserService.Current.LastSignInTime;
|
||||
if (lastSignInTime.HasValue)
|
||||
{
|
||||
if (DateTimeOffset.Now - lastSignInTime.Value >= TimeSpan.FromDays(1))
|
||||
{
|
||||
UserService.Current.User.IsSignIn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
}
|
||||
}
|
||||
|
||||
+16
-6
@@ -48,6 +48,12 @@
|
||||
Maximum="65535"/>
|
||||
</DockPanel>-->
|
||||
|
||||
<!--<DockPanel>
|
||||
<TextBlock Text="IPV6支持:" />
|
||||
<TextBlock Text="IPV6地址" ></TextBlock>
|
||||
<Button Content="{ReflectionBinding Path=Res.Refresh,Mode=OneWay,Source={x:Static resx:R.Current}}"></Button>
|
||||
</DockPanel>-->
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_AutoRunProxy,Mode=OneWay,Source={x:Static resx:R.Current}}" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
@@ -59,13 +65,13 @@
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.OnlyEnableProxyScript},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>
|
||||
|
||||
|
||||
<DockPanel>
|
||||
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_EnableHttpProxyToHttps,Mode=OneWay,Source={x:Static resx:R.Current}}" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.EnableHttpProxyToHttps},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>
|
||||
|
||||
|
||||
<!--<DockPanel>
|
||||
<Label Content="自定义根证书密码"></Label>
|
||||
<TextBox></TextBox>
|
||||
@@ -86,11 +92,13 @@
|
||||
</DockPanel>
|
||||
</Expander.Header>
|
||||
<StackPanel Spacing="10">
|
||||
--><!--<DockPanel>
|
||||
-->
|
||||
<!--<DockPanel>
|
||||
<TextBlock Text="启用" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.Socks5ProxyEnable},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>--><!--
|
||||
</DockPanel>-->
|
||||
<!--
|
||||
<DockPanel>
|
||||
<Label Content="{ReflectionBinding Path=Res.Settings_Proxy_ProxyPort,Mode=OneWay,Source={x:Static resx:R.Current}}"></Label>
|
||||
<NumericUpDown Maximum="65535"
|
||||
@@ -109,11 +117,13 @@
|
||||
</DockPanel>
|
||||
</Expander.Header>
|
||||
<StackPanel Spacing="10">
|
||||
--><!--<DockPanel>
|
||||
-->
|
||||
<!--<DockPanel>
|
||||
<TextBlock Text="启用" ></TextBlock>
|
||||
<ToggleSwitch
|
||||
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentEnable},Path=Value, Mode=TwoWay}"/>
|
||||
</DockPanel>--><!--
|
||||
</DockPanel>-->
|
||||
<!--
|
||||
|
||||
<DockPanel>
|
||||
<Label Content="{ReflectionBinding Path=Res.Settings_Proxy_ProxyType,Mode=OneWay,Source={x:Static resx:R.Current}}"></Label>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using DnsClient;
|
||||
using DnsClient.Protocol;
|
||||
using DynamicData;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
@@ -15,6 +16,11 @@ namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class DnsAnalysisServiceImpl : IDnsAnalysisService
|
||||
{
|
||||
public DnsAnalysisServiceImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static readonly LookupClient lookupClient = new();
|
||||
|
||||
public async Task<int> AnalysisHostnameTime(string url, CancellationToken cancellationToken = default)
|
||||
@@ -141,6 +147,11 @@ namespace System.Application.Services.Implementation
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<IPAddress?> GetHostIpv6Addres()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -536,6 +536,8 @@ namespace System.Application.Services.Implementation
|
||||
private const uint MagicNumber = 123094055U;
|
||||
private const uint MagicNumberV2 = 123094056U;
|
||||
|
||||
private static readonly Lazy<uint[]> MagicNumbers = new(new uint[] { MagicNumber, MagicNumberV2 });
|
||||
|
||||
/// <summary>
|
||||
/// 从steam本地客户端缓存文件中读取游戏数据
|
||||
/// </summary>
|
||||
@@ -556,15 +558,17 @@ namespace System.Application.Services.Implementation
|
||||
}
|
||||
using BinaryReader binaryReader = new(stream);
|
||||
uint num = binaryReader.ReadUInt32();
|
||||
if (num != MagicNumberV2 && num != MagicNumber)
|
||||
if (!MagicNumbers.Value.Contains(num))
|
||||
{
|
||||
Log.Error(nameof(GetAppInfos), string.Format("\"{0}\" magic code is not supported: 0x{1:X8}", Path.GetFileName(AppInfoPath), num));
|
||||
var msg = string.Format("\"{0}\" magic code is not supported: 0x{1:X8}", Path.GetFileName(AppInfoPath), num);
|
||||
Log.Error(nameof(GetAppInfos), msg);
|
||||
Toast.Show(msg, ToastLength.Long);
|
||||
return apps;
|
||||
}
|
||||
SteamApp? app = new();
|
||||
univeseNumber = binaryReader.ReadUInt32();
|
||||
var installAppIds = GetInstalledAppIds();
|
||||
while ((app = SteamApp.FromReader(binaryReader, installAppIds, isSaveProperties)) != null)
|
||||
while ((app = SteamApp.FromReader(binaryReader, installAppIds, isSaveProperties, num == MagicNumberV2)) != null)
|
||||
{
|
||||
if (app.AppId > 0)
|
||||
{
|
||||
|
||||
+65
-3
@@ -11,6 +11,8 @@ using System.Linq;
|
||||
using System.Management;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using _SR = System.Application.Properties.SR;
|
||||
|
||||
namespace System.Application.Services.Implementation;
|
||||
@@ -199,15 +201,71 @@ internal sealed partial class WindowsPlatformServiceImpl : IPlatformService
|
||||
/// <returns></returns>
|
||||
static Process? StartProcessRegedit(string? args) => Process2.Start(Regedit, args, workingDirectory: _windir.Value);
|
||||
|
||||
/// <summary>
|
||||
/// 使用 Explorer 降权运行进程
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="arguments"></param>
|
||||
/// <returns></returns>
|
||||
static Process? StartAsInvokerByExplorer(string fileName, string? arguments = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(arguments))
|
||||
return StartProcessExplorer($"\"{fileName}\"");
|
||||
//var processName = Path.GetFileNameWithoutExtension(fileName);
|
||||
var cacheCmdFile = IOPath.GetCacheFilePath(CacheTempDirName, "StartAsInvokerByExplorer", FileEx.CMD);
|
||||
File.WriteAllText(cacheCmdFile, $"@echo {Constants.HARDCODED_APP_NAME} StartAsInvokerByExplorer{Environment.NewLine}start \"\" \"{fileName}\" {arguments}{Environment.NewLine}exit 0");
|
||||
File.WriteAllText(cacheCmdFile, $"@echo {Constants.HARDCODED_APP_NAME} StartAsInvokerByExplorer{Environment.NewLine}start \"\" \"{fileName}\" {arguments}{Environment.NewLine}del %0");
|
||||
var process = StartProcessExplorer($"\"{cacheCmdFile}\"");
|
||||
IOPath.TryDeleteInDelay(process, cacheCmdFile);
|
||||
//if (process != null)
|
||||
//{
|
||||
// TryDeleteInDelay(process, cacheCmdFile, processName);
|
||||
//}
|
||||
return process;
|
||||
|
||||
//static async void TryDeleteInDelay(Process process, string filePath, string processName, int millisecondsDelay = 9000, int processWaitMillisecondsDelay = 9000)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var waitForExitResult = process.WaitForExit(processWaitMillisecondsDelay);
|
||||
// if (!waitForExitResult)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// process.KillEntireProcessTree();
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// millisecondsDelay = 0;
|
||||
// }
|
||||
// if (millisecondsDelay > 0)
|
||||
// {
|
||||
// var token = new CancellationTokenSource(millisecondsDelay);
|
||||
// try
|
||||
// {
|
||||
// await Task.Run(async () =>
|
||||
// {
|
||||
// while (true)
|
||||
// {
|
||||
// await Task.Delay(100, token.Token);
|
||||
// if (Process.GetProcessesByName(processName).Any())
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }, token.Token);
|
||||
// }
|
||||
// catch (TaskCanceledException)
|
||||
// {
|
||||
|
||||
// }
|
||||
// }
|
||||
// IOPath.FileTryDelete(filePath);
|
||||
//}
|
||||
}
|
||||
|
||||
public Process? StartAsInvoker(string fileName, string? arguments = null)
|
||||
@@ -216,7 +274,11 @@ internal sealed partial class WindowsPlatformServiceImpl : IPlatformService
|
||||
{
|
||||
// runas /trustlevel:0x20000 没有真正的降权,只是作为具有限制特权,使用 explorer 最好,但不接受参数,可以创建一个临时cmd脚本启动
|
||||
//return StartAsInvokerByRunas(fileName, arguments);
|
||||
return StartAsInvokerByExplorer(fileName, arguments);
|
||||
//return StartAsInvokerByExplorer(fileName, arguments);
|
||||
var currentDirectory = Path.GetDirectoryName(fileName) ?? "";
|
||||
Microsoft.NodejsTools.SharedProject.SystemUtility.
|
||||
ExecuteProcessUnElevated(fileName, arguments ?? "", currentDirectory);
|
||||
return null;
|
||||
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// https://github.com/microsoft/nodejstools/blob/main/Nodejs/Product/Nodejs/SharedProject/SystemUtilities.cs
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.NodejsTools.SharedProject;
|
||||
|
||||
/// <summary>
|
||||
/// Utility for accessing window IShell* interfaces in order to use them to launch a process unelevated
|
||||
/// </summary>
|
||||
internal static class SystemUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// We are elevated and should launch the process unelevated. We can't create the
|
||||
/// process directly without it becoming elevated. So to workaround this, we have
|
||||
/// explorer do the process creation (explorer is typically running unelevated).
|
||||
/// </summary>
|
||||
internal static void ExecuteProcessUnElevated(string process, string args, string currentDirectory = "")
|
||||
{
|
||||
var shellWindows = (IShellWindows)new CShellWindows();
|
||||
|
||||
// Get the desktop window
|
||||
object loc = CSIDL_Desktop;
|
||||
object unused = new object();
|
||||
var serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(ref loc, ref unused, SWC_DESKTOP, out var _, SWFO_NEEDDISPATCH);
|
||||
|
||||
// Get the shell browser
|
||||
var serviceGuid = SID_STopLevelBrowser;
|
||||
var interfaceGuid = typeof(IShellBrowser).GUID;
|
||||
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(ref serviceGuid, ref interfaceGuid);
|
||||
|
||||
// Get the shell dispatch
|
||||
var dispatch = typeof(IDispatch).GUID;
|
||||
var folderView = (IShellFolderViewDual)shellBrowser.QueryActiveShellView().GetItemObject(SVGIO_BACKGROUND, ref dispatch);
|
||||
var shellDispatch = (IShellDispatch2)folderView.Application;
|
||||
|
||||
// Use the dispatch (which is unelevated) to launch the process for us
|
||||
shellDispatch.ShellExecute(process, args, currentDirectory, string.Empty, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interop definitions
|
||||
/// </summary>
|
||||
private const int CSIDL_Desktop = 0;
|
||||
private const int SWC_DESKTOP = 8;
|
||||
private const int SWFO_NEEDDISPATCH = 1;
|
||||
private const int SW_SHOWNORMAL = 1;
|
||||
private const int SVGIO_BACKGROUND = 0;
|
||||
private static readonly Guid SID_STopLevelBrowser = new("4C96BE40-915C-11CF-99D3-00AA004AE837");
|
||||
|
||||
[ComImport]
|
||||
[Guid("9BA05972-F6A8-11CF-A442-00A0C90A8F39")]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
private class CShellWindows
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("85CB6900-4D95-11CF-960C-0080C7F4EE85")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
private interface IShellWindows
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.IDispatch)]
|
||||
object FindWindowSW([MarshalAs(UnmanagedType.Struct)] ref object pvarloc, [MarshalAs(UnmanagedType.Struct)] ref object pvarlocRoot, int swClass, out int pHWND, int swfwOptions);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IServiceProvider
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object QueryService(ref Guid guidService, ref Guid riid);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("000214E2-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IShellBrowser
|
||||
{
|
||||
void VTableGap01(); // GetWindow
|
||||
|
||||
void VTableGap02(); // ContextSensitiveHelp
|
||||
|
||||
void VTableGap03(); // InsertMenusSB
|
||||
|
||||
void VTableGap04(); // SetMenuSB
|
||||
|
||||
void VTableGap05(); // RemoveMenusSB
|
||||
|
||||
void VTableGap06(); // SetStatusTextSB
|
||||
|
||||
void VTableGap07(); // EnableModelessSB
|
||||
|
||||
void VTableGap08(); // TranslateAcceleratorSB
|
||||
|
||||
void VTableGap09(); // BrowseObject
|
||||
|
||||
void VTableGap10(); // GetViewStateStream
|
||||
|
||||
void VTableGap11(); // GetControlWindow
|
||||
|
||||
void VTableGap12(); // SendControlMsg
|
||||
|
||||
IShellView QueryActiveShellView();
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("000214E3-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
private interface IShellView
|
||||
{
|
||||
void VTableGap01(); // GetWindow
|
||||
|
||||
void VTableGap02(); // ContextSensitiveHelp
|
||||
|
||||
void VTableGap03(); // TranslateAcceleratorA
|
||||
|
||||
void VTableGap04(); // EnableModeless
|
||||
|
||||
void VTableGap05(); // UIActivate
|
||||
|
||||
void VTableGap06(); // Refresh
|
||||
|
||||
void VTableGap07(); // CreateViewWindow
|
||||
|
||||
void VTableGap08(); // DestroyViewWindow
|
||||
|
||||
void VTableGap09(); // GetCurrentInfo
|
||||
|
||||
void VTableGap10(); // AddPropertySheetPages
|
||||
|
||||
void VTableGap11(); // SaveViewState
|
||||
|
||||
void VTableGap12(); // SelectItem
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
object GetItemObject(uint aspectOfView, ref Guid riid);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("00020400-0000-0000-C000-000000000046")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
private interface IDispatch
|
||||
{
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("E7A1AF80-4D96-11CF-960C-0080C7F4EE85")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
private interface IShellFolderViewDual
|
||||
{
|
||||
object Application
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.IDispatch)]
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("A4C6892C-3BA9-11D2-9DEA-00C04FB16162")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
||||
public interface IShellDispatch2
|
||||
{
|
||||
void ShellExecute([MarshalAs(UnmanagedType.BStr)] string file, [MarshalAs(UnmanagedType.Struct)] object vArgs, [MarshalAs(UnmanagedType.Struct)] object vDir, [MarshalAs(UnmanagedType.Struct)] object vOperation, [MarshalAs(UnmanagedType.Struct)] object vShow);
|
||||
}
|
||||
}
|
||||
@@ -805,7 +805,7 @@ namespace System.Application.Models
|
||||
return this;
|
||||
}
|
||||
|
||||
public static SteamApp? FromReader(BinaryReader reader, uint[]? installedAppIds = null, bool isSaveProperties = false)
|
||||
public static SteamApp? FromReader(BinaryReader reader, uint[]? installedAppIds = null, bool isSaveProperties = false, bool is0x07564428 = true)
|
||||
{
|
||||
uint id = reader.ReadUInt32();
|
||||
if (id == 0)
|
||||
@@ -825,6 +825,9 @@ namespace System.Application.Models
|
||||
binaryReader.ReadBytes(20);
|
||||
app._changeNumber = binaryReader.ReadUInt32();
|
||||
|
||||
if (is0x07564428)
|
||||
binaryReader.ReadBytes(20);
|
||||
|
||||
var properties = SteamAppPropertyHelper.ReadPropertyTable(binaryReader);
|
||||
|
||||
if (properties == null)
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace System.Application.Services
|
||||
/// <param name="isIPv6"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<IPAddress>? DohAnalysisDomainIpAsync(string hostNameOrAddress, string? dnsServers, bool isIPv6, CancellationToken cancellationToken = default)
|
||||
IAsyncEnumerable<IPAddress>? DohAnalysisDomainIpAsync(string hostNameOrAddress, string? dnsServers, bool isIPv6, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -146,5 +146,7 @@ namespace System.Application.Services
|
||||
}
|
||||
|
||||
Task<bool> GetIsIpv6Support() => Task.FromResult(false);
|
||||
|
||||
Task<IPAddress?> GetHostIpv6Addres() => Task.FromResult(default(IPAddress));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,12 @@ namespace System.Application.Services
|
||||
|
||||
IsASFRunOrStoping = true;
|
||||
|
||||
//if (ASF.GlobalConfig?.SteamOwnerID is null or 0)
|
||||
//{
|
||||
// Toast.Show(AppResources.ASF_Starting, ToastLength.Long);
|
||||
// return;
|
||||
//}
|
||||
|
||||
var isOk = await archiSteamFarmService.Start();
|
||||
if (!isOk)
|
||||
{
|
||||
|
||||
@@ -90,6 +90,8 @@ namespace System.Application.Services
|
||||
}
|
||||
}
|
||||
|
||||
public DateTimeOffset? LastSignInTime { get; set; }
|
||||
|
||||
public async Task SignIn()
|
||||
{
|
||||
if (User == null)
|
||||
@@ -101,16 +103,12 @@ namespace System.Application.Services
|
||||
var state = await csc.AccountClockIn();
|
||||
if (state.IsSuccess)
|
||||
{
|
||||
LastSignInTime = DateTimeOffset.Now;
|
||||
User.Experience = state.Content!.Experience;
|
||||
User.NextExperience = state.Content!.NextExperience;
|
||||
User.Level = state.Content!.Level;
|
||||
User.EngineOil = state.Content!.Strength;
|
||||
User.IsSignIn = true;
|
||||
//_ = Task.Run(async () =>
|
||||
//{
|
||||
// await Task.Delay(DateTime.Now.Date.AddDays(1).Subtract(DateTime.Now));
|
||||
// IsSignedIn = false;
|
||||
//});
|
||||
Toast.Show(AppResources.User_SignIn_Ok);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -119,7 +119,7 @@ public sealed class SteamSettings : SettingsHost2<SteamSettings>
|
||||
[SupportedOSPlatform("Linux")]
|
||||
public static SerializableProperty<SystemEndMode>? DownloadCompleteSystemEndMode = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: SystemEndMode.Sleep) : null;
|
||||
|
||||
static readonly SerializableProperty<bool>? _IsRunSteamAdministrator = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
|
||||
static readonly SerializableProperty<bool>? _IsRunSteamAdministrator = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
|
||||
|
||||
/// <summary>
|
||||
/// 以管理员权限运行 Steam
|
||||
|
||||
@@ -126,9 +126,6 @@ namespace System.Application.UI.ViewModels
|
||||
this.RaisePropertyChanged(nameof(TypeFilterString));
|
||||
}));
|
||||
|
||||
SteamConnectService.Current.WhenAnyValue(x => x.IsLoadingGameList)
|
||||
.Subscribe(_ => this.RaisePropertyChanged(nameof(IsSteamAppsEmpty)));
|
||||
|
||||
SteamConnectService.Current.SteamApps
|
||||
.Connect()
|
||||
.Filter(nameFilter)
|
||||
@@ -144,6 +141,9 @@ namespace System.Application.UI.ViewModels
|
||||
CalcTypeCount();
|
||||
});
|
||||
|
||||
SteamConnectService.Current.WhenAnyValue(x => x.IsLoadingGameList)
|
||||
.Subscribe(_ => this.RaisePropertyChanged(nameof(IsSteamAppsEmpty)));
|
||||
|
||||
HideAppCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
IWindowManager.Instance.Show(CustomWindow.HideApp, resizeMode: ResizeMode.CanResize);
|
||||
@@ -217,7 +217,7 @@ namespace System.Application.UI.ViewModels
|
||||
[Reactive]
|
||||
public string? SearchText { get; set; }
|
||||
|
||||
public bool IsSteamAppsEmpty => !SteamApps.Any_Nullable() && !SteamConnectService.Current.IsLoadingGameList;
|
||||
public bool IsSteamAppsEmpty => !SteamConnectService.Current.SteamApps.Items.Any_Nullable() && !SteamConnectService.Current.IsLoadingGameList;
|
||||
|
||||
[Reactive]
|
||||
public ObservableCollection<EnumModel<SteamAppType>>? AppTypeFiltres { get; set; }
|
||||
|
||||
@@ -29,9 +29,12 @@ namespace System.Application.UI.ViewModels
|
||||
{
|
||||
this.WhenAnyValue(x => x.SteamUsers)
|
||||
.Subscribe(s => this.RaisePropertyChanged(nameof(IsUserEmpty)));
|
||||
LoginAccountCommand = ReactiveCommand.Create(LoginNewSteamAccount);
|
||||
LoginAccountCommand = ReactiveCommand.CreateFromTask(LoginNewSteamAccount);
|
||||
RefreshCommand = ReactiveCommand.Create(SteamConnectService.Current.RefreshSteamUsers);
|
||||
|
||||
SteamId_ClickCommand = ReactiveCommand.CreateFromTask<SteamUser>(SteamId_Click);
|
||||
OfflineModeButton_ClickCommand = ReactiveCommand.CreateFromTask<SteamUser>(OfflineModeButton_Click);
|
||||
|
||||
ShareManageCommand = ReactiveCommand.Create(OpenShareManageWindow);
|
||||
OpenBrowserCommand = ReactiveCommand.CreateFromTask<string>(x => Browser2.OpenAsync(x));
|
||||
|
||||
@@ -61,6 +64,10 @@ namespace System.Application.UI.ViewModels
|
||||
|
||||
public ReactiveCommand<Unit, Unit> LoginAccountCommand { get; }
|
||||
|
||||
public ReactiveCommand<SteamUser, Unit> SteamId_ClickCommand { get; }
|
||||
|
||||
public ReactiveCommand<SteamUser, Unit> OfflineModeButton_ClickCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> RefreshCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> ShareManageCommand { get; }
|
||||
@@ -99,9 +106,9 @@ namespace System.Application.UI.ViewModels
|
||||
|
||||
menus.Add(new MenuItemCustomName(title, AppResources.UserChange_BtnTootlip)
|
||||
{
|
||||
Command = ReactiveCommand.Create(() =>
|
||||
Command = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
SteamId_Click(user);
|
||||
await ReStartSteamByUser(user);
|
||||
|
||||
INotificationService.Instance.Notify(string.Format(AppResources.UserChange_ChangeUserTip, title), NotificationType.Message);
|
||||
}),
|
||||
@@ -114,19 +121,19 @@ namespace System.Application.UI.ViewModels
|
||||
#endregion
|
||||
}
|
||||
|
||||
public void SteamId_Click(SteamUser user)
|
||||
public async Task SteamId_Click(SteamUser user)
|
||||
{
|
||||
user.WantsOfflineMode = false;
|
||||
ReStartSteamByUser(user);
|
||||
await ReStartSteamByUser(user);
|
||||
}
|
||||
|
||||
public void OfflineModeButton_Click(SteamUser user)
|
||||
public async Task OfflineModeButton_Click(SteamUser user)
|
||||
{
|
||||
user.WantsOfflineMode = true;
|
||||
ReStartSteamByUser(user);
|
||||
await ReStartSteamByUser(user);
|
||||
}
|
||||
|
||||
private async void ReStartSteamByUser(SteamUser? user = null)
|
||||
private async Task ReStartSteamByUser(SteamUser? user = null)
|
||||
{
|
||||
foreach (var item in SteamUsers.Where(x => x.MostRecent))
|
||||
item.MostRecent = false;
|
||||
@@ -144,7 +151,7 @@ namespace System.Application.UI.ViewModels
|
||||
steamService.SetCurrentUser(string.Empty);
|
||||
}
|
||||
|
||||
steamService.StartSteamWithParameter();
|
||||
await Task.Run(steamService.StartSteamWithParameter);
|
||||
}
|
||||
|
||||
public async void DeleteUserButton_Click(SteamUser user)
|
||||
@@ -175,15 +182,14 @@ namespace System.Application.UI.ViewModels
|
||||
IPlatformService.Instance.OpenFolder(Path.Combine(ISteamService.Instance.SteamDirPath, user.UserdataPath));
|
||||
}
|
||||
|
||||
public void LoginNewSteamAccount()
|
||||
public async Task LoginNewSteamAccount()
|
||||
{
|
||||
var result = MessageBox.ShowAsync(AppResources.UserChange_LoginNewAccountTip, button: MessageBox.Button.OKCancel).ContinueWith(s =>
|
||||
var result = await MessageBox.ShowAsync(AppResources.UserChange_LoginNewAccountTip, button: MessageBox.Button.OKCancel);
|
||||
|
||||
if (result == MessageBox.Result.OK)
|
||||
{
|
||||
if (s.Result == MessageBox.Result.OK)
|
||||
{
|
||||
ReStartSteamByUser();
|
||||
}
|
||||
});
|
||||
await ReStartSteamByUser();
|
||||
}
|
||||
}
|
||||
|
||||
public async void EditRemarkAsync(SteamUser user)
|
||||
|
||||
Reference in New Issue
Block a user