Saturday, March 6, 2010

Network shares on Smb server could not be accessed - again

For a couple of days my server was down due to a hardware failure.  After I fixed the problem and I put the server back online I noticed a problem with the workstations: after login Windows popped up a balloon warning that “Could not reconnect all network drives”

NetworkDrives

All the drives I had mapped to Samba shares on my Infrant ReadyNAS system were now inaccessible, and they were showing disconnected in Windows Explorer.

NetworkDrives2

Double clicking the shares in Windows Explorer was displaying a logon prompt with the following error “The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you”.

MapError

Typing correct credentials was useless. The dialog just came back. Canceling the dialog was going through 2 more logon prompts and displaying a message listing all personal certificates on the machine. Needless to say, those were certificates for another domain and logon eventually failed.

I deleted the disconnected mapped drives and I was able to recreate them without problems and everything was fine again. Until the first reboot, that is. And then again, network drives were disconnected and “The system detected a possible attempt to compromise security” was back. :-(

Initially I thought Windows may have installed some update in the last week that strengthened the security settings and breaking network shares to old Linux boxes  (It wouldn’t have been the first time). But that wasn’t the case.

I checked access to the domain controller server. It was fine, I could ping it by its Wins name (SOL), by its fully qualified domain name (sol.constantin.comcast.net), by it’s IP address (192.168.0.2), I could access the network shares on the server, etc. So, server being inaccessible didn’t seem to be the problem.

I looked then in the System Event Log to see if any problems were logged. There were lots of errors like these:

  • Time-Service event ID 129: “NtpClient was unable to set a domain peer to use as a time source because of discovery error. NtpClient will try again in 3473457 minutes and double the reattempt interval thereafter. The error was: The entry is not found. (0x800706E1)”
  • GroupPolicy event ID 1129 “The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient condition. A success message would be generated once the machine gets connected to the domain controller and Group Policy has successfully processed. If you do not see a success message for several hours, then contact your administrator”. with error code 1222 - "The network is not present or not started."
  • Netlogon 5719: “ This computer was not able to set up a secure session with a domain controller in domain CONSTANTIN due to the following: There are currently no logon servers available to service the logon request. This may lead to authentication problems. Make sure that this computer is connected to the network. If the problem persists, please contact your domain administrator.”
I searched the net for more information them, but none of the solutions proposed or diagnostics like this seemed to lead anywhere in my case.

Eventually I rebooted the computer once more, and this time I got two different event types:

  • GroupPolicy event ID 1055: “The processing of Group Policy failed. Windows could not resolve the computer name. This could be caused by one of more of the following:
    a) Name Resolution failure on the current domain controller.
    b) Active Directory Replication Latency (an account created on another domain controller has not replicated to the current domain controller).”

    (and a similar event 1053 for “The processing of Group Policy failed. Windows could not resolve the user name”)

Searching the net for this one proved to be successful. I found this Microsoft support page, which indicated to look for an additional error code in Event Details tab. In my case the error code was 1355 “The specified domain either does not exist or could not be contacted.”. The support page instructed further to “Use nslookup to confirm you can resolve addresses of the domain controllers in the user domain.”

Sure enough, the DNS server was not able to resolve the name of the domain server computer…

Nslookup1

And then it hit me what was wrong. The DNS server I was using was the Wi-Fi router (192.168.0.1), a Netgear/Linux box. This was not able to provide DNS entries correctly for the local network computers, despite them being configured with static addresses. :-( It was my fault, too – I had set the router as preferred DNS when the DC server was down due to the hardware failure…

Solution

So, I went to Control Panel\Network and Sharing Center, clicked on LocalAreaConnection, Properties, selected “Internet Protocol Version 4”, clicked Properties, and switched the Preferred/Alternate DNS Severs to use the domain controller (192.168.0.2) as the Preferred DNS server.

Now I was able to resolve correctly the name of the Domain Controller, and I was able to access the network shares without problem again…

Nslookup2

If you reached this point and you’re asking why I told you all this, it’s because 12 months from now when I may hit again the same problem with the network shares it’s likely I won’t remember it may be due to an innocent switch of the DNS servers. Having it documented in the blog will help me remember. I hope if you searched and reached this article, it might help you too….

Tuesday, March 2, 2010

Implementing disabled WPF toolbar buttons for Visual Studio 2010

 

If you’ve ever wanted to implement a toolbar in WPF you may have come upon this limitation: you can easily set images for the toolbar buttons, but there is no default way of making these images appear grayed when the toolbar buttons are disabled.

To implement the toolbar buttons and menu items, Visual Studio 2010 uses a custom algorithm to create gray images from the original picture. This is publicly available  for consumption via a converter Microsoft.VisualStudio.PlatformUI.GrayscaleImageConverter, implemented in Microsoft.VisualStudio.Shell.10.0 assembly. The converter takes as input an ImageSource and converts to an Image element that uses for source the grayed out version of the image.

If you need to implement toolbars for your package/dialogs you should strongly consider using shell-implemented toolbars (defined by your application via *.vsct files) and used through IVsToolWindowToolbar/IVsToolWindowToolbarHost interfaces. That guarantees a consistent look of all the buttons, separators or split-buttons in your toolbar with the rest of the shell.

For instance, to display a shell-owned toolbar in a WPF dialog you can use IVsUIShell4.CreateToolbarTray() interface to obtain an IVsToolbarTrayHost, then call AddToolbar() on this object to add the toolbar using the guid of your package and the resource Id of the toolbar in vsct, then get the UIElement representing the toolbar using IVsToolbarTrayHost.GetToolbarTray() and position the element to your liking in the dialog.

 

However, there may be situations when you’ll want to implement your own WPF toolbar buttons. To maintain a consistent grayed out look of disabled buttons you may choose to reuse the GrayscaleImageConverter implemented by the shell. Below I describe a way to do this:

1)  Implement a ToolbarButtonImage class having a Source dependency property. You’ll use this to set the button’s image in the “normal” state.

2) The style of the ToolbarButtonImage class will use a trigger to switch the template of the button’s content when the button gets enabled/disabled between a control template (ToolbarButtonImage_Normal) containing the image in the normal state and a control template (ToolbarButtonImage_Disabled) containing the grayed out image produced by the  GrayscaleImageConverter.

3) Add the buttons to the toolbars as follows:

<ToolBar>
    <Button IsEnabled="{Binding ……….}">
       <local:ToolbarButtonImage Source="Resources\ButtonNormalImage.png"/>
    </Button>
</ToolBar>

Below is the sample code for the ToolbarButtonImage and its style:

----------------------------------------------
ToolbarButtonImage.cs
----------------------------------------------

using
System;

using
System.Windows;

using
System.Windows.Controls;

using
System.Windows.Data;

using
System.Windows.Media;

using
System.Windows.Media.Imaging;


namespace
YourApplicationNamespace 
{ 
    public class ToolbarButtonImage : UserControl
 
    { 
        static ToolbarButtonImage()
        {
              DefaultStyleKeyProperty.OverrideMetadata(
typeof(ToolbarButtonImage),

                                new FrameworkPropertyMetadata(typeof(ToolbarButtonImage)));
        } 

        public
static readonly DependencyProperty SourceProperty = DependencyProperty.Register

                               ("Source", typeof(BitmapSource), typeof(ToolbarButtonImage)); 

        public
BitmapSource
Source
        {
            get
            {
                 return (BitmapSource)GetValue(SourceProperty);
            }
            set

            {
                SetValue(SourceProperty,
value);
            }
        }
    }
}

----------------------------------------------
ToolbarButtonImageStyle.xaml
----------------------------------------------

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:YourApplicationNamespace"

    xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.10.0">


<ui:GrayscaleImageConverter x:Key="GrayscaleImageConverter"/>


<ControlTemplate x:Key="ToolbarButtonImage_Normal" TargetType="{x:Type local:ToolbarButtonImage}">

     <Image Width="16" Height="16" Source="{TemplateBinding Property=Source}"/>

</ControlTemplate>


<ControlTemplate x:Key="ToolbarButtonImage_Disabled" TargetType="{x:Type local:ToolbarButtonImage}">

     <ContentPresenter Width="16" Height="16" Content="{TemplateBinding Property=Source, Converter={StaticResource GrayscaleImageConverter}}"/>

</ControlTemplate>


<Style x:Key="{x:Type local:ToolbarButtonImage}" TargetType="{x:Type local:ToolbarButtonImage}">
 
    <Setter Property="Template" Value="{StaticResource ToolbarButtonImage_Normal}"/>

    <Style.Triggers>

        <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}}" Value="False">

            <Setter Property="Template" Value="{StaticResource ToolbarButtonImage_Disabled}"/>

        </DataTrigger>

    </Style.Triggers>

</Style>

</ResourceDictionary>