2 Stimmen

Datei im Hintergrundmodus öffnen mit Process

In meinem Programm muss ich eine Datei mit einer externen Anwendung öffnen (Bentley MicroStation, falls das wichtig ist). Ich brauche die Anwendung mit der geöffneten Datei für den Benutzer unsichtbar sein (ich werde einige Operationen über sie durchführen).

Der Weg, eine Datei mit Process zu öffnen, scheint bis auf eine Sache in Ordnung zu sein - Tests über "example.txt" oder "example.doc" zeigen, dass selbst wenn die ProcessStartInfo-Eigenschaft WindowStyle auf Minimized oder Hidden gesetzt ist, man trotzdem die Anwendung mit geöffneter Datei sieht.

Wie kann ich also eine Datei öffnen, ohne dem Benutzer meine Operationen zu zeigen? Natürlich ist es möglich, das App-Fenster danach auszublenden, aber das ist nicht das, was ich brauche...

Upd. Ich arbeite mit Bentley MicroStation XM Edition. Es gibt einen Splash-Screen, der deaktiviert werden kann.

Das Hauptproblem: Beim Start von MicroStation über Process und ProcessStartInfo mit Befehlszeilenargument (Name der zu öffnenden Datei) und verschiedenen Einstellungen wie WindowsStyle (Hidden), UseShellExecute (false), CreateNoWindow (true) ist das Anwendungsfenster vorhanden und sichtbar. Ein einfacher Test mit der Win-Api WinExec mit uCmdShow auf 0 (versteckt) ergibt das gleiche Ergebnis.

Jede Lösung zum Starten der Anwendung im Hintergrundmodus wird akzeptiert. Vielen Dank im Voraus.

3voto

Oleg Punkte 219333

Der einfachste Weg zur Umsetzung Ihrer Anforderungen scheint mir zu sein, einen neuen Prozess auf der anderen Windows-Desktop . Der Standard-Prozess-Pesktop ist "WinSta0 \Default ". In Bezug auf CreateDesktop Mit dieser Funktion können Sie z.B. einen neuen Desktop mit dem Namen "MeinDesktop" erstellen und dann den Prozess auf dem Desktop starten.

