Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.61/18: Рейтинг темы: голосов - 18, средняя оценка - 4.61
0 / 0 / 0
Регистрация: 03.07.2009
Сообщений: 6
1

Имитация запуска программы из командной строки

03.07.2009, 19:40. Показов 3537. Ответов 13
Метки нет (Все метки)

В своем проекте на C# под .Net 2.0 я использую Microsoft.VisualBasic.Interaction.Shell() для запуска архиватора сотни тысяч раз (пакетная обработка файлов).
Столкнулся с проблемой генерации исключения в методе класса, где вызывается Microsoft.VisualBasic.Interaction.Shell() с сообщением "File not Found", [хотя все параметры для Shell заданы правильно]. Ошибка "плавающая" - где-то через 20-30 тыс. запусков Microsoft.VisualBasic.Interaction.Shell(). Причем, генерация исключения напрямую зависит от используемой памяти.
Я написал стенд (ts.zip "весит" 198 кБ: http://ifolder.ru/12943260), c помощью которого можно увидеть "вылет" исключения на Microsoft.VisualBasic.Interaction.Shell(). Иногда тест проходит успешно, но при повторном его запуске - Microsoft.VisualBasic.Interaction.Shell() дает сбой через некоторое число запусков.
В Тесте в папке debug лежит уже скомпилированный ts.exe (тест), архив для теста 1.zip, архиваторы... Код при желании можно перекомпилировать, если нужно... Проект Теста написан на SharpDevelop 3.1, но код легко переложить и на MS VC#.
Помогите "обуздать" Microsoft.VisualBasic.Interaction.Shell(). Если есть другие способы иммитации запуска программы из коммандной строки - то подскажите, пожалуйста, какие. Мне важно использовать ИММЕННО Иммитацию запуска программы из коммандной строки (для возможности работы с любыми видами архиваторов).
Спасибо.

P.S. Нижеприведенный код - сильно упрощенный код Теста (если кому-нибудь не хочется скачивать Тест и просмотреть его работу).

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
long lCount = 30000;
for( int i=0; i!=lCount; ++i ) {
    // распаковка zip-фрхива
    string sTempDir = @Environment.CurrentDirectory;
    if( !Directory.Exists( sTempDir ) ) {
        Directory.CreateDirectory( sTempDir );
    }
            
    string s = "\"" + "7z.exe" + "\" e"; // Распаковать (для полных путей - x)
    s += " -y"; // На все отвечать yes
    s += " " + "\"" + "Test.zip" + "\""; // Файл который нужно распаковать
    s += " -o" + "\"" + sTempDir + "\""; // Временная папка распаковки
            
    try {
        return Microsoft.VisualBasic.Interaction.Shell(s, Microsoft.VisualBasic.AppWinStyle.Hide, true, -1);
    } catch( Exception e ) {
        string sMess = "Сообщение: "+e.Message;
        MessageBox.Show( sMess, "Исключение", MessageBoxButtons.OK, MessageBoxIcon.Warning );
    }
    if( File.Exists( sTxt ) ) {
        File.Delete( sTxt );
    }
}
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
03.07.2009, 19:40
Ответы с готовыми решениями:

Возможность запуска из командной строки
Привет всем! У меня есть условие в задании. "Программа должна представлять исполняемый файл и...

Запуск командной строки из кода программы
Пишу свою среду разработки программ на Ассемблере. Код из РичТекстБокса сохраняю в текстовый файл...

Как правильно прописать путь для запуска с командной строки?
Не получается запустить программу с командной строки . Прога лежит в...

Запуск программы из командной строки
Можно ли как-то ограничить вводимые аргументы? Функция static void Main(string args) должна...

13
1922 / 427 / 41
Регистрация: 12.07.2007
Сообщений: 2,062
05.07.2009, 11:43 2
Класс Process.
0
0 / 0 / 0
Регистрация: 03.07.2009
Сообщений: 6
05.07.2009, 21:50  [ТС] 3
Краткость - сестра таланта :-) . Вы не могли бы пояснить, что имели ввиду? Спасибо.
0
MCSD: APP BUILDER
8791 / 1070 / 104
Регистрация: 17.06.2006
Сообщений: 12,603
05.07.2009, 22:04 4
dikbsd,
Краткость - сестра таланта :-) . Вы не могли бы пояснить, что имели ввиду? Спасибо.

Это был ответ на вопрос
"Если есть другие способы иммитации запуска программы из коммандной строки "
1
Кибернетик
465 / 89 / 12
Регистрация: 10.04.2009
Сообщений: 424
05.07.2009, 23:19 5
Лучший ответ Сообщение было отмечено как решение

