Trabajar con las Shell Libraries en Windows 7

Una de las novedades que introduce Windows 7 a nivel de gestión de archivos, con respecto a sistemas operativos anteriores, es la organización de los mismos en bibliotecas temáticas. Con ello se pretende separar los distintos tipos de contenidos de manera que sea más fácil localizarlos y trabajar con ellos.

En la siguiente imagen se puede ver cual es la distribución establecida por defecto:

 

Esta distribución se puede personalizar, es decir, es posible crear nuevas bibliotecas con los contenidos específicos que nosotros deseemos. A nivel de usuario, esto se puede hacer de manera sencilla mediante la opción Nueva Biblioteca que nos aparece en la parte superior del explorador cuando hacemos clic sobre Bibliotecas.

Pero en nuestro caso nos interesa ir un poco más allá y ver como se puede explotar la funcionalidad de las bibliotecas desde el punto de vista del desarrollador. Para ello vamos a ver cómo podemos programar una aplicación para Windows 7 de manera que se automatice este proceso. Esto puede ser útil cuando nos interese, por ejemplo, redirigir un tipo de contenido específico de nuestra organización (compras) a una ubicación concreta y predefinida.

Pero ¿que es lo primero que tenemos que hacer?Al igual que para trabajar con la TaskBar, se necesita agregar a nuestro proyecto las referencias especificas que nos permitan trabajar con las características de Windows 7 ( Microsoft.WindowsAPICodePack y Microsoft.WindowsAPICodePack.Shell, que forman parte del WindowsAPICodePack. En mi caso no las he utilizado, ya que he reutilizado una aplicación iniciada hace unos meses y en la que utilizaba la VistaBridgeLibrary. Decir que, entre ambas, existen diferencias en cuanto a los nombres de los métodos que se utilizan, pero que el “fundamento” es el mismo. 

A continuación lo que vamos a ver es una aplicación básica que nos permite crear nuevas bibliotecas e ir añadiendo contenido a ellas (en forma de carpetas).

 

Como se puede ver dicha aplicación es un Windows Form que consta de una serie de botones, cuadros de texto, labels…que nos permiten crear un sistema sencillo de gestión de bibliotecas.

1º Damos nombre a nuestra biblioteca, y la añadimos > Añadir Biblioteca

2º Indicamos si queremos añadir una carpeta a la biblioteca creada o a otra ( nombre) > Añadir Carpeta. Y seleccionamos la carpeta deseada mediante el explorador que se no despliega.

 

3º Indicamos si queremos eliminar una carpeta de la biblioteca creada o de otra(nombre) > Eliminar Carpeta. Y seleccionamos la carpeta deseada mediante el explorador que se no despliega.

Y el código utilizado para implementar esta aplicación es el siguiente:

 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using Microsoft.SDK.Samples.VistaBridge.ShellLibrary;
  10. //nos permite trabajar con las ShellLibraries
  11.  
  12. namespace Libraries
  13. {
  14.     public partial class Form1 : Form
  15.     {
  16.         public Form1()
  17.         {
  18.             InitializeComponent();
  19.             //Personalizamos la ventana de nuestra apliación
  20.             this.Text = "Shell Libraries";
  21.             this.Icon = new Icon(Properties.Resources.windows7, new Size(100, 100));
  22.  
  23.         }
  24.  
  25.         private void AñadirBiblio_Click(object sender, EventArgs e)
  26.         {
  27.  
  28.             if (LibraryName.Text == "")//comprueba que se introduce un nombre para la biblioteca
  29.             {
  30.                 Creado.Text = "Debe introducir un nombre";
  31.  
  32.             }
  33.             else
  34.             {
  35.                 CreateLibrary(LibraryName.Text);//se crear la biblioteca con el nombre indicado
  36.                 Creado.Text = "* Biblioteca" + " " + LibraryName.Text + " " + "creada";//indicamos que biblioteca se crea
  37.  
  38.             }
  39.         }
  40.         public static void CreateLibrary(string name)
  41.         {
  42.             //se crea la biblioteca
  43.             using (ShellLibrary library = ShellLibrary.Create(name, true))
  44.             {
  45.  
  46.             }
  47.         }
  48.  
  49.         private void AñadirCarpeta_Click(object sender, EventArgs e)
  50.         {
  51.             FolderBrowserDialog folderAdd = new FolderBrowserDialog();//
  52.  
  53.             if (folderAdd.ShowDialog() == DialogResult.OK)
  54.             {
  55.                 if (radioButton1.Checked == true)//si
  56.                 {
  57.                     AddFolder(LibraryName.Text, folderAdd.SelectedPath);//añadimos la carpeta seleccionada a la biblioteca creada
  58.                     Añadida.Text = "*Se ha añadido la carpeta: " + "\n" + folderAdd.SelectedPath.ToString() + " a la biblioteca" + " " + LibraryName.Text;//indicamos que carpeta se añade a la biblioteca creada
  59.                 }
  60.                 else if (radioButton2.Checked == true)
  61.                 {
  62.                     AddFolder(OtherLibraries.Text, folderAdd.SelectedPath);//añadimos la carpeta seleccionada a cualquier biblioteca
  63.                     Añadida.Text = "* Se ha añadido la carpeta: " + "\n" + folderAdd.SelectedPath.ToString() + " a la biblioteca" + " " + OtherLibraries.Text;//indicamos que carpeta se añade a que biblioteca
  64.                 }
  65.  
  66.             }
  67.  
  68.         }
  69.         public static void AddFolder(string name, string folderPath)
  70.         {
  71.             //se añade una carpeta de una ShellLibrary
  72.             using (ShellLibrary library = ShellLibrary.Load(
  73.                          ShellLibrary.CreateLibraryFullName(name), true))
  74.             {
  75.                 library.AddFolder(folderPath);
  76.             }
  77.         }
  78.         public static void RemoveFolder(string name, string folderPath)
  79.         {
  80.             //se elimina una carpeta de una ShellLibrary
  81.             using (ShellLibrary library = ShellLibrary.Load(
  82.                     ShellLibrary.CreateLibraryFullName(name), true))
  83.             {
  84.                 library.RemoveFolder(folderPath);
  85.             }
  86.         }
  87.  
  88.         private void EliminarCarpeta_Click(object sender, EventArgs e)
  89.         {
  90.             FolderBrowserDialog folderRemove = new FolderBrowserDialog();
  91.             if (folderRemove.ShowDialog() == DialogResult.OK)
  92.             {
  93.                 if (radioButton4.Checked == true)
  94.                 {
  95.                     RemoveFolder(LibraryName.Text, folderRemove.SelectedPath);//eliminamos la carpeta seleccionada de la biblioteca creada
  96.                     Eliminada.Text = "* Se ha eliminado la carpeta: " + "\n" + folderRemove.SelectedPath.ToString() + " de la biblioteca" + " " + LibraryName.Text;
  97.                 }
  98.                 else if (radioButton3.Checked == true)
  99.                 {
  100.                     RemoveFolder(RemoveLibraries.Text, folderRemove.SelectedPath);//eliminamos la carpeta seleccionada de cualquie biblioteca
  101.                     Eliminada.Text = "* Se ha eliminado la carpeta: " + "\n" + folderRemove.SelectedPath.ToString() + " de la biblioteca " + "" + RemoveLibraries.Text;
  102.                 }
  103.  
  104.             }
  105.  
  106.         }
  107.  
  108.  
  109.  
  110.     }
  111. }

Personalizar Tasbar Windows 7(II). ProgressBar

Continuando con la temática de mi post anterior, hoy vamos a ver otra de las funcionalidades que se pueden aplicar a la barra de tareas de Windows 7. En esta ocasión veremos como mostrar una barra de progreso sobre el icono de nuestra aplicación mínimizada. De esta manera como su propio nombre indica veremos el progreso de la misma: activa, pausada, si se produce error, si esta pensando ….
 
Partiendo del proyecto anterior lo que hacemos es añadir un nuevo control WPF, cuyo código de definición es el siguiente:
 
  1. <UserControl x:Class="TaskBarIcons.ProgressBar"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  4.     <Grid Width="300">
  5.         <Grid.RowDefinitions>
  6.             <RowDefinition Height="Auto" />
  7.             <RowDefinition Height="Auto" />
  8.             <RowDefinition Height="Auto" />
  9.             <RowDefinition Height="Auto" />
  10.             <RowDefinition Height="Auto" />
  11.             <RowDefinition Height="*" />
  12.         </Grid.RowDefinitions>
  13.         <Rectangle Style="{DynamicResource BorderStyle}" Grid.RowSpan="4" />
  14.         <TextBlock Text="Taskbar Progress" Margin="{DynamicResource BoxedContentMargin}" Style="{DynamicResource SectionTitle}" />
  15.         <DockPanel Grid.Row="1" Margin="{DynamicResource BoxedContentMargin}">
  16.             <TextBlock Text="Status" DockPanel.Dock="Left"></TextBlock>
  17.             <ComboBox x:Name="ProgressStateSelection" Margin="5,0,0,0" HorizontalAlignment="Stretch"
  18.                 SelectionChanged="ProgressStateSelection_SelectionChanged"/>
  19.         </DockPanel>
  20.         <Slider x:Name="progressSlider" MaxWidth="300" Height="40" Minimum="0" Maximum="100" Grid.Row="2"
  21.             ValueChanged="progressSlider_ValueChanged" Margin="{DynamicResource BoxedContentMargin}"/>
  22.         <CheckBox x:Name="ShowProgressBar" Click="ShowProgressBar_Click" Grid.Row="3"
  23.               Margin="{DynamicResource BoxedContentMargin}">
  24.             <TextBlock Text="Show slider's value in progress bar" />
  25.         </CheckBox>
  26.     </Grid>
  27. </UserControl>
  28.  
  29. </form>

Y cuya lógica de funcionamiento viene definida a través del siguiente código:

  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using Microsoft.WindowsAPICodePack.Taskbar;
  5.  
  6. namespace TaskBarIcons
  7. {
  8.     /// <summary>
  9.     /// Interaction logic for ProgressBar.xaml
  10.     /// </summary>
  11.     public partial class ProgressBar : UserControl
  12.     {
  13.         public ProgressBar()
  14.         {
  15.             InitializeComponent();
  16.             this.Loaded += ProgressBar_Loaded;
  17.             this.Unloaded += ProgressBar_Unloaded;
  18.         }
  19.         private void ProgressBar_Unloaded(object sender, RoutedEventArgs e)
  20.         {
  21.             TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
  22.         }
  23.  
  24.         private void ProgressBar_Loaded(object sender, RoutedEventArgs e)
  25.         {
  26.             if (this.ProgressStateSelection.ItemsSource == null)
  27.             {
  28.                 this.ProgressStateSelection.ItemsSource = Enum.GetValues(typeof(TaskbarProgressBarState));
  29.                 ProgressStateSelection.SelectedItem = TaskbarProgressBarState.NoProgress;
  30.             }
  31.         }
  32.  
  33.         private void progressSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
  34.         {
  35.             UpdateProgress();
  36.         }
  37.  
  38.         //This method is part of the lab. If we are asked to show a progress bar,
  39.         //choose the appropriate TaskbarProgressState value and use the UpdateProgress
  40.         //method to perform the update.
  41.         private void ShowProgressBar_Click(object sender, RoutedEventArgs e)
  42.         {
  43.             if (ShowProgressBar.IsChecked.Value)
  44.             {
  45.                 ProgressStateSelection.SelectedItem = TaskbarProgressBarState.Normal;
  46.             }
  47.             else
  48.             {
  49.                 ProgressStateSelection.SelectedItem = TaskbarProgressBarState.NoProgress;
  50.             }
  51.             UpdateProgress();
  52.  
  53.         }
  54.  
  55.         //This method is part of the lab. When the progress bar state changes,
  56.         //synchronize it with the checkbox and use the UpdateProgress method to
  57.         //perform the update.
  58.         private void ProgressStateSelection_SelectionChanged(object sender, SelectionChangedEventArgs e)
  59.         {
  60.  
  61.             if ((TaskbarProgressBarState)ProgressStateSelection.SelectedItem == TaskbarProgressBarState.NoProgress)
  62.             {
  63.                 ShowProgressBar.IsChecked = false;
  64.             }
  65.             else
  66.             {
  67.                 ShowProgressBar.IsChecked = true;
  68.             }
  69.             UpdateProgress();
  70.  
  71.  
  72.         }
  73.  
  74.         //This method is part of the lab. When asked to update the progress state and
  75.         //we should indeed display a taskbar progress bar, use the TaskbarManager's
  76.         //SetProgressValue and SetProgressState methods to update the progress bar state.
  77.         private void UpdateProgress()
  78.         {
  79.  
  80.             if (ShowProgressBar.IsChecked.Value)
  81.             {
  82.                 TaskbarManager.Instance.SetProgressValue((int)progressSlider.Value, 100);
  83.                 TaskbarManager.Instance.SetProgressState((TaskbarProgressBarState)ProgressStateSelection.SelectedItem);
  84.             }
  85.             else
  86.             {
  87.                 TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.NoProgress);
  88.             }
  89.  
  90.  
  91.         }
  92.     }
  93. }

 
