Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.
Um aplicativo que chama um serviço da Web pode demorar mais do que o esperado para tornar o primeiro chamar quando comparado a chamadas subseqüentes. Esse atraso ocorre cada tempo que você executar o aplicativo.
Observação Este hotfix não pode ser aplicado em um sistema que está execução o Service Pack.NET Framework 1.1 Microsoft 1. Se você instalou o Service Pack.NET Framework 1.1 1 e estiver tendo o sintoma que é descrito na solicitação este artigo, o pacote cumulativo hotfix que descrito no artigo Microsoft Knowledge Base 890673 para obter uma resolução. Para obter informações adicionais, clique no número abaixo para ler o artigo na Base de Dados de Conhecimento da Microsoft::
890673
(http://support.microsoft.com/kb/890673/
)
Disponibilidade de XML Web Services Post-Service Pack 1.NET Framework 1.1 e XML Messaging pacote cumulativo hotfix 8
O atraso ocorre quando você executar um aplicativo cliente para o primeiro tempo porque o proxy serviço da Web usa um assembly serialização, e o assembly serialização é compilado dinamicamente no tempo de execução. O assembly serialização serializa e desserializa as informações de acordo com o solicitação de cliente e os resultados servidor que são retornados para a solicitação. O tempo adicional no primeiro chamar a ocorre because of a compilação de serialização da assembly.
Esse hotfix também deve ser instalada em computadores que executar os aplicativos que usam conjuntos pregenerated. Para resolver o problema, execute as seguintes etapas::
Obter e seguida, instalar o hotfix. Para fazer isto, execute as seguintes etapas::
Obter o hotfix com a seguinte pacote de hotfix:
890673
(http://support.microsoft.com/kb/890673/
)
Disponibilidade de XML Web Services Post-Service Pack 1.NET Framework 1.1 e XML Messaging pacote cumulativo hotfix 8
Extrair o hotfix para uma pasta.
Clique duas vezes o hotfix para instalar o hotfix em seu computador.
Pregenerate o assembly serializador. O seguinte é um aplicativo console exemplo mínimo, que irá gerar as montagens serializador para um assembly proxy. Para uma versão mais sofisticado deste aplicativo, consulte a seção " More Information ". Para criar o pregenerator serializador simples, siga estas etapas:
Criar um novo aplicativo console Microsoft Visual C#.NET que é nomeado PreGen.
Renomeie o arquivo Class1.cs como Pregen.cs.
Substituir todos a codificar existente no arquivo PreGen.cs pelo seguinte codificar.
namespace PreGenNS {
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using System.Text;
using System.Globalization;
using System.Web.Services.Protocols;
using System.Threading;
using System.CodeDom.Compiler;
public class Pregen {
public static int Main(string[] args) {
if (args.Length != 1) {
Console.WriteLine("usage: ");
Console.WriteLine(" pregen assembly");
return 1;
}
Pregen pregen = new Pregen();
return pregen.Run(args[0]);
}
int Run(string assemblyName) {
try {
GenerateAssembly(assemblyName);
}
catch (Exception e) {
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
throw;
}
Error(e, "Error: ");
return 1;
}
return 0;
}
void GenerateAssembly(string assemblyName) {
Assembly assembly = LoadAssembly(assemblyName, true);
Type[] types = assembly.GetTypes();
ArrayList mappings = new ArrayList();
ArrayList importedTypes = new ArrayList();
XmlReflectionImporter importer = new XmlReflectionImporter();
for (int i = 0; i < types.Length; i++) {
Type type = types[i];
if (HttpWebClientProtocol.GenerateXmlMappings(type, mappings)) {
importedTypes.Add(type);
}
}
if (importedTypes.Count > 0) {
Type[] serializableTypes = (Type[])importedTypes.ToArray(typeof(Type));
XmlMapping[] allMappings = (XmlMapping[])mappings.ToArray(typeof(XmlMapping));
bool gac = assembly.GlobalAssemblyCache;
string codePath = gac ? Environment.CurrentDirectory : Path.GetDirectoryName(assembly.Location);
string serializerName = assembly.GetName().Name + ".XmlSerializers" ;
string location = Path.Combine(codePath, serializerName + ".dll");
CompilerParameters parameters = new CompilerParameters();
parameters.TempFiles = new TempFileCollection(codePath);
parameters.GenerateInMemory = false;
parameters.IncludeDebugInformation = false;
parameters.TempFiles = new TempFileCollection(codePath, true);
Assembly serializer = XmlSerializer.GenerateSerializer(serializableTypes, allMappings, parameters);
if (serializer == null) {
Console.Out.WriteLine("Failed pregenerate serializer for '{0}'", assembly.Location);
}
else {
AssemblyName name = serializer.GetName();
Console.Out.WriteLine("Serialization Assembly Name: {0}", name.ToString());
Console.Out.WriteLine("Generated serialization assembly for assembly {0} --> '{1}'.", assembly.Location, location);
}
}
else {
Console.Out.WriteLine("Assembly '{0}' does not contain any serializable types.", assembly.Location);
}
}
static Assembly LoadAssembly(string assemblyName, bool throwOnFail) {
Assembly assembly = null;
string path = Path.GetFullPath(assemblyName).ToLower(CultureInfo.InvariantCulture);
if (File.Exists(path)) {
assembly = Assembly.LoadFrom(path);
}
else {
try {
assembly = Assembly.Load(assemblyName);
}
catch (Exception e) {
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
throw;
}
Error(e, "Error: ");
}
if (assembly == null) {
string justName = Path.GetFileNameWithoutExtension(assemblyName);
try {
assembly = Assembly.Load(justName);
}
catch (Exception e) {
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
throw;
}
Error(e, "Error: ");
}
}
}
if (assembly == null) {
if (throwOnFail)
throw new InvalidOperationException("Cannot load assembly " + assemblyName);
return null;
}
return assembly;
}
static void Error(Exception e, string prefix) {
Console.Error.WriteLine(prefix + e.Message);
if (e.InnerException != null) {
Error(e.InnerException, " - ");
}
}
static void Warning(Exception e) {
Console.Out.WriteLine(" - " + e.Message);
if (e.InnerException != null) {
Warning(e.InnerException);
}
}
}
}
Adicione uma referência para o arquivo System.Web.Services.dll.
Criar o projeto.
Copie o arquivo PreGen.exe para a pasta que contém o assembly que tenha a codificar proxy. Para exemplo, copiar o arquivo para o assembly que contém a codificar cliente de serviços da Web PreGen.exe.
Pregenerate os serializers para o serviço da Web usando o arquivo PreGen.exe preparado. Para exemplo, se seu codificar proxy estiver no arquivo WindowsApplication1.exe, executar o seguinte comando em um prompt de comando:
PreGen.exe
WindowsApplication1.exe
Observação um arquivo.dll é gerado na mesma pasta onde o assembly cliente é salvo como assim como você executar o comando na etapa g.
Abra seu código do cliente no Microsoft Visual Studio.NET IDE.
Em Gerenciador de Soluções, expansão do nó Web Reference . Para exemplo, se você tiver adicionado uma referência a Service1 usando localhost, expansão localhost .
Expanda Reference.Map , e clique clique duplo o arquivo Reference.cs.
Substituir a codificar na etapa k pela seguinte codificar.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="Service1Soap", Namespace="http://tempuri.org/")]
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(CodeBase="< Nome DLL >")]
Recriar o cliente de serviços da Web.
Observação você tem para reconstruir o cliente because of o atributo. O cliente agora tem um executar - dependência tempo no assembly que contém os serializers MySerializers.dll. Portanto, você deve implantar esse assembly com o aplicativo e tornar a disponível assembly na localidade onde o cliente carrega.
O tipo de argumento que você fornecer para o atributo XmlSerializerAssemblyAttribute determina a forma que o assembly serializador é carregado. Se o argumento CodeBase for usado, o assembly serializador será carregado usando o método LoadFrom . Se o argumento AssemblyName for usado, o assembly serializador será carregado usando o método LoadWithPartialName . Para obter mais informações sobre assembly carregando, visite o seguinte site da Microsoft:
Se você desejar para instalar seus conjuntos serializador para o Global Assembly Cache (GAC), você deve usar argumento AssemblyName , e fornecer o nome assembly totalmente qualificado.
Aplicativos que são implantados usando métodos de cliente inteligente
Se o assembly que contém o proxy é carregado e é executado o local do computador, é preferível para usar a sintaxe CodeBase para o atributo XmlSerializerAssemblyAttribute . Nesta maiúsculas e minúsculas, o assembly serializador deve ser implantado para a mesma pasta como o assembly que contém o proxy. Se o assembly é carregado usando o método LoadFrom sobre HTTP um cenário de implantação Smart Client, no exemplo, para o assembly serialização não será corretamente carregados pelo atributo XmlSerializerAssemblyAttribute . Esse problema ocorre porque o assembly proxy existe no contexto LoadFrom instead of o contexto de carga , o carregador do Common Language Runtime e probing não ocorrer. Para trabalho em torno esse problema, use outro a sintaxe AssemblyName que é com suporte pelo atributo com um fictício nome assembly.
O aplicativo pode e implementar um manipulador para o AppDomain do evento AssemblyResolve para interceptar a solicitação para carregar o serializador assembly e carregá-lo a localidade correta.
private void Form1_Load(object sender, System.EventArgs e)
{
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
}
static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
Assembly a = null;
string serializationAssemblyPartialName = "LoadMySerializerAssemblyNow";
if (args.Name == serializationAssemblyPartialName)
{string sSerializersDLL = "<Name Of The Serializer DLL>";
string smartDeploymentHostLocation = "<Full path location to the Serializer DLL>";
a = Assembly.LoadFrom(smartDeploymentHostLocation + sSerializersDLL);
}
return a;
}
O seguinte é uma versão mais sofisticado do aplicativo exemplo pregenerator serializador. Esta versão permite criar assinado serializador conjuntos. Use o seguinte codificar.
namespace PreGenNS
{
using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using System.Text;
using System.Globalization;
using System.Web.Services.Protocols;
using System.Threading;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.Text.RegularExpressions;
public class Pregen
{
private static bool _verbose = true;
// We use this as the standard suffix on all the serializer DLLs.
// It must match the short name of the proxy assembly class with
const string SerializerSuffix = ".Serializer.dll";
/// Key in the app config file with path of AssemblyInfo file.
private const string AssemblyInfoAppKey = "AssemblyInfoFile";
//private const string CSCCmd = "csc.exe";
// Obtain the full path for the compiler, just in case the path is not set correctly
private readonly string CSCCmd = System.Runtime.InteropServices.RuntimeEnvironment.RuntimeDirectory() + "csc.exe";
public static int Main(string[] args) {
// Are we in a recursive call?
//TODO: could really use a single value -- use filesToDelete...
if (AppDomain.CurrentDomain.GetData(CallingAppDomainKey) == null) {
return RunSlave(args);
}
string dllName = "";
bool invalidUsage = false;
if(args.Length == 1)
{
dllName = args[0];
}
else if(args.Length == 2)
{
if(!(args[0] == "/Q" || args[0] == "/q"))
{
invalidUsage = true;
}
else
{
dllName = args[1];
_verbose = false;
}
}
else
{
invalidUsage = true;
}
if (invalidUsage)
{
Console.WriteLine("usage: ");
Console.WriteLine(" pregen [/Q] assembly");
return 1;
}
// Update Private path setting in current application domain
if (updatePrivatePath() != 0)
{
return 1;
}
Pregen pregen = new Pregen();
int rc = pregen.Run(dllName);
//Console.Read();
return rc;
}
// Reads private path settings from config file and updates appdomain. This permits configurable probing that is needed for preserialization.
static int updatePrivatePath()
{
string defaultPrivatePath = System.Configuration.ConfigurationSettings.AppSettings["PregenDefaultPrivatePath"];
string dynamicPrivatePath = System.Configuration.ConfigurationSettings.AppSettings["PregenDynamicPrivatePath"];
string env_PREGEN_VALUES = Environment.GetEnvironmentVariable("PREGEN_VALUES");
string [] replacementBlocks, temp;
if (_verbose)
Console.WriteLine("Read PREGEN_VALUES Env Variable, Value = " + env_PREGEN_VALUES);
//process the dynamic path if the environment variable PREGEN_VALUES is present
if (env_PREGEN_VALUES == null || env_PREGEN_VALUES == "")
{
if (defaultPrivatePath != null && defaultPrivatePath != "")
{
AppDomain.CurrentDomain.AppendPrivatePath(defaultPrivatePath);
if (_verbose)
Console.WriteLine("Appended private path with: " + defaultPrivatePath);
}
}
else
{
if (dynamicPrivatePath != null && dynamicPrivatePath != "")
{
//do substitutions in dynamic path
replacementBlocks = env_PREGEN_VALUES.ToUpper().Split(";".ToCharArray());
dynamicPrivatePath = dynamicPrivatePath.ToUpper();
for(int i = 0; i < replacementBlocks.Length; i++)
{
temp = replacementBlocks[i].Split("=".ToCharArray());
if(temp.Length != 2)
{
Console.Error.WriteLine("Invalid Environment Variable format - PREGEN_VALUES");
return 1;
}
dynamicPrivatePath = dynamicPrivatePath.Replace(temp[0],temp[1]);
}
AppDomain.CurrentDomain.AppendPrivatePath(dynamicPrivatePath);
if (_verbose )
Console.WriteLine("Appended private path with: " + dynamicPrivatePath);
}
}
return 0;
}
int Run(string assemblyName)
{
try
{
GenerateAssembly(assemblyName);
}
catch (Exception e)
{
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
{
throw;
}
Error(e, "Error processing " + assemblyName + ": ");
return 1;
}
return 0;
}
// Generates the serializer assembly for the proxy assembly specified
void GenerateAssembly(string assemblyName)
{
Assembly assembly = LoadAssembly(assemblyName, true);
Type[] types = assembly.GetTypes();
ArrayList mappings = new ArrayList();
ArrayList importedTypes = new ArrayList();
XmlReflectionImporter importer = new XmlReflectionImporter();
//Obtain the imported serializable types
for (int i = 0; i < types.Length; i++)
{
Type type = types[i];
if (HttpWebClientProtocol.GenerateXmlMappings(type, mappings))
{
importedTypes.Add(type);
}
}
if (importedTypes.Count <= 0) {
Console.Out.WriteLine("Assembly '{0}' does not contain any serializable types.", assembly.Location);
return;
}
{
Type[] serializableTypes = (Type[])importedTypes.ToArray(typeof(Type));
XmlMapping[] allMappings = (XmlMapping[])mappings.ToArray(typeof(XmlMapping));
bool wasError = false;
bool gac = assembly.GlobalAssemblyCache;
string codePath = gac ? Environment.CurrentDirectory : Path.GetDirectoryName(assembly.Location);
//adjust compiler params
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = false;
parameters.IncludeDebugInformation = false;
parameters.TempFiles = new TempFileCollection(codePath, true);
//generate the serializer
Assembly serializer = XmlSerializer.GenerateSerializer(serializableTypes, allMappings, parameters);
if (serializer == null) {
Console.Out.WriteLine("Failed pregenerate serializer for '{0}'", assembly.Location);
wasError = true;
}
else
{
serializer = null;
}
// Determine whether there is an assemblyInfoFile in the config file.
string assemblyInfoFile = System.Configuration.ConfigurationSettings.AppSettings[AssemblyInfoAppKey];
if (assemblyInfoFile != null) {
if (! File.Exists(assemblyInfoFile)) {
Console.WriteLine("ERROR: AssemblyInfo file: {0} does not exist.", assemblyInfoFile);
wasError = true;
}
}
if (!wasError) {
// Recompile the Serializer, same options, except to include the assemblyInfo file and
// adjust the output name.
// We have to find
// 1. a .cs file (the serializer source)
// 2. a .cmdline file (the compiler options used)
// among the temp files from the first compile.
string csFile = null;
string cmdlineFile = null;
foreach (string curFile in parameters.TempFiles ) {
string fileNameLC = curFile.ToLower();
if (fileNameLC.EndsWith(".cs") ) {
csFile = curFile;
}
else if (fileNameLC.EndsWith(".cmdline")) {
cmdlineFile = curFile;
}
//Do not care about the other files...
}
if (csFile == null || cmdlineFile == null) {
Console.WriteLine("Error: needed to rebuild, but cannot find either .cs or .cmdline file\n");
DeleteTempFiles(parameters);
return;
}
// So now we have found the file and the cmdline args. We only need run the compiled application after
// adjusting the parameters to include the AssemblyInfo file and to change the output.
// Typical calling options to csc for this sequence are:
// csc /noconfig @xxx.cmdline
// we'll change this to expand the contents of the cmdline file
// build the right name for the target serializer.
//TODO: we should be able to read the attribute from the proxy DLL and match our output
// to that name.
string serializerName = Path.GetDirectoryName(assembly.Location) + @"\"
+ assembly.GetName().Name + SerializerSuffix;
string cmdLine = AdjustCmdLine(cmdlineFile, assemblyInfoFile, serializerName);
ProcessStartInfo ps = new ProcessStartInfo(CSCCmd, cmdLine);
ps.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(ps);
p.WaitForExit();
int rc = p.ExitCode;
if (rc > 0) {
//TODO: put useful handling here...
Console.WriteLine("ERROR: Compiler problem, rc = {0}", rc);
wasError = true;
}
//TODO: Cannot ditch temp assembly because the assembly is now loaded.
DeleteTempFiles(parameters);
if (!wasError) {
Console.Out.WriteLine("Generated Serialization Assembly Name: {0}", serializerName);
}
Console.Out.WriteLine("Done");
}
}
}
// Delete temporary files from a CompilerParameters list.
private void DeleteTempFiles(CompilerParameters cp) {
ArrayList unDeletedFiles = new ArrayList(10);
foreach(string fileName in cp.TempFiles) {
try {
File.Delete(fileName);
}
catch(Exception) {
unDeletedFiles.Add(fileName);
//Console.WriteLine("Warning: Unable to delete temp file: {0}, exception={1}(\"{2}\")",
// Path.GetFileName(fileName), e.GetType().FullName, e.Message);
}
}
if (unDeletedFiles.Count > 0) {
// put the list into the calling appDomain's environment for later deletion
string[] files = new string[unDeletedFiles.Count];
unDeletedFiles.CopyTo(files);
//TODO: should really be concatenating to any existing value -- maybe leave as an ArrayList?
AppDomain.CurrentDomain.SetData(FilesToDeleteKey, files);
}
}
/// Rebuild a commandline for csc, adding assemblyInfoFile to the end of the line and adjusting the
/// output file name as specified.
private string AdjustCmdLine(string cmdlineFile, string assemblyInfoFile, string outputFile) {
// Obtain the text from the @ response file that is used by the Framework Serialization builder
StreamReader file = File.OpenText(cmdlineFile);
string cmdLine = file.ReadToEnd();
file.Close();
// add the assemblyInfo file at the end of the command if it was specified
if (assemblyInfoFile != null)
cmdLine = String.Format(@"/noconfig {0} ""{1}""", cmdLine, assemblyInfoFile);
// replace the /OUT option with our value.
Regex re = new Regex(@"/OUT:""[^""]+.", RegexOptions.IgnoreCase);
cmdLine = re.Replace(cmdLine, @"/OUT:""" + outputFile + @"""");
return cmdLine;
}
static Assembly LoadAssembly(string assemblyName, bool throwOnFail)
{
Assembly assembly = null;
string path = Path.GetFullPath(assemblyName).ToLower(CultureInfo.InvariantCulture);
if (File.Exists(path))
{
assembly = Assembly.LoadFrom(path);
}
else
{
try
{
assembly = Assembly.Load(assemblyName);
}
catch (Exception e)
{
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
{
throw;
}
Error(e, "Error: ");
}
if (assembly == null)
{
string justName = Path.GetFileNameWithoutExtension(assemblyName);
try
{
assembly = Assembly.Load(justName);
}
catch (Exception e)
{
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
{
throw;
}
Error(e, "Error: ");
}
}
}
if (assembly == null)
{
if (throwOnFail)
throw new InvalidOperationException("Cannot load assembly " + assemblyName);
return null;
}
return assembly;
}
static void Error(Exception e, string prefix)
{
Console.Error.WriteLine(prefix + e.Message);
if (e.InnerException != null)
{
Error(e.InnerException, " - ");
}
}
static void Warning(Exception e)
{
Console.Out.WriteLine(" - " + e.Message);
if (e.InnerException != null)
{
Warning(e.InnerException);
}
}
private static AppDomain DuplicateAppDomain(AppDomain template, string newName) {
AppDomain res = AppDomain.CreateDomain(newName, template.Evidence, template.SetupInformation);
return res;
}
// keys in AppDomain properties
private const string CallingAppDomainKey = "__Calling_AppDomain__";
private const string FilesToDeleteKey = "__Files_To_Delete__";
// Called from Main to set up and run the second copy of the program.
// args: command-line arguments for second execution
private static int RunSlave(string[] args) {
// Start a copy of this program in another application domain
AppDomain ad = DuplicateAppDomain(AppDomain.CurrentDomain, "serializerAD");
Assembly ca = Assembly.GetExecutingAssembly();
// set a marker so target domain knows that it is the subordinate.
ad.SetData(CallingAppDomainKey, AppDomain.CurrentDomain.FriendlyName);
ad.SetData(FilesToDeleteKey, new string[0]);
int rc = ad.ExecuteAssembly(ca.Location, ca.Evidence, args);
// Now delete any files
string[] fileList = (string[])ad.GetData(FilesToDeleteKey);
AppDomain.Unload(ad);
if (fileList != null) {
foreach(string fileName in fileList) {
try {
File.Delete(fileName);
}
catch(Exception e) {
Console.WriteLine("Warning: Unable to delete temp file: {0}, exception={1}(\"{2}\")",
Path.GetFileName(fileName), e.GetType().FullName, e.Message);
}
}
}
return rc;
}
}
}
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Caso venha a encontrar erros neste artigo e queira colaborar no processo de aperfeiçoamento desta ferramenta, por favor preencha o formulário existente na parte inferior desta página. Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 872800
(http://support.microsoft.com/kb/872800/en-us/
)
Quanto esforço foi necessário para seguir os procedimentos deste artigo?
Muito baixo
Baixo
Moderado
Alto
Muito alto
Diga-nos o porque e o que podemos fazer para melhorar esta informação
Obrigado! Seus comentários são usados para nos ajudar a aperfeiçoar o conteúdo de suporte. Para obter mais opções de ajuda, visite a Home Page de Ajuda e Suporte.