Compartilhamento da área de transferência do Windows com o Web Services (Parte 2)

Cada objeto da área de transferência é armazenado em disco para que o cliente possa recuperá-lo posteriormente

Por | @oficinadanet Programação
target="_blank">Continuação da parte 1

C#

[WebMethod]
    public void InsertMessageStream(byte[] buffer, string format, string objectType, string transactionGuid, bool
    isFinalTransaction, string clipBoardGUID)
    {
        //always base the current directory on the clipboard that we're sending now.
        string clipBoardGUIDDirectory = System.Web.HttpContext.Current.Request.PhysicalApplicationPath + clipBoardGUID;

        try
        {
            //if the directory does not exist then delete all the other directories (clipboard instances) and create a new directory
            //if the directory already exists then this particular transaction is part of the same clipboard so don't do anything.
            //this works because othe clipboardDirectory is based off of the GUID sent from the client.
            if (!Directory.Exists(clipBoardGUIDDirectory))
            {
                string[] dirs = Directory.GetDirectories(System.Web.HttpContext.Current.Request.PhysicalApplicationPath);
                foreach (string dir in dirs)
                {
                    Directory.Delete(dir, true);
                }
                Directory.CreateDirectory(clipBoardGUIDDirectory);
            }
        }
        catch
        {
        }
        //create the filename based on the current transaction, format, and object type.  We will parse this out later
        //so we know how to add this back to the target clipboard.
        string fileName = clipBoardGUIDDirectory + "\" + transactionGuid + "_" + format + "_" + objectType;
        FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write);
        fs.Position = fs.Length;
        fs.Write(buffer, 0, buffer.Length);
        fs.Close();
}


VB

        Public Sub InsertMessageStream(ByVal buffer() As Byte, ByVal format As String, ByVal objectType As String, ByVal
transactionGuid As String, ByVal isFinalTransaction As Boolean, ByVal clipBoardGUID As String)
        'always base the current directory on the clipboard that we're sending now.
        Dim clipBoardDataDirectory As String = (System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "\Clipboard_Data")
        Dim clipBoardGUIDDirectory As String = (clipBoardDataDirectory + ("\" + clipBoardGUID))
        Try
            'if the directory does not exist then delete all the other directories (clipboard instances) and create a new directory
            'if the directory already exists then this particular transaction is part of the same clipboard so don't do anything.
            'this works because othe clipboardDirectory is based off of the GUID sent from the client.
            If Not Directory.Exists(clipBoardGUIDDirectory) Then
                Dim dirs() As String = Directory.GetDirectories(clipBoardDataDirectory)
                For Each dir As String In dirs
                    Directory.Delete(dir, True)
                Next
                Directory.CreateDirectory(clipBoardGUIDDirectory)
            End If
        Catch

        End Try
        'create the filename based on the current transaction, format, and object type.  We will parse this out later
        'so we know how to add this back to the target clipboard.
        Dim fileName As String = (clipBoardGUIDDirectory + ("\" _
                    + (transactionGuid + ("_" _
                    + (format + ("_" + objectType))))))
        Dim fs As FileStream = New FileStream(fileName, FileMode.Append, FileAccess.Write)
        fs.Position = fs.Length
        fs.Write(buffer, 0, buffer.Length)
        fs.Close()
End Sub



Cada objeto da área de transferência é armazenado em disco para que o cliente possa recuperá-lo posteriormente. Observe na captura de tela abaixo como o nome do arquivo é utilizado para armazenar a ID exclusiva da transação, que inclui dados do objeto, do tipo de objeto e do formato da área de transferência. Todas essas informações são necessárias para a remontagem correta dos itens na área de transferência de destino.
Compartilhamento da área de transferência do Windows com o Web Services (Parte 2)

Agora que temos uma representação de cada objeto da área de transferência no servidor, precisamos encontrar uma forma de colocar cada item na área de transferência de destino. O método Web Service a seguir fornece um resultado de retorno tipo “ClipboardStream”. O objeto ClipboardStream contém todas as informações necessárias para a remontagem de cada item na área de transferência de destino. Como um Web Service baseia-se em um relacionamento do tipo solicitação-resposta, ele espera que o cliente continue a chamá-lo até que todos os itens da área de transferência tenham sido recebidos com êxito. Além disso, ainda há uma maior complexidade, pois cada item da área de transferência pode ser dividido em vários itens, caso o tamanho definido pela constante “byteCount” seja excedido. Portanto, o computador de destino deve manter o controle de cada solicitação e avisar ao servidor onde parou a última transação por meio da variável “currentByte”. Veja abaixo o código do Web Service.

C#

[WebMethod]
    public ClipboardStream GetMessageStream(string transactionGUID,
    string[] previousTransactionGUIDs, string clipBoardGUID, long currentByte)
    {
        string clipBoardDataDirectory = System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "Clipboard_Data";
        string clipBoardGUIDDirectory = clipBoardDataDirectory + "\" + clipBoardGUID;
        string currentTransaction = "";
        bool isLastTransaction = false;


        //if the clipBoardGUID is not empty then we only need to make sure that the directory still exists.
        if (clipBoardGUID != "")
        {
            //if the directory does not exist throw an exception, it must have already been deleted.
            if (!Directory.Exists(clipBoardGUIDDirectory))
            {
                throw new Exception("Requested clipboard does not exist.  It must have been deleted.");
            }
        }
        //if the clipboardGUID is empty then this is the client's first contact with the server and we need
        //to select the available clipboard GUID to return to the user.
        else
        {
            string[] availableClipBoard = Directory.GetDirectories(clipBoardDataDirectory)[0].Split('\');
            clipBoardGUID = availableClipBoard[availableClipBoard.Length - 1];
            clipBoardGUIDDirectory += clipBoardGUID;
        }

        //we need to get the next transaction.  Each time we finish a transaction we add it to previousTransactionGUIDs
        //at the client end so we know not to send it again.
        currentTransaction = GetCurrentTransaction(clipBoardGUIDDirectory, previousTransactionGUIDs);

        //if the current transaction is null then we're done and there are no more to send to the client
        if (currentTransaction == null)
        {
            return null;
        }

        //open the filestream and set it to the position requested by the client.
        FileStream fs = new FileStream(currentTransaction, FileMode.Open);
        fs.Position = currentByte;

        //determind if this is the last transaction or not for this object so we can let the client know.
        long numBytesToRead = fs.Length - currentByte;
        if (numBytesToRead > byteCount)
        {
            numBytesToRead = byteCount;
            isLastTransaction = false;
        }
        else
        {
            isLastTransaction = true;
        }

        //read the filestream bytes to the buffer and populate the object to return to the client.
        byte[] buffer = new byte[numBytesToRead];
        fs.Read(buffer, 0, (int)numBytesToRead);
        fs.Close();


        FileInfo fi = new FileInfo(currentTransaction);
        ClipboardStream clipboardStream = new ClipboardStream();
        clipboardStream.Buffer = buffer;
        clipboardStream.ClipBoardID = clipBoardGUID;
        clipboardStream.Format = fi.Name.Split('_')[1];
        clipboardStream.ObjectType = fi.Name.Split('_')[2];
        clipboardStream.IsLastTransaction = isLastTransaction;
        clipboardStream.TransactionID = currentTransaction;

        return clipboardStream;

}



VB
 _
    Public Function GetMessageStream(ByVal transactionGUID As String, ByVal previousTransactionGUIDs() As String,
    ByVal clipBoardGUID As String, ByVal currentByte As Long) As ClipboardStream
        Dim clipBoardDataDirectory As String = (System.Web.HttpContext.Current.Request.PhysicalApplicationPath + "Clipboard_Data")
        Dim clipBoardGUIDDirectory As String = clipBoardDataDirectory
        Dim currentTransaction As String = ""
        Dim isLastTransaction As Boolean = False
        'if the clipBoardGUID is not empty then we only need to make sure that the directory still exists.
        If (clipBoardGUID <> "") Then
            'if the directory does not exist throw an exception, it must have already been deleted.
            If Not Directory.Exists(clipBoardGUIDDirectory) Then
                Throw New Exception("Requested clipboard does not exist.  It must have been deleted.")
            End If
        End If
        'if the clipboardGUID is empty then this is the client's first contact with the server and we need
        'to select the available clipboard GUID to return to the user.
        Dim availableClipBoard() As String = Directory.GetDirectories(clipBoardDataDirectory)(0).Split(Microsoft.VisualBasic.ChrW(92))
        clipBoardGUID = availableClipBoard((availableClipBoard.Length - 1))
        clipBoardGUIDDirectory = (clipBoardGUIDDirectory + "" + clipBoardGUID)
        'we need to get the next transaction.  Each time we finish a transaction we add it to previousTransactionGUIDs
        'at the client end so we know not to send it again.
        currentTransaction = GetCurrentTransaction(clipBoardGUIDDirectory, previousTransactionGUIDs)
        'if the current transaction is null then we're done and there are no more to send to the client
        If (currentTransaction Is Nothing) Then
            Return Nothing
        End If
        'open the filestream and set it to the position requested by the client.
        Dim fs As FileStream = New FileStream(currentTransaction, FileMode.Open)
        fs.Position = currentByte
        'determind if this is the last transaction or not for this object so we can let the client know.
        Dim numBytesToRead As Long = (fs.Length - currentByte)
        If (numBytesToRead > byteCount) Then
            numBytesToRead = byteCount
            isLastTransaction = False
        Else
            isLastTransaction = True
        End If
        'read the filestream bytes to the buffer and populate the object to return to the client.
        Dim buffer() As Byte = New Byte((numBytesToRead) - 1) {}
        fs.Read(buffer, 0, CType(numBytesToRead, Integer))
        fs.Close()

        Dim fi As FileInfo = New FileInfo(currentTransaction)
        Dim clipboardStream As ClipboardStream = New ClipboardStream
        clipboardStream.Buffer = buffer
        clipboardStream.ClipBoardID = clipBoardGUID
        clipboardStream.Format = fi.Name.Split(Microsoft.VisualBasic.ChrW(95))(1)
        clipboardStream.ObjectType = fi.Name.Split(Microsoft.VisualBasic.ChrW(95))(2)
        clipboardStream.IsLastTransaction = isLastTransaction
        clipboardStream.TransactionID = currentTransaction
        Return clipboardStream
    End Function



A última peça que falta para que o nosso projeto funcione corretamente é o código de cliente. Ele recebe o conteúdo da área de transferência do servidor e remonta cada item na ordem correta, adicionando-os à área de transferência com o formato correto à medida que cada um é concluído. Veja abaixo o código de cliente para esse procedimento.

C#

{
            string[] transactionGuids = null;

            ClipboardService.ClipboardStream clipBoardStream = new WindowsApplication1.ClipboardService.ClipboardStream();
            DataObject dataObject = new DataObject();
            clipBoardStream.ClipBoardID = "";
            clipBoardStream.IsLastTransaction = false;
            clipBoardStream.TransactionID = "";
            long currentByte = 0;

            Clipboard.Clear();

            //while we don't get null back keep on contacting the web service to get the next ojbect.
            while (clipBoardStream != null)
            {
                MemoryStream memStream = new MemoryStream();
                //while this is not the last transaction keep on contacting the web service to get the rest
                //of this particular object.
                while (clipBoardStream.IsLastTransaction == false)
                {
                    //contact the web service to get the next transaction
                    clipBoardStream = clipService.GetMessageStream(clipBoardStream.TransactionID,
    transactionGuids, clipBoardStream.ClipBoardID, currentByte);

                    if (clipBoardStream != null)
                    {
                        //write the results to the memory stream
                        memStream.Write(clipBoardStream.Buffer, 0, clipBoardStream.Buffer.Length);
                        //increment the current byte so next time we contact the webservice we'll pick up where we left off
                        currentByte = memStream.Position;

                        //if it is the last transaction then we need to place this item onto the clipboard.
                        if (clipBoardStream.IsLastTransaction)
                        {
                            //handle the clipBoardStream appropriately and add it to the dataObject
                            //for posting to the clipblard.
                            HandleFinalTransaction(clipBoardStream, memStream, ref dataObject);

                            //resize the transactionGuids array as necessary and add the current transaction
                            //so next time we contact the web service we won't get this one again.
                            if (transactionGuids == null)
                            {
                                Array.Resize(ref transactionGuids, 1);
                            }
                            else
                            {
                                Array.Resize(ref transactionGuids, transactionGuids.Length + 1);
                            }
                            transactionGuids[transactionGuids.Length - 1] = clipBoardStream.TransactionID;
                        }
                    }
                    else
                    {
                        break;
                    }

                }

                if (clipBoardStream != null)
                {
                    clipBoardStream.IsLastTransaction = false;
                    currentByte = 0;
                }
            }

            Clipboard.SetDataObject(dataObject, true);



VB
Dim transactionGuids() As String = Nothing
        Dim clipBoardStream As ClipboardService.ClipboardStream = New ClipboardVB.ClipboardService.ClipboardStream
        Dim dataObject As DataObject = New DataObject
        clipBoardStream.ClipBoardID = ""
        clipBoardStream.IsLastTransaction = False
        clipBoardStream.TransactionID = ""
        Dim currentByte As Long = 0
        Clipboard.Clear()
        'while we don't get null back keep on contacting the web service to get the next ojbect.

        While (Not (clipBoardStream) Is Nothing)
            Dim memStream As MemoryStream = New MemoryStream
            'while this is not the last transaction keep on contacting the web service to get the rest
            'of this particular object.

            While (clipBoardStream.IsLastTransaction = False)
                'contact the web service to get the next transaction

                clipBoardStream = clipService.GetMessageStream(clipBoardStream.TransactionID, transactionGuids,
clipBoardStream.ClipBoardID, currentByte)
                If (Not (clipBoardStream) Is Nothing) Then
                    'write the results to the memory stream
                    memStream.Write(clipBoardStream.Buffer, 0, clipBoardStream.Buffer.Length)
                    'increment the current byte so next time we contact the webservice we'll pick up where we left off
                    currentByte = memStream.Position
                    'if it is the last transaction then we need to place this item onto the clipboard.
                    If clipBoardStream.IsLastTransaction Then
                        'handle the clipBoardStream appropriately and add it to the dataObject
                        'for posting to the clipblard.
                        HandleFinalTransaction(clipBoardStream, memStream, dataObject)
                        'resize the transactionGuids array as necessary and add the current transaction
                        'so next time we contact the web service we won't get this one again.
                        If (transactionGuids Is Nothing) Then
                            Array.Resize(transactionGuids, 1)
                        Else
                            Array.Resize(transactionGuids, (transactionGuids.Length + 1))
                        End If
                        transactionGuids((transactionGuids.Length - 1)) = clipBoardStream.TransactionID
                    End If
                Else
                    Exit While
                End If

            End While
            If (Not (clipBoardStream) Is Nothing) Then
                clipBoardStream.IsLastTransaction = False
                currentByte = 0
            End If

        End While
        Clipboard.SetDataObject(dataObject, True)


Fonte: Microsoft MSDN

Mais sobre:
Share Tweet
DESTAQUESRecomendado
Mais compartilhados
Comentários