mirror of
https://github.com/mashed-potatoes/PotatoNV.git
synced 2024-11-12 18:04:14 +01:00
v2.2.0
This commit is contained in:
parent
69999e06ec
commit
79552c2097
11 changed files with 119 additions and 83 deletions
|
@ -11,17 +11,16 @@ namespace PotatoNV_next.Controls
|
||||||
public AboutTab()
|
public AboutTab()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
version.Text = string.Format(version.Text, GetVersion(3));
|
var versionTag = $"v{Common.GetAssemblyVersion(typeof(MainWindow).Assembly)}\n[" +
|
||||||
fireLogo.Source = MediaConverter.ImageSourceFromBitmap(Properties.Resources.Fire.ToBitmap());
|
string.Join(", ", new (string AssemblyName, string Tag)[] {
|
||||||
}
|
("Potato.Fastboot", "FB"),
|
||||||
|
("Potato.ImageFlasher", "IF"),
|
||||||
|
("LibUsbDotNet.LibUsbDotNet", "LD"),
|
||||||
|
("libusb-1.0", "LU"),
|
||||||
|
}.Select(x => $"{x.Tag} v{Common.GetAssemblyVersion($"{x.AssemblyName}.dll") ?? "??"}").ToArray()) + "]";
|
||||||
|
|
||||||
public static string GetVersion(int depth = 3)
|
version.Text = versionTag;
|
||||||
{
|
fireLogo.Source = MediaConverter.ImageSourceFromBitmap(Properties.Resources.Fire.ToBitmap());
|
||||||
return string.Join(".",
|
|
||||||
typeof(MainWindow).Assembly.GetName().Version
|
|
||||||
.ToString()
|
|
||||||
.Split('.')
|
|
||||||
.Take(depth));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
|
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
<UserControl x:Class="PotatoNV_next.Controls.LogBox"
|
<UserControl x:Class="PotatoNV_next.Controls.LogBox"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
|
||||||
<Grid Margin="4">
|
<Grid Margin="4">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
|
@ -13,9 +9,10 @@
|
||||||
|
|
||||||
<TextBox x:Name="logBox"
|
<TextBox x:Name="logBox"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Margin="0,5"
|
Margin="0"
|
||||||
IsReadOnlyCaretVisible="True"
|
IsReadOnlyCaretVisible="True"
|
||||||
IsReadOnly="True" />
|
IsReadOnly="True"
|
||||||
|
ScrollViewer.VerticalScrollBarVisibility="Visible" />
|
||||||
<ProgressBar x:Name="progressBar" Grid.Row="1" />
|
<ProgressBar x:Name="progressBar" Grid.Row="1" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -37,7 +37,11 @@ namespace PotatoNV_next.Controls
|
||||||
Dispatcher.Invoke(() => logBox.AppendText(e.Message));
|
Dispatcher.Invoke(() => logBox.AppendText(e.Message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logBox.AppendText(e.Message);
|
logBox.AppendText(e.Message);
|
||||||
|
logBox.Focus();
|
||||||
|
logBox.CaretIndex = logBox.Text.Length;
|
||||||
|
logBox.ScrollToEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnProgress(Log.ProgressEventArgs progressEventArgs)
|
private void OnProgress(Log.ProgressEventArgs progressEventArgs)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800" IsEnabledChanged="NVForm_IsEnabledChanged">
|
IsEnabledChanged="NVForm_IsEnabledChanged">
|
||||||
<StackPanel Style="{x:Null}">
|
<StackPanel Style="{x:Null}">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Label Content="Target device" />
|
<Label Content="Target device" />
|
||||||
|
@ -15,11 +15,8 @@
|
||||||
<ComboBox Name="deviceBootloader" />
|
<ComboBox Name="deviceBootloader" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Label Content="Unlock code" />
|
<CheckBox x:Name="disableFBLOCK" Content="Disable FBLOCK (not recommended)" IsChecked="False" />
|
||||||
<TextBox x:Name="nvUnlockCode" />
|
<CheckBox x:Name="reboot" Content="Reboot after unlock" IsChecked="True" />
|
||||||
</StackPanel>
|
|
||||||
<StackPanel>
|
|
||||||
<CheckBox x:Name="disableFBLOCK" Content="Disable FBLOCK" IsChecked="True" />
|
|
||||||
<Button x:Name="startButton" Content="Start!" Height="40" Margin="0,10,0,0" Click="StartButton_Click" />
|
<Button x:Name="startButton" Content="Start!" Height="40" Margin="0,10,0,0" Click="StartButton_Click" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
|
@ -37,11 +37,6 @@ namespace PotatoNV_next.Controls
|
||||||
{
|
{
|
||||||
deviceBootloader.SelectedIndex = 0;
|
deviceBootloader.SelectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var random = new Random(Guid.NewGuid().GetHashCode());
|
|
||||||
|
|
||||||
nvUnlockCode.Text = new string(Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 16)
|
|
||||||
.Select(s => s[random.Next(s.Length)]).ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FormEventArgs : EventArgs
|
public class FormEventArgs : EventArgs
|
||||||
|
@ -50,6 +45,7 @@ namespace PotatoNV_next.Controls
|
||||||
public string Target { get; set; }
|
public string Target { get; set; }
|
||||||
public string UnlockCode { get; set; }
|
public string UnlockCode { get; set; }
|
||||||
public bool DisableFBLOCK { get; set; }
|
public bool DisableFBLOCK { get; set; }
|
||||||
|
public bool Reboot { get; set; }
|
||||||
public Bootloader Bootloader { get; set; } = null;
|
public Bootloader Bootloader { get; set; } = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,8 +106,6 @@ namespace PotatoNV_next.Controls
|
||||||
"Check connection and required drivers.");
|
"Check connection and required drivers.");
|
||||||
|
|
||||||
Assert(deviceBootloader.SelectedIndex != -1, "Couldn't find any valid bootloader!");
|
Assert(deviceBootloader.SelectedIndex != -1, "Couldn't find any valid bootloader!");
|
||||||
|
|
||||||
Assert(VerifyNVValue(nvUnlockCode.Text, true), "Unlock code is not valid.");
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -126,8 +120,8 @@ namespace PotatoNV_next.Controls
|
||||||
? UsbController.Device.DMode.Fastboot
|
? UsbController.Device.DMode.Fastboot
|
||||||
: UsbController.Device.DMode.DownloadVCOM,
|
: UsbController.Device.DMode.DownloadVCOM,
|
||||||
Target = deviceList.SelectedItem.ToString(),
|
Target = deviceList.SelectedItem.ToString(),
|
||||||
UnlockCode = nvUnlockCode.Text,
|
DisableFBLOCK = disableFBLOCK.IsChecked.Value,
|
||||||
DisableFBLOCK = disableFBLOCK.IsChecked.Value
|
Reboot = reboot.IsChecked.Value
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!IsSelectedDeviceInFastbootMode)
|
if (!IsSelectedDeviceInFastbootMode)
|
||||||
|
@ -142,7 +136,6 @@ namespace PotatoNV_next.Controls
|
||||||
{
|
{
|
||||||
deviceList.IsEnabled = IsEnabled;
|
deviceList.IsEnabled = IsEnabled;
|
||||||
deviceBootloader.IsEnabled = IsEnabled;
|
deviceBootloader.IsEnabled = IsEnabled;
|
||||||
nvUnlockCode.IsEnabled = IsEnabled;
|
|
||||||
disableFBLOCK.IsEnabled = IsEnabled;
|
disableFBLOCK.IsEnabled = IsEnabled;
|
||||||
startButton.IsEnabled = IsEnabled;
|
startButton.IsEnabled = IsEnabled;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using PotatoNV_next.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
@ -82,17 +83,28 @@ namespace PotatoNV_next
|
||||||
var build = fb.Command("oem get-build-number");
|
var build = fb.Command("oem get-build-number");
|
||||||
Log.Info($"Build number: {build.Payload.Replace(":", "")}");
|
Log.Info($"Build number: {build.Payload.Replace(":", "")}");
|
||||||
|
|
||||||
var regex = new Regex(@"FB[\w: ]{1,}UNLOCKED");
|
|
||||||
var fblock = fb.Command("oem lock-state info");
|
var fblock = fb.Command("oem lock-state info");
|
||||||
var state = regex.IsMatch(fblock.Payload);
|
var state = Regex.IsMatch(fblock.Payload, @"FB[\w: ]{1,}UNLOCKED");
|
||||||
|
|
||||||
Log.Info($"FBLOCK state: {(state ? "unlocked" : "locked")}");
|
Log.Info($"FBLOCK state: {(state ? "unlocked" : "locked")}");
|
||||||
LogResponse(fblock);
|
LogResponse(fblock);
|
||||||
|
|
||||||
if (!state)
|
if (!state)
|
||||||
{
|
{
|
||||||
Log.Error("*** FBLOCK is locked! ***");
|
throw new Exception("*** FBLOCK is locked! ***");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var factoryKey = ReadFactoryKey();
|
||||||
|
|
||||||
|
if (factoryKey != null)
|
||||||
|
{
|
||||||
|
Log.Info($"Unlock key: {factoryKey}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var random = new Random(Guid.NewGuid().GetHashCode());
|
||||||
|
|
||||||
|
args.UnlockCode = factoryKey ?? new string(Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 16)
|
||||||
|
.Select(s => s[random.Next(s.Length)]).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetNVMEProp(string prop, byte[] value)
|
private void SetNVMEProp(string prop, byte[] value)
|
||||||
|
@ -122,7 +134,7 @@ namespace PotatoNV_next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetHWDogCertify(byte state)
|
private void SetHWDogState(byte state)
|
||||||
{
|
{
|
||||||
foreach (var command in new[] { "hwdog certify set", "backdoor set" })
|
foreach (var command in new[] { "hwdog certify set", "backdoor set" })
|
||||||
{
|
{
|
||||||
|
@ -139,24 +151,12 @@ namespace PotatoNV_next
|
||||||
Log.Error("Failed to set FBLOCK state!");
|
Log.Error("Failed to set FBLOCK state!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WidevineLock()
|
private string ReadFactoryKey()
|
||||||
{
|
{
|
||||||
Log.Debug("WV Lock");
|
|
||||||
var res = fb.Command("getvar:nve:WVLOCK");
|
var res = fb.Command("getvar:nve:WVLOCK");
|
||||||
LogResponse(res);
|
var match = Regex.Match(res.Payload, @"\w{16}");
|
||||||
if (res.Status != Fastboot.Status.Fail && res.Payload.Replace("\n", "").Trim() != "UUUUUUUUUUUUUUUU")
|
|
||||||
{
|
|
||||||
Log.Info($"Read factory key: {res.Payload}");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
return match.Success ? match.Value : null;
|
||||||
{
|
|
||||||
SetNVMEProp("WVLOCK", Encoding.ASCII.GetBytes(args.UnlockCode));
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Log.Error("Failed to set the WVLOCK.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteNVME()
|
private void WriteNVME()
|
||||||
|
@ -171,13 +171,13 @@ namespace PotatoNV_next
|
||||||
{
|
{
|
||||||
Log.Error("Failed to set the FBLOCK, using the alternative method...");
|
Log.Error("Failed to set the FBLOCK, using the alternative method...");
|
||||||
Log.Debug(ex.Message);
|
Log.Debug(ex.Message);
|
||||||
SetHWDogCertify(fblockState);
|
SetHWDogState(fblockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
SetNVMEProp("WVLOCK", Encoding.ASCII.GetBytes(args.UnlockCode));
|
||||||
SetNVMEProp("USRKEY", GetSHA256(args.UnlockCode));
|
SetNVMEProp("USRKEY", GetSHA256(args.UnlockCode));
|
||||||
WidevineLock();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -207,11 +207,16 @@ namespace PotatoNV_next
|
||||||
ReadInfo();
|
ReadInfo();
|
||||||
WriteNVME();
|
WriteNVME();
|
||||||
|
|
||||||
Log.Info("Rebooting...");
|
Log.Info("Finalizing...");
|
||||||
|
LogResponse(fb.Command($"oem unlock {args.UnlockCode}"));
|
||||||
|
|
||||||
fb.Command("reboot");
|
if (args.Reboot)
|
||||||
|
{
|
||||||
|
Log.Info("Rebooting...");
|
||||||
|
fb.Command("reboot");
|
||||||
|
}
|
||||||
|
|
||||||
Log.Info($"New bootloader unlock code: {args.UnlockCode}");
|
Log.Info($"Bootloader unlock code: {args.UnlockCode}");
|
||||||
|
|
||||||
fb.Disconnect();
|
fb.Disconnect();
|
||||||
}
|
}
|
||||||
|
@ -220,10 +225,6 @@ namespace PotatoNV_next
|
||||||
Log.Error(ex.Message);
|
Log.Error(ex.Message);
|
||||||
Log.Debug(ex.StackTrace);
|
Log.Debug(ex.StackTrace);
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
fb.Disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartProcess(Controls.NVForm.FormEventArgs args)
|
public void StartProcess(Controls.NVForm.FormEventArgs args)
|
||||||
|
|
|
@ -6,36 +6,47 @@
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
Title="PotatoNV"
|
Title="PotatoNV"
|
||||||
Width="720"
|
Width="450"
|
||||||
Height="416"
|
Height="500"
|
||||||
ResizeMode="NoResize"
|
ResizeMode="NoResize"
|
||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<Style TargetType="StackPanel">
|
<Style TargetType="CheckBox">
|
||||||
<Setter Property="Margin" Value="4" />
|
<Setter Property="Margin" Value="3,6,0,0" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style TargetType="TextBox">
|
<Style TargetType="ProgressBar">
|
||||||
<Setter Property="MaxLength" Value="16" />
|
<Setter Property="Margin" Value="0,3,0,0" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style TargetType="TextBlock">
|
<Style TargetType="TextBlock">
|
||||||
<Setter Property="TextAlignment" Value="Center" />
|
<Setter Property="TextAlignment" Value="Center" />
|
||||||
<Setter Property="Padding" Value="2" />
|
<Setter Property="Padding" Value="2" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBox">
|
||||||
|
<Setter Property="FontFamily" Value="Consolas" />
|
||||||
|
</Style>
|
||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
|
|
||||||
<UniformGrid Columns="2">
|
<TabControl Grid.Row="0" Margin="4">
|
||||||
<TabControl Margin="3">
|
<TabItem Header="Bootloader unlock">
|
||||||
<TabItem Header="NVME Update">
|
<Grid>
|
||||||
<controls:NVForm x:Name="nvFrom" />
|
<Grid.RowDefinitions>
|
||||||
</TabItem>
|
<RowDefinition Height="Auto" />
|
||||||
<TabItem Header="About program">
|
<RowDefinition Height="*" />
|
||||||
<controls:AboutTab />
|
</Grid.RowDefinitions>
|
||||||
</TabItem>
|
|
||||||
</TabControl>
|
<controls:NVForm x:Name="nvFrom" Margin="4" />
|
||||||
|
|
||||||
<controls:LogBox x:Name="logBox" />
|
<Grid Height="Auto" Grid.Row="1">
|
||||||
</UniformGrid>
|
<controls:LogBox x:Name="logBox" Grid.Row="0" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</TabItem>
|
||||||
|
<TabItem Header="About">
|
||||||
|
<controls:AboutTab />
|
||||||
|
</TabItem>
|
||||||
|
</TabControl>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using PotatoNV_next.Utils;
|
using PotatoNV_next.Utils;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
|
@ -96,11 +99,11 @@ namespace PotatoNV_next
|
||||||
SetupLog();
|
SetupLog();
|
||||||
core.StartProcess(formEventArgs);
|
core.StartProcess(formEventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetupLog()
|
public void SetupLog()
|
||||||
{
|
{
|
||||||
logBox.Clear();
|
logBox.Clear();
|
||||||
Log.Info($"PotatoNV v{Controls.AboutTab.GetVersion()}");
|
Log.Info($"PotatoNV v{Common.GetAssemblyVersion(typeof(MainWindow).Assembly)}");
|
||||||
Log.Info("User manual: https://kutt.it/pnv-"
|
Log.Info("User manual: https://kutt.it/pnv-"
|
||||||
+ (CultureInfo.InstalledUICulture.TwoLetterISOLanguageName == "ru"
|
+ (CultureInfo.InstalledUICulture.TwoLetterISOLanguageName == "ru"
|
||||||
? "ru"
|
? "ru"
|
||||||
|
|
|
@ -116,6 +116,7 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Core.cs" />
|
<Compile Include="Core.cs" />
|
||||||
<Compile Include="Utils\Bootloader.cs" />
|
<Compile Include="Utils\Bootloader.cs" />
|
||||||
|
<Compile Include="Utils\Common.cs" />
|
||||||
<Compile Include="Utils\Log.cs" />
|
<Compile Include="Utils\Log.cs" />
|
||||||
<Compile Include="Utils\MediaConverter.cs" />
|
<Compile Include="Utils\MediaConverter.cs" />
|
||||||
<Compile Include="Utils\UsbController.cs" />
|
<Compile Include="Utils\UsbController.cs" />
|
||||||
|
|
|
@ -20,5 +20,5 @@ using System.Windows;
|
||||||
ResourceDictionaryLocation.SourceAssembly
|
ResourceDictionaryLocation.SourceAssembly
|
||||||
)]
|
)]
|
||||||
|
|
||||||
[assembly: AssemblyVersion("2.1.0.0")]
|
[assembly: AssemblyVersion("2.2.0.0")]
|
||||||
[assembly: AssemblyFileVersion("2.1.0.0")]
|
[assembly: AssemblyFileVersion("2.2.0.0")]
|
||||||
|
|
30
PotatoNV-next/Utils/Common.cs
Normal file
30
PotatoNV-next/Utils/Common.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PotatoNV_next.Utils
|
||||||
|
{
|
||||||
|
class Common
|
||||||
|
{
|
||||||
|
public static string GetAssemblyVersion(Assembly assembly)
|
||||||
|
{
|
||||||
|
return assembly.GetName().Version.ToString(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetAssemblyVersion(string name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return FileVersionInfo.GetVersionInfo(name).FileVersion;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue