How to: Handle Specialized Deployment
A deployment is an optional operation for projects. A Web project, for example, supports a deployment to let a project update a Web server. Likewise, a Smart Device project supports a deployment to copy a built application to the target device. Project subtypes can supply specialized deployment behavior by implementing the IVsDeployableProjectCfg interface. This interface defines a complete set of the deployment operations:
The actual deployment operation should be performed in the separate thread to make Visual Studio even more responsive to the user interaction. The methods provided by IVsDeployableProjectCfg are called asynchronously by Visual Studio and operate in the background, allowing the environment to query the status of a deployment operation at any time or to stop the operation, if necessary. The IVsDeployableProjectCfg interface deployment operations are called by the environment when the user selects the deploy command.
To notify the environment that a deployment operation has begun or ended, the project subtype needs to call the OnStartDeploy and the OnEndDeploy methods.
Handling Specialized Deployment
To handle a specialized deployment by a subtype project
Implement the AdviseDeployStatusCallback method to register the environment to receive notifications of deployment status events.
Private adviseSink As Microsoft.VisualStudio.Shell.EventSinkCollection = New Microsoft.VisualStudio.Shell.EventSinkCollection() Public Function AdviseDeployStatusCallback(ByVal pIVsDeployStatusCallback As IVsDeployStatusCallback, _ ByRef pdwCookie As UInteger) As Integer If pIVsDeployStatusCallback Is Nothing Then Throw New ArgumentNullException("pIVsDeployStatusCallback") End If pdwCookie = adviseSink.Add(pIVsDeployStatusCallback) Return VSConstants.S_OK End Function
private Microsoft.VisualStudio.Shell.EventSinkCollection adviseSink = new Microsoft.VisualStudio.Shell.EventSinkCollection(); public int AdviseDeployStatusCallback(IVsDeployStatusCallback pIVsDeployStatusCallback, out uint pdwCookie) { if (pIVsDeployStatusCallback == null) throw new ArgumentNullException("pIVsDeployStatusCallback"); pdwCookie = adviseSink.Add(pIVsDeployStatusCallback); return VSConstants.S_OK; }
Implement the UnadviseDeployStatusCallback method to cancel the environment's registration to receive notifications of deployment status events.
Public Function UnadviseDeployStatusCallback(ByVal dwCookie As UInteger) As Integer adviseSink.RemoveAt(dwCookie) Return VSConstants.S_OK End Function
public int UnadviseDeployStatusCallback(uint dwCookie) { adviseSink.RemoveAt(dwCookie); return VSConstants.S_OK; }
Implement the Commit method to perform the commit operation specific to your application. This method is used mainly for database deployment.
Public Function Commit(ByVal dwReserved As UInteger) As Integer 'Implement commit operation here. Return VSConstants.S_OK End Function
public int Commit(uint dwReserved) { //Implement commit operation here. return VSConstants.S_OK; }
Implement the Rollback method to perform a rollback operation. When this method is called, the deployment project must do whatever is appropriate to rollback changes and restore the state of the project. This method is used mainly for database deployment.
Public Function Commit(ByVal dwReserved As UInteger) As Integer 'Implement commit operation here. Return VSConstants.S_OK End Function
public int Rollback(uint dwReserved) { //Implement Rollback operation here. return VSConstants.S_OK; }
Implement the QueryStartDeploy method to determine whether or not a project is able to start a deployment operation.
Public Function QueryStartDeploy(ByVal dwOptions As UInteger, ByVal pfSupported As Integer(), ByVal pfReady As Integer()) As Integer If Not pfSupported Is Nothing AndAlso pfSupported.Length > 0 Then pfSupported(0) = 1 End If If Not pfReady Is Nothing AndAlso pfReady.Length > 0 Then pfReady(0) = 0 If Not deploymentThread Is Nothing AndAlso (Not deploymentThread.IsAlive) Then pfReady(0) = 1 End If End If Return VSConstants.S_OK End Function
public int QueryStartDeploy(uint dwOptions, int[] pfSupported, int[] pfReady) { if (pfSupported != null && pfSupported.Length >0) pfSupported[0] = 1; if (pfReady != null && pfReady.Length >0) { pfReady[0] = 0; if (deploymentThread != null && !deploymentThread.IsAlive) pfReady[0] = 1; } return VSConstants.S_OK; }
Implement the QueryStatusDeploy method to determine whether or not a deployment operation has completed successfully.
Public Function QueryStatusDeploy(ByRef pfDeployDone As Integer) As Integer pfDeployDone = 1 If Not deploymentThread Is Nothing AndAlso deploymentThread.IsAlive Then pfDeployDone = 0 End If Return VSConstants.S_OK End Function
public int QueryStatusDeploy(out int pfDeployDone) { pfDeployDone = 1; if (deploymentThread != null && deploymentThread.IsAlive) pfDeployDone = 0; return VSConstants.S_OK; }
Implement the StartDeploy method to begin a deployment operation in a separate thread. Place the code specific to your application's deployment inside the Deploy method.
Public Function StartDeploy(ByVal pIVsOutputWindowPane As IVsOutputWindowPane, ByVal dwOptions As UInteger) As Integer If pIVsOutputWindowPane Is Nothing Then Throw New ArgumentNullException("pIVsOutputWindowPane") End If If Not deploymentThread Is Nothing AndAlso deploymentThread.IsAlive Then Throw New NotSupportedException("Cannot start deployment operation when it is already started; Call QueryStartDeploy first") End If outputWindow = pIVsOutputWindowPane ' Notify that deployment is about to begin and see if any user wants to cancel. If (Not NotifyStart()) Then Return VSConstants.E_ABORT End If operationCanceled = False ' Create and start our thread deploymentThread = New Thread(AddressOf Me.Deploy) deploymentThread.Name = "Deployment Thread" deploymentThread.Start() Return VSConstants.S_OK End Function
public int StartDeploy(IVsOutputWindowPane pIVsOutputWindowPane, uint dwOptions) { if (pIVsOutputWindowPane == null) throw new ArgumentNullException("pIVsOutputWindowPane"); if (deploymentThread != null && deploymentThread.IsAlive) throw new NotSupportedException("Cannot start deployment operation when it is already started; Call QueryStartDeploy first"); outputWindow = pIVsOutputWindowPane; // Notify that deployment is about to begin and see if any user wants to cancel. if (!NotifyStart()) return VSConstants.E_ABORT; operationCanceled = false; // Create and start our thread deploymentThread = new Thread(new ThreadStart(this.Deploy)); deploymentThread.Name = "Deployment Thread"; deploymentThread.Start(); return VSConstants.S_OK; }
Implement the StopDeploy method to stop a deployment operation. This method is called when a user presses the Cancel button during the deployment process.
Public Function StopDeploy(ByVal fSync As Integer) As Integer If Not deploymentThread Is Nothing AndAlso deploymentThread.IsAlive Then Return VSConstants.S_OK End If outputWindow.OutputStringThreadSafe("Canceling deployment") operationCanceled = True If fSync <> 0 Then ' Synchronous request, wait for the thread to terminate. If (Not deploymentThread.Join(10000)) Then Debug.Fail("Deployment thread did not terminate before the timeout, Aborting thread") deploymentThread.Abort() End If End If Return VSConstants.S_OK End Function
public int StopDeploy(int fSync) { if (deploymentThread != null && deploymentThread.IsAlive) return VSConstants.S_OK; outputWindow.OutputStringThreadSafe("Canceling deployment"); operationCanceled = true; if (fSync != 0) { // Synchronous request, wait for the thread to terminate. if (!deploymentThread.Join(10000)) { Debug.Fail("Deployment thread did not terminate before the timeout, Aborting thread"); deploymentThread.Abort(); } } return VSConstants.S_OK; }
Notes
All code examples provided in this topic are parts of a larger example, Visual Studio Extensibility Samples.