Der folgende Code demonstriert die Technik:

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace HiddenDesktop {
    class Program {
        static void Main (string[] args) {
            string desktopName = "MyDesktop";
            string appPath = @"%SystemRoot%\system32\cmd.exe";
            string parameters = @"/c dir C:\ >%TEMP%\dir.txt";
            IntPtr hDesktop = IntPtr.Zero;
            NativeMethods.ProcessInformation processInfo = new NativeMethods.ProcessInformation ();
            bool isSuccess;

            try {
                hDesktop = NativeMethods.CreateDesktop (desktopName, null, null, 0,
                        NativeMethods.ACCESS_MASK.MAXIMUM_ALLOWED, null);
                if (hDesktop == IntPtr.Zero) {
                    DisplayLastErrorMessage ();
                    return;
                }

                NativeMethods.StartupInfo startupInfo = new NativeMethods.StartupInfo ();
                NativeMethods.CreateProcessFlags dwCreationFlags = NativeMethods.CreateProcessFlags.NormalPriorityClass;
                startupInfo.cb = Marshal.SizeOf (typeof (NativeMethods.StartupInfo));
                startupInfo.lpDesktop = "WinSta0\\" + desktopName;
                string currentDirectory = Environment.CurrentDirectory;
                appPath = Environment.ExpandEnvironmentVariables (appPath);
                //if (appPath.IndexOf (' ') != -1)
                //    appPath = '\"' + appPath + '\"';
                StringBuilder sbParameters = new StringBuilder (3 + appPath.Length + parameters.Length);
                if (appPath.IndexOf (' ') != -1) {
                    sbParameters.Append ('\"');
                    sbParameters.Append (appPath);
                    sbParameters.Append ('\"');
                }
                else
                    sbParameters.Append (appPath);
                sbParameters.Append (' ');
                sbParameters.Append (parameters);
                // appPath - full path to the exe without having " if the file has blanks in the path
                isSuccess = NativeMethods.CreateProcess (appPath,
                    sbParameters.ToString(), IntPtr.Zero, IntPtr.Zero, false, dwCreationFlags,
                IntPtr.Zero, currentDirectory, ref startupInfo, out processInfo);
                if (!isSuccess) {
                    DisplayLastErrorMessage ();
                    return;
                }
                NativeMethods.CloseHandle (processInfo.hThread);
                processInfo.hThread = IntPtr.Zero;

                if (NativeMethods.WaitForSingleObject (processInfo.hProcess, NativeMethods.Infinite) == NativeMethods.WaitObject0) {
                    Console.WriteLine ("the process is ended");
                }
            }
            finally {
                if (processInfo.hThread != IntPtr.Zero)
                    isSuccess = NativeMethods.CloseHandle (processInfo.hThread);
                if (processInfo.hProcess != IntPtr.Zero)
                    isSuccess = NativeMethods.CloseHandle (processInfo.hProcess);
                if (hDesktop != IntPtr.Zero)
                    isSuccess = NativeMethods.CloseDesktop (hDesktop);
            }
        }
        static void DisplayLastErrorMessage () {
            int errorCode = Marshal.GetLastWin32Error ();
            Win32Exception error32 = new Win32Exception (errorCode);
            Console.WriteLine ("Error {0}: {1}", errorCode, error32.Message);
        }
    }
    internal static class NativeMethods {
        internal const int NoError = 0;
        internal const UInt32 Infinite = 0xFFFFFFFF;

        internal const UInt32 WaitAbandoned = 0x00000080;
        internal const UInt32 WaitObject0 = 0x00000000;
        internal const UInt32 WaitTimeout = 0x00000102;

        [Flags]
        internal enum ACCESS_MASK : uint {
            DELETE = 0x00010000,
            READ_CONTROL = 0x00020000,
            WRITE_DAC = 0x00040000,
            WRITE_OWNER = 0x00080000,
            SYNCHRONIZE = 0x00100000,

            STANDARD_RIGHTS_REQUIRED = 0x000f0000,

            STANDARD_RIGHTS_READ = 0x00020000,
            STANDARD_RIGHTS_WRITE = 0x00020000,
            STANDARD_RIGHTS_EXECUTE = 0x00020000,

            STANDARD_RIGHTS_ALL = 0x001f0000,

            SPECIFIC_RIGHTS_ALL = 0x0000ffff,

            ACCESS_SYSTEM_SECURITY = 0x01000000,

            MAXIMUM_ALLOWED = 0x02000000,

            GENERIC_READ = 0x80000000,
            GENERIC_WRITE = 0x40000000,
            GENERIC_EXECUTE = 0x20000000,
            GENERIC_ALL = 0x10000000,

            DESKTOP_READOBJECTS = 0x00000001,
            DESKTOP_CREATEWINDOW = 0x00000002,
            DESKTOP_CREATEMENU = 0x00000004,
            DESKTOP_HOOKCONTROL = 0x00000008,
            DESKTOP_JOURNALRECORD = 0x00000010,
            DESKTOP_JOURNALPLAYBACK = 0x00000020,
            DESKTOP_ENUMERATE = 0x00000040,
            DESKTOP_WRITEOBJECTS = 0x00000080,
            DESKTOP_SWITCHDESKTOP = 0x00000100,

            WINSTA_ENUMDESKTOPS = 0x00000001,
            WINSTA_READATTRIBUTES = 0x00000002,
            WINSTA_ACCESSCLIPBOARD = 0x00000004,
            WINSTA_CREATEDESKTOP = 0x00000008,
            WINSTA_WRITEATTRIBUTES = 0x00000010,
            WINSTA_ACCESSGLOBALATOMS = 0x00000020,
            WINSTA_EXITWINDOWS = 0x00000040,
            WINSTA_ENUMERATE = 0x00000100,
            WINSTA_READSCREEN = 0x00000200,

            WINSTA_ALL_ACCESS = 0x0000037f
        }

        [StructLayout (LayoutKind.Sequential)]
        public class SECURITY_ATTRIBUTES {
            public int nLength;
            public IntPtr lpSecurityDescriptor;
            public int bInheritHandle;
        }
        [StructLayout (LayoutKind.Sequential)]
        internal struct ProcessInformation {
            internal IntPtr hProcess;
            internal IntPtr hThread;
            internal int dwProcessId;
            internal int dwThreadId;
        }

        [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct StartupInfo {
            internal Int32 cb;
            internal string lpReserved;
            internal string lpDesktop;
            internal string lpTitle;
            internal Int32 dwX;
            internal Int32 dwY;
            internal Int32 dwXSize;
            internal Int32 dwYSize;
            internal Int32 dwXCountChars;
            internal Int32 dwYCountChars;
            internal Int32 dwFillAttribute;
            internal Int32 dwFlags;
            internal Int16 wShowWindow;
            internal Int16 cbReserved2;
            internal IntPtr lpReserved2;
            internal IntPtr hStdInput;
            internal IntPtr hStdOutput;
            internal IntPtr hStdError;
        }
        [Flags]
        internal enum CreateProcessFlags : uint {
            DebugProcess = 0x00000001,
            DebugOnlyThisProcess = 0x00000002,
            CreateSuspended = 0x00000004,
            DetachedProcess = 0x00000008,
            CreateNewConsole = 0x00000010,
            NormalPriorityClass = 0x00000020,
            IdlePriorityClass = 0x00000040,
            HighPriorityClass = 0x00000080,
            RealtimePriorityClass = 0x00000100,
            CreateNewProcessGroup = 0x00000200,
            CreateUnicodeEnvironment = 0x00000400,
            CreateSeparateWowVdm = 0x00000800,
            CreateSharedWowVdm = 0x00001000,
            CreateForcedos = 0x00002000,
            BelowNormalPriorityClass = 0x00004000,
            AboveNormalPriorityClass = 0x00008000,
            InheritParentAffinity = 0x00010000,
            InheritCallerPriority = 0x00020000,  // Deprecated
            CreateProtectedProcess = 0x00040000,
            ExtendedStartupinfoPresent = 0x00080000,
            ProcessModeBackgroundBegin = 0x00100000,
            ProcessModeBackgroundEnd = 0x00200000,
            CreateBreakawayFromJob = 0x01000000,
            CreatePreserveCodeAuthzLevel = 0x02000000,
            CreateDefaultErrorMode = 0x04000000,
            CreateNoWindow = 0x08000000,
            ProfileUser = 0x10000000,
            ProfileKernel = 0x20000000,
            ProfileServer = 0x40000000,
            CreateIgnoreSystemDefault = 0x80000000,
        }

        [DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        internal static extern IntPtr CreateDesktop (
                        string desktopName,
                        string device, // must be null.
                        string deviceMode, // must be null,
                        int flags,  // use 0
                        ACCESS_MASK accessMask,
                        SECURITY_ATTRIBUTES attributes);
        [DllImport ("user32.dll", SetLastError = true)]
        [return: MarshalAs (UnmanagedType.Bool)]
        internal static extern bool CloseDesktop (IntPtr hDesktop);

        [DllImport ("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        [return: MarshalAs (UnmanagedType.Bool)]
        internal static extern bool CreateProcess (string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes,
            bool bInheritHandles, CreateProcessFlags dwCreationFlags, IntPtr lpEnvironment,
            string lpCurrentDirectory, ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);

        [DllImport ("kernel32.dll", SetLastError = true)]
        [return: MarshalAs (UnmanagedType.Bool)]
        internal static extern bool CloseHandle (IntPtr hObject);
        [DllImport ("kernel32.dll", SetLastError = true)]
        internal static extern UInt32 WaitForSingleObject (IntPtr hHandle, UInt32 dwMilliseconds);
    }
}

1voto

Giorgi Punkte 29625

Versuchen Sie die Einstellung CreateNoWindow auf true, um das Fenster auszublenden.

0voto

feelapi Punkte 1

Wenn Sie das Microstation-Fenster ausblenden wollen, müssen Sie eine Microstation-App per mdl oder .net-Addin erstellen, in der Sie Ihre Arbeit erledigen können und die von Microstation geladen und ausgeführt wird. dann können Sie eine Microstation in einem nicht-grafischen Modus erstellen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X