Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.69/29: Рейтинг темы: голосов - 29, средняя оценка - 4.69
1 / 1 / 0
Регистрация: 28.07.2015
Сообщений: 13
1

C# + Wscript.Shell

28.07.2015, 21:57. Показов 5356. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем доброго времени суток.
Вопрос такой, имеется некая команда, которая выполняется через Shell с использованием следующего кода.
C#
1
2
dynamic shell = Activator.CreateInstance(Type.GetTypeFromProgID("Wscript.Shell"));
int result = shell.Run(cmdLine, 1, -1);
Соответственно, требуется дождаться окончания выполнения команды и дальше предпринимать какие-либо действия, но код проскакивает команду Run сразу же и не ждет ее завершения (хотя я вижу, что команда выполняется), пробовал разные вариации ничего не помогает. Кто сталкивался или есть другой метод просьба поделиться.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.07.2015, 21:57
Ответы с готовыми решениями:

Использование Shell
Может я ваще не туда копаю, дело в том что я только начала работать в среде .NET. Я пытаюсь...

Создание ActiveX WScript.Shell
Всем хорошего Дня! В VBScript (в JavaScript самое) пишу: set WshShell =...

Запуск процесса с помощью WScript.Shell
здравствуйте если в бат файл записать: Print #1, ".\smartid_sample.exe " & Chr$(34) & sFP &...

Выполнение команды не юзая WScript.Shell
Всем привет вопрос в заголовке нужно выполнить команду например start 123.exe или ping google.com ...

8
Администратор
Эксперт .NET
17027 / 13379 / 5218
Регистрация: 17.03.2014
Сообщений: 27,369
Записей в блоге: 1
28.07.2015, 22:40 2
hamec, Process.Start + Process.WaitForExit.

Добавлено через 10 минут
Хотя Process.WaitForExit может и не помочь. Код с методом Run рабочий. Похоже выполняемая команда запускает другое приложение, а сама завершается.

Добавлено через 9 минут
На stackoverflow описывают алгоритм с использованием job-ов: создаем новый job с помощью CreateJobObject; создаем процесс в suspended состоянии с помощью CreateProcess; ассоциируем процесс с job с помощью AssignProcessToJobObject; запускаем процесс - ResumeThread для дескриптора полученного от CreateProcess. Далее советы разделяются. Надо использовать WaitForSingleObject на дескрипторе job или создать IO completion port и ждать сообщения JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO.
0
1 / 1 / 0
Регистрация: 28.07.2015
Сообщений: 13
29.07.2015, 21:31  [ТС] 3
Доброго времени суток.
Спасибо за ответ, начал смотреть в эту сторону получил такой результат.
Создаю job, создаю процесс в suspend, присоединяю, стартую, дальше жду следующим кодом
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
try
            {
                if (WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0)
                    return true;
            }
            catch (Exception ex)
            {
                return false;
            }
 
const UInt32 INFINITE = 0xFFFFFFFF;
const UInt32 WAIT_ABANDONED = 0x00000080;
const UInt32 WAIT_OBJECT_0 = 0x00000000;
const UInt32 WAIT_TIMEOUT = 0x00000102;
По диспетчеру задач отслеживаю, что процесс завершился, но происходит зацикливание и код из цикла не возвращается. WaitForSingleObject применяю к job.
В какую сторону еще посмотреть?
0
Администратор
Эксперт .NET
17027 / 13379 / 5218
Регистрация: 17.03.2014
Сообщений: 27,369
Записей в блоге: 1
29.07.2015, 21:48 4
hamec, значит придется IO completion port использовать. В комментарии на stackoverflow упоминалось что WaitForSingleObject может не сработать.
0
1 / 1 / 0
Регистрация: 28.07.2015
Сообщений: 13
29.07.2015, 21:55  [ТС] 5
А не подскажете какой-нибудь пример, нашел пример с записью файла, но не могу понять какое состояние и состояние чего отслеживать мне?
Правильно ли я понимаю, что создавая задачу я подвязываю ее на IOCP и мониторю статусы которые мне возвращаются?
0
6219 / 2467 / 725
Регистрация: 11.04.2015
Сообщений: 3,987
Записей в блоге: 43
29.07.2015, 23:02 6
Так у процесса ведь есть событие Exited
C#
1
2
3
4
5
           var proc = new Process();
            proc.EnableRaisingEvents = true;
            proc.Exited += (sender, e) => Console.WriteLine("Process exited");
            proc.StartInfo = new ProcessStartInfo("wscript", cmdLine);
            proc.Start();
