Обновление Защитника + TXT инструкции
This commit is contained in:
parent
833ec4ca6f
commit
ce851f8ef2
@ -10,211 +10,310 @@ by:kotovskij393
|
||||
Вот этот функционал скопировать. Где то в точке старта будем вызывать (Отдельным файлом):
|
||||
##### Код
|
||||
```cs
|
||||
#region DEFENCE
|
||||
#region DEFENCE
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct PROCESS_INFORMATION
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct STARTUPINFO
|
||||
{
|
||||
public int cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern bool CreateProcess(
|
||||
string lpApplicationName,
|
||||
string lpCommandLine,
|
||||
IntPtr lpProcessAttributes,
|
||||
IntPtr lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
uint dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory,
|
||||
ref STARTUPINFO lpStartupInfo,
|
||||
out PROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct STARTUPINFO
|
||||
{
|
||||
public int cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern bool CreateProcess(
|
||||
string lpApplicationName,
|
||||
string lpCommandLine,
|
||||
IntPtr lpProcessAttributes,
|
||||
IntPtr lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
uint dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory,
|
||||
ref STARTUPINFO lpStartupInfo,
|
||||
out PROCESS_INFORMATION lpProcessInformation);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool CloseHandle(IntPtr hObject);
|
||||
private const uint WAIT_TIMEOUT = 0x00000102;
|
||||
private const uint WAIT_OBJECT_0 = 0x00000000;
|
||||
|
||||
private const uint WAIT_TIMEOUT = 0x00000102;
|
||||
private const uint WAIT_OBJECT_0 = 0x00000000;
|
||||
private System.Collections.IEnumerator CheckLicenseCoroutine()
|
||||
{
|
||||
// Ждём один кадр, чтобы Unity завершил инициализацию
|
||||
yield return null;
|
||||
|
||||
private System.Collections.IEnumerator CheckLicenseCoroutine()
|
||||
{
|
||||
// Ждём один кадр, чтобы Unity завершил инициализацию
|
||||
yield return null;
|
||||
|
||||
bool licenseValid = false;
|
||||
bool checkCompleted = false;
|
||||
//bool licenseValid = true;
|
||||
//bool checkCompleted = true;
|
||||
string errorMessage = "";
|
||||
bool licenseValid = false;
|
||||
bool checkCompleted = false;
|
||||
//bool licenseValid = true;
|
||||
//bool checkCompleted = true;
|
||||
string errorMessage = "";
|
||||
|
||||
// Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
|
||||
System.Threading.Thread thread = new System.Threading.Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
licenseValid = CheckLicense();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
checkCompleted = true;
|
||||
}
|
||||
});
|
||||
// Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
|
||||
System.Threading.Thread thread = new System.Threading.Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
licenseValid = CheckLicense();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
checkCompleted = true;
|
||||
}
|
||||
});
|
||||
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
|
||||
float timerest = 30f;
|
||||
|
||||
while (!checkCompleted && timerest > 0)
|
||||
{
|
||||
timerest -= Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
float timerest = 30f;
|
||||
while (!checkCompleted && timerest > 0)
|
||||
{
|
||||
timerest -= Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (!checkCompleted) licenseValid = false;
|
||||
if (!checkCompleted) licenseValid = false;
|
||||
|
||||
if (!licenseValid)
|
||||
{
|
||||
yield return new WaitForSeconds(3f);
|
||||
|
||||
if (!licenseValid)
|
||||
{
|
||||
yield return new WaitForSeconds(3f);
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.isPlaying = false;
|
||||
EditorApplication.isPlaying = false;
|
||||
#else
|
||||
Application.Quit();
|
||||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//exclusive
|
||||
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
|
||||
Screen.SetResolution(1920, 1080, true);
|
||||
ClickCenter();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет лицензию через внешний лаунчер RRLauncher.exe.
|
||||
/// Возвращает true, если проверка пройдена, иначе false.
|
||||
/// </summary>
|
||||
private bool CheckLicense()
|
||||
{
|
||||
try
|
||||
{
|
||||
string launcherName = "RRLauncher.exe";
|
||||
string launcherPath = null;
|
||||
|
||||
// Поиск лаунчера рядом с исполняемым файлом
|
||||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string pathInBase = Path.Combine(baseDirectory, launcherName);
|
||||
|
||||
if (File.Exists(pathInBase))
|
||||
{
|
||||
launcherPath = pathInBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
|
||||
if (File.Exists(streamingAssetsPath))
|
||||
{
|
||||
launcherPath = streamingAssetsPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
STARTUPINFO si = new STARTUPINFO();
|
||||
si.cb = Marshal.SizeOf(si);
|
||||
PROCESS_INFORMATION pi;
|
||||
private bool CheckLicense()
|
||||
{
|
||||
try
|
||||
{
|
||||
string launcherName = "RRLauncher.exe";
|
||||
string launcherPath = null;
|
||||
|
||||
string workingDir = Path.GetDirectoryName(launcherPath);
|
||||
// Поиск лаунчера рядом с исполняемым файлом
|
||||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string pathInBase = Path.Combine(baseDirectory, launcherName);
|
||||
|
||||
bool success = CreateProcess(
|
||||
launcherPath,
|
||||
null,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
false,
|
||||
0,
|
||||
IntPtr.Zero,
|
||||
workingDir,
|
||||
ref si,
|
||||
out pi);
|
||||
if (File.Exists(pathInBase))
|
||||
{
|
||||
launcherPath = pathInBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
|
||||
if (File.Exists(streamingAssetsPath))
|
||||
{
|
||||
launcherPath = streamingAssetsPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) return false;
|
||||
try
|
||||
{
|
||||
STARTUPINFO si = new STARTUPINFO();
|
||||
si.cb = Marshal.SizeOf(si);
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
|
||||
string workingDir = Path.GetDirectoryName(launcherPath);
|
||||
|
||||
if (waitResult == WAIT_TIMEOUT)
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return false;
|
||||
}
|
||||
bool success = CreateProcess(
|
||||
launcherPath,
|
||||
null,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
false,
|
||||
0,
|
||||
IntPtr.Zero,
|
||||
workingDir,
|
||||
ref si,
|
||||
out pi);
|
||||
|
||||
// Получение кода возврата
|
||||
uint exitCode;
|
||||
|
||||
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return false;
|
||||
}
|
||||
if (!success) return false;
|
||||
uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
if (waitResult == WAIT_TIMEOUT)
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exitCode == 0) return true;
|
||||
// Получение кода возврата
|
||||
uint exitCode;
|
||||
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception outerEx)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
|
||||
UnityEngine.Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
ForceToFront();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception outerEx)
|
||||
{
|
||||
Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
|
||||
Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region FORCE TO FRONT
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetForegroundWindow(IntPtr hwnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetActiveWindow();
|
||||
|
||||
public void ForceToFront()//Метод который возвращает фокус а окно после открытия защиты
|
||||
{
|
||||
IntPtr handle = GetActiveWindow();
|
||||
SetForegroundWindow(handle);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region клик в центр
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct INPUT
|
||||
{
|
||||
public uint type;
|
||||
public MOUSEINPUT mi;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MOUSEINPUT
|
||||
{
|
||||
public int dx;
|
||||
public int dy;
|
||||
public uint mouseData;
|
||||
public uint dwFlags;
|
||||
public uint time;
|
||||
public IntPtr dwExtraInfo;
|
||||
}
|
||||
|
||||
private const uint INPUT_MOUSE = 0;
|
||||
private const uint MOUSEEVENTF_MOVE = 0x0001;
|
||||
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
|
||||
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
|
||||
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
||||
|
||||
public static void ClickCenter()
|
||||
{
|
||||
int screenX = Screen.currentResolution.width / 2;
|
||||
int screenY = Screen.currentResolution.height / 2;
|
||||
|
||||
// WinAPI использует координаты 0–65535
|
||||
int absoluteX = (int)(screenX * 65535 / Screen.currentResolution.width);
|
||||
int absoluteY = (int)(screenY * 65535 / Screen.currentResolution.height);
|
||||
|
||||
INPUT[] inputs = new INPUT[3];
|
||||
|
||||
// движение мыши
|
||||
inputs[0] = new INPUT
|
||||
{
|
||||
type = INPUT_MOUSE,
|
||||
mi = new MOUSEINPUT
|
||||
{
|
||||
dx = absoluteX,
|
||||
dy = absoluteY,
|
||||
dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||||
}
|
||||
};
|
||||
|
||||
// нажатие
|
||||
inputs[1] = new INPUT
|
||||
{
|
||||
type = INPUT_MOUSE,
|
||||
mi = new MOUSEINPUT
|
||||
{
|
||||
dwFlags = MOUSEEVENTF_LEFTDOWN
|
||||
}
|
||||
};
|
||||
|
||||
// отпускание
|
||||
inputs[2] = new INPUT
|
||||
{
|
||||
type = INPUT_MOUSE,
|
||||
mi = new MOUSEINPUT
|
||||
{
|
||||
dwFlags = MOUSEEVENTF_LEFTUP
|
||||
}
|
||||
};
|
||||
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
```
|
||||
|
||||
##### Привязка к игре
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
1. Поместить RRLauncher.exe в папку Assets\StreamingAssets\
|
||||
2. Добавить в какой либо скрипт содержимое файла Защитник.txt.
|
||||
В идеале в bootstrap-script если он реализован
|
||||
3. Запустить корутину с защитой (пример в файле Вызов.txt)
|
||||
|
||||
|
||||
ВНИМАНИЕ!!!
|
||||
В алгоритме есть такой костыль, может мешать работе если другое разрешение или несколько мониторов.
|
||||
Можно пробовать запустить без костыля и дай бог всё будет хорошо
|
||||
На фишке до какой то поры всё было хорошо, потом сломалось.
|
||||
|
||||
else
|
||||
{
|
||||
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
|
||||
Screen.SetResolution(1920, 1080, true);
|
||||
ClickCenter();
|
||||
}
|
||||
|
||||
|
||||
Лицензирование производится отдельной программой, которую можно попросить у Бори или Тимура
|
||||
@ -0,0 +1,6 @@
|
||||
private void Awake()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
StartCoroutine(CheckLicenseCoroutine());
|
||||
#endif
|
||||
}
|
||||
@ -0,0 +1,304 @@
|
||||
#region DEFENCE
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct PROCESS_INFORMATION
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct STARTUPINFO
|
||||
{
|
||||
public int cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern bool CreateProcess(
|
||||
string lpApplicationName,
|
||||
string lpCommandLine,
|
||||
IntPtr lpProcessAttributes,
|
||||
IntPtr lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
uint dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory,
|
||||
ref STARTUPINFO lpStartupInfo,
|
||||
out PROCESS_INFORMATION lpProcessInformation);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
private const uint WAIT_TIMEOUT = 0x00000102;
|
||||
private const uint WAIT_OBJECT_0 = 0x00000000;
|
||||
|
||||
private System.Collections.IEnumerator CheckLicenseCoroutine()
|
||||
{
|
||||
// Ждём один кадр, чтобы Unity завершил инициализацию
|
||||
yield return null;
|
||||
|
||||
bool licenseValid = false;
|
||||
bool checkCompleted = false;
|
||||
//bool licenseValid = true;
|
||||
//bool checkCompleted = true;
|
||||
string errorMessage = "";
|
||||
|
||||
// Запускаем проверку в отдельном потоке (совместимо с IL2CPP)
|
||||
System.Threading.Thread thread = new System.Threading.Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
licenseValid = CheckLicense();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
}
|
||||
finally
|
||||
{
|
||||
checkCompleted = true;
|
||||
}
|
||||
});
|
||||
|
||||
thread.IsBackground = true;
|
||||
thread.Start();
|
||||
|
||||
float timerest = 30f;
|
||||
while (!checkCompleted && timerest > 0)
|
||||
{
|
||||
timerest -= Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (!checkCompleted) licenseValid = false;
|
||||
|
||||
if (!licenseValid)
|
||||
{
|
||||
yield return new WaitForSeconds(3f);
|
||||
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.isPlaying = false;
|
||||
#else
|
||||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//exclusive
|
||||
Screen.fullScreenMode = FullScreenMode.ExclusiveFullScreen;
|
||||
Screen.SetResolution(1920, 1080, true);
|
||||
ClickCenter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool CheckLicense()
|
||||
{
|
||||
try
|
||||
{
|
||||
string launcherName = "RRLauncher.exe";
|
||||
string launcherPath = null;
|
||||
|
||||
// Поиск лаунчера рядом с исполняемым файлом
|
||||
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string pathInBase = Path.Combine(baseDirectory, launcherName);
|
||||
|
||||
if (File.Exists(pathInBase))
|
||||
{
|
||||
launcherPath = pathInBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
string streamingAssetsPath = Path.Combine(Application.streamingAssetsPath, launcherName);
|
||||
if (File.Exists(streamingAssetsPath))
|
||||
{
|
||||
launcherPath = streamingAssetsPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
STARTUPINFO si = new STARTUPINFO();
|
||||
si.cb = Marshal.SizeOf(si);
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
string workingDir = Path.GetDirectoryName(launcherPath);
|
||||
|
||||
bool success = CreateProcess(
|
||||
launcherPath,
|
||||
null,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
false,
|
||||
0,
|
||||
IntPtr.Zero,
|
||||
workingDir,
|
||||
ref si,
|
||||
out pi);
|
||||
|
||||
if (!success) return false;
|
||||
uint waitResult = WaitForSingleObject(pi.hProcess, 30000);
|
||||
|
||||
if (waitResult == WAIT_TIMEOUT)
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Получение кода возврата
|
||||
uint exitCode;
|
||||
if (!GetExitCodeProcess(pi.hProcess, out exitCode))
|
||||
{
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
ForceToFront();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception outerEx)
|
||||
{
|
||||
Debug.LogError($"[License] CRITICAL ERROR in CheckLicense: {outerEx.Message}");
|
||||
Debug.LogError($"[License] Stack trace: {outerEx.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region FORCE TO FRONT
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetForegroundWindow(IntPtr hwnd);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern IntPtr GetActiveWindow();
|
||||
|
||||
public void ForceToFront()//Метод который возвращает фокус а окно после открытия защиты
|
||||
{
|
||||
IntPtr handle = GetActiveWindow();
|
||||
SetForegroundWindow(handle);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region клик в центр
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct INPUT
|
||||
{
|
||||
public uint type;
|
||||
public MOUSEINPUT mi;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MOUSEINPUT
|
||||
{
|
||||
public int dx;
|
||||
public int dy;
|
||||
public uint mouseData;
|
||||
public uint dwFlags;
|
||||
public uint time;
|
||||
public IntPtr dwExtraInfo;
|
||||
}
|
||||
|
||||
private const uint INPUT_MOUSE = 0;
|
||||
private const uint MOUSEEVENTF_MOVE = 0x0001;
|
||||
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
|
||||
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
|
||||
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
|
||||
|
||||
public static void ClickCenter()
|
||||
{
|
||||
int screenX = Screen.currentResolution.width / 2;
|
||||
int screenY = Screen.currentResolution.height / 2;
|
||||
|
||||
// WinAPI использует координаты 0–65535
|
||||
int absoluteX = (int)(screenX * 65535 / Screen.currentResolution.width);
|
||||
int absoluteY = (int)(screenY * 65535 / Screen.currentResolution.height);
|
||||
|
||||
INPUT[] inputs = new INPUT[3];
|
||||
|
||||
// движение мыши
|
||||
inputs[0] = new INPUT
|
||||
{
|
||||
type = INPUT_MOUSE,
|
||||
mi = new MOUSEINPUT
|
||||
{
|
||||
dx = absoluteX,
|
||||
dy = absoluteY,
|
||||
dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
|
||||
}
|
||||
};
|
||||
|
||||
// нажатие
|
||||
inputs[1] = new INPUT
|
||||
{
|
||||
type = INPUT_MOUSE,
|
||||
mi = new MOUSEINPUT
|
||||
{
|
||||
dwFlags = MOUSEEVENTF_LEFTDOWN
|
||||
}
|
||||
};
|
||||
|
||||
// отпускание
|
||||
inputs[2] = new INPUT
|
||||
{
|
||||
type = INPUT_MOUSE,
|
||||
mi = new MOUSEINPUT
|
||||
{
|
||||
dwFlags = MOUSEEVENTF_LEFTUP
|
||||
}
|
||||
};
|
||||
SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
Loading…
x
Reference in New Issue
Block a user