实际部署操作应在单独的线程中执行,以使 Visual Studio 更能响应用户交互。 Visual Studio 提供 IVsDeployableProjectCfg 的方法由 Visual Studio 异步调用,并在后台运行,允许环境随时查询部署操作的状态,或者在必要时停止操作。 IVsDeployableProjectCfg当用户选择部署命令时,环境会调用接口部署操作。
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;
}
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
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;
}
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 QueryStatusDeploy(out int pfDeployDone)
{
pfDeployDone = 1;
if (deploymentThread != null && deploymentThread.IsAlive)
pfDeployDone = 0;
return VSConstants.S_OK;
}
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 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;
}
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 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;
}
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