Finalmente consegui ter uma versão do Extended WebBrowser Control para colocar no CodePlex.
Ainda é um trabalho em curso, mas está usável (isto é uma palavra?). Estejam à vontade para descarregar, comentar e registra incidentes. Um tabbed web browserestá incluído como demonstração.
Depois de ter a minha aplicação .NET 1.1 a correr no ambiente de execução .NET 2.0 (^), comecei a planear migrá-la para .NET 2.0, mas faseadamente.
Porque não quero ter de manter 2 soluções (uma em Visual Studio 2003 para as assemblies .NET 1.1 e outra em Visual Studio 2008 para as assemblies .NET 2.0) decidi experimentar o MSBee e ter apenas uma solução Visual Studio 2008.
O MSBee é um projecto que esiste no CodePlex. Pode ser descarregado daí ou dos Microsoft Downloads. Porque a versão existente no Microsoft Downloads me pareceu ser a mais estável, foi a que descarreguei e instalei. O pacote contem um documento Word com as instruções de utilização.
Antes de se instalar o MSBee é necessário instalar o .NET 1.1 SDK.
Depois de tudo instalado, bastou abrir a solução Visual Studio 2003 no Visual Studio 2008 e deixá-lo convertê-la e aos projectos (quase 30).
Após a conversão, para compilar os projectos usando o compilador C# da plataforma .NET 1.1 C#, é necessário editar os ficheiros de de prjecto (.csproj) para sobrepor os targets po omissão peloas do MSBee adicionando o imports do MSBee a seguir aos da linguagem do projecto:
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\MSBee\MSBuildExtras.FX1_1.CSharp.targets" />
Outra alteração necessária (para Visual Studio 2008 - não sei se era necessária para Visual Studio 2005) é a versão das ferramentas. O MSBee necessita da versão 2.0. Para fazer esta alteração é ncessário alterar o atributo ToolsVersion no elemento raíz o ficheiro de projecto:
<Project DefaultTargets="Build" ToolsVersion="2.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
O MSBee tem a sua própria ideia acerca de onde coloca o resultado da compilação que não é a que eu tinha definido para os meus projectos. Há alguma informação acreca disto na documentação, mas decidi simplesmente comentar esta parte no ficheiro $(MSBuildExtensionsPath)\MSBee\MSBuildExtras.FX1_1.Common.targets:
<!-- Paulo
<Choose>
<When Condition=" '$(BaseFX1_1OutputPath)' == '' ">
<PropertyGroup>
<OutputPath>bin\FX1_1\</OutputPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<OutputPath>$(BaseFX1_1OutputPath)</OutputPath>
<OutputPath Condition=" !HasTrailingSlash('$(OutputPath)') ">$(OutputPath)\</OutputPath>
</PropertyGroup>
</Otherwise>
</Choose>
-->
<!-- Paulo
<PropertyGroup>
<BaseIntermediateOutputPath>obj\FX1_1\</BaseIntermediateOutputPath>
<IntermediateOutputPath Condition=" '$(PlatformName)' == 'AnyCPU' ">$(BaseIntermediateOutputPath)$(Configuration)\</IntermediateOutputPath>
<IntermediateOutputPath Condition=" '$(PlatformName)' != 'AnyCPU' ">$(BaseIntermediateOutputPath)$(PlatformName)\$(Configuration)\</IntermediateOutputPath>
<OutputPath Condition=" '$(PlatformName)' == 'AnyCPU' ">$(OutputPath)$(Configuration)\</OutputPath>
<OutputPath Condition=" '$(PlatformName)' != 'AnyCPU' ">$(OutputPath)$(PlatformName)\$(Configuration)\</OutputPath>
<- Once OutputPath is determined, set OutDir to its value. ->
<OutDir>$(OutputPath)</OutDir>
</PropertyGroup>
-->
Tudo parecia funcionar na minha elha máquina Windows XP sem qualquer plug-ins de terceiras partes para o Visual Studio, mas quando tentei na minha máquina Windows Vista X64, encontrei os seguintes problemas:
-
License Compiler
Porque estou a ausar controlso da Infragistics existe um ficheiro licences.licx que vai ser compilado. E isto costituiu um porblema.
O MSBee copia todos os ficheiros que necessita para o processo de compilação para uma pasta temporária, compila e depois copia o resultado para a localização configurada (output path).
O LC.exe parecia nunca ser capaz de encontrar as assemblies de que necessitava. Pesquisando, pareceu-me que era um problema antigo (desde os tempos da .NET 1.1) e a solução apontava para não compilar os ficheiros de licença. Por isso, comentei essa parte do ficheiro $(MSBuildExtensionsPath)\MSBee\MSBuildExtras.FX1_1.Common.targets:
<Target
Name="CompileLicxFiles" Condition="'@(_LicxFile)'!=''"
DependsOnTargets="$(CompileLicxFilesDependsOn)"
Inputs="$(MSBuildAllProjects);@(_LicxFile);@(ReferencePath);@(ReferenceDependencyPaths)"
Outputs="$(IntermediateOutputPath)$(TargetFileName).licenses">
<!--
<LC
Sources="@(_LicxFile)"
LicenseTarget="$(TargetFileName)"
OutputDirectory="$(IntermediateOutputPath)"
OutputLicense="$(IntermediateOutputPath)$(TargetFileName).licenses"
ReferencedAssemblies="@(ReferencePath);@(ReferenceDependencyPaths)"
ToolPath="$(TargetFrameworkSDKDirectory)bin\">
<Output TaskParameter="OutputLicense" ItemName="CompiledLicenseFile"/>
<Output TaskParameter="OutputLicense" ItemName="FileWrites"/>
</LC>
-->
</Target>
-
Resource Generator
Apesar de tudo fucionar bem em linha de comando, dentro do Visual Studio ocorria um erro na execução do ResGen.exe.
Consulanado o Windows Application Log descobri isto:
Faulting application Resgen.exe, version 1.1.4322.573, time stamp 0x3e559b5f, faulting module MockWeaver.dll, version 0.0.0.0, time stamp 0x4adb072e, exception code 0xc0000005, fault offset 0x00018fac, process id 0x4a50, application start time 0x01ca53c14488a2fb.
MockWeaver.dll pertence ao Isolator e basta-me inibi-lo quando compilo dentro do Visual Studio. Esperava começar a usar o Isolator neste projecto, mas, por enquanto, não vai ser possível.
Espero que isto possa ajudar alguém. Se precisarem de mais ajuda, provavelmente encontrá-la-ão nos foruns do MSBee no CodePlex.
O que interessa é: Não precisam do Visual Studio 2003!
Uma das aplicações que desenvolvo é uma aplicação Windows Forms .NET 1.1 usada por cerca de 5000 utilizadores e crítica para o negócio.
Sendo uma aplicação complexa e crítica, migrá-la para o ambiente de execução 2.0 apenas porque sim não seria uma opção porque significaria instalar um novo ambiente de execução e plataforma no ambiente estável dos postos de trabalho (Windows XP) e testar todas as aplicações.
Com o passar dos tempos, um elemento da equipa recebeu um novo posto de trabalho com o Windows Vista. Uma vez que apenas necessitava de .NET 2.0 para os seus desenvolvimentos, nunca instalou a .NET 1.1.
Um outro membro da equipa já tinha tentado migrar a aplicação para .NET 2.0 e deparou-se com os seguintes problemas:
-
O principal componente da aplicação é o
Web Browser Control. Este controlo extende o
AxHost, que, na transição da 1.1 para a 2.0 sofreu alterações e necessitava de profundas alterações para que pudesse ser compilado para a plataform 2.0.
-
Misturar chamadas síncronas e assíncronas não é permitido na plataforma 2.0 e a aplicação tinha, pelo menos, um caso desses na utilização de
HttpWebRequest/
HttpWebResponse.
A .NET 2.0 foi desenvolvida para ter o máximo de retro compatibilidade com a .NET 1.1 por forma a poder correr com o mínimo e impactos (nenhum, na maioria dos casos) aplicações desenvolvidas para a .NET 1.1. De facto, algumas das alterações passaram apenas por aplicar o atributo ObsoleteAttribute de modo a que o compilador dê erro, impedindo a compilação de novo código mas não impedindo a utilização por parte de código previamente compilado. Era este o caso do WebBrowserControl/AxHost e usar a assembly compilada para .NET 1.1, provavelmente, seria suficiente. E foi.
A questão do síncrono/assíncrono também foi fácil de resolver. Apenas requereu alterar isto:
request.GetRequestStream()
para isto:
request.EndGetRequestStream(response.BeginGetRequestStream(null, null))
E tudo funcionou como se estivesse a correr em .NET 1.1.
Mas ainda não é o fim da história. Mais tarde veio um requisito para que uma das páginas web que correm no controlo web browser usassem um componente ActiveX desenvolvido em .NET 2.0.
Por esta altura já os postos de trabalho tinham a plataforma 2.0 instalada.
Mas, como forçar a aplicação a correr no ambiente de execução 2.0 em vez de 1.1 dado que ambos estavam instalados nos postos de trabalho?
Tão simples como adicionar isto ao ficheiro de configuração (App.config):
<configuration>
<startup>
<requiredRuntime version="v2.0.50727" safemode="true"/>
</startup>
</configuration>
O LINQ trouxe-nos uma forma muito amigável de escrever consultas de forma independente do domínio das mesmas.
O facto de que o modo como as consultas são escritas é independente do domínio não quer dizer que todas vão ser compiladas e executadas do mesmo modo. É sempre necessário saber como o provedor se vai comportar.
O LINQ Para Objectos, por exemplo, vai compilar as consultas para chamadas a funções do tipo Func<> que retornam implementações de IEnumerable(T).
Por outro lado, o LINQ Para SQL vai compilar as consultas para uma árvore de expressões do tipo Expression<Func<>> e a sua execução retornará implementações de <IQueryable(T).
Porque as consultas LINQ Para SQL são compiladas para uma árvore de expressões, é possível que o provedor trate os elementos da árvore como bem entender.
Neste caso, isto quer dizer que todas as operações que poderem ser executadas na base de dados serão executadas na base de dados e o programador(a) tem de ter noção disto quando escrever as consultas.
Consideremos um exemplo usando a base de dados AdventureWorks (se não tiverem, podem descarregar daqui).
Eu quero construír uma lista de saudações para todos os empregados que tenham a marcaSalariedFlag, na forma:
[Mr.|Mrs.|Miss] <first name> <middle name> <last name>
Mas há um pequeno detalhe na base de dados: FirstName, MiddleName e LastName podem ter espaços no fim e eu não os quero.
É algo tão simples como isto:
var q1 = from e in context.Employees
where e.SalariedFlag
select
((e.Gender == 'F') ? ((e.MaritalStatus == 'S') ? "Miss" : "Mrs.") : "Mr.") + " " +
e.Person.FirstName.Trim() +
(e.Person.MiddleName == null || e.Person.MiddleName.Trim().Length == 0 ? " " : " " + e.Person.MiddleName.Trim() + " ") +
e.Person.LastName.Trim();
que será executado na base de dados como:
SELECT ((((
(CASE
WHEN UNICODE([t0].[Gender]) = @p0 THEN
(CASE
WHEN UNICODE([t0].[MaritalStatus]) = @p1 THEN @p2
ELSE @p3
END)
ELSE CONVERT(NVarChar(4),@p4)
END)) + @p5) + LTRIM(RTRIM([t1].[FirstName]))) + (
(CASE
WHEN ([t1].[MiddleName] IS NULL) OR (LEN(LTRIM(RTRIM([t1].[MiddleName]))) = @p6) THEN CONVERT(NVarChar(MAX),@p7)
ELSE (@p8 + LTRIM(RTRIM([t1].[MiddleName]))) + @p9
END))) + LTRIM(RTRIM([t1].[LastName])) AS [value]
FROM [HumanResources].[Employee] AS [t0]
INNER JOIN [Person].[Person] AS [t1] ON [t1].[BusinessEntityID] = [t0].[BusinessEntityID]
WHERE [t0].[SalariedFlag] = 1
-- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [70]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [83]
-- @p2: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [Miss]
-- @p3: Input NVarChar (Size = 4; Prec = 0; Scale = 0) [Mrs.]
-- @p4: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [Mr.]
-- @p5: Input NVarChar (Size = 1; Prec = 0; Scale = 0) [ ]
-- @p6: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
-- @p7: Input NVarChar (Size = 1; Prec = 0; Scale = 0) [ ]
-- @p8: Input NVarChar (Size = 1; Prec = 0; Scale = 0) [ ]
-- @p9: Input NVarChar (Size = 1; Prec = 0; Scale = 0) [ ]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
Como podem ver, há um elevado número de operações sobre texto a serem feitas, na base de dados, por cada linha retornada.
Dependendo do número de linhas ou da carga na base de dados isto pode ser muito mau. Pode inclusive resultar num timeout.
Sendo assim, como é que forçamos as operações de texto a ocorrer no cliente em vez da base de dados?
Apenas os IQueryable<T> serão traduzidos para T-SQL. Por isso, tudo o que é necessário fazer é mudar o tipo de enumerador a iterar.
Uma forma de o fazer é usar o método AsEnumerable da classe Enumerable.
A nova consulta será escrita assim:
var q2 = from e in context.Employees.Where(e => e.SalariedFlag).AsEnumerable()
select
((e.Gender == 'F') ? ((e.MaritalStatus == 'S') ? "Miss" : "Mrs.") : "Mr.") + " " + e.Person.FirstName.Trim() +
(e.Person.MiddleName == null || e.Person.MiddleName.Trim().Length == 0 ? " " : " " + e.Person.MiddleName.Trim() + " ") +
e.Person.LastName.Trim();
e executada na base de dados como:
SELECT
[t0].[BusinessEntityID],
[t0].[LoginID],
[t0].[NationalIDNumber],
[t0].[JobTitle],
[t0].[MaritalStatus],
[t0].[BirthDate],
[t0].[Gender],
[t0].[HireDate],
[t0].[SalariedFlag],
[t0].[VacationHours],
[t0].[SickLeaveHours],
[t0].[CurrentFlag],
[t0].[rowguid],
[t0].[ModifiedDate],
[t1].[BusinessEntityID] AS [BusinessEntityID2],
[t1].[PersonType],
[t1].[NameStyle],
[t1].[Title],
[t1].[FirstName],
[t1].[MiddleName],
[t1].[LastName],
[t1].[Suffix],
[t1].[EmailPromotion],
[t1].[AdditionalContactInfo],
[t1].[Demographics],
[t1].[rowguid] AS [rowguid2],
[t1].[ModifiedDate] AS [ModifiedDate2]
FROM [HumanResources].[Employee] AS [t0]
INNER JOIN [Person].[Person] AS [t1] ON [t1].[BusinessEntityID] = [t0].[BusinessEntityID]
WHERE [t0].[SalariedFlag] = 1
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
Como podem notar, as operações de texto já não são executadas na base de dados mas, em contrapartida, todas as colunas de ambas as tabelas estão a ser retornadas. E isto continua a ser mau porque está a ser consumida largura de banda desnecessáriamente.
A forma de escolher as columas que serão retornadas na consulta é seleccionar apenas as colunas pretendidas. Mas porque continuamos a querer que as operações sobre texto sejam executadas no cliente, temos de projectar essas colunas num objecto intremédio. Prque não necessitamos desse objecto fora da consulta, usaremos um tipo anónimo.
A consulta será agora escrita assim:
var q3 = from n in
(
from e in context.Employees
where e.SalariedFlag
select new
{
Gender = e.Gender,
MaritalStatus = e.MaritalStatus,
FirstName = e.Person.FirstName,
MiddleName = e.Person.MiddleName,
LastName = e.Person.LastName
}
).AsEnumerable()
select ((n.Gender == 'F') ? ((n.MaritalStatus == 'S') ? "Miss" : "Mrs.") : "Mr.") + " " + n.FirstName.Trim()
+ (n.MiddleName == null || n.MiddleName.Trim().Length == 0 ? " " : " " + n.MiddleName.Trim() + " ")
+ n.LastName.Trim();
e executada na base de dados como:
SELECT
[t0].[Gender],
[t0].[MaritalStatus],
[t1].[FirstName],
[t1].[MiddleName],
[t1].[LastName]
FROM [HumanResources].[Employee] AS [t0]
INNER JOIN [Person].[Person] AS [t1] ON [t1].[BusinessEntityID] = [t0].[BusinessEntityID]
WHERE [t0].[SalariedFlag] = 1
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
Note-se que a chamada a Enumerable.AsEnumerable para traduzir de LINQ Para SQL para LINQ Para Objectos.
E, para terminar, Se não se usarem operações de texto na consulta, estas não serão, obviamente, traduzidas para T-SQL:
var q4 = from e in context.Employees
where e.SalariedFlag
select BuildSalutation(e.Gender, e.MaritalStatus, e.Person.FirstName, e.Person.MiddleName, e.Person.LastName);
em que BuildSalutation é implementado como:
private static object BuildSalutation(char gender, char maritalStatus, string firstName, string middleName, string lastName)
{
return ((gender == 'F') ? ((maritalStatus == 'S') ? "Miss" : "Mrs.") : "Mr.") + " "
+ firstName.Trim()
+ (middleName == null || middleName.Trim().Length == 0 ? " " : " " + middleName.Trim() + " ")
+ lastName.Trim();
}
e executado na base de dados como:
SELECT
[t0].[Gender] AS [gender],
[t0].[MaritalStatus] AS [maritalStatus],
[t1].[FirstName] AS [firstName],
[t1].[MiddleName] AS [middleName],
[t1].[LastName] AS [lastName]
FROM [HumanResources].[Employee] AS [t0]
INNER JOIN [Person].[Person] AS [t1] ON [t1].[BusinessEntityID] = [t0].[BusinessEntityID]
WHERE [t0].[SalariedFlag] = 1
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
É de notar que a consulta T-SQL gerada é praticamente a mesma que no caso anterior.
Se ainda está a ler. espero que tenha ficado com a noção de que, a forma como escrever as consultas LINQ Para SQL afecta o T-SQL gerado.
Hoje, dia 23 de Setembro, quarta-feira, pelas 20h00 no auditório da Microsoft irá ser feito o PréRemix.
Consistirá na apresentação das mesmas duas sessões focadas na Cloud que serão apresentadas no Remix.
Cloud computing: A plataforma Azure
Luis Martins e Pedro Félix
Saiba como construir aplicações na cloud ou usar serviços interoperaveis sobre a infraestrutura Microsoft. Venha aprender como poderá tirar partido desta plataforma para solucionar os desafios de desenvolvimento de software. Nesta sessão poderá ainda ouvir os conceitos essenciais do Windows Azure, o que há de novo e como se posiciona face à concorrência.
Armazenamento na cloud
José António Silva
A escalabilidade do storage implica tipicamente um conjunto de decisões de arquitectura, de forma a manter afastadas as limitações impostas pelos sistemas de gestão de base de dados relacionais. Estas decisões não são mais opcionais neste entusiasmante mundo dos cloud services.
A boa notícia diz-nos que, assim que começamos a desenvolver para os novos storage engines, o mais provável é que fiquemos viciados nestes modelos mais flexíveis.
Junte-se a nós nesta sessão e fique a conhecer as tables, queues, key-values e outros patterns que nos ajudam a criar camadas de dados persistentes escaláveis e distribuídas para a cloud.