Решение

Небольшие пояснения
Класс Process Предоставляет доступ к локальным и удаленным процессам и позволяет запускать и останавливать локальные системные процессы.

Свойство StartInfo предоставляет набор используемых параметров для запуска процесса. При вызове метода Start, свойство StartInfo используется для указания процессу запуститься. Единственный необходимый для задания элемент свойства StartInfo — свойство FileName.

В следующем примере для запуска процесса используется сам класс Process и статический метод Start.

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
using System;
using System.Diagnostics;
using System.ComponentModel;
 
namespace MyProcessSample
{
    class MyProcess
    {
       
        void OpenApplication(string myFavoritesPath)
        {
            // Start Internet Explorer. Defaults to the home page.
            Process.Start("IExplore.exe");
                    
            // Display the contents of the favorites folder in the browser.
            Process.Start(myFavoritesPath);
 
        }
        
        /// <summary>
        /// Opens urls and .html documents using Internet Explorer.
        /// </summary>
        void OpenWithArguments()
        {
            // url's are not considered documents. They can only be opened
            // by passing them as arguments.
            Process.Start("IExplore.exe", "www.northwindtraders.com");
            
            // Start a Web page using a browser associated with .html and .asp files.
            Process.Start("IExplore.exe", "C:\\myPath\\myFile.htm");
            Process.Start("IExplore.exe", "C:\\myPath\\myFile.asp");
        }
        
        /// <summary>
        /// Uses the ProcessStartInfo class to start new processes, both in a minimized 
        /// mode.
        /// </summary>
        void OpenWithStartInfo()
        {
            
            ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
            startInfo.WindowStyle = ProcessWindowStyle.Minimized;
            
            Process.Start(startInfo);
            
            startInfo.Arguments = "www.northwindtraders.com"; //так аргументы передаем
            
            Process.Start(startInfo);
            
        }
 
        static void Main()
        {
                    // Get the path that stores favorite links.
                    string myFavoritesPath = 
                    Environment.GetFolderPath(Environment.SpecialFolder.Favorites);
 
                    MyProcess myProcess = new MyProcess();
 
            myProcess.OpenApplication(myFavoritesPath);
            myProcess.OpenWithArguments();
            myProcess.OpenWithStartInfo();
 
            }   
    }
}
0
0 / 0 / 0
Регистрация: 03.07.2009
Сообщений: 6
06.07.2009, 19:34  [ТС] 6
Цитата Сообщение от Rififi Посмотреть сообщение
dikbsd,
Краткость - сестра таланта :-) . Вы не могли бы пояснить, что имели ввиду? Спасибо.

Это был ответ на вопрос
"Если есть другие способы иммитации запуска программы из коммандной строки "
Спасибо за идею про Process - сделал, работает. НО!
В Microsoft.VisualBasic.Interaction.Shell() последний параметр - число задержки в млсек до выполнения следующей строки кода, а если этот параметр = -1, то следующая строка кода не будет выполнена до тех пор, пока не отработает Microsoft.VisualBasic.Interaction.Shell().
Например
C#
1
Microsoft.VisualBasic.Interaction.Shell(s, Microsoft.VisualBasic.AppWinStyle.Hide, true, -1);
Как мне "заставить" строку после Process ждать, пока Process() не отработает полностью? Иначе в цикле запускается сразу несколько процессов, а строки ниже "не успевают" обрабатывать данные, и генерится исключени, что файл уже используется другим процессом.
Вот код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Archiver {
    ...
    public void unrar( string sUnRarPath, string sFilePath, string sTempDir ) {
        string s = " e";                // Распаковать (для полных путей - x)
        s += " -y";                     // На все отвечать yes
        s += " \"" + sFilePath + "\"";  // Файл который нужно распаковать
        s += " \"" + sTempDir + "\"";   // Временная папка распаковки
 
        ProcessStartInfo startInfo = new ProcessStartInfo( "\""+sUnRarPath+"\"", s );
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Process.Start(startInfo);
    }
}
...
Archiver a = new Archiver();
// lFilesList - список путей к файлам
foreach( string sFile in lFilesList ) {
    a.unrar( m_sUnRarPath, sFile, "Temp" );
    // обработка распакованного файла во временной папке
    // удаление временной папки
}
Нужно, чтобы в строке
C#
1
a.unrar( m_sUnRarPath, sFile, "Temp" );
файл распоковался, потом обработался и временная папка удалилась. А получается: файл распаковался, обрабатывается, а в это время идет распаковка других файлов из
C#
1
lFilesList
по
C#
1
a.unrar( m_sUnRarPath, sFile, "Temp" );
Как мне "заставить"
C#
1
a.unrar( m_sUnRarPath, sFile, "Temp" );
ждать строку // обработка распакованного файла
Спасибо за помощь.
0
Кибернетик
465 / 89 / 12
Регистрация: 10.04.2009
Сообщений: 424
06.07.2009, 19:51 7
Это называется синхронизация потоков, для этого есть конструкция lock.
вот пример использования:
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
using System;
using System.Threading;
 
