EXIBIR PDF NO WEBBROWSER DE UM RESOURCE

LUIS.HERRERA 15/05/2013 17:32:41
#423548
Estou exibindo o help do sistema de um arquivo HTML na pasta do programa.

Mas estava querendo colocar todos os helps dentro de um resource, mas não consegui exibí-lo.

pelo arquivo individual na pasta faço assim:

string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
path = path + @[Ô]\Ajuda\cargos.html[Ô]; // Monta o caminho completo incluindo o nome do arquivo
string result = [Ô]file://[Ô] + path.Replace(@[Ô]\[Ô], [Ô]/[Ô]); // Monta dados para o webBrowser, já que vai navegar localmente e troca as barras
if (File.Exists(path))
webAjuda.Navigate(new Uri(result));


Como seria para usar um PDF do Resource?
DENNERFOX 16/05/2013 10:57:14
#423585
Luis, o webbrowser também recebe o pdf normalmente. No meu projeto eu coloquei ele para buscar o arquivo com um CommonDialog, então eu localiza na máquina onde está o arquivo e ele monta no WebBrowser.

Tanto Imagens quanto PDF abre normal.

Da uma olhada no exemplo que tenho.

DENNERFOX 16/05/2013 11:26:50
#423587
Só uma observação, o exemplo que te enviei é em VB6 caso te ajude precisa fazer algumas alterações.
LUIS.HERRERA 16/05/2013 14:06:19
#423593
DENNERFOX boa tarde.

O problema não é abrir, isso eu já consegui como postei o código. O problema é que quero colocar todos os PDF's, são vários um para cada tela do sistema, tudo dentro de um arquivo de recursos do VS 2008. Assim não teria problemas com deixar arquivos soltos em pastas que poderiam ser alterados ou perdidos e o sistema ficar sem o help.

O problema é que não consegui usar o PDF do Resource no Webbrowser, dá erro. Primeiro que ele lê o Resource como array de Byte[].

Eu consigo usar outros objetos de um resource, como imagens para colocar na propriedade ico dos controles e forms, só o PDF no webbrowser não consegui ainda.
FFCOUTO 16/05/2013 18:53:16
#423609
Luis,

Porque você não grava o pdf na pasta temp após ler o mesmo do resource?
Depois você poderia fazer uma rotina no fim do programa para excluir esses pdf.

LUIS.HERRERA 17/05/2013 10:41:48
#423645
Fabiano estou tentando fazer o que disse, parece uma alterativa se não der para fazer direto pela memória. Porém deu um erro que não estou sabendo como resolver.

Pesquisando achei um método que faz exatamente isso para relatórios do Crystal Report. Como isso será uma coisa que ainda veris (relatórios), achei interessante fazer o método que funcione para as duas situações, HELP e RELATÓRIOS, pois irá extrair arquivos do resource.

O método criado numa classe public static (DLL) é:

public static void extrairRelatorio(string relatorio, string destino)
{
System.IO.FileInfo fi = new System.IO.FileInfo(destino);
if (fi.Exists) fi.Delete();
System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
foreach (string str in asm.GetManifestResourceNames())
if (str.ToLower().IndexOf(relatorio.ToLower()) > -1) relatorio = str;
System.IO.Stream file = asm.GetManifestResourceStream(relatorio);
System.IO.FileStream outFile = new System.IO.FileStream(destino, System.IO.FileMode.Create);
int bufferLen = 1024;
byte[] buffer = new byte[bufferLen];
int bytesRead;
do
{
bytesRead = file.Read(buffer, 0, bufferLen); [txt-color=#e80000]//ERRO QUI[/txt-color] outFile.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
outFile.Close();
}


Mas está dando erro na lnha comentada em vermelho o erro é:
NullReferenceException (referencia de um objeto não definida para uma instância de um objeto).

A chamada que faço no formulário é:

Evento Load
string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string relArquivo = [Ô]cargosPT.pdf[Ô];
path = path + @[Ô]\Ajuda\cargosPT.pdf[Ô]; // Monta o caminho completo incluindo o nome do arquivo
ClasseAcoesForms.extrairRelatorio(relArquivo, @path);

string result = [Ô]file://[Ô] + path.Replace(@[Ô]\[Ô], [Ô]/[Ô]); // Monta dados para o webBrowser, já que vai navegar localmente e troca as barras
if (File.Exists(path))
webAjuda.Navigate(new Uri(result)); // Ok, arquivo na tela
else
{
//pega o texto no idioma selecionado
MessageBox.Show(Idioma.RetornaMensagem([Ô]ArquivoAjudaNao[Ô]), Idioma.RetornaMensagem([Ô]TituloAvisoMSG[Ô]), MessageBoxButtons.OK, MessageBoxIcon.Stop);
}


O que pode ser isso?
FOXMAN 17/05/2013 11:34:55
#423650
Luiz, no meu novo sistema irei implementar o help. Porém o mesmo ficar no banco de dados da aplicação.

Posso guardar tudo, inclusive as imagens no banco(eu não sou adepto de guardar imagem em banco de dados) mas desta vez vou guardar e testar.

Voce pode montar uma tabela que irá receber o código do HTML, e a imagem, uma breve descrição, um atalho, etc...etc...
Fica algo mais fácil de gerenciar uma vez que vc somente precisa gerar uma string sql para inserir novos help.

O que você acha ?
LUIS.HERRERA 17/05/2013 11:50:22
#423651
Foxman tudo bem?

Eu já acho que não é tão interessante essa opção. O Resource com PDF é melhor veja:
Toda vez que alguém acessar uma tela será feita uma consulta SQL para trazer o help, pois ela já fica no formulário pronto para exibir (ABA com webbrowser), isso aumenta o fluxo de acessos e dados na rede.

Já com resource, tudo é feito localmente no micro do usuário. além disso um pdf fica com alguns Kbytes, já o banco fica com um tamanho maior para todos os helps.

Outra coisa é que a manutenção dos helps fica super complicada, pois como se trata de um aplicativo para n clientes, não tenho acesso aos bancos. Com isso teria ou de criar um outro aplicativo que enviasse os helps para o banco atualizar, isso se torma trabalhoso e corre-se o risco do cliente não usar o aplicativo.

Minha opinião claro.

Sobre o problema de extrair o PDF do resource e colocar numa pasta, tentei esse outro código e ocorre o mesmo erro na linha indicada abaixo. Agora eu não usei a classe, coloquei esse código direto no form então não estou entendendo, pois pensei que tivesse alguma relação com o fato de chamar um método estático sem instanciar, mas não foi isso.

Assembly currentAssembly = Assembly.GetExecutingAssembly();
FileInfo fileInfoOutputFile = new FileInfo(path);
//CHECK IF FILE EXISTS AND DO SOMETHING DEPENDING ON YOUR NEEDS
if (fileInfoOutputFile.Exists)
{
//overwrite if desired (depending on your needs)
fileInfoOutputFile.Delete();
}
//OPEN NEWLY CREATING FILE FOR WRITTING
FileStream streamToOutputFile = fileInfoOutputFile.OpenWrite();
//GET THE STREAM TO THE RESOURCES
Stream streamToResourceFile = currentAssembly.GetManifestResourceStream(relArquivo);

//---------------------------------
//SAVE TO DISK OPERATION
//---------------------------------
const int size = 4096;
byte[] bytes = new byte[4096];
int numBytes;
while ((numBytes = streamToResourceFile.Read(bytes, 0, size)) > 0) [txt-color=#e80000]// Errp aqui[/txt-color]
{
streamToOutputFile.Write(bytes, 0, numBytes);
}
streamToOutputFile.Close();
streamToResourceFile.Close();


Nota: O estranho é que nos dois casos, o arquivo é criado mas fica vazio = 0 kb.
FOXMAN 17/05/2013 13:24:16
#423656
Realmente cada caso é um caso.

Eu costumo não carregar informações antes que seja solicitada pelo usuário, pois da forma que vc esta propondo, mesmo que ele não vá utilizar o HELP o mesmo será carregado.
Não seria mais intuitivo, se ao clicar no botão/aba/etc HELP o usuario carregaria tal conteúdo?

Não sei qual a sua forma de atualizar o sistema no cliente, pois de qualquer forma se vc disponiblizar conetúdo no Resource terá de atualizar os HTMLS OU PDF tbem no cliente.

No caso eu disponibilizaria uma instrução sql em um arquivo de texto simples e executaria este arquivo na atualização do cliente.

Recentemente um cliente me solicitou uma alteração no sistema. A atualização consistia em disponibilizar 3 relatorios com 3 imagens(jpg).
Utilizei o Resource para armazenar, para minha surpresa o Instalador pulou de 11 MB para 27MB.
Ou seja.
Todo cuidado é pouco para utilizar o Resource.

LUIS.HERRERA 17/05/2013 16:03:51
#423664
Bem consegui resolver. Mas vou avaliar esse problema de tamanho do [Ô]bichinho[Ô] depois, se realmente comprometer muito, vou buscar outra opção.

Ficou assim se alguém precisar:
Método publico estático para não precisar instanciar.

public static void extrairArquivoResource(string myArquivo, string destino, string myExtensao)
{
System.Reflection.Assembly thisExe;
thisExe = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream fileIn = null;

switch (myExtensao)
{
case [Ô]pdf[Ô]:
fileIn = thisExe.GetManifestResourceStream([Ô]myApp.Resources.Ajuda.[Ô] + myArquivo);
break;
case [Ô]rpf[Ô]: //-> relatórios do crystal report se for usar
fileIn = thisExe.GetManifestResourceStream([Ô]myApp.Resources.Relatorios.[Ô] + myArquivo);
break;
}

if (fileIn == null)
return;

//Create a stream for a temporary file
System.IO.Stream fileOut = System.IO.File.OpenWrite(destino);

//Write the file and close it
const int SIZE_BUFF = 1024;
byte[] buffer = new Byte[SIZE_BUFF];
int bytesRead;
while ((bytesRead = fileIn.Read(buffer, 0, SIZE_BUFF)) > 0)
{
fileOut.Write(buffer, 0, bytesRead);
}
fileOut.Close();
}


Para usar em cada form:
webAjuda.AllowWebBrowserDrop = false;   // Impede que o Webbrowser abra páginas externas

// Abrir arquivo de ajuda
string filename = [Ô]cargos.pdf[Ô];
string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
path = path + @[Ô]\Ajuda\cargos.pdf[Ô]; // Monta o caminho completo incluindo o nome do arquivo

ClasseAcoesForms.extrairArquivoResource(filename, path, [Ô]pdf[Ô]);

if (File.Exists(path))
{
string result = [Ô]file://[Ô] + path.Replace(@[Ô]\[Ô], [Ô]/[Ô]); // Monta dados para o webBrowser, já que vai navegar localmente e troca as barras
webAjuda.Navigate(new Uri(result));
}
else
{
//pega o texto no idioma selecionado
MessageBox.Show([Ô]ArquivoAjudaNaoEncontrado[Ô],[Ô]TituloAvisoMSG[Ô], MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
Tópico encerrado , respostas não são mais permitidas