Pelo valioso contributo que têm trazido à discussão e partilha de boas práticas sobre a utilização da plataforma .NET, a Microsoft Portugal está a oferecer, aos membros da comunidade pontoNETpt, vouchers com 20% de desconto sobre o preço do registo no REMIX.
Quem estiver interessado em fazer uso deste benefício deverá enviar um e-mail para cristina.carvalho at microsoft.com com pedido de voucher-desconto. O e-mail deverá ter como assunto pontoNETpt no ReMIX e incluír no seu corpo o endereço do seu perfil na comunidade (http://pontonetpt.com/members/<membro>/).
Actualização: Para quem já fez o pagamento, e não podendo fazer retorno do investimento, a Microsoft tem o maior gosto em oferecer um voucher com 50% de desconto para oferecer a quem considere ter interesse nos conteúdos deste evento.
Há algum tempo necessitei que fosse alterada a validationKey do elemento machineKey de uma aplicação ASP.NET e descobri que a plataforma não disponibiliza nenhuma ferramenta para isto.
Encontrei algumas ferramentas e exemplos de código para o fazer, mas para que fosse um administrador de sistemas a fazer esta tarefa, teria de desenvolver uma aplicação de consola (testar e documentar) e trabalho a mais para a tarefa em questão.
Sempre apoiei a ideia do PowerShell mas nunca tinha realmente usado. Apenas porque quase sempre tenho o Visual Studio e fazer uma simples aplicação de consola é mais rápido que aprender PowerShell.
Desta vez decidi que utilizaria PowerShell.
Em C# eu faria algo deste género:
class Program
{
private static string GenerateKey()
{
var buff = new byte[64];
(new System.Security.Cryptography.RNGCryptoServiceProvider()).GetBytes(buff);
var sb = new System.Text.StringBuilder();
foreach (var b in buff)
{
sb.AppendFormat("{0:X2}", b);
}
return sb.ToString();
}
private static void Main(string[] args)
{
var path = args[0];
var config = System.Web.Configuration.WebConfigurationManager.OpenMachineConfiguration(path);
var systemWeb = config.GetSectionGroup("system.web") as System.Web.Configuration.SystemWebSectionGroup;
var machineKey = systemWeb.MachineKey;
machineKey.ValidationKey = GenerateKey();
config.Save(System.Configuration.ConfigurationSaveMode.Modified);
}
}
Como seria em PowerShell? Tão simples como:
function GenerateKey
{
[System.Byte[]]$buff = 0..63
(new-object System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($buff)
$sb = new-object System.Text.StringBuilder(128)
for($i = 0; ($i -lt $buff.Length); $i++)
{
$sb = $sb.AppendFormat("{0:X2}", $buff[$i])
}
return $sb.ToString()
}
[System.Reflection.Assembly]::LoadWithPartialName("System.Web")
$config = [System.Web.Configuration.WebConfigurationManager]::OpenWebConfiguration("<path>")
$systemWeb = $config.GetSectionGroup("system.web");
$machineKey = $systemWeb.MachineKey
$machineKey.ValidationKey=GenerateKey
$config.save("Modified")
Querem saber como passei de não saber PowerShell para este código? Simples. Algo que o verdadeiro programador .NET deve ter sempre à mão: o .NET Reflector (com um PowerShell add-in, claro).
Reactivámos o blogue do pontoNETpt para dar notícias sobre desta comunidade aos seus membros. Subscrevam este blogue para saberem as últimas notícias sobre comunidade.
O meu filho herda as minhas máquinas antigas.
A sua máquina actual é uma máquina que começou com Windows Vista x86 Ultimate RTM, depois SP1 e finalmente SP2. Pelo caminho, conheceu várias versões de Microsoft Office, .NET, Visual Studio, SQL Server e muito mais.
Eu costumo ter dezenas de aplicações instaladas. Recuperar licenças e voltar a instalá-las é tão trabalhoso que eu, sempre que posso, actualizo as máquinas em vez de as instalar.
Agora que saíu o Windows 7 e a beta do Office 2010, o meu filho queria actualizar a sua máquina.
Porque a máquina já tinha passado por tantas actualizações e ele não gostava da forma como eu tinha orgnaizado as partições do disco, recomendei-lhe que formatasse o disco e fizesse uma instalação de raíz.
Um dos incómodos de fazer uma instalação de raíz é perder todas as definições tais como definições e favoritos do Internet Explorer e contas e PSTs do Microsoft Outlook (especialmente se se tiver contas IMAP).
Como já tinha usado com sucesso o Windows Easy Transfer para migrar o portátil do trabalho de Windows XP (x86) para Windows Vista x64 Enterprise, disse-lhe para não se preocupar.
O Windows Easy Transfer guia-nos pelo processo de transferir ficheiros e definições de uma instalação do Windows para outra.
With Windows Easy Transfer you can transfer:
-
Ficheiros e pastas.
Tudo o que se encontre nas pastas Documentos, Imagens e Documentos Partilhados. Utilizando opções avançadas, poderá seleccionar ficheiros e pastas adicionais para transferência.
-
Definições, contactos e mensagens de correio electrónico.
Mensagens, definições de conta e livros de endereços do Microsoft Outlook Express, Outlook, Correio do Windows e outros programas de correio electrónico.
-
Definições de programas.
Definições que mantêm os seus programas configurados tal como os tinha na instalação anterior. Em primeiro lugar, deve instalar os programas no computador novo, porque o Windows Easy Transfer não transfere os próprios programas. Alguns programas podem não funcionar com esta versão do Windows, incluindo programas de segurança, programas antivírus, programas de firewall (o seu computador novo já deve ter uma firewall a funcionar para ajudar a garantir a segurança durante a transferência) e programas com controladores de software.
-
Contas de utilizador e definições.
Esquemas de cores, fundos do ambiente de trabalho, ligações de rede, protecções de ecrã, tipos de letra, opções do menu Iniciar, opções da barra de ferramentas, pastas, ficheiros específicos, impressoras e unidades de rede e opções de acessibilidade.
-
Definições da Internet e favoritos.
Definições de ligação à Internet, favoritos e cookies.
-
Música.
Ficheiros de música, listas de reprodução e imagens do álbum.
-
Imagens e vídeo.
Imagens—incluindo qualquer tipo de ficheiro visual (por exemplo, .jpg, .bmp, .gif)—e vídeos pessoais.
Depois de gravar tudo para o ficheiro .MIG, foi necessário apenas instalar o Windows 7 e o Office 2010 e importar as definições de volta.
Para obter os outros ficheiros e pastas que existiam no disco, porque temos um Windows Home Server que faz cópias de segurança de todos os PCs da casa, foi necessário apenas montar uma cópia de segurança como disco e copiar os ficheiros desejados.
É tão fácil que ele o fez sozinho, e acabou e fazer 14 anos. Portanto, se alguém recisar de fazer isto, mantenha a calma. É mesmo fácil.
A Comunidade NetPonto vai levar a cabo a sua 2ª reunião presencial no próximo sábado dia 19 de Setembro.
Se se interessam por eXtreme Programming e ASP.NET MVC e não se importam de perder uma “madrugada” de sábado, inscrevam-se.
Pela primeira vez, o ReMIX vem a Portugal.
O evento terá. além da sessão de abertura, 12 sessões distribuídas por 3 percursos (Web Developer, UX and Architect) e apresentadas pelos melhores oradores sobre cada assunto.
Não percam! Registem-se!
Hoje deparei-me com este problema ao tentar entrar no Windows Live Messenger.
No entanto, todas as pessoas com que falei conseguiam entrar, por isso tentei entrar com outra conta e também consegui.
Binguei à procura de solução e encontrei várias referências a uma entrada no blogue do Messenger Support com a solução para este problema. No meu caso (Windows 7 x64) a solução passava por remover a pasta %LOCALAPPDATA%\Microsoft\Windows Live Contacts (geralmente C:\Users\<Windows Logon name>\AppData\Local\Microsoft\Windows Live Contacts).
Em vez de remover a pasta, optei por lhe mudar o nome para evitar remover os contactos de todas as minhas contas (com que até conseguia entrar). Quando o tentei, recebi um erro porque a pasta em questão estava em uso por outra aplicação.
Como tinha o Windows Live Mail aberto e assumi que usasse o mesmo repositório de contactos, fechei-o e passei a conseguir entrar no Windows Live Messenger com a conta com que antes não conseguia.
Como arquitecto e programador, perturba-me um pouco que este tipo de erros seja apresentado deste modo ao utilizador. A mensagem sugeria um problema ao entrar no servidor e, afinal, era um problema com uma única conta de um único utilizador Windows em uma única máquina.
Portanto, programadores e arquitectos (eu incluído), deem sempre ao utilizador(a) mensagens com significado para o problema que está a ter. Adicionar informação técnica a pedido expresso do utilizador(a) é sempre uma boa opção (essa parte, o Windows Live Messenger faz bem).
Ao fim de sete vezes, ainda sinto que é uma honra pertencer a tão ilustre grupo.
E é com grande satisfação que escrevo esta entrada no novo sítio do PontoNetPT.
Pois é, ao fim de muitos testes e tentativas, conseguimos migrar os blogues do PontoNetPT da antiga plataforma para uma plataforma Community Server (gentilmente oferecida pela Telligent).
Está aberto o Registo para o Microsoft Tech•Ed Europe 2009.
Há algumas novidades este ano:
-
Devio aos pedidos dos participantes ambos eventos (Developer e IT Pro) coexistirão (9-13 Novembro).
-
-
Os preços de registo são baseados numa aproximação por camadas de modo que quanto mais cedo for efectuado o registo, mais barato fica.
Rasões Para Ir Ao Tech·Ed Europe 2009
-
Todos podem aprender sobre:
-
MICROSOFT WINDOWS 7 – O sistema operativo da Microsoft para a próxima geração
O Windows 7 trás importantes avanços para a produtividade dos utilizadores, segurança e gestão.
-
MICROSOFT OFFICE e novas formas de maximizar a produtividade do negócio
O percurso do Office System pode ajudar a instalação, adopção e desenvolvimento de aplicações de produtividade para o negócio.DEVELOPERS CAN LEARN MORE ABOUT:
-
Programadores e Arquitectos podem aprender sobre:
-
Aplicações na cloud
Descubram como a Azure™ Services Platform reduz a necessidade de aquisição anticipada de tecnhologia, e permite aos programadores e arquitectos criar, com rapidez e facilidade, aplicações que correm na cloud.
-
Segurança que ajuda a cortar custos no suporte às aplicações
Descubram como a tecnologia Microsoft’s ForeFront pode tornar os ambientes IT seguros com maior rapidez e a escrever código mais seguro e elimiar custos de suporte a aplicações.
-
TRUTH about maximizing deployments and search
Descubram como o SharePoint pode ajudar a criar um repositório central, maximizando as instalações e pesquisa e eliminando multiplas versões e mal-entendidos acerca da origem da “verdade” em qualquer project.
-
Profissionais de IT podem aprender sobre:
-
Virtualização que ajuda a podenciar investimentos existentes
Obtenham um entendimento profundo das actuais tecnologias de virtualização de baixo custo e como podem ajudar a tirar o maior partido dos investimentos existentes em software e hardware.
-
Hospedagem para economias de escala
Descubram como tirar partido dos hosted services Microsoft para ampliar a oferta de comunicações e colaboração dos departamenteos de IT. E baixar os custos de hardware, gestão e consumo de energia.
-
Unificação para redução de custos e aumento de eficácia
Comunicações verdadeiramente unificadas que formam uma infra-estrutura única de comunicações.
-
Maximizar a infrastrutura IT existente para se fazer mais om o que se tem
Descubram como tirar o máximo partido da infra-estrutura de IT existente.
DCom tudo desenvolvido e testado em no meu portátil usando oSQL Server 2008, era o momento de instalar na máquina de testes com SQL Server 2005.
O primeiro problema que encontrei quando executei:
CREATE ASSEMBLY [MyAssembly]
AUTHORIZATION [dbo]
FROM '...\MyAssembly.dll'
WITH PERMISSION_SET = SAFE
GO
foi:
Msg 10327, Level 14, State 1, Line 1
Assembly 'MyAssembly' references assembly 'system.xml.linq, version=3.5.0.0, culture=neutral, publickeytoken=b77a5c561934e089.',
which is not present in the current database.
SQL Server attempted to locate and automatically load the referenced assembly from the same location where referring assembly came from,
but that operation has failed (reason: 2(The system cannot find the file specified.)).
Please load the referenced assembly into the current database and retry your request.
Parece que o SQL Server 2005 não conhece a .NET Framework 3.5. Tinha de carregar as assemblies usadas: System.Core e System.Linq.Xml:
CREATE ASSEMBLY [System.Core]
AUTHORIZATION [dbo]
FROM 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll'
WITH PERMISSION_SET = SAFE
GO
Mas não é assim tão simples:
Warning: The Microsoft .Net frameworks assembly 'system.core, version=3.5.0.0, culture=neutral, publickeytoken=b77a5c561934e089, processorarchitecture=msil.' you are registering is not fully tested in SQL Server hosted environment.
Msg 6218, Level 16, State 2, Line 1
CREATE ASSEMBLY for assembly 'System.Core' failed because assembly 'System.Core' failed verification. Check if the referenced assemblies are up-to-date and trusted (for external_access or unsafe) to execute in the database. CLR Verifier error messages if any will follow this message
[ : System.Diagnostics.Eventing.EventProvider::EtwRegister][mdToken=0x600003b][offset 0x0000003D][found Native Int][expected unmanaged pointer] Unexpected type on the stack.
[ : System.Diagnostics.Eventing.EventProvider::EncodeObject][mdToken=0x6000046][offset 0x00000000] Unmanaged pointers are not a verifiable type.
[ : System.Diagnostics.Eventing.EventProvider::WriteMessageEvent][mdToken=0x6000047][offset 0x0000003C][found ref 'System.String'] Expected numeric type on the stack.
[ : System.Diagnostics.Eventing.EventProvider::WriteEvent][mdToken=0x6000049][offset 0x0000012E] Instruction cannot be verified.
[ : System.Diagnostics.Eventing.EventProvider::WriteEvent][mdToken=0x6000049][offset 0x00000030] Instruction cannot be verified.
[ : System.Diagnostics.Eventing.EventProvider::WriteEvent][mdToken=0x600004a][offset 0x0000005F][found ref 'System.String'] Expected numeric type on the stack.
[ : System.Diagnostics.Eventing.EventProvider::WriteEvent][mdToken=0x600004b][offset 0x00000010][found unmanaged pointer][expected unmanaged pointer] Unexpected type on the stack.
[ : System.Diagnostics.Eventing.EventProvider::WriteTransferEvent][mdToken=0x600004c][offset 0x0000007D] Instruction cannot be verified.
[ : System.Diagnostics.Eventing.EventProvider::WriteTransferEvent][mdToken=0x600004c][offset 0x00000309][found Native Int][expected unmanaged pointer] Unexpected type on the stack.
[ : System.Diagnostics.Eventing.EventProvider::WriteTransferEvent][mdToken=0x600004d][offset 0x0000001B][found unmanaged pointer][expected unmanaged pointer] Unexpected type on the stack.
[ : System.Security.Cryptography.CapiNative::ImportSymmetricKey][mdToken=0x60007c2][offset 0x00000071][found address of Byte] Expected numeric type on the stac...
Bem, carrega-se com PERMISSION_SET = UNSAFE:
CREATE ASSEMBLY [MyAssembly]
AUTHORIZATION [dbo]
FROM '...\MyAssembly.dll'
WITH PERMISSION_SET = UNSAFE
GO
Ainda não:
Warning: The Microsoft .Net frameworks assembly 'system.core, version=3.5.0.0, culture=neutral, publickeytoken=b77a5c561934e089, processorarchitecture=msil.' you are registering is not fully tested in SQL Server hosted environment.
Msg 10327, Level 14, State 1, Line 1
CREATE ASSEMBLY for assembly 'System.Core' failed because assembly 'System.Core' is not authorized for PERMISSION_SET = UNSAFE.
The assembly is authorized when either of the following is true: the database owner (DBO) has UNSAFE ASSEMBLY permission and the database has the TRUSTWORTHY database property on; or the assembly is signed with a certificate or an asymmetric key that has a corresponding login with UNSAFE ASSEMBLY permission.
If you have restored or attached this database, make sure the database owner is mapped to the correct login on this server.
If not, use sp_changedbowner to fix the problem.
Mas fácil de resolver:
ALTER DATABASE MyDatabase SET TRUSTWORTHY ON
GO
I finalmente foi possível carregar as assemblies .NET 3.5:
CREATE ASSEMBLY [System.Core]
AUTHORIZATION [dbo]
FROM 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll'
WITH PERMISSION_SET = UNSAFE
GO
CREATE ASSEMBLY [System.Xml.Linq]
AUTHORIZATION [dbo]
FROM 'C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll'
WITH PERMISSION_SET = UNSAFE
GO
Tendo todas as depêndencias carregadas, tentei carregar a minha assembly com PERMISSION_SET = SAFE sem sucesso:
Msg 6212, Level 16, State 1, Line 1
CREATE ASSEMBLY failed because method 'ShortPropsToXml' on type 'ShortProps' in safe assembly 'Esi.SA.Encyclopedia' is storing to a static field.
Storing to a static field is not allowed in safe assemblies.
Teve de ser com PERMISSION_SET = UNSAFE.
Depois de ter carregado as assemblies com sucesso, pude finalmente criar as definições Transact-SQL das funções (vêr Parte I e Part II).
Agora é que os DBAs não vão mesmo deixar-me usar isto. Mas foi divertido fazê-lo.