gpt4 book ai didi

c# - 如果出现任何错误,如何自动重新打开/重新启动 WPF 应用程序?

转载 作者:行者123 更新时间:2023-12-03 08:14:08 25 4
gpt4 key购买 nike

这个问题在这里已经有了答案:





How do I restart a WPF application? [duplicate]

(8 个回答)


8年前关闭。




我有一个在 Windows 7 Ultimate 上启动时运行的全屏 WPF 应用程序。如果应用程序在发生未处理的异常时崩溃/关闭,我需要自动重新启动 WPF 应用程序。

最简单的方法是什么?

最佳答案

在上述情况下,您可以使用 Windows 服务来监控应用程序。在进程中是否运行。如果它因任何原因停止,则服务必须再次启动此应用程序。

扭扭 : 在 Windows Vista 中微软更改了 windows 安全系统。 Windows 服务将在 Session 0 下启动。这是这里要考虑的问题。但要从窗口服务执行 Windows 应用程序,您可以使用以下代码。

 public class ProcessAsUser
{

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);


[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel,
Int32 dwTokenType,
ref IntPtr phNewToken);


[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
UInt32 DesiredAccess,
ref IntPtr TokenHandle);

[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
ref IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);


[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
IntPtr lpEnvironment);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(
IntPtr hObject);

private const short SW_SHOW = 5;
private const uint TOKEN_QUERY = 0x0008;
private const uint TOKEN_DUPLICATE = 0x0002;
private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
private const int GENERIC_ALL_ACCESS = 0x10000000;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_FORCEONFEEDBACK = 0x00000040;
private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;


private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock)
{
bool result = false;


PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);

STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);


//if this member is NULL, the new process inherits the desktop
//and window station of its parent process. If this member is
//an empty string, the process does not inherit the desktop and
//window station of its parent process; instead, the system
//determines if a new desktop and window station need to be created.
//If the impersonated user already has a desktop, the system uses the
//existing desktop.

si.lpDesktop = @"WinSta0\Default"; //Modify as needed
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
//Set other si properties as required.

result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);


if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Debug.WriteLine(message);

}

return result;
}


private static IntPtr GetPrimaryToken(int processId)
{
IntPtr token = IntPtr.Zero;
IntPtr primaryToken = IntPtr.Zero;
bool retVal = false;
Process p = null;

try
{
p = Process.GetProcessById(processId);
}

catch (ArgumentException)
{

string details = String.Format("ProcessID {0} Not Available", processId);
Debug.WriteLine(details);
throw;
}


//Gets impersonation token
retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
if (retVal == true)
{

SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = (uint)Marshal.SizeOf(sa);

//Convert the impersonation token into Primary token
retVal = DuplicateTokenEx(
token,
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref primaryToken);

//Close the Token that was previously opened.
CloseHandle(token);
if (retVal == false)
{
string message = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}

}

else
{

string message = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);

}

//We'll Close this token after it is used.
return primaryToken;

}

private static IntPtr GetEnvironmentBlock(IntPtr token)
{

IntPtr envBlock = IntPtr.Zero;
bool retVal = CreateEnvironmentBlock(ref envBlock, token, false);
if (retVal == false)
{

//Environment Block, things like common paths to My Documents etc.
//Will not be created if "false"
//It should not adversley affect CreateProcessAsUser.

string message = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);

}
return envBlock;
}

public static bool Launch(string appCmdLine /*,int processId*/)
{

bool ret = false;

//Either specify the processID explicitly
//Or try to get it from a process owned by the user.
//In this case assuming there is only one explorer.exe

Process[] ps = Process.GetProcessesByName("explorer");
int processId = -1;//=processId
if (ps.Length > 0)
{
processId = ps[0].Id;
}

if (processId > 1)
{
IntPtr token = GetPrimaryToken(processId);

if (token != IntPtr.Zero)
{

IntPtr envBlock = GetEnvironmentBlock(token);
ret = LaunchProcessAsUser(appCmdLine, token, envBlock);
if (envBlock != IntPtr.Zero)
DestroyEnvironmentBlock(envBlock);

CloseHandle(token);
}

}
return ret;
}

}

[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}



[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
public uint nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}


[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;

}

internal enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}

internal enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}

使用上面的代码。

ProcessAsUser.Launch("applicationlocation.exe");

或者你可以试试这个。

在您的 Wpf App.cs 代码文件中。
 protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
System.Windows.Forms.Application.Restart();

}

但是这个解决方案不能保证应用程序在关闭后会重新启动。所以我已经使用了 Windows 服务之一。

关于c# - 如果出现任何错误,如何自动重新打开/重新启动 WPF 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20092388/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com