El control que hemos creado es el que se observa en la parte inferior de la imagen:
 
progressbar
 
A través de él podemos seleccionar los distintos estados:
en progreso, que se mostrará como una barra verde gradual
error, se mostrará una barra roja gradual
en pausa, se mostrará una barra amarilla gradual
pensando se mostrará una barra verde intermitente
 
De manera que veremos los estados de nuestra aplicación de la siguiente forma:
 
progbar1            progbar2           progbar3
En Progreso              Error                  Pensando
 
Desde mi punto de vista, este tipo de desarrollos son muy interesantes no sólo visualmente, sino también a nivel de usabilidad. 

Personalizar Taskbar Windows 7 (I). Overlay Icons

Dado que apenas quedan unos meses para que Windows 7 “se encuentre definitivamente entre nosotros”, vamos a ir viendo algunas características interesantes que presenta este nuevo sistema operativo. Estas características o funcionalidades no son sólo atractivas desde el punto de vista de desarrollo sino también para el propio usuario, ya que tienen como objetivo facilitar y simplificar el trabajo diario.

El ejemplo que vamos a ver a continuación se trata de mostrar una serie de iconos sobre nuestra aplicación minimizada. Y la pregunta es ¿Para que nos sirve esto? Podemos utilizar los iconos para indicar el estado en que se encuentra una aplicación o un archivo, para marcar el tipo de contenido de una carpeta…