class Account
{
    private Object thisLock = new Object(); //НУЖНО создать обьект!
    int balance;
 
    Random r = new Random();
 
    public Account(int initial)
    {
        balance = initial;
    }
 
    int Withdraw(int amount)
    {
 
        // This condition will never be true unless the lock statement
        // is commented out:
        if (balance < 0)
        {
            throw new Exception("Negative Balance");
        }
 
        // Comment out the next line to see the effect of leaving out 
        // the lock keyword:
        lock(thisLock) // ЗДЕСЬ идет блокировка, пока терущий процесс не ваполниться, другой сюда не попадет
        {
            if (balance >= amount)
            {
                Console.WriteLine("Balance before Withdrawal :  " + balance);
                Console.WriteLine("Amount to Withdraw        : -" + amount);
                balance = balance - amount;
                Console.WriteLine("Balance after Withdrawal  :  " + balance);
                return amount;
            }
            else
            {
                return 0; // transaction rejected
            }
        }
    }
 
    public void DoTransactions()
    {
        for (int i = 0; i < 100; i++)
        {
            Withdraw(r.Next(1, 100));
        }
    }
}
 
class Test
{
    static void Main()
    {
        Thread[] threads = new Thread[10];
        Account acc = new Account(1000);
        for (int i = 0; i < 10; i++)
        {
            Thread t = new Thread(new ThreadStart(acc.DoTransactions));
            threads[i] = t;
        }
        for (int i = 0; i < 10; i++)
        {
            threads[i].Start();
        }
    }
}
Если вкраце то:
C#
1
2
3
4
5
6
7
...
private Object thisLock = new Object(); //НУЖНО создать обьект!
...
lock(thisLock)
{
... //тут критический участок кода (тот который должен обрабатываться 1м потоком, остальные ждут)
}
и все будет ок!
0
MCSD: APP BUILDER
8791 / 1070 / 104
Регистрация: 17.06.2006
Сообщений: 12,603
06.07.2009, 21:09 8
всё делается гораздо проще.
C#
1
2
3
4
Process p = new Process();
// заполняем p;
p.Start();
p.WaitForExit();
1
Кибернетик
465 / 89 / 12
Регистрация: 10.04.2009
Сообщений: 424
06.07.2009, 21:26 9
Цитата Сообщение от Rififi Посмотреть сообщение
всё делается гораздо проще.

Process p = new Process();
// заполняем p;
p.Start();
p.WaitForExit();
Это проще, но мой должен быстрее работать. гыгы Смысл многопоточности теряется, когда каждый поток ждем от запуска до выполнения.
0
0 / 0 / 0
Регистрация: 03.07.2009
Сообщений: 6
06.07.2009, 21:36  [ТС] 10
Спасибо, я посмортю...
0
1922 / 427 / 41
Регистрация: 12.07.2007
Сообщений: 2,062
07.07.2009, 05:55 11
Цитата Сообщение от СyberSpec Посмотреть сообщение
Это проще, но мой должен быстрее работать. гыгы Смысл многопоточности теряется, когда каждый поток ждем от запуска до выполнения.
Да, но вопрос был:
Как мне "заставить" строку после Process ждать, пока Process() не отработает полностью? Иначе в цикле запускается сразу несколько процессов, а строки ниже "не успевают" обрабатывать данные, и генерится исключени, что файл уже используется другим процессом.
и ответ все таки
Код
p.WaitForExit();
0
0 / 0 / 0
Регистрация: 03.07.2009
Сообщений: 6
07.07.2009, 22:00  [ТС] 12
Спасибо за советы. Возможно я некорректно выразил мысль в прошлый раз.
Я навоял такой код (корявый):
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
public static void unrar( string sUnRarPath, string sFilePath, string sTempDir ) {
    // распаковка rar-архива
    Regex rx    = new Regex( @"\\+" );
    sUnRarPath  = rx.Replace( sUnRarPath, "\\" );
    sFilePath   = rx.Replace( sFilePath, "\\" );
    sTempDir    = rx.Replace( sTempDir, "\\" );
            
    if( !Directory.Exists( sTempDir ) ) {
        Directory.CreateDirectory( sTempDir );
    }
    
    string s = " e";                    // Распаковать (для полных путей - x)
    s += " -y";                         // На все отвечать yes
    s += " " + "\"" + sFilePath + "\""; // Файл который нужно распаковать
    s += " " + "\"" + sTempDir + "\"";  // Временная папка распаковки
    
    ProcessStartInfo startInfo = new ProcessStartInfo( sUnRarPath, s );
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    int nIdP = Process.Start(startInfo).Id;
    // заглушка - блокировка выхода из процесса, пока запущенная программа - архиватор еще открыта и работает, т.к. перехватить ее завершение не представляется возможным (или не знаю КАК)
    try {
        Process _p = Process.GetProcessById( nIdP );
        while( _p != null ) {
            _p = Process.GetProcessById( nIdP );
        }
    } catch( System.ArgumentException ) { }
}
Код жутко тормозит на цикле, но все же управление не выходит из метода, пока архиватор не отработает и не закроется (тогда сгенерируется исключение, т.к. процесса с PID = nIdP больше нет), что и нужно.
Есть ли другой способ "не выпустить" управление из этого метода, до тех пор, пока Процесс с PID = nIdP не завершится?
Спасибо.
0
Эксперт С++
3058 / 1400 / 421
Регистрация: 19.01.2009
Сообщений: 3,769
08.07.2009, 00:12 13
А зачем так сложно?

Вот простенькая консольная программа:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    class ProcWaitExample
    {
        public static void func(string exePath, string args)
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(exePath, args);
            // startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            // раскоментируй это, чтобы процесс опят стал скрытым
            
            Process p = new Process();
            p.StartInfo = startInfo;             
            p.Start();
            p.WaitForExit();
        }
        
        public static void Main()
        {
            Console.WriteLine("ДО ЗАПУСКА");
            func("c:\\windows\\notepad.exe", "c:\\boot.ini");
            Console.WriteLine("ПОСЛЕ ЗАПУСКА");
        }
    }
Обратите внимание, что пока Вы не закроете Блокнот, строка "ПОСЛЕ ЗАПУСКА" не появиться в консоли.
0
0 / 0 / 0
Регистрация: 03.07.2009
Сообщений: 6
08.07.2009, 19:35  [ТС] 14
Добрый вечер! Спасибо всем, кто помог мне в решении моего вопроса! Я начинал своей проект с использованием Shell(), но из-за того, что при его использовании несколько десятков или сотен тысяч раз в цикле, я заменил его на Process(). Вроде все работает.
Вот код, если кому интересно:

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
public static void rar( string sRarPath, string sFilePath,
                     string sFB2RarFilePath, bool bRestoreInfo ) {
    // упаковка в rar-фрхив
    Regex rx        = new Regex( @"\\+" );
    sRarPath        = rx.Replace( sRarPath, "\\" );
    sFilePath       = rx.Replace( sFilePath, "\\" );
    sFB2RarFilePath = rx.Replace( sFB2RarFilePath, "\\" );
            
    string s = " a -m5";    // запаковать с максимальным сжатием
    if( bRestoreInfo ) {
        s += " -rr";        // добавить информацию для восстановления
    }
    s += " -y";                             // На все отвечать yes
    s += " -ep";                            // Исключить пути из имен
    s += " \"" + sFB2RarFilePath + "\"";    // файл-архив .fb2.rar
    s += " \"" + sFilePath + "\"";          // Файл который нужно запаковать
            
    ProcessStartInfo startInfo = new ProcessStartInfo( sRarPath, s );
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    Process p = Process.Start(startInfo);
    //p.PriorityClass = ProcessPriorityClass.High; // приоритет процесса
    p.WaitForExit();
    p.Close();
    p.Dispose();
}
Думаю, тему можно закрыть. Еще раз спасибо!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.07.2009, 19:35

Запуск графической программы с параметрами из командной строки
Пишу примитивный нотифер, нужно что бы через консоль можно было передавать текст в label и listbox....

Ввод аргументов для программы из командной строки
Хочу добавлять через командную строку аргументы в программу. Например в программе есть аргументы...

Как при запуска программы из командной строки узнать код возврата?
int main() { return 0; } Как при запуска этой программы из командной строки узнать код...

Имитация командной строки
Написать программу на С++, имитирующую командную строку. Программа должна уметь запускать...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.