Открыть файл в фоновом режиме, используя Process - PullRequest
2 голосов
/ 11 октября 2010

В моей программе мне нужно открыть файл с помощью внешнего приложения (Bentley MicroStation, если это важно).Мне нужно, чтобы приложение с открытым файлом было невидимым для пользователя (я буду выполнять над ним некоторые операции).

Способ открытия файла с помощью Process выглядит неплохо, за исключением одного - тесты над "example.txt"или «example.doc» показывает, что даже если свойство ProcessStartInfo WindowStyle установлено в значение Minimized или Hidden, тем не менее вы видите приложение с открытым файлом.

Итак, как я могу открыть файл, не показывая свои операции пользователю?Конечно, впоследствии можно скрыть окно приложения, но это не то, что мне нужно ...

Upd. Я работаю с Bentley MicroStation XM edition.У него есть заставка, которую можно отключить.

Основная проблема: при запуске MicroStation через Process и ProcessStartInfo с аргументом командной строки (имя открываемого файла) и различными настройками, такими как WindowsStyle (скрытый), UseShellExecute (false), CreateNoWindow (true) окно приложенияи видимый.Простой тест с Win API WinExec с uCmdShow, установленным в 0 (скрытый), дает тот же результат.

Любое решение для запуска приложения в фоновом режиме принимается.Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 15 октября 2010

Мне кажется, самый простой способ реализовать ваши требования - запустить новый процесс на другом рабочем столе Windows . Процесс по умолчанию pesktop "WinSta0 \ Default". Что касается функции CreateDesktop , вы можете создать новый рабочий стол, например, с именем «MyDesktop», а затем запустить процесс на рабочем столе.

Следующий код демонстрирует технику:

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);
    }
}
1 голос
/ 11 октября 2010

Попробуйте установить CreateNoWindow в значение true, чтобы скрыть окно.

0 голосов
/ 22 апреля 2013

Если вы хотите скрыть окно Microstation, вам нужно создать приложение Microstation с помощью mdl или .net addin, в котором вы можете выполнять свою работу, и какую Microstation загружать и запускать. затем вы можете создать микростанцию ​​в неграфическом режиме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...