taskbar1

A través del listbox que aparece en la imagen, podemos seleccionar los distintos iconos que se muestran de manera que si activamos el checkbox “Show selected icon as overlay”, el icono que se encuentre seleccionado, aparecerá sobre el  icono de nuestra aplicación, cuando esta se encuentra minimizada. A continuación podemos ver alguno de los ejemplos:

taskbar2 taskbar3 taskbar4
 

Una vez visto esto vamos a entrar en el código de la aplicación. Creamos nuestro proyecto de tipo Windows Forms, y añadimos las referencias al Windows API Code Pack, previamente instalado en nuestro equipo. A continuación añadimos un control de tipo WPF, y los recursos que vayamos a utilizar, y pasamos a programar dicho control.

Por un lado está el archivo .xaml, donde definiremos las características gráficas del control y cuyo código debe ser el siguiente:
  1. <UserControl x:Class="TaskBarIcons.OverlayIcons"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6.              mc:Ignorable="d"
  7.              xmlns:local="clr-namespace:TaskBarIcons">
  8.     <UserControl.Resources>
  9.         <local:IconToBitmapSourceConverter x:Key="IconToBitmapSourceConverter" />
  10.         <DataTemplate x:Key="ImageTemplate">
  11.             <Grid>
  12.                 <Image Source="{Binding Converter={StaticResource IconToBitmapSourceConverter}, Mode=Default}"/>
  13.             </Grid>
  14.         </DataTemplate>
  15.         <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
  16.             <VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal"/>
  17.         </ItemsPanelTemplate>
  18.         <SolidColorBrush x:Key="ListBoxItemUnselected" Color="#002685E2" />
  19.         <SolidColorBrush x:Key="ListBoxItemSelected" Color="#FF2685E2" />
  20.         <Style x:Key="ListBoxItemStyle1" TargetType="{x:Type ListBoxItem}">
  21.             <Setter Property="Background" Value="Transparent"/>
  22.             <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  23.             <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  24.             <Setter Property="Padding" Value="2,0,0,0"/>
  25.             <Setter Property="Template">
  26.                 <Setter.Value>
  27.                     <ControlTemplate TargetType="{x:Type ListBoxItem}">
  28.                         <Border x:Name="Bd" SnapsToDevicePixels="true"
  29.                     Background="{TemplateBinding Background}"
  30.                     Padding="{TemplateBinding Padding}" HorizontalAlignment="Center"
  31.                     VerticalAlignment="Center"
  32.                     BorderBrush="{DynamicResource ListBoxItemUnselected}" BorderThickness="2">
  33.                             <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
  34.                         </Border>
  35.                         <ControlTemplate.Triggers>
  36.                             <Trigger Property="IsSelected" Value="true">
  37.                                 <Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource ListBoxItemSelected}"/>
  38.                             </Trigger>
  39.                             <Trigger Property="IsEnabled" Value="false">
  40.                                 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
  41.                             </Trigger>
  42.                         </ControlTemplate.Triggers>
  43.                     </ControlTemplate>
  44.                 </Setter.Value>
  45.             </Setter>
  46.         </Style>
  47.     </UserControl.Resources>
  48.     <Grid>
  49.         <Grid Margin="2" Width="200" VerticalAlignment="Top">
  50.             <Grid.RowDefinitions>
  51.                 <RowDefinition Height="Auto" />
  52.                 <RowDefinition Height="*" MinHeight="50"/>
  53.                 <RowDefinition Height="Auto" />
  54.                 <RowDefinition Height="Auto" />
  55.             </Grid.RowDefinitions>
  56.             <Rectangle Style="{DynamicResource BorderStyle}" Grid.RowSpan="4" />
  57.             <TextBlock Text="Overlay Icons"
  58.                  Margin="{DynamicResource BoxedContentMargin}"
  59.                  Style="{DynamicResource SectionTitle}" />
  60.             <ListBox x:Name="iconsList"
  61.                Margin="{DynamicResource BoxedContentMargin}"
  62.                Grid.Row="1" ItemTemplate="{DynamicResource ImageTemplate}"
  63.                ItemsPanel="{DynamicResource ItemsPanelTemplate1}"
  64.                ItemContainerStyle="{DynamicResource ListBoxItemStyle1}"
  65.                SelectionChanged="iconsList_SelectionChanged" />
  66.             <CheckBox x:Name="ShowOverlay" Click="ShowOverlay_Click" Grid.Row="2"
  67.                 Margin="{DynamicResource BoxedContentMargin}">
  68.                 <TextBlock Text="Show selected icon as overlay" TextWrapping="Wrap" />
  69.             </CheckBox>
  70.         </Grid>
  71.     </Grid>
  72. </UserControl>
  73.  
  74. </form>

Por otro lado el archivo .cs, donde definiremos la lógica de funcionamiento del mismo y cuyo código será:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Globalization;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Media.Imaging;
  9. using Microsoft.WindowsAPICodePack.Taskbar;
  10.  
  11. namespace TaskBarIcons
  12. {
  13.     /// <summary>
  14.     /// Interaction logic for UserControl1.xaml
  15.     /// </summary>
  16.     public partial class OverlayIcons : UserControl
  17.     {
  18.         public OverlayIcons()
  19.         {
  20.             InitializeComponent();
  21.             this.Loaded += Overlays_Loaded;
  22.             this.Unloaded += Overlays_Unloaded;
  23.         }
  24.         private void Overlays_Unloaded(object sender, RoutedEventArgs e)
  25.         {
  26.             TaskbarManager.Instance.SetOverlayIcon(null, null);
  27.         }
  28.  
  29.         private void Overlays_Loaded(object sender, RoutedEventArgs e)
  30.         {
  31.             if (this.iconsList.ItemsSource == null)
  32.             {
  33.                 this.iconsList.ItemsSource = OverlayIcons.Icons;
  34.             }
  35.             else
  36.             {
  37.                 ShowOrHideOverlayIcon();
  38.             }
  39.         }
  40.  
  41.         static List<Icon> _icons;
  42.         public static List<Icon> Icons
  43.         {
  44.             get
  45.             {
  46.                 if (_icons == null)
  47.                 {
  48.                     _icons = new List<Icon>()
  49.                     {
  50.                        
  51.                         TaskBarIcons.Resources.Discussion,
  52.                         TaskBarIcons.Resources.Mail,
  53.                         TaskBarIcons.Resources.Add_Appointment,
  54.                         TaskBarIcons.Resources.Add_To_Favorite,
  55.                         TaskBarIcons.Resources.Desktop,
  56.                         TaskBarIcons.Resources.Movie_CD,
  57.                         TaskBarIcons.Resources.Mr__Bomb,
  58.                         TaskBarIcons.Resources.Smiley_Star_Pink
  59.  
  60.                     };
  61.                 }
  62.                 return _icons;
  63.             }
  64.         }
  65.  
  66.         private void ShowOverlay_Click(object sender, RoutedEventArgs e)
  67.         {
  68.             ShowOrHideOverlayIcon();
  69.         }
  70.  
  71.         private void iconsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
  72.         {
  73.             ShowOrHideOverlayIcon();
  74.         }
  75.  
  76.         //The following method is part of the lab. If we are asked to show an
  77.         //overlay icon, use the TaskbarManager.SetOverlayIcon method to set it.
  78.         //Use the same method with a null icon to reset it, so that no icon is
  79.         //displayed.
  80.         private void ShowOrHideOverlayIcon()
  81.         {
  82.             if (ShowOverlay.IsChecked.Value)
  83.             {
  84.                 Icon icon = iconsList.SelectedItem as Icon;
  85.                 if (icon != null)
  86.                     TaskbarManager.Instance.SetOverlayIcon(icon, "icon" + iconsList.SelectedIndex.ToString());
  87.             }
  88.             else
  89.             {
  90.                 TaskbarManager.Instance.SetOverlayIcon(null, null);
  91.             }
  92.  
  93.         }
  94.  
  95.     }
  96.     public class IconToBitmapSourceConverter : IValueConverter
  97.     {
  98.         #region IValueConverter Members
  99.  
  100.         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  101.         {
  102.             Icon icon = value as Icon;
  103.             if (icon != null)
  104.             {
  105.                 BitmapSource bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
  106.                     icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
  107.                 return bitmap;
  108.             }
  109.             return value;
  110.         }
  111.  
  112.         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  113.         {
  114.             throw new NotImplementedException();
  115.         }
  116.  
  117.         #endregion
  118.     }
  119.  
  120. }

 