0
1 / 1 / 0
Регистрация: 28.07.2015
Сообщений: 13
30.07.2015, 14:34  [ТС] 7
Добрый день.
Спасибо за ответ, но не поможет.
Process запускает команду на запуск иной программы, в контексте проекта это 1С.
Соответственно Process запустил и закончил свою работу.
Получается мне нужно мониторить созданный процесс от Process, если я правильно понял логику.
Только не могу понять как...

Добавлено через 5 минут
Опять же если я правильно понял, моя задача заключается в следующем:
1) Процесс по запуску программы является родительским;
2) Запускаемая программа, является дочерним процессом;
3) Нужно запретить завершаться родительскому процессу, пока не завершиться дочерний процесс

Добавлено через 4 минуты
Или как хотя бы получить ID процесса, запущенного от выполнения команды?

Добавлено через 2 часа 31 минуту
Более менее разобрался, что происходит.
Я вызываю файл 1cestart.exe, это launcher, который в свою очередь вызывает уже исполняемый файл 1cs.exe.
Остался только вопрос, как можно перехватить запуск исполняемого файла?
0
Администратор
Эксперт .NET
17027 / 13379 / 5218
Регистрация: 17.03.2014
Сообщений: 27,369
Записей в блоге: 1
30.07.2015, 19:07 8
Лучший ответ Сообщение было отмечено hamec как решение

Решение

hamec, вот готовый метод который запускает процесс и ждет завершения как самого процесса так и всех дочерних процессов:
ProcessHelper
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
static class ProcessHelper
{
    public static void StartProcessAndWaitForAllChildrenToExit(string fileName, string arguments = null)
    {
        IntPtr hJob = NativeMethods.CreateJobObject(IntPtr.Zero, null);
        IntPtr hPort = IntPtr.Zero;
        if (hJob != IntPtr.Zero)
        {
            // Создаем процесс в suspended состоянии
            STARTUPINFO startupInfo = STARTUPINFO.New();
            PROCESS_INFORMATION processInformation;
            if (NativeMethods.CreateProcess(
                fileName, "\"" + fileName + "\" " + arguments,
                IntPtr.Zero, IntPtr.Zero,
                false,
                ProcessCreationFlags.CreateSuspended | ProcessCreationFlags.CreateNewConsole,
                IntPtr.Zero,
                null,
                ref startupInfo,
                out processInformation
                ))
            {
                // Связываем процесс с job объектом
                NativeMethods.AssignProcessToJobObject(hJob, processInformation.hProcess);
 
                // Создаем I/O completion port и связываем его с job объектом
                hPort = NativeMethods.CreateIoCompletionPort(NativeMethods.InvalidHandleValue, IntPtr.Zero, IntPtr.Zero, 0);
                var jobPortAssoc = new JOBOBJECT_ASSOCIATE_COMPLETION_PORT();
                jobPortAssoc.CompletionPort = hPort;
                jobPortAssoc.CompletionKey = Marshal.AllocHGlobal(10);
                bool infoSet = NativeMethods.SetInformationJobObject(
                    hJob,
                    JOBOBJECTINFOCLASS.AssociateCompletionPortInformation,
                    ref jobPortAssoc,
                    (uint)Marshal.SizeOf<JOBOBJECT_ASSOCIATE_COMPLETION_PORT>()
                );
 
                // Запускаем процесс
                NativeMethods.ResumeThread(processInformation.hThread);
 
                // Ждем сообщения JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO
                // Оно говорит что процесс и все его дочерние процессы завершились
                uint completionCode;
                const int JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO = 4;
                UIntPtr completionKey;
                IntPtr overlapped;
                const uint INFINITE = UInt32.MaxValue;
                while (NativeMethods.GetQueuedCompletionStatus(hPort, out completionCode, out completionKey, out overlapped, INFINITE) && completionCode != JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO)
                {
                }
 
                Marshal.FreeHGlobal(jobPortAssoc.CompletionKey);
                NativeMethods.CloseHandle(processInformation.hThread);
                NativeMethods.CloseHandle(processInformation.hProcess);
            }
            NativeMethods.CloseHandle(hJob);
            if (hPort != IntPtr.Zero) NativeMethods.CloseHandle(hPort);
        }
    }
 
