]> localhost Git - gists.git/commitdiff
Restart for both .NET 4.x and .NET 5.0+
authormisomosi <[email protected]>
Mon, 18 May 2026 18:28:35 +0000 (14:28 -0400)
committermisomosi <[email protected]>
Mon, 18 May 2026 18:28:35 +0000 (14:28 -0400)
DotnetProcessRestart/.gitignore
DotnetProcessRestart/ProcessRestart.cs

index ca5b692ddd2a1fe68d62938344bd55a079f26829..431fe7cace17b6e89747099f441ebbc2469b6b80 100644 (file)
@@ -5,3 +5,6 @@
 obj/
 bin/
 lib/
+
+# Test-specific ignores
+restart.txt
index 85af26accfaad67e9e22c5d9b9e74d2a05445137..72f7bfbc48f99405b891375c53785e124fd1c147 100644 (file)
@@ -1,36 +1,87 @@
 using System;
+using System.IO;
 using System.Runtime.InteropServices;
+using System.Text;
+
 class RestartExample {
 #if NET5_0_OR_GREATER
+       // Simpler restart for .NET Core
        public static void Restart() {
-               System.Console.WriteLine("Core!");
-               // Use ProcessStartInfo.ArgumentList to pass args
+               string[] args = Environment.GetCommandLineArgs();
+               System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(args[0]);
+               for (int i = 1; i < args.Length; i++)
+                       psi.ArgumentList.Add(args[i]);
+               psi.UseShellExecute = false;
+               System.Diagnostics.Process.Start(psi);
                Environment.Exit(0);
        }
 #else
-       // Technically an unsafe API but we keep it private
+       // ArgumentList in ProcessStartInfo isn't always present before .NET 5.0
+       // Restart using KERNEL32's CreateProcessW and Environment.CommandLine
+       // We have a lot of unsafe structs and imports, so
+       // keep them private and just use them for the restart
+       [StructLayout(LayoutKind.Sequential)]
+       private struct STARTUPINFOW
+       {
+               public uint cb;
+               public IntPtr lpReserved;    // char *
+               public IntPtr lpDesktop;     // char *
+               public IntPtr lpTitle;       // char *
+               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 ushort uShowWindow;
+               public ushort cbReserved2;
+               public IntPtr lpReserved2;   // void *
+               public IntPtr hStdInput;     // HANDLE
+               public IntPtr hStdOutput;    // HANDLE
+               public IntPtr hStdError;     // HANDLE
+       }
+       [StructLayout(LayoutKind.Sequential)]
+       private struct PROCESS_INFORMATION
+       {
+               IntPtr hProcess;  // HANDLE
+               IntPtr hThread;   // HANDLE
+               uint dwProcessId;
+               uint dwThreadId;
+       }
+       // SECURITY_ATTRIBUTES not needed, so not defined
        [DllImport("KERNEL32.dll", ExactSpelling=true, SetLastError=true)]
        private static extern int CreateProcessW(
-               string lpApplicationName,
-               char[] lpCommandLine,
-               IntPtr lpProcesAttributes,
-               IntPtr lpThreadAttributes,
+               [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,
+               [MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpCommandLine,
+               IntPtr lpProcesAttributes,  // SECURITY_ATTRIBUTES *
+               IntPtr lpThreadAttributes,  // SECURITY_ATTRIBUTES *
                int bInheritHandles,
                uint dwCreationFlags,
-               IntPtr lpEnvironment,
-               string lpCurrentDirectory,
-               IntPtr lpStartupInfo,
-               IntPtr lpProcessInformation
+               IntPtr lpEnvironment,       // void *
+               [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,
+               ref STARTUPINFOW lpStartupInfo,
+               out PROCESS_INFORMATION lpProcessInformation
        );
        public static void Restart() {
-               Console.WriteLine("Windows!");
-               char[] lpCommandLine = Environment.CommandLine.ToCharArray();
-               // Use CreateProcessW with lpCommandLine to relaunch process
+               StringBuilder lpCommandLine = new StringBuilder(Environment.CommandLine);
+               STARTUPINFOW si = new STARTUPINFOW();
+               PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
+               si.cb = (uint)Marshal.SizeOf(si);
+               CreateProcessW(null, lpCommandLine, IntPtr.Zero, IntPtr.Zero, 0, 0, IntPtr.Zero, null, ref si, out pi);
                Environment.Exit(0);
        }
 #endif
 
        public static void Main(string[] args) {
-               Restart();
+               string fname = "restart.txt";
+               if (File.Exists(fname)) {
+                       Console.WriteLine("Restarted!");
+               } else {
+                       Console.WriteLine("Restarting!");
+                       File.WriteAllText(fname, "");
+                       Restart();
+               }
        }
 }