Si queremos aprovechar otras de las características que presenta Windows 7, existe un kit de entrenamiento que podemos descargar aquí, y en el cual encontramos numerosos tutoriales para crear distintas aplicaciones.

 

Sistemas antivirus y SharePoint

En la línea de mis últimos artículos y ¡¡¡ para no variar!!! hoy vamos a ver otro PROBLEMA que se nos ha planteado en nuestra aplicación SharePoint.

De la noche a la mañana apareció un error que no sabíamos muy bien porqué. No era posible acceder a uno de nuestro sitios ni tampoco podíamos ver los elementos de una biblioteca de imágenes, dándonos como única explicación Excepción de HRESULT: 0x80041051. Lo que nos hizo plantearnos que era lo último que habíamos hecho en nuestro sitio SharePoint para que hubiera aparecido dicho problema. Y era un export de  la aplicación.

Tras buscar información al respecto he encontrado numerosas fuentes que apuntan a que este problema puede ser debido a la existencia o detección de virus en algún documento en MOSS, a través de ForeFront u otras soluciones de Antivirus. Debido a su nivel de seguridad, en algunas ocasiones, detectan virus en algunas páginas o elementos de nuestro sitio SharePoint (existan o no), como se puede ver en el siguiente link:

http://www.guillesql.es/Articulos/MOSS_Exception_from_HRESULT_0x80041050_SharePoint_STSADM_Export.aspx

Otra de las fuentes de las que he obtenido información es http://support.microsoft.com/kb/928169, donde se indican los síntomas de este problema, las posibles causas y soluciones. Con ayuda de estas páginas y otras que se indican al final del artículo, y siguiendo los pasos que se enumeran a continuación, hemos conseguido solucionar el problema.

Pasos a seguir:

1. Conectarnos a la base de datos de contenido de SharePoint

2. Ejecutar la siguiente consulta sobre la misma:

SELECT *
FROM AllDocs
WHERE (VirusStatus > 0) and (VirusStatus is not null)

3. Si obtenemos una serie de elementos “posiblemente infectados”, lo que debemos hacer es:

    1º Analizar manualmente dichos elementos para comprobar que se encuentran libres de virus, con un sistema antivirus. 

     2º En caso de que se encuentren correctamente, debemos cambiar el valor de la columna VirusStatus a NULL. Para ello implementamos la siguiente consulta:

UPDATE AllDocs
SET VirusStatus = null
WHERE (VirusStatus > 0) and (VirusStatus is not null)

4. Por último, aunque no es necesario, inicializaremos a nula también la información relacionada para no dar lugar a confusión (una vez limpiado el estado), para ello ejecutaremos la siguiente consulta:

    UPDATE AllDocs
    SET VirusInfo = null
    WHERE (VirusInfo is not null)

    De esta manera comprobamos de nuevo nuestra aplicación y vemos que todo funciona correctamente.

    Si no se visualizan los cambios deberemos reiniciar el IIS mediante el comando iisreset.

     

    Links de interés:

    http://gtechcentre.blogspot.com/2007/07/link-httpsupport.html

    http://imoss.blogspot.com/2008/09/com-exception-error-in-sharepoint-with.html?showComment=1223478240000

    http://rawatsumit.blogspot.com/2009/07/exception-from-hresult-0x80041051-on.html

    http://social.technet.microsoft.com/Forums/en-US/forefrontSharePoint/thread/3f20ae34-03ba-4da0-af20-2b6cfa61663b