Dicas sobre desenvolvimento de software, gestão e tributações

Rede Social

30 de setembro de 2015

Impressão utilizando spool do windows C#


Aqui vai uma forma de enviar string para a impressora utilizando o spool do windows.
Este método é bastante utilizado para impressoras não fiscais, pois com ele se tem um envio genérico para o spool do windows,
não dependendo de DLLs de terceiros.
Algumas vantagens de se utilizar o spool são:
- O windows gerencia, então caso seja enviado conteúdo para impressão e a impressora esteja desligada, é só liga-la
  que a impressão será realizada.
- Caso acabe o papel no meio da impressão, pode-se colocar mais que a impressão continuará de onde parou.
- A fila de impressão também é gerenciada pelo windows

Criei dois métodos para facilitar a chamada pelo aplicativo, um publico que será o método chamado em qualquer lugar da aplicação
e um privado para ninguém ter acesso a ele sem necessidade.
Mas antes disso precisamos criar uma classe que será a estrutura do documento enviado.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private class DocInfoA
{
[MarshalAs(UnmanagedType.LPStr)]
public string pDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string pOutputFile;
[MarshalAs(UnmanagedType.LPStr)]
public string pDataType;
}

Depois importaremos os métodos do spool que iremos utilizar.

//Abrir os trabalhos na impressora
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

//Fechar a comunicação com a impressora
[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool ClosePrinter(IntPtr hPrinter);

//Abrir o documento que será impresso
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

//Fechar o documento
[DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool EndDocPrinter(IntPtr hPrinter);

//Abrir uma página dentro do documento
[DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool StartPagePrinter(IntPtr hPrinter);

//Encerrar página
[DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool EndPagePrinter(IntPtr hPrinter);

//Enviar texto para a página aberta
[DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
private static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);


private bool EnviaBytesParaImpressora(IntPtr pBytes, Int32 tamanhoTexto)
{
Int32 dwWritten = 0;
IntPtr hPrinter = new IntPtr(0);
DocInfoA di = new DocInfoA();
bool retorno = false;

try
{
//pDocName = Nome do documento, pode ser o nome de sua preferência
di.pDocName = "Impressora Nao Fiscal";
di.pDataType = "RAW";

//Inicia comunicação com a impressora
if (OpenPrinter(NomeImpressora.Normalize(), out hPrinter, IntPtr.Zero))
{
//Abre o documento
if (StartDocPrinter(hPrinter, 1, di))
{
//Insere uma página
if (StartPagePrinter(hPrinter))
{
//Envia o conteúdo para impressora
retorno = WritePrinter(hPrinter, pBytes, tamanhoTexto, out dwWritten);

EndPagePrinter(hPrinter);
}

EndDocPrinter(hPrinter);
}

ClosePrinter(hPrinter);
}
else
{
retorno = false;
}
}
//Caso algum problema ocorra a comunicação com a impressora é fechada para não ficar ocupando-a
catch
{
ClosePrinter(hPrinter);
}

return retorno;
}

public bool EnviaStringImpressora(string texto)
{
IntPtr pBytes;
Int32 tamanhoTexto;
bool retorno = false;

tamanhoTexto = texto.Length;

//carrega o ponteiro para a string na memória
pBytes = Marshal.StringToCoTaskMemAnsi(texto);

retorno = EnviaBytesParaImpressora(pBytes, tamanhoTexto);

//Limpa o ponteiro da memória
Marshal.FreeCoTaskMem(pBytes);

return retorno;
}

Ler

29 de setembro de 2015

Descobrir memória RAM do PC C#


Existem algumas formas de se saber quanto de memória o PC tem, nesta dica motrarei uma delas utilizando apenas C#.
No System.Management existem as classes ManagementObject e ManagementObjectSearcher, da qual iremos utilizar.

Primeiro uma variável que servirá para armazenar o valor da memória.
int memoriaRam = 0;

O ManagementObjectSearcher trabalha com uma espécie de consulta, como se fosse um comando SQL, no nosso caso utilizaremos esta.
string Consulta = "SELECT MaxCapacity FROM Win32_PhysicalMemoryArray";
ManagementObjectSearcher objetoPesquisado = new ManagementObjectSearcher(Consulta);

Feito isso iremos somar todos os valores encontrados para a memória RAM.
foreach (ManagementObject WniPART in objetoPesquisado.Get())
{
UInt32 tamanhoKB = Convert.ToUInt32(WniPART.Properties["MaxCapacity"].Value);
UInt32 tamanhoMB = tamanhoKB / 1024;
memoriaRam += Convert.ToInt32(tamanhoMB);
}

Concluído o foreach teremos o valor em MB da memória RAM do PC
Ler

28 de setembro de 2015

Alterar cor de objeto WPF por programação C#


Neste simples tutorial irei mostrar como alterar a cor de um objeto WPF através do C#.

Os objetos no WPF são:
<Rectangle x:Name="retang">
<ListView  x:Name="list">

Para mostrar que é possível utilizar da mesma forma para objetos diferentes.

Trabalharemos com cores no formato RGB. Imagine que quero um tom de cinza claro, então
vou setar uma string com o seguinte texto "190,190,190".

string cor = "191,191,191";

//Separando o R, G e B
var converterBrush = new System.Windows.Media.BrushConverter();
string[] coresRGB = cor.Split(',');

//criando a cor
var cor = Color.FromArgb(coresRGB[0].ToInt32(), coresRGB[1].ToInt32(), coresRGB[2].ToInt32());
var brush = (System.Windows.Media.Brush)converterBrush.ConvertFromString("#" + cor.Name);

//Pintando Rectangle e o ListView
retang.Fill = brush;
list.Background = brush;
Ler

27 de setembro de 2015

Criar número randômico com C#


Aqui vou mostrar uma forma de criar um número randômico com C#.
Existem n utilizações para isso, mas a necessidade comigo surgiu quando estava
desenvolvendo uma dll de comunicação com SATs onde é necessário à cada método
enviado, passar um número randômico como parâmetro.
Utilizaremos a classe Random que está no namespace System mesmo.

Random random = new Random();
int randomicoInteiro = random.Next(0, 999999);

Existe também a possibilidade de se trabalhar com double, neste caso é só
substituir o .Next por .NextDouble

double randomicoDouble = random.NextDouble();

Um número entre 0.0 e 1.0 será retornado
Ler

26 de setembro de 2015

Pegar peso da balança Toledo C#


Nesta dica iremos pegar peso de uma balança Toledo através da DLL P05 com C#.

Primeiro vamos declarar os métodos utilizados.

[DllImport(P05.DLL")]
public static extern int AbrePorta(int porta, int velocidade, int dataBits, int paridade);

[DllImport(P05.DLL")]
public static extern int FechaPorta();

[DllImport(P05.DLL")]
public static extern int PegaPeso(int tipoEscrita, StringBuilder peso, string diretorio);
O tipo escrita serve para disponibilizar em arquivo texto quando 0 e quando 1 é para disponibilizar na área de transferência
O diretório é para indicar onde será salvo o arquivo.

Após isso vou criar um método que irá abrir a porta, pegar o peso e fechá-la.

public decimal RetornaPeso(int portaCom)
{
int retorno = P05.AbrePorta(portaCom, 0, 0, 2);

if (retorno == 1)
{
StringBuilder pesoString = new StringBuilder();
retorno = P05.PegaPeso(1, pesoString, "");
decimal peso = pesoString.ToString().ConvertTo<decimal>();

retorno = P05.FechaPorta();

if(retorno == 1)
{
return peso;
}
else
{
//Erro ao fechar porta
}
}
else
{
//Erro ao abrir a porta
}

return 0;
}

private const string LOCAL_ESCRITA = ""; //Diretorio onde será gravado o arquivo. Se vazio significa o diretorio local do programa
private const int OPCAO_ESCRITA = 1; //Disponibilizar em     => 0 = Arq Texto, 1 = Área de Transferência
Ler

Setar memória máxima para uso do SQLServer


Configurar o uso de memória do SQLServer é bem simples pelo seu gerenciador
No Pesquisador de Objetos, clique com o botão direito do mouse em um servidor e selecione Propriedades.
Clique no nó Memória.
Em Opções de Memória do Servidor, insira a quantidade desejada para Memória mínima do servidor e Memória máxima do servidor.

Mas pode ser interessante setar esta propriedade diretamente com comando.
Obs. os comandos a seguir sempre deve ser executados e depois confirmados com o comando RECONFIGURE.

Primeiro vamos permitir executar comandos com as opções avançadas.
sp_configure 'show advanced options', 1;
RECONFIGURE;
 
Depois vamos alterar a memória máxima para 1024 MB.
sp_configure 'max server memory', 1024;
RECONFIGURE;

Feito, o SQLServer já está com o valor alterado, caso queira conferir é só ir no mesmo menu descrito acima.

Lembrando que como é um comando T-SQL você pode usá-lo com sua aplicação executando o comando que funcionará,
não precisa necessariamente ser executado do Management Studio.
Ler

25 de setembro de 2015

Verificar permissão de escrita em pasta C#


Certo dia me deparei com a seguinte questão, precisava que meu aplicativo gravasse um arquivo em uma pasta que estava na rede,
mas o usuário logado não tinha permissão de escrita nela, somente de leitura, então o método de gravar arquivo retornava um erro
genérico e não conseguia saber ao certo qual era o problema. Quando fui no servidor conferir vi que aquele usuário daquela máquina
não tinha permissão, então com este método que vou lhes mostrar fica fácil saber que o usuário não tem permissão e é possível
mostrar mais detalhadamente isso ao usuário do aplicativo.

public bool PermissaoEscrita(string diretorio)
{
try
{
System.Security.AccessControl.FileSystemSecurity security;

if (File.Exists(diretorio))
{
security = File.GetAccessControl(diretorio);
}
else
{
security = Directory.GetAccessControl(diretorio);
}

var regras = security.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));

var usuarioCorrente = new System.Security.Principal.WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent());
bool resultado = false;

foreach (System.Security.AccessControl.FileSystemAccessRule regra in regras)
{
if (0 == (regra.FileSystemRights &
(System.Security.AccessControl.FileSystemRights.WriteData | System.Security.AccessControl.FileSystemRights.Write)))
{ continue; }

if (regra.IdentityReference.Value.StartsWith("S-1-"))
{
var sid = new System.Security.Principal.SecurityIdentifier(regra.IdentityReference.Value);

if (!usuarioCorrente.IsInRole(sid))
{ continue; }
}
else
{
if (!usuarioCorrente.IsInRole(regra.IdentityReference.Value))
{ continue; }
}

if (regra.AccessControlType == System.Security.AccessControl.AccessControlType.Deny)
{ return false; }
if (regra.AccessControlType == System.Security.AccessControl.AccessControlType.Allow)
{ resultado = true; }
}

return resultado;
}
catch
{
return false;
}
}

Este método recebe como parâmetro uma string com o caminho do diretorio, verifica se o usuário atual tem permissão de escrita nela e retorna verdadeiro ou falso.
A partir disso pode ser exibida uma mensagem personalizada ao usuário, ou então uma tomada de decisão no código, enfim são várias as possibilidades.
Ler

24 de setembro de 2015

Entendendo a extensão do arquivo de NFP


O arquivo de NFP (Nota Fiscal Paulista) tem um padrão de nomenclatura para facilitar a identificação do arquivo sem a necessidade de abri-lo.
Iremos utilizar como exemplo o nome fictício DR200173.18B.
Onde DR indica a marca do ECF, como nos exemplos:
DR - Daruma
BE - Bematech
EL - Elgin
SW - Sweda

200173 indicam uma identificação do ECF (número série).

E agora o foco dessa postagem que é a extensão do arquivo. Ela sempre terá 3 caracteres, onde o primeiro indica o dia, o segundo indica o mês e o terceiro indica o ano.
No nosso exemplo temos 18B, que traduzindo significa dia 1 do mês 8 (agosto) do ano B (2011).
Espere B significa 2011 como isso? Sim pois como só existe um dígito para indicar cada uma das partes da data o que acontece quando o valor passa de 9, não podemos colocar 10 pois ocuparia dois dígitos, então é substituído por letras começando do A, por isso B no espaço do ano significa 2011, pois B significa 11.
Vamos para outros exemplos:
37D - traduzindo significa dia três, do mês sete (julho), do ano treze (2013).
EAF - dia quatorze de outubro de 2015
V8F - 31/08/2015

Vou deixar uma tabela para facilitar o trabalho de vocês na hora de traduzir a extensão.

A = 10        M = 22
B = 11        N = 23
C = 12        O = 24
D = 13        P = 25
E = 14        Q = 26
F = 15        R = 27
G = 16        S = 28
H = 17        T = 29
I = 18        U = 30
J = 19        V = 31
K = 20
L = 21
Ler

Bloquear mouse e teclado C#


Quando estamos executando algum método, consulta ou algo que demore a retornar é possível que o usuário tecle ou clique em algo que atrapalhe a execução.
Aqui irei mostrar uma das formas de bloquear o mouse e o teclado do usuário na aplicação enquanto ela executa alguma função.
Utilizaremos o método BlockInput que está na USER32, então teremos que importá-lo, ele não retorna nenhuma valor e recebe como parâmetro um boleano indicando bloqueio quando true e desbloqueio quando false, como segue abaixo.

[DllImport("USER32.DLL")]
public static extern void BlockInput(bool block);

Feito isso é só chamar este método passando o parâmetro boleano true quando quiser bloquear e passar o parâmetro false quando quiser desbloquear.
Veja no exemplo.

BlockInput(true);
MetodoPesquisaClientesBanco(string cpf);
BlockInput(false);

Pronto enquanto eu executo o método de pesquisa de clientes no banco através do CPF o teclado e o mouse do usuário ficarão bloqueados na aplicação.
Obs. O usuário ainda poderá utilizar algumas funções do teclado como pressionar Ctrl + Alt + Del por exemplo.
Ler

23 de setembro de 2015

Verificar portas Seriais (COM) instaladas no computador C#


Com esta dica ficará fácil saber quais portas com estão instaladas no computador. Existem várias aplicações possíveis para a necessidade de saber se tal porta com existe
ou ter um retorno de todas as que estão instaladas atualmente no computador como por exemplo ao tentar comunicar com uma impressora não fiscal instalada em uma porta COM.
Imagine que tenho COM1 e COM2 no meu computador, mas o usuário do sistema o configurou erroneamente na COM3, sabendo que a COM3 se quer existe no computador, nem preciso
testar a comunicação posso retornar um erro diretamente ao usuário de uma forma mais rápida.
Vamos ao código.

Primeiramente irei declarar a System.IO.Ports, pois ela contém o método que iremos utilizar.
using System.IO.Ports

Agora vou criar um método que recebe como parâmetro a porta COM que desejo utilizar e retorna um boleano para saber se a porta existe.
public bool VerificaPortaCom(string portaCOM)
{
string[] portasInstaladas = SerialPort.GetPortNames();

if (portasInstaladas.Any(x => x.Equals(portaCOM))) //procura no vetor se existe alguma string com o conteúdo igual ao da variável portaCOM
{ retur true; }
else
{ retur false; }
}

Pronto o retorno do método já me indicará se a porta passada como parâmetro existe ou não, bem simples.

string porta = "COM2"
if(VerificaPortaCom(porta))
{ ComunicarImpressoraNaoFiscal(porta); }
else
{ ExibeTelaErro("Porta " + porta + " não existe") }
Ler

Beep sonoro C#


Algumas vezes pode ser interessante chamar a atenção do usuário, seja por uma validação de campo, mensagem de aviso ou de erro na aplicação.
Para irei demonstrar a utilização de beeps  do windows sendo chamados via programação.

A primeira coisa a fazer é importar o método nativo de Beep que está na DLL kernel32. Ele tem dois parâmetros um para a frequência do beep,
ou seja, se ele será mais grave, mais agudo, enfim definir a frequência sonora dele, o outro parâmetro é para indicar o tempo de duração
deste beep.

[DllImport("kernel32.dll")]
public static extern bool Beep(int frequencia, int duracao);

Alguns exemplos de utilização deste método:
Beep(800, 100);
Beep(670, 75);
Beep(930, 260);

if(ExisteCampoEmBranco)
{
Beep(800, 100);
ExibeTelaErro("Favor preencher todos os campos");
}
Ler

22 de setembro de 2015

Executar comandos no cmd do windows com C#


Esta dica é de como executar algum comando no cmd do windows direto com programação em C#.
De forma bem simples você pode criar um método que chame este comando, que é o único necessário para abrir, executar e fechar o cmd.

//declarando uma string com o comando somente para facilitar a visualização
string executar = @"/C " + "comando que deseja executar no cmd";

//Executa o comando no cmd do windows e aguarda a execução do mesmo para fechá-lo
System.Diagnostics.Process.Start("CMD.exe", executar).WaitForExit();

Imagine que quero que a minha aplicação crie uma pasta pelo prompt meu método ficaria com estas linhas:

string executar = @"/C " + "md programarAutomacao";
System.Diagnostics.Process.Start("CMD.exe", executar).WaitForExit();
Ler

C# Organizando as DLLs que sua aplicação utiliza


A dica de hoje é sobre organização.
Algumas vezes utilizamos DLLs externas em nossas aplicações e organizá-las em pastas pode ser uma boa ideia. Para isso existe uma forma simples em C# para setar o caminho onde a DLL desejada está e com isso a aplicação à chamar sem maiores problemas.
O método utilizado será o SetCurrentDirectory que está em System.IO.Directory.
Vamos ao exemplo comentado:

string current = Directory.GetCurrentDirectory(); //serve para saber qual é o diretório corrente
string caminho = @"\DLLs"; //Indica o caminho para localizar a dll em questão

Directory.SetCurrentDirectory(current + caminho);

Com isso é setado como diretório corrente "diretório da sua aplicação\DLLs", com a DLL nesta pasta primeiramente o windows procurará nela, depois na pasta do aplicativo e por fim na pasta system32. Então qualquer informação ou execução de métodos poderá ser realizado nesta DLL da pasta "\DLLs "

Feito isso você deverá voltar o diretório corrente para o diretório da aplicação, o que também é bastante simples veja:

current = Directory.GetCurrentDirectory().Replace(caminho, ""); //seleciona o caminho raiz da aplicação
Directory.SetCurrentDirectory(current); //seta o diretório como corrente para a aplicação continuar a sua execução normalmente
Ler