Atualizando projetos
As alterações no modelo de projeto de uma versão do Visual Studio para a próxima podem exigir que projetos e soluções sejam atualizados para que eles possam ser executados na versão mais recente. O SDK do Visual Studio oferece interfaces que podem ser usadas para implementar o suporte de atualização em seus próprios projetos.
Estratégias de atualização
Para oferecer suporte a uma atualização, a implementação de sistema do projeto deve definir e implementar uma estratégia de atualização. Ao determinar sua estratégia, você pode optar por oferecer suporte a backup lado a lado (SxS), backup de cópia ou ambos.
Backup SxS significa que um projeto cópia apenas os arquivos que precisam de atualização no local, adicionando um sufixo de nome de arquivo adequado, por exemplo, ".old".
Backup de cópia significa que um projeto copia todos os itens de projeto para um local de backup fornecido pelo usuário. Os arquivos relevantes no local original do projeto são então atualizados.
Como funciona a atualização
Quando uma solução criada em uma versão anterior do Visual Studio é aberta em uma versão mais recente, o IDE verifica o arquivo de solução para determinar se ele precisa ser atualizado. Se a atualização for necessária, o Assistente de Atualização será iniciado automaticamente para orientar o usuário durante o processo de atualização.
Quando uma solução precisa de atualização, ela consulta cada fábrica de projeto para obter sua estratégia de atualização. A estratégia determina se a fábrica do projeto oferece suporte a backup de cópia ou backup SxS. As informações são enviadas para o Assistente de Atualização, que coleta as informações necessárias para o backup e apresenta as opções aplicáveis ao usuário.
Soluções multiprojetos
Se uma solução contém vários projetos e as estratégias de atualização forem diferentes, como quando um projeto C++ que oferece suporte apenas ao backup SxS e um projeto da Web que oferece suporte apenas ao backup de cópia, as fábricas de projeto devem negociar a estratégia de atualização.
A solução consulta cada fábrica de projeto em IVsProjectUpgradeViaFactory. Em seguida, ela chama UpgradeProject_CheckOnly para ver se os arquivos de projeto globais precisam de atualização e para determinar as estratégias de atualização aceitas. O Assistente de Atualização é então chamado.
Depois que o usuário concluir o assistente, UpgradeProject será chamado em cada fábrica de projeto para executar a atualização real. Para facilitar o backup, os métodos IVsProjectUpgradeViaFactory fornecem o serviço SVsUpgradeLogger para registrar em log os detalhes do processo de atualização. Esse serviço não pode ser armazenado em cache.
Depois de atualizar todos os arquivos globais relevantes, cada fábrica de projeto pode optar por instanciar um projeto. A implementação do projeto deve ter suporte para o IVsProjectUpgrade. O método UpgradeProject é então chamado para atualizar todos os itens de projeto relevantes.
Observação
O método UpgradeProject não oferece o serviço SVsUpgradeLogger. Esse serviço pode ser obtido chamando QueryService.
Práticas Recomendadas
Use o serviço SVsQueryEditQuerySave para verificar se você pode editar um arquivo, antes de editá-lo, e se pode salvar um arquivo, antes de salvá-lo. Isso ajudará suas implementações de backup e atualização a lidar com arquivos de projeto sob controle do código-fonte, arquivos com permissões insuficientes e assim por diante.
Use o serviço SVsUpgradeLogger durante todas as fases de backup e atualização para fornecer informações sobre o sucesso ou a falha do processo de atualização.
Para obter mais informações sobre como fazer backup e atualizar projetos, consulte os comentários de IVsProjectUpgrade em vsshell2.idl.
Atualizando projetos personalizados
Se você alterar as informações persistentes no arquivo de projeto entre diferentes versões do Visual Studio do seu produto, então terá que dar suporte à atualização do arquivo de projeto da versão antiga para a nova. Para oferecer suporte à atualização e permitir que você participe do Assistente de conversão do Visual Studio, implemente a interface IVsProjectUpgradeViaFactory. Essa interface contém o único mecanismo disponível para atualização de cópia. A atualização do projeto acontece quando parte da solução é aberta. A interface IVsProjectUpgradeViaFactory é implementada pela fábrica do projeto, ou pelo menos deve ser obtida da fábrica do projeto.
O mecanismo antigo que usa a interface IVsProjectUpgrade ainda é suportado, mas conceitualmente atualiza o sistema de projeto como parte da abertura do projeto. A interface IVsProjectUpgrade é, portanto, chamada pelo ambiente do Visual Studio mesmo se a interface IVsProjectUpgradeViaFactory for chamada ou implementada. Essa abordagem permite que você use IVsProjectUpgradeViaFactory para implementar a cópia e projetar apenas partes da atualização e delegue o restante do trabalho a ser feito no local (possivelmente no novo local) pela interface IVsProjectUpgrade.
Para obter um exemplo de implementação de IVsProjectUpgrade, consulte Exemplos de VSSDK.
Os seguintes cenários aparecem com as atualizações do projeto:
Se o arquivo for de um formato mais recente do que o projeto pode suportar, ele deve retornar um erro informando isso. Isso pressupõe que a versão mais antiga do produto inclua código para verificar a versão.
Se o sinalizador PUVFF_SXSBACKUP for especificado no método UpgradeProject, a atualização será implementada como uma atualização in-loco antes da abertura do projeto.
Se o sinalizador PUVFF_COPYBACKUP for especificado no método UpgradeProject, a atualização será implementada como uma atualização de cópia.
Se o sinalizador UPF_SILENTMIGRATE for especificado na chamada UpgradeProject, o usuário foi solicitado pelo ambiente a atualizar o arquivo de projeto como uma atualização in-loco, depois que o projeto for aberto. Por exemplo, o ambiente solicita que o usuário atualize quando ele abre uma versão mais antiga da solução.
Se o sinalizador UPF_SILENTMIGRATE não for especificado na chamada UpgradeProject, você deverá solicitar que o usuário atualize o arquivo de projeto.
Este é um exemplo de uma mensagem de solicitação de atualização:
"O projeto '%1' foi criado com uma versão mais antiga do Visual Studio. Se você o abrir com essa versão do Visual Studio, talvez não seja possível abri-lo com versões mais antigas do Visual Studio. Deseja continuar e abrir esse projeto?"
Para implementar IVsProjectUpgradeViaFactory
Implemente o método da interface IVsProjectUpgradeViaFactory, especificamente o método UpgradeProject na implementação da fábrica do projeto, ou torne as implementações chamáveis pela implementação da fábrica do projeto.
Se você quiser fazer uma atualização in-loco como parte da abertura da solução, forneça o sinalizador PUVFF_SXSBACKUP como parâmetro
VSPUVF_FLAGS
em sua implementação UpgradeProject.Se você quiser fazer uma atualização in-loco como parte da abertura da solução, forneça o sinalizador PUVFF_COPYBACKUP como parâmetro
VSPUVF_FLAGS
em sua implementação UpgradeProject.Para as etapas 2 e 3, as etapas reais de atualização de arquivo, usando IVsQueryEditQuerySave2, podem ser implementadas conforme descrito na seção "Implementação de
IVsProjectUpgade
", a seguir, ou você pode delegar a atualização de arquivo real para IVsProjectUpgrade.Use os métodos de IVsUpgradeLogger para postar mensagens relacionadas à atualização para o usuário usando o Assistente de migração do Visual Studio.
A interface IVsFileUpgrade é usada para implementar qualquer tipo de atualização de arquivo que precisa acontecer como parte da atualização do projeto. Essa interface não é chamada a partir de IVsProjectUpgradeViaFactory, sendo fornecida como um mecanismo para atualizar arquivos que fazem parte do sistema de projeto, mas o sistema de projeto principal pode não estar diretamente ciente disso. Por exemplo, essa situação pode surgir se os arquivos e propriedades relacionados ao compilador não forem manipulados pela mesma equipe de desenvolvimento que manipula o restante do sistema do projeto.
Implementação de IVsProjectUpgrade
Se o sistema de projeto implementa somente IVsProjectUpgrade, ele não pode participar do Assistente de conversão do Visual Studio. No entanto, mesmo que você implemente a interface IVsProjectUpgradeViaFactory, ainda poderá delegar a atualização de arquivo para implementação de IVsProjectUpgrade.
Para implementar IVsProjectUpgrade
Quando um usuário tenta abrir um projeto, o método UpgradeProject é chamado pelo ambiente depois que o projeto é aberto e antes que qualquer outra ação do usuário possa ser tomada no projeto. Se o usuário já tiver sido solicitado a atualizar a solução, o sinalizador UPF_SILENTMIGRATE será passado no parâmetro
grfUpgradeFlags
. Se o usuário abrir um projeto diretamente, como usando o comando Adicionar Projeto Existente, o sinalizador UPF_SILENTMIGRATE não será passado e o projeto precisará solicitar que o usuário o atualize.Em resposta à chamada UpgradeProject, o projeto deve avaliar se o arquivo de projeto está atualizado. Se o projeto não precisar atualizar o tipo de projeto para uma nova versão, ele poderá simplesmente retornar o sinalizador S_OK.
Se o projeto precisar atualizar o tipo de projeto para uma nova versão, ele deverá determinar se o arquivo de projeto pode ser modificado chamando o método QueryEditFiles e passando um valor de tagVSQueryEditFlags para o parâmetro
rgfQueryEdit
. O projeto, então, precisa fazer o seguinte:Se o valor de
VSQueryEditResult
retornado no parâmetropfEditCanceled
for QER_EditOK, a atualização poderá continuar porque o arquivo de projeto pode ser gravado.Se o valor de
VSQueryEditResult
retornado no parâmetropfEditCanceled
for QER_EditNotOK e o valor deVSQueryEditResult
tiver o bit QER_ReadOnlyNotUnderScc marcado, então UpgradeProject deverá retornar a falha, pois os próprios usuários deverão resolver o problema de permissões. O projeto deve então fazer o seguinte:Relatar o erro ao usuário chamando ReportErrorInfo e retornar o código de erro VS_E_PROJECTMIGRATIONFAILED para IVsProjectUpgrade.
Se o valor de
VSQueryEditResult
for QER_EditNotOK e o valor deVSQueryEditResultFlags
tiver o bit QER_ReadOnlyUnderScc marcado, o arquivo de projeto deverá ser submetido a check-out chamando QueryEditFiles (QEF_ForceEdit_NoPrompting, QEF_DisallowInMemoryEdits,...).
Se a chamada QueryEditFiles no arquivo de projeto fizer com que o arquivo seja submetido a check-out e a versão mais recente seja recuperada, o projeto será descarregado e recarregado. O método UpgradeProject é chamado novamente quando outra instância do projeto é criada. Nessa segunda chamada, o arquivo de projeto pode ser gravado no disco; recomenda-se que o projeto salve uma cópia do arquivo de projeto no formato anterior com uma extensão .OLD, faça as alterações de atualização necessárias e salve o arquivo de projeto no novo formato. Novamente, se qualquer parte do processo de atualização falhar, o método deve indicar a falha retornando VS_E_PROJECTMIGRATIONFAILED. Isso faz com que o projeto seja descarregado no Gerenciador de Soluções.
É importante entender o processo completo que ocorre no ambiente para o caso em que a chamada para o método QueryEditFiles (especificando um valor de ReportOnly) retorna os sinalizadores QER_EditNotOK e QER_ReadOnlyUnderScc.
O usuário tenta abrir o arquivo de projeto.
O ambiente chama sua implementação CanCreateProject.
Se CanCreateProject retornar
true
, o ambiente chamará sua implementação CanCreateProject.O ambiente chama sua implementação Load para abrir o arquivo e inicializar o objeto de projeto, por exemplo, Project1.
O ambiente chama sua implementação
IVsProjectUpgrade::UpgradeProject
para determinar se o arquivo de projeto precisa ser atualizado.Você chama QueryEditFiles e passa um valor de QEF_ReportOnly para o parâmetro
rgfQueryEdit
.O ambiente retorna QER_EditNotOK para
VSQueryEditResult
e o bit QER_ReadOnlyUnderScc é definido comoVSQueryEditResultFlags
.Sua implementação de IVsProjectUpgrade chama
IVsQueryEditQuerySave::QueryEditFiles
(QEF_ForceEdit_NoPrompting, QEF_DisallowInMemoryEdits).
Essa chamada pode fazer com que uma nova cópia do arquivo de projeto seja verificada e a versão mais recente recuperada, além da necessidade de recarregar o arquivo de projeto. Nesse ponto, uma de duas coisas irá acontecer:
Se você lidar com sua própria recarga de projeto, o ambiente chamará sua implementação ReloadItem (VSITEMID_ROOT). Quando você receber essa chamada, recarregue a primeira instância do seu projeto (Project1) e continue atualizando seu arquivo de projeto. O ambiente sabe que você manipula sua própria recarga de projeto se você retornar
true
para GetProperty (VSHPROPID_HandlesOwnReload).Se você não lidar com sua própria recarga de projeto, então retorne
false
para GetProperty (VSHPROPID_HandlesOwnReload). Nesse caso, antes que QueryEditFiles(QEF_ForceEdit_NoPrompting, QEF_DisallowInMemoryEdits) retorne, o ambiente cria outra nova instância do seu projeto, por exemplo, Project2, da seguinte maneira:O ambiente chama Close no seu primeiro objeto de projeto, Project1, colocando assim esse objeto no estado inativo.
O ambiente chama sua implementação
IVsProjectFactory::CreateProject
para criar uma segunda instância do seu projeto, Project2.O ambiente chama sua implementação
IPersistFileFormat::Load
para abrir o arquivo e inicializar o segundo objeto de projeto, Project2.O ambiente chama
IVsProjectUpgrade::UpgradeProject
uma segunda vez para determinar se o objeto de projeto deve ser atualizado. No entanto, essa chamada é feita em uma nova segunda instância do projeto, Project2. Esse é o projeto que é aberto na solução.Observação
Na instância em que seu primeiro projeto, Project1, é colocado no estado inativo, você deve retornar S_OK na primeira chamada para sua implementação UpgradeProject.
Você chama QueryEditFiles e passa um valor de QEF_ReportOnly para o parâmetro
rgfQueryEdit
.O ambiente retorna QER_EditOK e a atualização pode continuar porque o arquivo de projeto pode ser gravado.
Se você não conseguir atualizar, retorne VS_E_PROJECTMIGRATIONFAILED de IVsProjectUpgrade::UpgradeProject
. Se nenhuma atualização for necessária ou se você optar por não atualizar, trate a chamada IVsProjectUpgrade::UpgradeProject
como uma no-op. Se você retornar VS_E_PROJECTMIGRATIONFAILED, um nó de espaço reservado será adicionado à solução para o seu projeto.
Atualizando Itens de Projeto
Se você adicionar ou gerenciar itens dentro de sistemas de projeto que você não implementar, talvez seja necessário participar do processo de atualização do projeto. O Crystal Reports é um exemplo de item que pode ser adicionado ao sistema do projeto.
Normalmente, os implementadores de item de projeto desejam aproveitar um projeto já totalmente instanciado e atualizado porque precisam saber quais são as referências do projeto e quais são as outras propriedades do projeto para tomar uma decisão de atualização.
Para obter a notificação de atualização do projeto
Defina o sinalizador SolutionOrProjectUpgrading (definido em vsshell80.idl) na implementação do item de projeto. Isso faz com que o item de projeto VSPackage seja carregado automaticamente quando o shell do Visual Studio determinar que um sistema de projeto está no processo de atualização.
Avise a interface IVsSolutionEventsProjectUpgrade através do método AdviseSolutionEvents.
A interface IVsSolutionEventsProjectUpgrade é acionada depois que a implementação do sistema do projeto tiver concluído suas operações de atualização e o novo projeto atualizado for criado. Dependendo do cenário, a interface IVsSolutionEventsProjectUpgrade é acionada após os métodos OnAfterOpenSolution, OnAfterOpenProject ou OnAfterLoadProject.
Para atualizar os arquivos de item de projeto
Você deve gerenciar cuidadosamente o processo de backup de arquivos na implementação do item de projeto. Isso se aplica, em particular, a um backup lado a lado, em que o parâmetro
fUpgradeFlag
do método UpgradeProject é definido como PUVFF_SXSBACKUP, onde os arquivos dos quais foi feito backup são colocados ao lado dos arquivos designados como ".old". Os arquivos de backup mais antigos do que a hora do sistema quando o projeto foi atualizado podem ser designados como obsoletos. Além disso, eles podem ser substituídos, a menos que você tome medidas específicas para evitar isso.No momento em que seu item de projeto recebe uma notificação da atualização do projeto, o Assistente de conversão do Visual Studio ainda é exibido. Portanto, você deve usar os métodos da interface IVsUpgradeLogger para fornecer mensagens de atualização para a interface do usuário do assistente.