    static class NativeMethods
    {
        public static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
 
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr CreateJobObject(IntPtr jobAttributes, string name);
 
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateProcessW")]
        public static extern bool CreateProcess(
            [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,
            [MarshalAs(UnmanagedType.LPWStr)] string lpCommandLine,
            IntPtr lpProcessAttributes,
            IntPtr lpThreadAttributes,
            bool bInheritHandles,
            //uint dwCreationFlags,
            ProcessCreationFlags creationFlags,
            IntPtr lpEnvironment,
            [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,
            [In] ref STARTUPINFO lpStartupInfo,
            out PROCESS_INFORMATION lpProcessInformation);
 
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr hObject);
 
        [DllImport("kernel32.dll")]
        public static extern uint ResumeThread(IntPtr hThread);
 
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
 
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr CreateIoCompletionPort(IntPtr fileHandle, IntPtr existingCompletionPort,
            IntPtr completionKey, uint numberOfConcurrentThreads);
 
        [DllImport("kernel32.dll")]
        public static extern bool SetInformationJobObject(IntPtr hJob,
            JOBOBJECTINFOCLASS jobObjectInfoClass, ref JOBOBJECT_ASSOCIATE_COMPLETION_PORT lpJobObjectInfo,
            uint cbJobObjectInfoLength);
 
        [DllImport("kernel32.dll")]
        public static extern bool GetQueuedCompletionStatus(IntPtr completionPort, out uint lpNumberOfBytes,
            out UIntPtr lpCompletionKey, out IntPtr lpOverlapped, uint dwMilliseconds);
    }
 
 
    [StructLayout(LayoutKind.Sequential)]
    struct JOBOBJECT_ASSOCIATE_COMPLETION_PORT
    {
        public IntPtr CompletionKey;
        public IntPtr CompletionPort;
    }
 
    enum JOBOBJECTINFOCLASS
    {
        AssociateCompletionPortInformation = 7,
        BasicLimitInformation = 2,
        BasicUIRestrictions = 4,
        EndOfJobTimeInformation = 6,
        ExtendedLimitInformation = 9,
        SecurityLimitInformation = 5,
        GroupInformation = 11
    }
 
    [Flags]
    enum ProcessCreationFlags
    {
        CreateSuspended = 0x00000004,
        DetachedProcess = 0x00000008,
        CreateNewConsole = 0x00000010
    }
 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct STARTUPINFO
    {
        public Int32 cb;
        public IntPtr lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
 
        public static STARTUPINFO New()
        {
            STARTUPINFO startupInfo = new STARTUPINFO();
            startupInfo.cb = Marshal.SizeOf<STARTUPINFO>();
            startupInfo.lpReserved = IntPtr.Zero;
            startupInfo.cbReserved2 = 0;
            startupInfo.lpReserved2 = IntPtr.Zero;
            return startupInfo;
        }
    }
 
    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }
 
    //[StructLayout(LayoutKind.Sequential)]
    //public struct SECURITY_ATTRIBUTES
    //{
    //  public int Length;
    //  public IntPtr SecurityDescriptor;
    //  public int InheritHandle;
    //}
}

В классе всего одна функция - StartProcessAndWaitForAllChildrenToExit. Первым аргументом нужно передать полный путь к исполняемому файлу. Вторым необязательным аргументом параметры командной строки.

Цитата Сообщение от hamec Посмотреть сообщение
3) Нужно запретить завершаться родительскому процессу, пока не завершиться дочерний процесс
...
Остался только вопрос, как можно перехватить запуск исполняемого файла?
Ничего запрещать или перехватывать не надо. Нужно было всего лишь написать код ожидающий завершения родительского процесса и всех дочерних с помощью I/O completion port. Код выше именно это и делает.
1
1 / 1 / 0
Регистрация: 28.07.2015
Сообщений: 13
30.07.2015, 20:16  [ТС] 9
Огромное спасибо. Действительно работает, пойду разбираться.
0
30.07.2015, 20:16
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.07.2015, 20:16
Помогаю со студенческими работами здесь

Не получается корректно работать с Wscript.shell
В результате длительных исследований написал примерно вот такой агент: Sub Initialize On Error...

Wscript.Shell.Run не выводит результат в файл
Доброго всем времени! Ситуация такая: Нужно запустить экзешник с параметрами, который на...

Вызов объектов Wscript.Shell с именем из переменной
Задача: есть переменная, в которой задается количество объектов Wscript.Shell, которые надо...

Как запустить CreateObject ("WScript.Shell") под администратором?
такой батник работает @echo on ( echo Open xx.xx.xx.xx echo Login echo pass echo PROMPT...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru