Exemplo de uso.
Eu resolvi assim:
Eu redirecionei tanto a entrada, saída e erro e lidou com a leitura de fluxos de saída e erro. Essa solução funciona para o SDK 7- 8,1, tanto para o Windows 7 quanto para o Windows 8.
Eu tentei fazer uma classe que resolveria seu problema usando leitura de fluxo assíncrona, levando em consideração Mark Byers, Rob, stevejay respostas. Ao fazer isso, percebi que há um erro relacionado à leitura do fluxo de saída do processo assíncrono.
Você não pode fazer isso:
Você receberá System. InvalidOperationException: StandardOut não foi redirecionado ou o processo ainda não foi iniciado.
Então você precisa iniciar a leitura assíncrona após o processo ser iniciado:
Fazendo isso, faça uma condição de corrida porque o fluxo de saída pode receber dados antes de defini-los como assíncronos:
Então, algumas pessoas podem dizer que você só precisa ler o fluxo antes de defini-lo como assíncrono. Mas o mesmo problema ocorre. Haverá uma condição de corrida entre a leitura síncrona e o fluxo em modo assíncrono.
Não há como obter uma leitura assíncrona segura de um fluxo de saída de um processo na maneira real como "Process" e "ProcessStartInfo" foram projetados.
Provavelmente, é melhor usar a leitura assíncrona, como sugerido por outros usuários para o seu caso. Mas você deve estar ciente de que pode perder alguma informação devido à condição de corrida.
Nenhuma das respostas acima está fazendo o trabalho.
A solução Rob trava e a solução 'Mark Byers' obtém a exceção descartada (tentei as "soluções" das outras respostas).
Então decidi sugerir outra solução:
Este código depurado e funciona perfeitamente.
Introdução.
A resposta aceita atualmente não funciona (gera exceção) e há muitas soluções alternativas, mas nenhum código completo. Isto é, obviamente, desperdiçando muito tempo das pessoas, porque esta é uma questão popular.
Combinando a resposta de Mark Byers e a resposta de Karol Tyl, escrevi o código completo com base em como eu quero usar o método Process. Start.
Eu usei-o para criar um diálogo de progresso em torno dos comandos do git. É assim que eu usei:
Em teoria, você também pode combinar stdout e stderr, mas eu não testei isso.
As outras soluções (incluindo EM0s) ainda estão em deadlock para meu aplicativo, devido a tempos limite internos e ao uso de StandardOutput e StandardError pelo aplicativo gerado. Aqui está o que funcionou para mim:
Editar: adicionada inicialização do StartInfo ao exemplo de código.
Este post talvez desatualizado, mas eu descobri a causa principal porque normalmente travar é devido ao estouro de pilha para a saída redirectStandard ou se você tiver redirectStandarderror.
Como os dados de saída ou os dados de erro são grandes, isso causará um tempo de interrupção, pois ainda está sendo processado por duração indefinida.
então, para resolver esse problema:
Eu acho que essa é uma abordagem simples e melhor (não precisamos do AutoResetEvent):
Eu estava tendo o mesmo problema, mas o motivo era diferente. No entanto, isso aconteceria no Windows 8, mas não no Windows 7. A linha a seguir parece ter causado o problema.
A solução foi NÃO desabilitar o UseShellExecute. Eu agora recebi uma janela popup do Shell, que é indesejada, mas muito melhor do que o programa esperando que nada de especial aconteça. Então eu adicionei a seguinte solução para isso:
Agora, a única coisa que me incomoda é por que isso está acontecendo no Windows 8 em primeiro lugar.
Eu sei que esta é a ceia de idade, mas, depois de ler esta página inteira, nenhuma das soluções estava funcionando para mim, embora eu não tenha tentado Muhammad Rehan como o código foi um pouco difícil de seguir, embora eu acho que ele estava no caminho certo . Quando eu digo que não funcionou isso não é inteiramente verdade, às vezes funcionaria bem, eu acho que é algo a ver com o comprimento da saída antes de uma marca EOF.
De qualquer forma, a solução que funcionou para mim foi usar diferentes threads para ler o StandardOutput e StandardError e escrever as mensagens.
Espero que isso ajude alguém, que pensou que isso poderia ser tão difícil!
Depois de ler todos os posts aqui, resolvi a solução consolidada de Marko Avlijaš. No entanto, isso não resolveu todos os meus problemas.
Em nosso ambiente, temos um serviço do Windows que está programado para executar centenas de arquivos. bat. cmd. exe diferentes. etc arquivos que se acumularam ao longo dos anos e foram escritos por muitas pessoas diferentes e em diferentes estilos. Nós não temos controle sobre a escrita dos programas & amp; scripts, somos responsáveis apenas pelo agendamento, execução e geração de relatórios sobre sucesso / falha.
Então eu tentei praticamente todas as sugestões aqui com diferentes níveis de sucesso. A resposta de Marko foi quase perfeita, mas quando executada como um serviço, nem sempre captava stdout. Eu nunca cheguei ao fundo do por que não.
Process waitforexit c # tempo limite
Se você quiser iniciar outro processo e aguardar (com o tempo limite) para concluir, você pode usar o seguinte (do MSDN).
Se você quiser iniciar outro processo e ler sua saída, então você pode usar o seguinte padrão (de SO)
Como você pode combinar os dois para ler todas as entradas, não ficar preso no deadlock e ter um tempo limite se o processo de execução der errado?
Essa técnica será interrompida se o buffer de saída for preenchido com mais de 4KB de dados. Um método mais seguro é registrar delegados para serem notificados quando algo é gravado no fluxo de saída. Eu já sugeri este método antes em outro post:
Você não precisa combinar os dois - a classe Process tem um evento que é acionado quando a saída é enviada para o StandardOutput - OutputDataReceived.
Se você assinar o evento, você poderá ler a saída quando ela chegar e, no seu loop de programa principal, você ainda pode esperar o tempo limite.
Você pode tentar modificar o primeiro método para algo como isto.
Você também pode usar o APM, assim:
Defina um delegado para a chamada ReadToEnd:
Em seguida, use o delegado para chamar o método assim:
EDIT: Manipulação de erros removida para maior clareza.
Basta adicionar tudo do primeiro exemplo abaixo da chamada WaitForExit () para o segundo exemplo.
Aprendendo C # pelo Exemplo.
Última atualização: 30 de abril de 2016.
Aqui estão 14 anos de receitas e notas embaralhadas em C # dispostas aleatoriamente em um fluxo de modo de consciência. Alguns métodos são substituídos pela funcionalidade além de C # 1.0. Um dia eu vou organizá-los em um todo coerente, até que por favor use "search" no seu navegador. As outras páginas desta série C # são muito melhores formatadas e mais informativas.
O exemplo obrigatório para qualquer idioma,
Você pode compilar c # usando a versão da linha de comando.
Você pode obter o Nant, uma ferramenta de construção como o antigo 'make', do sourceforge / projects / nant.
Identificadores são os nomes que damos a coisas como classes, variáveis e métodos. Em C #, os identificadores devem começar com um sublinhado ou uma letra e serem compostos de letras, números e sublinhados.
Por convenção variáveis locais, argumentos passados em métodos e campos privados são camelCase. Outros identificadores são PascalCase.
Palavras-chave reservadas como "público", "estático" não podem ser usadas para identificadores, a menos que você prefaça o nome da variável com "@", por exemplo, @class = "abc".
Aqui está uma lista de palavras-chave reservadas em c #
Aqui está uma lista de palavras-chave contextuais. Os identificadores podem ser nomeados com estas palavras e o compilador pode dizer se a palavra é um identificador ou uma palavra-chave pelo seu contexto.
Um tipo tem "membros de dados" e "membros de função", como "int", que contém um valor e tem métodos como "ToString ()".
Todos os valores em C # são instâncias de um tipo.
O C # fornece tipos incorporados, ou predefinidos, diretamente na linguagem que o compilador entende e separa palavras-chave para eles.
Os tipos de valor são: sbyte, short, int, long, byte, ushort, uint, ulong, float, double, decimal, bool e char. (Nota aleatória: use "decimal" por dinheiro).
Os tipos de referência predefinidos são: string, object.
Esses tipos são alias em tipos no namespace "System", como "int" sendo um alias para System. Int32.
C # também fornece tipos internos no namespace System como DateTime, embora o compilador não tenha conhecimento direto deles.
Cada objeto tem um ponteiro para o seu tipo. O método "GetType ()" retornará, no tempo de execução, o objeto Type descrevendo o objeto. O operador "typeof" fará o mesmo, mas geralmente em tempo de compilação. "typeof (string)"
Todos os tipos C # estão em uma das seguintes categorias:
Tipos de valor (principalmente tipos internos como "int", "double" e custom "struct" e "enum" que não têm nenhum método apenas um valor, embora com métodos de encaixotamento automático e implícito ele parece que eles fazem. Isso é armazenado em a pilha.)
Variáveis não atribuídas a um valor recebem valores padrão; todos os tipos de referência são definidos como nulo, numérico e enums são definidos como zero, char é definido como '\ 0' e bool é definido como falso. Se você precisar obter o valor padrão, poderá usar a palavra-chave "padrão". Você pode até usá-lo em genéricos: padrão (Cacher & lt; string & gt;)
Tipos de referência (qualquer classe, matrizes, delegados; qualquer coisa que seja um ponteiro para um bloco de memória, estes são armazenados no heap.)
Parâmetros de tipo genérico.
Você cria seus próprios tipos com classes.
Exemplo de construtores, construtor estático e destruidor:
Para chamar o construtor do pai:
Se uma classe não chamar explicitamente o construtor do pai com "base", o construtor sem parâmetros do pai da classe será chamado por padrão se o pai tiver um construtor sem parâmetros.
Esse construtor é chamado apenas uma vez antes do primeiro objeto desse tipo ser chamado. (É garantido ser chamado se nenhum objeto deste tipo é criado?) Ele só pode referenciar objetos estáticos e não possui parâmetros.
Aqui vemos um método não virtual. O objeto em:
O código acima, por incrível que pareça, irá imprimir "300" para a velocidade dos aviões, já que o TopSpeed () não é virtual. Para corrigir o problema, precisamos declarar o método virtual * e * que a subclasse "sobrescreve" o método. Se não definirmos o método do Jet para substituir, ainda teremos "300")
Em uma subclasse, você pode reutilizar um nome de variável, mas o compilador avisará que o membro com subclasse está "ocultando" a variável do pai.
Se uma nova variável é realmente desejada, diga ao compilador para parar de reclamar usando o modificador "novo" (não confundir com o operador "novo").
Útil se o arquivo pode ser muito grande.
Leia uma string do console.
WriteAllText criará o arquivo se ele não existir, caso contrário, ele será substituído. Ele também irá fechar o arquivo.
"using" faz uma chamada implícita para Dispose () quando o bloco using está completo. Com arquivos, isso fechará o arquivo. O código a seguir mostra que "using" realmente fecha o arquivo, caso contrário, 5000 arquivos abertos causariam problemas.
Nota muitos operadores devem ser sobrecarregados como um par, por exemplo, & gt; , & lt;
Dado um método sobrecarregado, a decisão sobre qual método chamar normalmente é feita em tempo de compilação com base no tipo declarado do argumento. Mesmo que o objeto "mammal" seja realmente um tipo Tiger, o compilador chamará a sobrecarga do Mammal - a menos que você o converta para um tipo "dinâmico", caso em que ele chamará o método com base no tipo real do objeto.
As estruturas são semelhantes às classes, a Microsoft as chama de objetos "leves". Estruturas podem ser mais eficientes, pois não precisam alocar memória no heap e inicializar um objeto real.
Stucts não possuem herança, mas podem implementar uma interface.
Embora possam ser criados com o operador 'novo', os structs vivem na pilha. Se você usar o operador "novo", todos os campos de uma estrutura serão inicializados. Sem o "novo", todos os campos devem ser inicializados antes que a estrutura possa ser usada.
As structs não têm destruidores ou finalizadores, o que faz sentido, já que eles não têm nada a reclamar, a não ser a pequena quantidade de memória na pilha.
Structs tem um construtor sem parâmetros padrão que não pode ser redefinido.
Estruturas não podem ter membros virtuais.
Muitos dos tipos internos em C # são estruturas. Por exemplo, um C # "int" é realmente um tipo de "System. Int32". Um c # "float" é um alias para "System. Single". Se você olhar os documentos oficiais em "int" você pode ver que é uma estrutura e implementa várias interfaces:
Aqui está um exemplo para fazer um ponto sobre as estruturas:
Exemplo de uso de propriedades em vez de métodos de acesso. Observe o uso especial da variável "value" em "set".
(DateTime. UtcNow é mais rápido que o DateTime. Now, pois não precisa fazer os cálculos de tempo de economia diários malucos).
Ou você pode a conveniente classe Stopwatch do System. Diagnostics.
Quais são as unidades para o argumento de dormir? Você pode torná-lo mais implícito usando o formato TimeSpan. From *:
Escreva a hora atual.
Para especificar um formato: dt. ToString ("yyyy / MM / dd")
O formato universal independente de cultura: dt. ToString ("u")
que imprime "yyyy '-' MM '-' dd HH ':' mm ':' ss'Z '"
O System. Convert contém muitas pequenas rotinas de conversão.
Use a útil (se um pouco obscura) classe System. Text. Encoding. UTF8.
Não seja tentado pelo Lado Negro a fazer o seguinte:
Como nem todos os caracteres em strings são mapeados para um pequeno byte amigável (lembre-se de nossos amigos europeus?), A contagem de caracteres em strings não é igual ao número de bytes.
O C # converterá automaticamente alguns tipos para nós se as duas condições a seguir forem verdadeiras:
1. O compilador pode saber que a conversão será bem-sucedida.
2. Nenhuma informação é perdida durante a conversão.
Uma pequena piada de programação: (theWind) fate;
'params' deve ser o último parâmetro na lista.
O resultado é assim:
Matrizes podem ser irregulares como C ou Java, ou verdadeiras matrizes multidimensionais.
Shorthand para criar matrizes de dimensão única.
Para classificar uma matriz, use o método estático na classe Array. (Eu não sei porque array. sort () não existe como um método)
"C" permite que você aliasse um tipo como outro com typedef. Em C # você pode fazer isso com "using" (podemos criar outra sobrecarga para "using" apenas para torná-lo mais confuso?) Em todos os lugares que o tipo "RowCollection" é usado, o C # o entenderá como "List & lt; Node & gt; "
O C # fornece uma maneira especial de descartar objetos após o uso - é o bloco "using". O objeto da instrução "using" deve implementar a interface IDisposable que contém um membro, Dispose (). Como mostrado abaixo, após o bloqueio "using" ser executado, Dispose () é imediatamente chamado.
A ambigüidade com nomes de classes pode ser resolvida pela palavra-chave "using".
Isso informa ao compilador que todas as instâncias de 'Set' no restante do arquivo são referências a 'MyUtil. Set'. Isso seria útil se 'Set' se tornasse uma classe de coleção real em uma versão futura e você codificasse a sua.
Muitas vezes é conveniente imprimir o estado de um objeto. Em vez de sobrescrever o método ToString () e imprimir explicitamente cada campo, você pode deixar o C # fazer o trabalho para você com um pouco de Reflection. Você pode até adicionar código para imprimir recursivamente o estado dos objetos de composição também. Isso é deixado como um exercício para o aluno.
Como invocar um método estático em um objeto dinâmico. Isso chama o método estático "Get (nome da string)" em um objeto de classe "myType" e retorna uma instância de um MyObjectType.
Este exemplo mostra a invocação de um método de instância no objeto "this", embora qualquer outro objeto funcione tão bem quanto você obtenha o objeto methodInfo de sua classe.
Como mostra o código a seguir, as interfaces podem ser estendidas e, diferentemente das classes, várias interfaces podem ser estendidas.
Exemplo de uso de um atributo para determinar se o código SQL associado a esse objeto deve ser gerado automaticamente. O código do atributo:
A colocação do atributo em uma classe.
A recuperação do atributo de classes.
Às vezes, quando você quer ficar suja com a memória, você pode dizer ao C # que você vai assumir o controle e usar, gulp. , ponteiros reais como todos aqueles cowboys em C e C ++. Para fazer isso, você precisa marcar a seção de código com a palavra-chave "inseguro" e dizer ao compilador que pode ser confiável para lidar com a memória bruta, adicionando a opção "/ inseguro". Você pode obter benefícios de desempenho de código não seguro, mas tenha cuidado.
Com ponteiros, você pode usar os símbolos C padrão: & amp; para obter o endereço do ponteiro; * para chegar onde o ponteiro está apontando; e - & gt; para obter um membro de uma estrutura de dados.
Ao usar ponteiros, certifique-se de usar a palavra-chave "fixed" para tornar a memória de destino fixa, para que o coletor de lixo não a mova ao compactar a memória.
Definir um serviço da web é muito fácil. Adicione uma referência a "System. Web. Services" no Visual Studio, adicione o "usando System. Web. Services;" linha no seu código, subclasse de "System. Web. Services. WebService" e, finalmente, colocar o atributo "[WebMethod]" em seu método.
Para criar um arquivo WSDL para um serviço, basta anexar "? Wsdl" ao nome do serviço dentro do IE.
Use o Wsdl. exe para ler o documento WSDL e crie uma classe de wrapper.
Código para percorrer uma montagem e imprimir todos os métodos de instância públicos.
Você pode imaginar uma maneira mais detalhada de fazer isso?
Ou você pode trapacear com isso:
ou você pode usar a string. Equals com um argumento extra.
Delegados são objetos que sabem como executar um método. Delegados são um refinamento de ponteiros de método em C, mas com segurança incorporada. O objeto delegado é ligado a um método que usa o número exato e o tipo de variáveis como argumentos e retorna o tipo correto.
Nota: quando você usa o nome da função sem os parênteses, por exemplo "PrintHello", você está se referindo a um "grupo de métodos", já que o método pode estar sobrecarregado. C # escolherá o método sobrecarregado correto com base na assinatura.
Os delegados podem ser declarados anonimamente atribuindo um delegado a uma função precedida de "delegado" (isso é mais fácil em uma versão posterior de quando funções anônimas são permitidas). Isso melhora a legibilidade do código.
Delegados, como cordas, são imutáveis. Ao usar "+ =", você está criando um novo Delegado.
Todos os delegados têm capacidade de multicast - eles podem ser encadeados para chamar mais de um método. Você pode usar o operador "+ =" para adicionar métodos para chamar (e "- =" para subtraí-los). Eles serão invocados em seqüência, começando com o primeiro. Se você tiver um valor de retorno, somente o último método chamado retornará um valor. Os outros valores de retorno são perdidos para sempre.
Se uma exceção não identificada for lançada, a execução retornará diretamente para o código de chamada e os demais delegados não serão executados.
Use variáveis "ref" para passar informações entre delegados encadeados. As alterações na variável serão passadas para o próximo delegado.
O valor de "i" abaixo no delegado não é usado, mas uma referência a "i" levando a situações estranhas às vezes. O exemplo abaixo não é o uso correto e o resharper avisará que o delegado está usando uma referência a uma variável fora do escopo.
Curiosamente, por padrão, o C # não lança uma exceção para estouros ou underflows numéricos. Para ter a verificação em C #, você deve usar a palavra-chave "check" ou configurar seu projeto para verificar toda a aritmética.
Para verificar se há under / overflows para todo o programa, use um switch de compilador "/ checked +". Se você não precisa verificar uma determinada expressão, use "desmarcado".
O C # fará um tipo upcast automaticamente para você (tornando uma subclasse uma classe pai), mas você deve explicitamente fazer um downcast, já que ele pode falhar. Não decepcione o compilador fazendo lançamentos ruins - a confiança é muitas vezes difícil de recuperar.
Usar o modificador de parâmetro "out" ou "ref" permitirá que os valores sejam retornados.
"out" costuma ser usado para retornar mais de um valor de um método.
Qual a diferença entre "ref" e "out"? "ref" requer que um objeto seja atribuído antes de passá-lo ao método. "out" requer que o método seja chamado para atribuir um valor à variável.
Exemplo de uso de "ref"
O operador terciário '?' tem um amigo, o '?? operador. Se o valor antes do '?? é não nulo, o valor é retornado. Se o valor for nulo, o valor após o '?? é retornado. As duas declarações abaixo funcionam de forma idêntica.
Exemplo de código ASP.
Valide um widget de caixa de texto.
'Global Event Handlers' pode ser definido neste arquivo.
Use System. Web. HttpUtility. HtmlEncode () para codificar strings para exibição no navegador. Converte "& lt;" para & amp; lt ;, um bom primeiro passo contra a invasão de seu site.
Na página aspx:
Para obter um valor de uma página de formulário.
Incluir o conteúdo de um arquivo dentro de uma página asp.
Leia o QueryString e imprima para a página da web.
Na página aspx:
No código por trás:
Definir um item em uma lista suspensa como o atualmente selecionado.
Isso permitirá que você verifique se todos os erros encontrados no nível superior são registrados.
Para ter a execução acima, ela deve ser registrada como um retorno de chamada.
Você pode definir um FileWatcher para invocar um retorno de chamada sempre que um arquivo for alterado por uma força externa.
Use o prático objeto StackTrace como mostrado abaixo. Nota: o método write () é definido em outro lugar.
Adicione isto ao seu web. config (dentro do elemento de configuração)
Isso é muito útil para retornar xml bruto para invocações de AJAX.
Adicione este trecho ao seu web. config.
Isso é útil quando você precisa saber se uma determinada página foi visualizada. A lógica para gravar o evento é feita em outro lugar e, em seguida, chama essa rotina.
Se você tiver apenas uma string para transmitir entre seu servidor e cliente, você pode trapacear e usar o "Response. StatusDescription" para passar uma mensagem de string. No método Page_Load do servidor, defina o campo StatusDescription do objeto Response.
No cliente, invoque uma url no servidor e observe o campo "StatusDescription" para obter informações minúsculas.
Infelizmente você não pode simplesmente adicioná-lo no código HTML. Você tem que ir para o código por trás da página.
Quando um questionado é encaminhado para essa página, ele é redirecionado para outra página com base no valor de "x". Todos os parâmetros GET também são transmitidos. Se x = ABCDE, eles são encaminhados para ABCDE. html.
A abordagem mais simples é usar o WebClient se você estiver usando uma versão recente do.
Como obter o conteúdo da página mesmo com erros como 500 ou 404 é mostrado abaixo:
Vamos retornar uma única string de um banco de dados.
Se você receber a seguinte exceção:
System. Data. SqlClient. SqlException: o tempo limite expirou. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo. em System. Data. SqlClient. SqlConnection. OnError (exceção SqlException, breakConnection booleano)
Seu comando pode realmente demorar muito no banco de dados e foi morto. Você pode aumentar o tempo padrão de 30 segundos usando o campo "CommandTimeout" no objeto "Command" como mostrado abaixo:
Não se deixe enganar pela opção de string de conexão do banco de dados, "Tempo limite de conexão", por exemplo, "Fonte de dados = myMachine; Segurança integrada = SSPI; banco de dados = Northwind; Tempo limite de conexão = 60". Esse tempo limite é para obter a conexão, não por quanto tempo consulta o banco de dados.
Exemplo de adição de um manipulador InforMessage a um objeto de conexão.
Exemplo de uma função de utilitário que usa ExecuteScalar e uma função de utilitário para liberar recursos (que agora está obsoleta - você deve usar a construção "using").
Para evitar ataques de injeção de SQL, você sempre deve usar parâmetros.
pode ser encurtado para.
Já a direção padrão é "Input". Implicações de desempenho do método de atalho não são conhecidas.
um bloco "using" executará seu conteúdo e imediatamente chamará "Dispose ()" no objeto using. Para conexões, isso fechará a conexão.
Se você incluir o 'Nome do aplicativo' na seqüência de conexão, o criador de perfil do SQL pode mostrar isso para você. Isso facilita o ajuste do db.
Se este método lançar uma exceção, ele passará no teste. Se não der uma exceção, o teste falhará.
Em versões posteriores do NUnit você pode usar esta sintaxe que é melhor.
Por padrão, um gerador de números aleatórios é propagado, em parte, com o tempo. Mas se você está criando múltiplos geradores de números aleatórios para execução paralela, você precisa de algo melhor para semear o Random.
Isso examina todos os arquivos terminados em ".cs"
Uma advertência: DirectoryInfo. GetFiles às vezes retornará mais do que você deseja. Ele também retornará arquivos cuja extensão possui caracteres extras. Procurar por "*.xml" também renderá "*.xmlabc", que pode ser, no mínimo, irritante.
Por exemplo, você pode querer encontrar um diretório "config" que é alguns níveis acima do seu diretório de execução. Use algo como "Assmebly. GetAssembly" para localizar um startingDirectory e "\\ Config \\ settings. xml" para um arquivo de destino.
Isso inicia uma instância do navegador, aguarda 15 segundos e depois fecha.
Usando um timer com um TimerCallback você pode dizer para invocar repetidamente um método em um agendamento. O código é um pouco detalhado para fins de instrução.
Por padrão, o dev studio cria um pequeno arquivo chamado "AssemblyInfo. cs". Dentro há vários atributos no nível da montagem. Se você preencher essas informações, quando a. dll for consultada por meio de um clique direito do mouse e a seleção "Propriedades", as informações serão exibidas na caixa de diálogo.
Utilitário para pseudo-randomizar elementos de uma ArrayList em tempo linear.
Esse método recursivamente despeja as informações de uma exceção.
A seguir será impresso "Void ExistInDatabase ()"
Utilitário para pseudo-randomizar elementos de uma ArrayList em tempo linear.
Exemplo de execução de comandos de um programa csharp.
Um namespace pode ter um alias para reduzir a desordem.
A estrutura "decimal" dá 28 dígitos significativos e pode ser usada para a maioria das aplicações de moeda. Use o sufixo "m" para constantes.
Se a máquina de destino não estiver instalada, você poderá instalar o Dotnetfx. exe durante a instalação do programa e o Dotnetfx instalará a estrutura.
controle 'machine. config' é as configurações para o ASP. Ele é encontrado em um diretório como "C: \ WINDOWS \ Microsoft \ Framework \ v1.1.4322 \ CONFIG".
Por motivos de segurança, somente os clientes no host local podem acessar a versão da página da web de um serviço da web. Para permitir que qualquer cliente acesse o serviço, coloque o seguinte no web. config dentro do elemento "system. web". Isso elimina o "O formulário de teste está disponível apenas para solicitações da máquina local". mensagem.
Três maneiras de inicializar uma matriz.
Nossos velhos amigos, comandos "Pré-processador", estão disponíveis.
Enums em C # são bem desenvolvidos e possuem muitos métodos interessantes. Enums derivam de System. Enum que contêm métodos como Format () e GetName (). GetValues () retornará todos os valores possíveis de um enum.
Por padrão, os valores int são atribuídos começando com zero. Você pode usar potências de dois para criar sinalizadores combináveis que podem ser usados para operações bit a bit, como "& amp;" e "|".
const é definido em tempo de compilação e somente leitura em tempo de execução.
testes para determinar se um objeto é de um tipo específico.
semelhante a uma conversão de tipo, mas se o objeto não for o esperado, "as" retornará um valor nulo enquanto uma conversão de tipo lança uma exceção. Não executa conversões de tipo personalizadas.
Use "selado" como um modificador de método para que nenhuma subclasse possa estender a classe (como "final" do java). Você também pode selar métodos para que eles não possam ser anulados, mas eles podem ser ocultados.
Além desses modificadores de acesso, o '[assembly: InternalsVisibleTo ("Friend")]' permite acesso a membros de outros assemblies para testar o código.
Odeio digitar o nome de usuário e senhas? Deixe Nant fazer o trabalho para você.
Dentro do programa instalador, leia os valores.
Com o csc. exe é fácil reprimir o aviso com a opção "nowarn". Com o MSBuild é um pouco complicado. Use o interruptor "property" e inclua seus números de aviso com "& amp; quot;", o que é um pouco estranho.
Esta pequena função auxiliar cria a entrada e a fecha. O argumento "source" é o nome do seu aplicativo.
Remova todos os caracteres não alfanuméricos.
Isso eleva o nome do banco de dados de uma cadeia de conexão.
Um identificador com um prefixo "@" é chamado de identificador integral.
O VS fornece expressões regulares para substituir o string que pode ser um salva-vidas. Aqui estão alguns exemplos de operações a serem realizadas em muitos arquivos:
Removendo um atributo xml.
O que significa o RE: encontre a string "& lt; Survey" seguida de um monte de caracteres, seguido da string "cluster =" seguida por um monte de caracteres não espaciais. Substitua apenas com o "& lt; Survey" e os caracteres antes de "cluster".
Neste caso, quero renomear o atributo 'id' do elemento 'Survey' para 'registrarId', mas não o atributo 'id' dos outros elementos. O nome do elemento e o atributo a ser alterado devem estar na mesma linha para que isso funcione. Um pequeno fragmento de expressão regular na caixa de diálogo "Localizar e substituir" funcionou: o "Localizar o que" indica "& lt; Pesquisa" seguido por qualquer caractere seguido por "id =". O "\ 1" leva o valor de todos os caracteres ignorados com o.
Isso imprimirá a versão definida em Properties / AssemblyInfo. cs.
C # fornece uma maneira de liberar recursos quando um objeto morre. Como em C ++, o destruidor tem o mesmo nome que a classe com um "
Isso produz o seguinte, mas não de forma confiável, uma vez que o Console. Out pode ter sido fechado até então.
Uma das grandes vantagens do C # e do Java é a coleta automática de lixo. Em vez de precisar especificamente liberar memória, o Coletor de Lixo (GC) é executado ocasionalmente e libera a memória de objetos não utilizados para nós.
O GC é executado em um thread separado e inicia na raiz de um aplicativo e marca todos os objetos que podem ser referenciados. Depois, olha para todos os objetos e liberta, ou recolhe, todos os objetos sem a marca.
Após a coleta, o GC move todos os objetos "vivos" restantes para o início do heap para evitar o fracionamento de memória.
O GC separa objetos em três gerações:
Gen0 contém objetos recém criados.
Gen1 são objetos que sobreviveram a uma coleção.
Objetos Gen2 são de longa duração.
Como a maioria do churn ocorre nos objetos Gen0, eles podem ser coletados com frequência e os objetos Gen1 e Gen2 serão coletados com menos frequência.
O Large Object Heap (LOH) é um heap especial usado para objetos muito grandes. O GC usa regras especiais para lidar com esses objetos, pois são diferentes dos objetos comuns.
Você pode fazer com que o GC o notifique quando estiver prestes a iniciar um ciclo de coleta conectando-se a "GC. RegisterForFullGCNotification".
O Garbage Collector pode ser iniciado executando "System. GC. Collect ()".
Ao descartar objetos, o coletor de lixo coloca objetos com finalizadores em uma coleção especial que terá seus finalizadores chamados por um ou mais encadeamentos. Tenha cuidado ao acessar as variáveis estáticas de uma classe (como decrementar um contador de objetos), pois o CLR pode criar mais de um thread em execução no finalizador. Depois que o finalizador for chamado, um objeto estará qualificado para ser descartado durante a próxima rodada de coleta de lixo.
Às vezes, os objetos podem não ser importantes o suficiente para serem mantidos na memória, se estivermos com pouca memória. Nesse caso, podemos usar a classe "WeakReference" para apontar para esses objetos. O Garbage Collector não contará essas referências ao decidir colher esses objetos.
Usar o atributo CLSCompliant (true) marca o assembly como compatível com a especificação de linguagem comum, para que o VB e outros idiomas possam usar seu assembly. Ao compilar com este atributo, o compilador avisa você com a mensagem de erro CS3008 de problemas não compatíveis, como nomes de variáveis expostas que diferem apenas no caso.
Se você tiver muitos arquivos xml de teste para criar objetos e precisar adicionar um novo atributo, será fácil usar expressões regulares. Por exemplo, se você precisar adicionar "newattribute = '1'" a todos os elementos "Pesquisa" espalhados por muitos arquivos como este:
Digite "control-h" para abrir a caixa de diálogo Substituir e marque a caixa de seleção "Usar:" no canto inferior esquerdo e verifique se ele exibe "Expressões regulares". Em seguida, digite estes:
Isso corresponderá a todos os caracteres entre "& lt; Survey" e "& gt;". Colocar a expressão entre chaves permite que você use a sintaxe "\ 1" para colocar nos caracteres correspondentes. O resultado final é.
Delegados são ponteiros de função de tipo seguro.
Olhando para os métodos Anônimos no C # 2.0, você pode fazer o mesmo que acima com uma aparência mais limpa. Nós não temos que declarar um método real, podemos apenas incorporá-lo:
.aspx. cs - formulários da web, como páginas jsp. ascx. cs - objetos de código c #.asmx - serviços da web. asax - objetos globais. ashx - módulos http.
Três tipos de controles.
Controles do servidor HTML Controles do servidor da Web Notas de validação em. A Common Language Infrastructure (CLI) consiste em 5 partes da Partição I - Architecture Common Lanugage Specification (CLS)
regras que garantem um idioma podem interoperar com outros se seguirem a especificação.
Tipo Tipos de valor Tipos de valores internos Tipos inteiros Tipos de ponto flutuante Referências digitadas Enums definidos pelo usuário Sistema de execução virtual (VES) Partição II - Partição de metadados III - bytecode da linguagem intermediária comum (CIL) Partição IV - Partição de biblioteca V - Anexos.
Reinos do Nemo.
Sobre um pouco de tudo, mas principalmente sobre a verdade.
Pós-navegação.
Parando aplicativos de linha de comando programaticamente com o evento Ctrl-C de & # 8211; uma demonstração de trabalho.
A história por trás.
O problema de iniciar e parar os aplicativos de console / linha de comando de um programa host é muito mais difundido do que se poderia pensar à primeira vista. Iniciar um aplicativo e até mesmo redirecionar sua saída é relativamente fácil de ser alcançado. Parar bem, por outro lado, é difícil. & # 8220; bem & # 8221; é a palavra-chave aqui. Pode-se sempre chamar a função de membro Kill () de um objeto Process. No entanto, isso encerraria o processo infantil imediatamente, sem dar a chance de fazer qualquer limpeza, o que em alguns casos pode ser desastroso.
Em um ambiente Unix, um programador normalmente emitirá um sinal SIGINT e / ou SIGTERM, antes de recorrer ao SIGKILL. O Windows tem algo quase, mas não inteiramente assim. Ele pode gerar um ConsoleControlEvent, que é traduzido de uma tecla Ctrl-C ou Ctrl-Break. Esses eventos são enviados não para um aplicativo, mas para o console / terminal com o qual um aplicativo é registrado e, em seguida, propagado para todos os manipuladores em cada aplicativo até que um dos aplicativos reconheça o evento. Então, na realidade, um envia um sinal de terminação para todos os aplicativos, que são iniciados de / com um console específico, e não apenas para um aplicativo específico. Isso também pode significar problemas.
Uma solução bastante comum, que quase nunca funciona, é localizar o identificador de janela de um processo (isso pressupõe que o processo de linha de comando possui uma janela, o que nem sempre é o caso) e enviar uma série de mensagens para ele. - down e key-up events, mapeando para o & # 8216; Ctrl & # 8217; e para o & # 8216; C & # 8217; teclas no teclado.
Eu estava apontando para essa abordagem, até me deparar com uma solução mais elegante e aparentemente mais infalível. Cada solução será descrita e brevemente explicada na lista abaixo. Faça o download e estude o código-fonte da implementação real (todas as funções do trabalhador estão concentradas em uma classe estática em Experiments. cs). Se você tiver uma solução de trabalho para o cenário PostMessage, compartilhe-a com a comunidade através dos comentários desta postagem.
Esboço dos cenários.
Se o aplicativo iniciado (ping. exe) não for interrompido (principalmente como resultado de seus próprios experimentos ou do cenário 2), pressione o botão Panic amarelo para encerrá-lo com força.
Apenas dois cenários representam soluções reais para o problema & # 8211; 1 e 4, sendo o # 4 preferido. Cenário # 2 nunca foi concluído devido a restrições de tempo (sinta-se livre para preencher os espaços em branco;)), enquanto o Cenário # 3 está lá por uma questão de completude.
Comece com uma janela visível usando, esconda com pinvoke, corra por 6 segundos, mostre com pinvoke, pare com.
Este método é uma mistura de pinvoke. Ele interrompe o processo fechando sua janela de comando, semelhante a clicar no botão & # 8216; X & # 8217; botão no canto superior direito. Isso gera um evento Ctrl-C para todos os programas registrados com esse console. Para encontrar a janela, ela deve existir e estar visível. Aqui eu uso o método FindWindowHandleFromProcessObjectWithVisibleWindow () na classe Experiments, que usa a funcionalidade. Como alternativa, eu poderia ter usado um método pinvoke, que faz uso do EnumWindows. Isso é implementado em FindWindowHandleFromPid () na classe Experiments.
A desvantagem desse método é que ele mostra brevemente a janela de recomendação ao iniciar e ao interromper o processo. Outro problema é que um processo leva muito tempo para fechar, será encerrado. Este método funciona bem para o ping, mas para as minhas necessidades estava finalizando o processo rapidamente. Pinvoke only: Start with invisible window, get window handle, run for 6 seconds, stop using window handle. (Unfinished!)
It turned out that it was impossible to start a command window with an invisible, but still existing window using pinvoke CreateProcess. The start sequence ended up being the same as for Scenario 1, but bypassing . Stopping a process with PostMessage did not work out either, even though I read of successful attempts. I abandoned this scenario as I did not want to use an inordinate amount of time on what started to look like a dead end. Brutal : Start without window; run for 6 seconds; stop by killing the process.
This scenario is is here for completeness. This is the most brutal method, which relies entirely on functionality. When stopping the process, it simply kills it, without giving it any chance to clean up. Note that ping command does not display any summary when it is stopped in this fashion. Start without a window using , run for 6 seconds, stop by attaching console and issuing ConsoleCtrlEvent.
After finding a hint at the bottom of this thread, I finally bit the bullet and started the process without a window. When the time comes to stop a process, the parent attaches its console to the child, stops itself listening to Ctrl-C event and issues the event to the console, so that the attached child terminates. It then reinstates the Ctrl-C handler for itself and frees the console.
UPDATE: Please read comment by Michal Svoboda below for an improved version for this scenario.
During the research phase, I got ideas and inspiration from the following posts and sites. Some them were dead ends, while others lead to something usable. The post in particular (the first link) was a real revelation, and is incorporated in the fourth scenario in the demo application.
14 thoughts on “ Stopping command-line applications programatically with Ctrl-C event from – a working demo ”
Awesome life saver 🙂 🙂
Obrigado! Realmente util.
You my friend are a fine man indeed. Até aí tudo bem & # 8230; worked very first time! If only Id read this 12 hours ago… thank you sir 🙂
My god… After 6 hours of trial and error, you had the right answer all along. You’re magnificent and I can’t thank you enough!
Sorry here is the complete working example. just paste into a new C# console project and run. hit ctrl-c or X the window out.
Jason Jakob, your solution is similar to my example #4, with the difference that I start a process without a console window, which is desirable when you write a front-end application that takes over the stdout/stderr streams of the child process. My solution is also slightly more robust.
Your post helped me. Thanks alot.
This is great, man. I’ve search to find a solution for hours. I was missing the console attaching.
Thank you for a very well written article.
Thank you for your article – it help me a lot.
The solution #4 work fine for me.
Unfortunately, sometimes it happens, the process is not exited after Ctrl-C and the application stuck in “process. WaitForExit();”.
As solution for this, I propose little improvement of your “StopProgramByAttachingToItsConsoleAndIssuingCtrlCEvent” method – to add there timer which (after a specified timeout) kills the process if the process has not exited automatically.
Here is the updated method:
Thank you, Michal. I’ve updated the main post, pointing to your improved solution.
Was totally stumped by this issue – really appreciate your taking the time to post it.
qshinoの日記.
Powershell関係と徒然なこと.
外部プログラム起動方法調査.
Strart-job 内でStart-peocess - waitを呼ぶとどうなる?
Start-Process.
同期/非同期両方可能 終了コード入手可能 標準入出力。ファイル指定可 コンソールウインドウ出る。消すことも可 Eventが4種類.
終了コードは$proc = start-process - PassThruで起動し、終了後に$proc. ExitCode で受け取る。 終了確認は、event又は、$proc. HasExited にて確認。
例 $proc = Start-Process a. bat - PassThru.
HasExited ExitCode.
同期/非同期両方可能 終了コード、不明 標準出力受け取れる コンソールウインドウでない.
同期のみ 終了コードは$LastExitCode コンソールウインドウ表示されない 標準出力受け取れる.
System. Diagnostics. Process.
$Sender $Event $EventSubscriber $EventArgs $Args.
$args = $event. SourceArgs $EventArgs = $event. SourceEventArgs $Sender = $event. Sender $Event = PSEventArgs.
PSEventArgs.
ComputerName EventIdentifier RunSpaceId SourceIdentifier Sender SourceArgs SourceEventArgs MessageData TimeGenerated.
SourceArgs.
SourceArgs Gets any original arguments of the event that were captured and passed on by the source when the event was raised. This property is introduced in Windows PowerShell 2.0.
SourceEventArgs.
SourceEventArgs Gets any arguments that were added by the source when the event was raised. This property is introduced in Windows PowerShell 2.0.
Contains an array of the undeclared parameters and\/or parameter values that are passed to a function, script, or script block. When you create a function, you can declare the parameters by using the param keyword or by adding a comma-separated list of parameters in parentheses after the function name.
In an event action, the $Args variable contains objects that represent the event arguments of the event that is being processed. This variable is populated only within the Action block of an event registration command. The value of this variable can also be found in the SourceArgs property of the PSEventArgs object (System. Management. Automation. PSEventArgs) that Get-Event returns.
Contains a PSEventArgs object that represents the event that is being processed. This variable is populated only within the Action block of an event registration command, such as Register-ObjectEvent. The value of this variable is the same object that the Get-Event cmdlet returns. Therefore, you can use the properties of the $Event variable, such as $Event. TimeGenerated , in an Action script block.
Contains an object that represents the first event argument that derives from EventArgs of the event that is being processed. This variable is populated only within the Action block of an event registration command. The value of this variable can also be found in the SourceEventArgs property of the PSEventArgs (System. Management. Automation. PSEventArgs) object that Get-Event returns.
$EVENTSUBSCRIBER.
Contains a PSEventSubscriber object that represents the event subscriber of the event that is being processed. This variable is populated only within the Action block of an event registration command. The value of this variable is the same object that the Get-EventSubscriber cmdlet returns.
Processo . GetCurrentProcess Method ()
A documentação de referência da API tem uma nova casa. Visite o Navegador da API em docs. microsoft para ver a nova experiência.
Gets a new Process component and associates it with the currently active process.
Assembly: System (no System. dll)
Valor de retorno.
A new Process component associated with the process resource that is running the calling application.
Use this method to create a new Process instance and associate it with the process resource on the local computer.
Like the similar GetProcessById, GetProcessesByName, and GetProcesses methods, GetCurrentProcess associates an existing resource with a new Process component.
The following example retrieves information of the current process, processes running on the local computer, all instances of Notepad running on the local computer, and a specific process on the local computer. It then retrieves information for the same processes on a remote computer.
para confiança total para o chamador imediato. Este membro não pode ser usado por código parcialmente confiável.
No comments:
Post a Comment