使用Process在后台模式下打开文件

时间:2010-10-11 08:23:59

标签: c# process

在我的程序中,我需要使用外部应用程序打开文件(Bentley MicroStation,如果它很重要)。我需要打开文件的应用程序对用户不可见(我将对它执行一些操作)。

使用Process打开文件的方式似乎很好,除了一件事 - 对“example.txt”或“example.doc”的测试表明,即使ProcessStartInfo属性WindowStyle设置为Minimized或Hidden,你仍然会看到应用程序打开文件。

那么,如何在不向用户显示操作的情况下打开文件?当然,之后可以隐藏应用程序窗口,但这不是我需要的......

更新。我使用Bentley MicroStation XM版。它有一个可以禁用的启动画面。

主要问题:当使用Process和ProcessStartInfo通过命令行参数(要打开的文件名)和各种设置(如WindowsStyle(隐藏),UseShellExecute(false),CreateNoWindow(true)应用程序窗口启动并可见时,启动MicroStation。使用win api WinExec进行简单测试,并将uCmdShow设置为0(隐藏),结果相同。

接受以后台模式启动应用程序的任何解决方案。提前谢谢。

3 个答案:

答案 0 :(得分:3)

在我看来,实现您的要求的最简单方法是在另一个windows desktop上启动新流程。默认进程pesktop是“WinSta0 \ Default”。关于CreateDesktop功能,您可以使用名称“MyDesktop”创建新桌面,然后在桌面上启动proccess。

以下代码演示了该技术:

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 :(得分:1)

尝试将CreateNoWindow 设置为true以隐藏窗口。

答案 2 :(得分:0)

如果你想隐藏Microstation窗口,你必须通过mdl或.net addin创建一个Microstation应用程序,你可以在其中完成你的工作,以及Microstation将加载和运行。然后,您可以在非图形模式下创建微观状态。